/**************************************************************************
*
* Copyright 2008 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* @file
*
* Fake WGL API implementation.
*
* These functions implement the WGL API, on top of the ICD DDI, so that the
* resulting DLL can be used as a drop-in replacement for the system's
* opengl32.dll.
*
* These functions never get called for ICD drivers, which use exclusively the
* ICD DDI, i.e., the Drv* entrypoints.
*/
#include <windows.h>
#include "util/u_debug.h"
#include "stw_icd.h"
#include "stw_context.h"
#include "stw_pixelformat.h"
#include "stw_wgl.h"
#include "stw_ext_context.h"
static void
overrideOpenGL32EntryPoints(void);
WINGDIAPI BOOL APIENTRY
wglCopyContext(
HGLRC hglrcSrc,
HGLRC hglrcDst,
UINT mask )
{
return DrvCopyContext( (DHGLRC)(UINT_PTR)hglrcSrc,
(DHGLRC)(UINT_PTR)hglrcDst,
mask );
}
WINGDIAPI HGLRC APIENTRY
wglCreateContext(
HDC hdc )
{
overrideOpenGL32EntryPoints();
return (HGLRC) DrvCreateContext(hdc);
}
WINGDIAPI HGLRC APIENTRY
wglCreateLayerContext(
HDC hdc,
int iLayerPlane )
{
overrideOpenGL32EntryPoints();
return (HGLRC) DrvCreateLayerContext( hdc, iLayerPlane );
}
WINGDIAPI BOOL APIENTRY
wglDeleteContext(
HGLRC hglrc )
{
return DrvDeleteContext((DHGLRC)(UINT_PTR)hglrc );
}
WINGDIAPI HGLRC APIENTRY
wglGetCurrentContext( VOID )
{
return (HGLRC)(UINT_PTR)stw_get_current_context();
}
WINGDIAPI HDC APIENTRY
wglGetCurrentDC( VOID )
{
return stw_get_current_dc();
}
WINGDIAPI HDC APIENTRY
wglGetCurrentReadDCARB( VOID )
{
return stw_get_current_read_dc();
}
WINGDIAPI BOOL APIENTRY
wglMakeCurrent(
HDC hdc,
HGLRC hglrc )
{
return DrvSetContext( hdc, (DHGLRC)(UINT_PTR)hglrc, NULL ) ? TRUE : FALSE;
}
WINGDIAPI BOOL APIENTRY
wglSwapBuffers(
HDC hdc )
{
return DrvSwapBuffers( hdc );
}
WINGDIAPI DWORD WINAPI
wglSwapMultipleBuffers(UINT n,
CONST WGLSWAP *ps)
{
UINT i;
for (i =0; i < n; ++i)
wglSwapBuffers(ps->hdc);
return 0;
}
WINGDIAPI BOOL APIENTRY
wglSwapLayerBuffers(
HDC hdc,
UINT fuPlanes )
{
return DrvSwapLayerBuffers( hdc, fuPlanes );
}
WINGDIAPI PROC APIENTRY
wglGetProcAddress(
LPCSTR lpszProc )
{
return DrvGetProcAddress( lpszProc );
}
WINGDIAPI int APIENTRY
wglChoosePixelFormat(
HDC hdc,
CONST PIXELFORMATDESCRIPTOR *ppfd )
{
if (ppfd->nSize != sizeof( PIXELFORMATDESCRIPTOR ) || ppfd->nVersion != 1)
return 0;
if (ppfd->iPixelType != PFD_TYPE_RGBA)
return 0;
if (!(ppfd->dwFlags & PFD_DRAW_TO_WINDOW))
return 0;
if (!(ppfd->dwFlags & PFD_SUPPORT_OPENGL))
return 0;
if (ppfd->dwFlags & PFD_DRAW_TO_BITMAP)
return 0;
if (ppfd->dwFlags & PFD_SUPPORT_GDI)
return 0;
if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && (ppfd->dwFlags & PFD_STEREO))
return 0;
return stw_pixelformat_choose( hdc, ppfd );
}
WINGDIAPI int APIENTRY
wglDescribePixelFormat(
HDC hdc,
int iPixelFormat,
UINT nBytes,
LPPIXELFORMATDESCRIPTOR ppfd )
{
return DrvDescribePixelFormat( hdc, iPixelFormat, nBytes, ppfd );
}
WINGDIAPI int APIENTRY
wglGetPixelFormat(
HDC hdc )
{
return stw_pixelformat_get( hdc );
}
WINGDIAPI BOOL APIENTRY
wglSetPixelFormat(
HDC hdc,
int iPixelFormat,
const PIXELFORMATDESCRIPTOR *ppfd )
{
/* SetPixelFormat (hence wglSetPixelFormat) must not touch ppfd, per
* http://msdn.microsoft.com/en-us/library/dd369049(v=vs.85).aspx
*/
(void) ppfd;
return DrvSetPixelFormat( hdc, iPixelFormat );
}
WINGDIAPI BOOL APIENTRY
wglUseFontBitmapsA(
HDC hdc,
DWORD first,
DWORD count,
DWORD listBase )
{
return wglUseFontBitmapsW(hdc, first, count, listBase);
}
WINGDIAPI BOOL APIENTRY
wglShareLists(
HGLRC hglrc1,
HGLRC hglrc2 )
{
return DrvShareLists((DHGLRC)(UINT_PTR)hglrc1,
(DHGLRC)(UINT_PTR)hglrc2);
}
WINGDIAPI BOOL APIENTRY
wglUseFontBitmapsW(
HDC hdc,
DWORD first,
DWORD count,
DWORD listBase )
{
GLYPHMETRICS gm;
MAT2 tra;
FIXED one, minus_one, zero;
void *buffer = NULL;
BOOL result = TRUE;
one.value = 1;
one.fract = 0;
minus_one.value = -1;
minus_one.fract = 0;
zero.value = 0;
zero.fract = 0;
tra.eM11 = one;
tra.eM22 = minus_one;
tra.eM12 = tra.eM21 = zero;
for (int i = 0; i < count; i++) {
DWORD size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, 0,
NULL, &tra);
glNewList(listBase + i, GL_COMPILE);
if (size != GDI_ERROR) {
if (size == 0) {
glBitmap(0, 0, -gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y,
gm.gmCellIncX, gm.gmCellIncY, NULL);
}
else {
buffer = realloc(buffer, size);
size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm,
size, buffer, &tra);
glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
-gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y,
gm.gmCellIncX, gm.gmCellIncY, buffer);
}
}
else {
result = FALSE;
}
glEndList();
}
free(buffer);
return result;
}
WINGDIAPI BOOL APIENTRY
wglUseFontOutlinesA(
HDC hdc,
DWORD first,
DWORD count,
DWORD listBase,
FLOAT deviation,
FLOAT extrusion,
int format,
LPGLYPHMETRICSFLOAT lpgmf )
{
(void) hdc;
(void) first;
(void) count;
(void) listBase;
(void) deviation;
(void) extrusion;
(void) format;
(void) lpgmf;
assert( 0 );
return FALSE;
}
WINGDIAPI BOOL APIENTRY
wglUseFontOutlinesW(
HDC hdc,
DWORD first,
DWORD count,
DWORD listBase,
FLOAT deviation,
FLOAT extrusion,
int format,
LPGLYPHMETRICSFLOAT lpgmf )
{
(void) hdc;
(void) first;
(void) count;
(void) listBase;
(void) deviation;
(void) extrusion;
(void) format;
(void) lpgmf;
assert( 0 );
return FALSE;
}
WINGDIAPI BOOL APIENTRY
wglDescribeLayerPlane(
HDC hdc,
int iPixelFormat,
int iLayerPlane,
UINT nBytes,
LPLAYERPLANEDESCRIPTOR plpd )
{
return DrvDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
}
WINGDIAPI int APIENTRY
wglSetLayerPaletteEntries(
HDC hdc,
int iLayerPlane,
int iStart,
int cEntries,
CONST COLORREF *pcr )
{
return DrvSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
}
WINGDIAPI int APIENTRY
wglGetLayerPaletteEntries(
HDC hdc,
int iLayerPlane,
int iStart,
int cEntries,
COLORREF *pcr )
{
return DrvGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
}
WINGDIAPI BOOL APIENTRY
wglRealizeLayerPalette(
HDC hdc,
int iLayerPlane,
BOOL bRealize )
{
(void) hdc;
(void) iLayerPlane;
(void) bRealize;
assert( 0 );
return FALSE;
}
/* When this library is used as a opengl32.dll drop-in replacement, ensure we
* use the wglCreate/Destroy entrypoints above, and not the true opengl32.dll,
* which could happen if this library's name is not opengl32.dll exactly.
*
* For example, Qt 5.4 bundles this as opengl32sw.dll:
* https://blog.qt.io/blog/2014/11/27/qt-weekly-21-dynamic-opengl-implementation-loading-in-qt-5-4/
*/
static void
overrideOpenGL32EntryPoints(void)
{
wglCreateContext_func = &wglCreateContext;
wglDeleteContext_func = &wglDeleteContext;
}