diff options
author | marha <marha@users.sourceforge.net> | 2010-12-28 16:10:20 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2010-12-28 16:10:20 +0000 |
commit | 807c6931fe683fd844ceec1b023232181e6aae03 (patch) | |
tree | 1a131ed95fe2200d0ad33da8f7755a7ed2364adc /mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c | |
parent | 973099dda7e49e5abe29819a7124b3b1e7bd8b92 (diff) | |
download | vcxsrv-807c6931fe683fd844ceec1b023232181e6aae03.tar.gz vcxsrv-807c6931fe683fd844ceec1b023232181e6aae03.tar.bz2 vcxsrv-807c6931fe683fd844ceec1b023232181e6aae03.zip |
xserver and mesa git update 28-12-2010
Diffstat (limited to 'mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c')
-rw-r--r-- | mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c | 5928 |
1 files changed, 2964 insertions, 2964 deletions
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c index 74ecb01a5..37e681dfc 100644 --- a/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c +++ b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c @@ -1,2964 +1,2964 @@ -/**************************************************************************** -* -* Mesa 3-D graphics library -* Direct3D Driver Interface -* -* ======================================================================== -* -* Copyright (C) 1991-2004 SciTech Software, 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, sublicense, -* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL -* SCITECH SOFTWARE INC 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. -* -* ====================================================================== -* -* Language: ANSI C -* Environment: Windows 9x (Win32) -* -* Description: OpenGL window functions (wgl*). -* -****************************************************************************/ - -#include "dglwgl.h" -#ifdef _USE_GLD3_WGL -#include "gld_driver.h" -#endif - -#include "gl/glu.h" // MUST USE MICROSOFT'S GLU32! - -#ifndef _USE_GLD3_WGL -extern DGL_mesaFuncs mesaFuncs; -#endif - -// Need to export wgl* functions if using GLD3, -// otherwise export GLD2 DGL_* functions. -#ifdef _USE_GLD3_WGL -#define _GLD_WGL_EXPORT(a) wgl##a -#else -#define _GLD_WGL_EXPORT(a) DGL_##a -#endif - -// Calls into Mesa 4.x are different -#ifdef _USE_GLD3_WGL -#include "dlist.h" -#include "drawpix.h" -#include "get.h" -#include "matrix.h" -// NOTE: All the _GLD* macros now call the gl* functions direct. -// This ensures that the correct internal pathway is taken. KeithH -#define _GLD_glNewList glNewList -#define _GLD_glBitmap glBitmap -#define _GLD_glEndList glEndList -#define _GLD_glDeleteLists glDeleteLists -#define _GLD_glGetError glGetError -#define _GLD_glTranslatef glTranslatef -#define _GLD_glBegin glBegin -#define _GLD_glVertex2fv glVertex2fv -#define _GLD_glEnd glEnd -#define _GLD_glNormal3f glNormal3f -#define _GLD_glVertex3f glVertex3f -#define _GLD_glVertex3fv glVertex3fv -#else // _USE_GLD3_WGL -#define _GLD_glNewList (*mesaFuncs.glNewList) -#define _GLD_glBitmap (*mesaFuncs.glBitmap) -#define _GLD_glEndList (*mesaFuncs.glEndList) -#define _GLD_glDeleteLists (*mesaFuncs.glDeleteLists) -#define _GLD_glGetError (*mesaFuncs.glGetError) -#define _GLD_glTranslatef (*mesaFuncs.glTranslatef) -#define _GLD_glBegin (*mesaFuncs.glBegin) -#define _GLD_glVertex2fv (*mesaFuncs.glVertex2fv) -#define _GLD_glEnd (*mesaFuncs.glEnd) -#define _GLD_glNormal3f (*mesaFuncs.glNormal3f) -#define _GLD_glVertex3f (*mesaFuncs.glVertex3f) -#define _GLD_glVertex3fv (*mesaFuncs.glVertex3fv) -#endif // _USE_GLD3_WGL - -// *********************************************************************** - -// Emulate SGI DDK calls. -#define __wglMalloc(a) GlobalAlloc(GPTR, (a)) -#define __wglFree(a) GlobalFree((a)) - -// *********************************************************************** - -// Mesa glu.h and MS glu.h call these different things... -//#define GLUtesselator GLUtriangulatorObj -//#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA - -// For wglFontOutlines - -typedef GLUtesselator *(APIENTRY *gluNewTessProto)(void); -typedef void (APIENTRY *gluDeleteTessProto)(GLUtesselator *tess); -typedef void (APIENTRY *gluTessBeginPolygonProto)(GLUtesselator *tess, void *polygon_data); -typedef void (APIENTRY *gluTessBeginContourProto)(GLUtesselator *tess); -typedef void (APIENTRY *gluTessVertexProto)(GLUtesselator *tess, GLdouble coords[3], void *data); -typedef void (APIENTRY *gluTessEndContourProto)(GLUtesselator *tess); -typedef void (APIENTRY *gluTessEndPolygonProto)(GLUtesselator *tess); -typedef void (APIENTRY *gluTessPropertyProto)(GLUtesselator *tess, GLenum which, GLdouble value); -typedef void (APIENTRY *gluTessNormalProto)(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRY *gluTessCallbackProto)(GLUtesselator *tess, GLenum which, void (CALLBACK *)()); - -static HINSTANCE gluModuleHandle; -static gluNewTessProto gluNewTessProc; -static gluDeleteTessProto gluDeleteTessProc; -static gluTessBeginPolygonProto gluTessBeginPolygonProc; -static gluTessBeginContourProto gluTessBeginContourProc; -static gluTessVertexProto gluTessVertexProc; -static gluTessEndContourProto gluTessEndContourProc; -static gluTessEndPolygonProto gluTessEndPolygonProc; -static gluTessPropertyProto gluTessPropertyProc; -static gluTessNormalProto gluTessNormalProc; -static gluTessCallbackProto gluTessCallbackProc; - -static HFONT hNewFont, hOldFont; -static FLOAT ScaleFactor; - -#define LINE_BUF_QUANT 4000 -#define VERT_BUF_QUANT 4000 - -static FLOAT* LineBuf; -static DWORD LineBufSize; -static DWORD LineBufIndex; -static FLOAT* VertBuf; -static DWORD VertBufSize; -static DWORD VertBufIndex; -static GLenum TessErrorOccurred; - -static int AppendToLineBuf( - FLOAT value); - -static int AppendToVertBuf( - FLOAT value); - -static int DrawGlyph( - UCHAR* glyphBuf, - DWORD glyphSize, - FLOAT chordalDeviation, - FLOAT extrusion, - INT format); - -static void FreeLineBuf(void); - -static void FreeVertBuf(void); - -static long GetWord( - UCHAR** p); - -static long GetDWord( - UCHAR** p); - -static double GetFixed( - UCHAR** p); - -static int InitLineBuf(void); - -static int InitVertBuf(void); - -static HFONT CreateHighResolutionFont( - HDC hDC); - -static int MakeDisplayListFromGlyph( - DWORD listName, - UCHAR* glyphBuf, - DWORD glyphSize, - LPGLYPHMETRICSFLOAT glyphMetricsFloat, - FLOAT chordalDeviation, - FLOAT extrusion, - INT format); - -static BOOL LoadGLUTesselator(void); -static BOOL UnloadGLUTesselator(void); - -static int MakeLinesFromArc( - FLOAT x0, - FLOAT y0, - FLOAT x1, - FLOAT y1, - FLOAT x2, - FLOAT y2, - DWORD vertexCountIndex, - FLOAT chordalDeviationSquared); - -static int MakeLinesFromGlyph( UCHAR* glyphBuf, - DWORD glyphSize, - FLOAT chordalDeviation); - -static int MakeLinesFromTTLine( UCHAR** pp, - DWORD vertexCountIndex, - WORD pointCount); - -static int MakeLinesFromTTPolycurve( UCHAR** pp, - DWORD vertexCountIndex, - FLOAT chordalDeviation); - -static int MakeLinesFromTTPolygon( UCHAR** pp, - FLOAT chordalDeviation); - -static int MakeLinesFromTTQSpline( UCHAR** pp, - DWORD vertexCountIndex, - WORD pointCount, - FLOAT chordalDeviation); - -static void CALLBACK TessCombine( double coords[3], - void* vertex_data[4], - FLOAT weight[4], - void** outData); - -static void CALLBACK TessError( GLenum error); - -static void CALLBACK TessVertexOutData( FLOAT p[3], - GLfloat z); - -// *********************************************************************** - -#ifdef GLD_THREADS -#pragma message("compiling DGLWGL.C vars for multi-threaded support") -extern CRITICAL_SECTION CriticalSection; -extern DWORD dwTLSPixelFormat; // TLS index for current pixel format -#endif -int curPFD = 0; // Current PFD (static) - -// *********************************************************************** - -int dglGetPixelFormat(void) -{ -#ifdef GLD_THREADS - int iPixelFormat; - // get thread-specific instance - if (glb.bMultiThreaded) { - __try { - iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat); - } - __except(EXCEPTION_EXECUTE_HANDLER) { - iPixelFormat = curPFD; - } - } - // get global static var - else { - iPixelFormat = curPFD; - } - return iPixelFormat; -#else - return curPFD; -#endif -} - -// *********************************************************************** - -void dglSetPixelFormat(int iPixelFormat) -{ -#ifdef GLD_THREADS - // set thread-specific instance - if (glb.bMultiThreaded) { - __try { - TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat); - } - __except(EXCEPTION_EXECUTE_HANDLER) { - curPFD = iPixelFormat; - } - } - // set global static var - else { - curPFD = iPixelFormat; - } -#else - curPFD = iPixelFormat; -#endif -} - -// *********************************************************************** - -int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)( - HDC a, - CONST PIXELFORMATDESCRIPTOR *ppfd) -{ - DGL_pixelFormat *lpPF = glb.lpPF; - - PIXELFORMATDESCRIPTOR ppfdBest; - int i; - int bestIndex = -1; - int numPixelFormats; - DWORD dwFlags; - - char buf[128]; - char cat[8]; - - DWORD dwAllFlags = - PFD_DRAW_TO_WINDOW | - PFD_DRAW_TO_BITMAP | - PFD_SUPPORT_GDI | - PFD_SUPPORT_OPENGL | - PFD_GENERIC_FORMAT | - PFD_NEED_PALETTE | - PFD_NEED_SYSTEM_PALETTE | - PFD_DOUBLEBUFFER | - PFD_STEREO | - /*PFD_SWAP_LAYER_BUFFERS |*/ - PFD_DOUBLEBUFFER_DONTCARE | - PFD_STEREO_DONTCARE | - PFD_SWAP_COPY | - PFD_SWAP_EXCHANGE | - PFD_GENERIC_ACCELERATED | - 0; - - // Validate license - if (!dglValidate()) - return 0; - - // List may not be built until dglValidate() is called! KeithH - lpPF = glb.lpPF; - - // - // Lets print the input pixel format to the log - // ** Based on "wglinfo" by Nate Robins ** - // - ddlogMessage(DDLOG_SYSTEM, "ChoosePixelFormat:\n"); - ddlogMessage(DDLOG_INFO, "Input pixel format for ChoosePixelFormat:\n"); - ddlogMessage(DDLOG_INFO, - " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n"); - ddlogMessage(DDLOG_INFO, - " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n"); - ddlogMessage(DDLOG_INFO, - "-----------------------------------------------------------------\n"); - sprintf(buf, " . "); - - sprintf(cat, "%2d ", ppfd->cColorBits); - strcat(buf, cat); - if(ppfd->dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn "); - else if(ppfd->dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm "); - else sprintf(cat, ". "); - strcat(buf, cat); - - /* should find transparent pixel from LAYERPLANEDESCRIPTOR */ - sprintf(cat, " . "); - strcat(buf, cat); - - sprintf(cat, "%2d ", ppfd->cColorBits); - strcat(buf, cat); - - /* bReserved field indicates number of over/underlays */ - if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved); - else sprintf(cat, " . "); - strcat(buf, cat); - - sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c'); - strcat(buf, cat); - - sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.'); - strcat(buf, cat); - - sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.'); - strcat(buf, cat); - - if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA) - sprintf(cat, "%2d ", ppfd->cRedBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA) - sprintf(cat, "%2d ", ppfd->cGreenBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA) - sprintf(cat, "%2d ", ppfd->cBlueBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA) - sprintf(cat, "%2d ", ppfd->cAlphaBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cAuxBuffers) sprintf(cat, "%2d ", ppfd->cAuxBuffers); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cDepthBits) sprintf(cat, "%2d ", ppfd->cDepthBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cStencilBits) sprintf(cat, "%2d ", ppfd->cStencilBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cAccumRedBits) sprintf(cat, "%2d ", ppfd->cAccumRedBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cAccumBlueBits) sprintf(cat, "%2d ", ppfd->cAccumBlueBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits); - else sprintf(cat, " . "); - strcat(buf, cat); - - /* no multisample in Win32 */ - sprintf(cat, " . .\n"); - strcat(buf, cat); - - ddlogMessage(DDLOG_INFO, buf); - ddlogMessage(DDLOG_INFO, - "-----------------------------------------------------------------\n"); - ddlogMessage(DDLOG_INFO, "\n"); - - // - // Examine the flags for correctness - // - dwFlags = ppfd->dwFlags; - if (dwFlags != (dwFlags & dwAllFlags)) - { - /* error: bad dwFlags */ - ddlogPrintf(DDLOG_WARN, - "ChoosePixelFormat: bad flags (0x%x)", - dwFlags & (~dwAllFlags)); - // Mask illegal flags and continue - dwFlags = dwFlags & dwAllFlags; - } - - switch (ppfd->iPixelType) { - case PFD_TYPE_RGBA: - case PFD_TYPE_COLORINDEX: - break; - default: - /* error: bad iPixelType */ - ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n"); - return 0; - } - - switch (ppfd->iLayerType) { - case PFD_MAIN_PLANE: - case PFD_OVERLAY_PLANE: - case PFD_UNDERLAY_PLANE: - break; - default: - /* error: bad iLayerType */ - ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n"); - return 0; - } - - numPixelFormats = glb.nPixelFormatCount; - - /* loop through candidate pixel format descriptors */ - for (i=0; i<numPixelFormats; ++i) { - PIXELFORMATDESCRIPTOR ppfdCandidate; - - memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR)); - - /* - ** Check attributes which must match - */ - if (ppfd->iPixelType != ppfdCandidate.iPixelType) { - continue; - } - - if (ppfd->iLayerType != ppfdCandidate.iLayerType) { - continue; - } - - if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) & - (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP | - PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL)) - { - continue; - } - - if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) { - if ((dwFlags & PFD_DOUBLEBUFFER) != - (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER)) - { - continue; - } - } - -// if (!(dwFlags & PFD_STEREO_DONTCARE)) { - if ((dwFlags & PFD_STEREO) != - (ppfdCandidate.dwFlags & PFD_STEREO)) - { - continue; - } -// } - - if (ppfd->iPixelType==PFD_TYPE_RGBA - && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) { - continue; - } - - if (ppfd->iPixelType==PFD_TYPE_RGBA - && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) { - continue; - } - - if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) { - continue; - } - - if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) { - continue; - } - - if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) { - continue; - } - - /* - ** See if candidate is better than the previous best choice - */ - if (bestIndex == -1) { - ppfdBest = ppfdCandidate; - bestIndex = i; - continue; - } - - if ((ppfd->cColorBits > ppfdBest.cColorBits && - ppfdCandidate.cColorBits > ppfdBest.cColorBits) || - (ppfd->cColorBits <= ppfdCandidate.cColorBits && - ppfdCandidate.cColorBits < ppfdBest.cColorBits)) - { - ppfdBest = ppfdCandidate; - bestIndex = i; - continue; - } - - if (ppfd->iPixelType==PFD_TYPE_RGBA - && ppfd->cAlphaBits - && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits) - { - ppfdBest = ppfdCandidate; - bestIndex = i; - continue; - } - - if (ppfd->iPixelType==PFD_TYPE_RGBA - && ppfd->cAccumBits - && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits) - { - ppfdBest = ppfdCandidate; - bestIndex = i; - continue; - } - - if ((ppfd->cDepthBits > ppfdBest.cDepthBits && - ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) || - (ppfd->cDepthBits <= ppfdCandidate.cDepthBits && - ppfdCandidate.cDepthBits < ppfdBest.cDepthBits)) - { - ppfdBest = ppfdCandidate; - bestIndex = i; - continue; - } - - if (ppfd->cStencilBits && - ppfdCandidate.cStencilBits > ppfdBest.cStencilBits) - { - ppfdBest = ppfdCandidate; - bestIndex = i; - continue; - } - - if (ppfd->cAuxBuffers && - ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers) - { - ppfdBest = ppfdCandidate; - bestIndex = i; - continue; - } - } - - if (bestIndex != -1) { - ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1); - return bestIndex + 1; - } - - // Return the pixelformat that has the most capabilities. - // ** NOTE: This is only possible due to the way the list - // of pixelformats is built. ** - // Now picks best pixelformat. KeithH - bestIndex = numPixelFormats; // most capable double buffer format - ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen by default", bestIndex); - return (bestIndex); -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)( - HGLRC a, - HGLRC b, - UINT c) -{ - // Validate license - if (!dglValidate()) - return FALSE; - UNSUPPORTED("wglCopyContext") - return FALSE; // Failed -} - -// *********************************************************************** - -HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)( - HDC a) -{ - int ipf; - - // Validate license - if (!dglValidate()) - return 0; - - // Check that the current PFD is valid - ipf = dglGetPixelFormat(); - if (!IsValidPFD(ipf)) - return (HGLRC)0; - - return dglCreateContext(a, &glb.lpPF[ipf-1]); -} - -// *********************************************************************** - -HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)( - HDC a, - int b) -{ - // Validate license - if (!dglValidate()) - return 0; - - UNSUPPORTED("wglCreateLayerContext") - return NULL; // Failed -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)( - HGLRC a) -{ - // Validate license - if (!dglValidate()) - return FALSE; - - return dglDeleteContext(a); -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)( - HDC hDC, - int iPixelFormat, - int iLayerPlane, - UINT nBytes, - LPLAYERPLANEDESCRIPTOR plpd) -{ - // Validate license - if (!dglValidate()) - return FALSE; - - UNSUPPORTED("DGL_DescribeLayerPlane") - -// gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane); - - return FALSE; -} - -// *********************************************************************** - -int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)( - HDC a, - int b, - UINT c, - LPPIXELFORMATDESCRIPTOR d) -{ - UINT nSize; - - // Validate license - if (!dglValidate()) - return 0; - - if (d == NULL) // Calling app requires max number of PF's - return glb.nPixelFormatCount; - - // The supplied buffer may be larger than the info that we - // will be copying. - if (c > sizeof(PIXELFORMATDESCRIPTOR)) - nSize = sizeof(PIXELFORMATDESCRIPTOR); - else - nSize = c; - - // Setup an empty PFD before doing validation check - memset(d, 0, nSize); - d->nSize = nSize; - d->nVersion = 1; - - if (!IsValidPFD(b)) - return 0; // Bail if PFD index is invalid - - memcpy(d, &glb.lpPF[b-1].pfd, nSize); - - return glb.nPixelFormatCount; -} - -// *********************************************************************** - -HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void) -{ - // Validate license - if (!dglValidate()) - return 0; - - return dglGetCurrentContext(); -} - -// *********************************************************************** - -HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void) -{ - // Validate license - if (!dglValidate()) - return 0; - - return dglGetCurrentDC(); -} - -// *********************************************************************** - -PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)( - LPCSTR a) -{ - // Validate license - if (!dglValidate()) - return NULL; - - UNSUPPORTED("DGL_GetDefaultProcAddress") - return NULL; -} - -// *********************************************************************** - -int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)( - HDC a, - int b, - int c, - int d, - COLORREF *e) -{ - // Validate license - if (!dglValidate()) - return 0; - - UNSUPPORTED("DGL_GetLayerPaletteEntries") - return 0; -} - -// *********************************************************************** - -int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)( - HDC a) -{ - // Validate license - if (!dglValidate()) - return 0; - - return dglGetPixelFormat(); -} - -// *********************************************************************** - -PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)( - LPCSTR a) -{ - PROC dglGetProcAddressD3D(LPCSTR a); - - // Validate license - if (!dglValidate()) - return NULL; - -#ifdef _USE_GLD3_WGL - return _gldDriver.wglGetProcAddress(a); -#else - return dglGetProcAddressD3D(a); -#endif -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)( - HDC a, - HGLRC b) -{ - // Validate license - if (!dglValidate()) - return FALSE; - - return dglMakeCurrent(a, b); -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)( - HDC a, - int b, - BOOL c) -{ - // Validate license - if (!dglValidate()) - return FALSE; - - UNSUPPORTED("DGL_RealizeLayerPalette") - return FALSE; -} - -// *********************************************************************** - -int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)( - HDC a, - int b, - int c, - int d, - CONST COLORREF *e) -{ - // Validate license - if (!dglValidate()) - return 0; - - UNSUPPORTED("DGL_SetLayerPaletteEntries") - return 0; -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)( - HDC a, - int b, - CONST PIXELFORMATDESCRIPTOR *c) -{ - // Validate license - if (!dglValidate()) - return FALSE; - - if (IsValidPFD(b)) { - ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b); - dglSetPixelFormat(b); - return TRUE; - } else { - ddlogPrintf(DDLOG_ERROR, - "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b); - return FALSE; - } -} - -// *********************************************************************** -/* - * Share lists between two gl_context structures. - * This was added for WIN32 WGL function support, since wglShareLists() - * must be called *after* wglCreateContext() with valid GLRCs. (DaveM) - */ -// -// Copied from GLD2.x. KeithH -// -static GLboolean _gldShareLists( - GLcontext *ctx1, - GLcontext *ctx2) -{ - /* Sanity check context pointers */ - if (ctx1 == NULL || ctx2 == NULL) - return GL_FALSE; - /* Sanity check shared list pointers */ - if (ctx1->Shared == NULL || ctx2->Shared == NULL) - return GL_FALSE; - /* Decrement reference count on sharee to release previous list */ - ctx2->Shared->RefCount--; -#if 0 /* 3DStudio exits on this memory release */ - if (ctx2->Shared->RefCount == 0) - free_shared_state(ctx2, ctx2->Shared); -#endif - /* Re-assign list from sharer to sharee and increment reference count */ - ctx2->Shared = ctx1->Shared; - ctx1->Shared->RefCount++; - return GL_TRUE; -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)( - HGLRC a, - HGLRC b) -{ - DGL_ctx *dgl1, *dgl2; - - // Validate license - if (!dglValidate()) - return FALSE; - - // Mesa supports shared lists, but you need to supply the shared - // GL context info when calling gl_create_context(). An auxiliary - // function gl_share_lists() has been added to update the shared - // list info after the GL contexts have been created. (DaveM) - dgl1 = dglGetContextAddress(a); - dgl2 = dglGetContextAddress(b); - if (dgl1->bAllocated && dgl2->bAllocated) { -#ifdef _USE_GLD3_WGL - return _gldShareLists(dgl1->glCtx, dgl2->glCtx); -#else - return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx); -#endif - } - return FALSE; -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)( - HDC a) -{ - // Validate license - if (!dglValidate()) - return FALSE; - - return dglSwapBuffers(a); -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)( - HDC a, - UINT b) -{ - // Validate license - if (!dglValidate()) - return FALSE; - - return dglSwapBuffers(a); -} - -// *********************************************************************** - -// *********************************************************************** -// Note: This ResizeBuffers() function may be called from -// either MESA glViewport() or GLD wglMakeCurrent(). - -BOOL dglWglResizeBuffers( - GLcontext *ctx, - BOOL bDefaultDriver) -{ - DGL_ctx *dgl = NULL; - RECT rcScreenRect; - DWORD dwWidth; - DWORD dwHeight; - DDSURFACEDESC2 ddsd2; - DDSCAPS2 ddscaps2; - IDirectDrawClipper *lpddClipper = NULL; - DWORD dwFlags; - HRESULT hResult; - - DWORD dwMemoryType; - - int i; - struct gl_texture_object *tObj; - struct gl_texture_image *image; - - BOOL bWasFullscreen; - BOOL bSaveDesktop; - BOOL bFullScrnWin = FALSE; - DDSURFACEDESC2 ddsd2DisplayMode; - - DDBLTFX ddbltfx; - POINT pt; - RECT rcDst; -#ifdef _USE_GLD3_WGL - GLD_displayMode glddm; -#endif - -#define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL) - - // Validate license - if (!dglValidate()) - return FALSE; - - // Sanity checks - if (ctx == NULL) - return FALSE; - dgl = ctx->DriverCtx; - if (dgl == NULL) - return FALSE; - - // Get the window size and calculate its dimensions - if (dgl->hWnd == NULL) { - // Check for non-window DC = memory DC ? - if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR) - SetRect(&rcScreenRect, 0, 0, 0, 0); - } - else if (!GetClientRect(dgl->hWnd, &rcScreenRect)) - SetRect(&rcScreenRect, 0, 0, 0, 0); - dwWidth = rcScreenRect.right - rcScreenRect.left; - dwHeight = rcScreenRect.bottom - rcScreenRect.top; - CopyRect(&dgl->rcScreenRect, &rcScreenRect); - - // This will occur on Alt-Tab - if ((dwWidth == 0) && (dwHeight == 0)) { - //dgl->bCanRender = FALSE; - return TRUE; // No resize possible! - } - - // Some apps zero only 1 dimension for non-visible window... (DaveM) - if ((dwWidth == 0) || (dwHeight == 0)) { - dwWidth = 8; - dwHeight = 8; - } - - // Test to see if a resize is required. - // Note that the dimensions will be the same if a prior resize attempt failed. - if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) { - return TRUE; // No resize required - } - - ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight); -#ifndef _USE_GLD3_WGL - // Work out where we want our surfaces created - dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY; -#endif // _USE_GLD3_WGL - - // Note previous fullscreen vs window display status - bWasFullscreen = dgl->bFullscreen; - -#ifdef _USE_GLD3_WGL - if (_gldDriver.GetDisplayMode(dgl, &glddm)) { - if ( (dwWidth == glddm.Width) && - (dwHeight == glddm.Height) ) { - bFullScrnWin = TRUE; - } - if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) { - dgl->bFullscreen = TRUE; - ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n"); - } - else { - dgl->bFullscreen = FALSE; - ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n"); - } - // Cache the display mode dimensions - dgl->dwModeWidth = glddm.Width; - dgl->dwModeHeight = glddm.Height; - } - - // Clamp the effective window dimensions to primary surface. - // We need to do this for D3D viewport dimensions even if wide - // surfaces are supported. This also is a good idea for handling - // whacked-out window dimensions passed for non-drawable windows - // like Solid Edge. (DaveM) - if (dgl->dwWidth > glddm.Width) - dgl->dwWidth = glddm.Width; - if (dgl->dwHeight > glddm.Height) - dgl->dwHeight = glddm.Height; -#else // _USE_GLD3_WGL - // Window resize may have changed to fullscreen - ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode)); - ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode); - hResult = IDirectDraw4_GetDisplayMode( - dgl->lpDD4, - &ddsd2DisplayMode); - if (SUCCEEDED(hResult)) { - if ( (dwWidth == ddsd2DisplayMode.dwWidth) && - (dwHeight == ddsd2DisplayMode.dwHeight) ) { - bFullScrnWin = TRUE; - } - if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) { - dgl->bFullscreen = TRUE; - ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n"); - } - else { - dgl->bFullscreen = FALSE; - ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n"); - } - // Cache the display mode dimensions - dgl->dwModeWidth = ddsd2DisplayMode.dwWidth; - dgl->dwModeHeight = ddsd2DisplayMode.dwHeight; - } - - // Clamp the effective window dimensions to primary surface. - // We need to do this for D3D viewport dimensions even if wide - // surfaces are supported. This also is a good idea for handling - // whacked-out window dimensions passed for non-drawable windows - // like Solid Edge. (DaveM) - if (dgl->dwWidth > ddsd2DisplayMode.dwWidth) - dgl->dwWidth = ddsd2DisplayMode.dwWidth; - if (dgl->dwHeight > ddsd2DisplayMode.dwHeight) - dgl->dwHeight = ddsd2DisplayMode.dwHeight; -#endif // _USE_GLD3_WGL - - // Note if fullscreen vs window display has changed? - bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE; - // Save the desktop primary surface from being destroyed - // whenever remaining in windowed mode, since the stereo mode - // switches are expensive... - -#ifndef _USE_GLD3_WGL - // Don't need to re-allocate persistant buffers. (DaveM) - // Though we should clear the back buffers to hide artifacts. - if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) { - dgl->dwWidth = dwWidth; - dgl->dwHeight = dwHeight; - ZeroMemory(&ddbltfx, sizeof(ddbltfx)); - ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwFillColor = dgl->dwClearColorPF; - IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL, - DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); - return TRUE; - } - - // Ensure all rendering is complete - if (ctx->Driver.Finish) - (*ctx->Driver.Finish)(ctx); - if (dgl->bSceneStarted == TRUE) { - IDirect3DDevice3_EndScene(dgl->lpDev3); - dgl->bSceneStarted = FALSE; - } -#endif // _USE_GLD3_WGL - dgl->bCanRender = FALSE; - -#ifdef GLD_THREADS - // Serialize access to DirectDraw and DDS operations - if (glb.bMultiThreaded) - EnterCriticalSection(&CriticalSection); -#endif - -#ifndef _USE_GLD3_WGL - // Release existing surfaces - RELEASE(dgl->lpDev3); - RELEASE(dgl->lpDepth4); - RELEASE(dgl->lpBack4); - if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) - ; - else - RELEASE(dgl->lpFront4); -#endif // _USE_GLD3_WGL - dgl->dwWidth = dwWidth; - dgl->dwHeight = dwHeight; - - // Set defaults - dgl->dwModeWidth = dgl->dwWidth; - dgl->dwModeHeight = dgl->dwHeight; - -#ifdef _USE_GLD3_WGL - if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers)) - goto cleanup_and_return_with_error; -#else // _USE_GLD3_WGL - - if (dgl->bFullscreen) { - // - // FULLSCREEN - // - - // Disable warning popups when in fullscreen mode - ddlogWarnOption(FALSE); - - // Have to release the persistant DirectDraw primary surface - // if switching to fullscreen mode. So if application wants - // persistant display in fullscreen mode, a fullscreen-size - // window should be used instead via fullscreen-blit option. - if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) { - RELEASE(glb.lpPrimary4); - glb.bDirectDrawPrimary = FALSE; - } - - dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT; - if (glb.bFastFPU) - dwFlags |= DDSCL_FPUSETUP; // optional - hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult); - goto cleanup_and_return_with_error; - } - - hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4, - dgl->dwModeWidth, - dgl->dwModeHeight, - dgl->dwBPP, - 0, - 0); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult); - goto cleanup_and_return_with_error; - } - - // ** The display mode has changed, so dont use MessageBox! ** - - ZeroMemory(&ddsd2, sizeof(ddsd2)); - ddsd2.dwSize = sizeof(ddsd2); - - if (dgl->bDoubleBuffer) { - // Double buffered - // Primary surface - ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | - DDSCAPS_FLIP | - DDSCAPS_COMPLEX | - DDSCAPS_3DDEVICE | - dwMemoryType; - ddsd2.dwBackBufferCount = 1; - hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult); - goto cleanup_and_return_with_error; - } - // Render target surface - ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct. - ddscaps2.dwCaps = DDSCAPS_BACKBUFFER; - hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult); - goto cleanup_and_return_with_error; - } - } else { - // Single buffered - // Primary surface - ddsd2.dwFlags = DDSD_CAPS; - ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | - //DDSCAPS_3DDEVICE | - dwMemoryType; - - hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult); - goto cleanup_and_return_with_error; - } - - dgl->lpBack4 = NULL; - } - } else { - // WINDOWED - - // OK to enable warning popups in windowed mode - ddlogWarnOption(glb.bMessageBoxWarnings); - - // Ditto if persistant DirectDraw primary - if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) - goto DoClipperOnly; - - // WINDOWED - dwFlags = DDSCL_NORMAL; - if (glb.bMultiThreaded) - dwFlags |= DDSCL_MULTITHREADED; - if (glb.bFastFPU) - dwFlags |= DDSCL_FPUSETUP; // optional - hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, - dgl->hWnd, - dwFlags); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult); - goto cleanup_and_return_with_error; - } - // Primary surface - ZeroMemory(&ddsd2, sizeof(ddsd2)); - ddsd2.dwSize = sizeof(ddsd2); - ddsd2.dwFlags = DDSD_CAPS; - ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult); - goto cleanup_and_return_with_error; - } - - // Cache the primary surface for persistant DirectDraw state - if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) { - glb.lpPrimary4 = dgl->lpFront4; - IDirectDrawSurface4_AddRef(glb.lpPrimary4); - glb.bDirectDrawPrimary = TRUE; - } - - // Clipper object - hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult); - goto cleanup_and_return_with_error; - } - hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd); - if (FAILED(hResult)) { - RELEASE(lpddClipper); - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult); - goto cleanup_and_return_with_error; - } - hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper); - RELEASE(lpddClipper); // We have finished with it. - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult); - goto cleanup_and_return_with_error; - } -DoClipperOnly: - // Update the window for the original clipper - if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) { - IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper); - IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd); - RELEASE(lpddClipper); - } - - if (dgl->bDoubleBuffer) { - // Render target surface - ZeroMemory(&ddsd2, sizeof(ddsd2)); - ddsd2.dwSize = sizeof(ddsd2); - ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd2.dwWidth = dgl->dwWidth; - ddsd2.dwHeight = dgl->dwHeight; - ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | - DDSCAPS_OFFSCREENPLAIN | - dwMemoryType; - hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult); - goto cleanup_and_return_with_error; - } - - } else { - dgl->lpBack4 = NULL; - } - } - - // - // Now create the Zbuffer - // - if (dgl->bDepthBuffer) { - // Get z-buffer dimensions from the render target - // Setup the surface desc for the z-buffer. - ZeroMemory(&ddsd2, sizeof(ddsd2)); - ddsd2.dwSize = sizeof(ddsd2); - ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; - ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType; - ddsd2.dwWidth = dgl->dwWidth; - ddsd2.dwHeight = dgl->dwHeight; - memcpy(&ddsd2.ddpfPixelFormat, - &glb.lpZBufferPF[dgl->iZBufferPF], - sizeof(DDPIXELFORMAT) ); - - // Create a z-buffer - hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult); - goto cleanup_and_return_with_error; - } - - // Attach Zbuffer to render target - TRY(IDirectDrawSurface4_AddAttachedSurface( - dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4, - dgl->lpDepth4), - "dglResize: Attach Zbuffer"); - - } - - // Clear the newly resized back buffers for the window client area. - ZeroMemory(&ddbltfx, sizeof(ddbltfx)); - ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwFillColor = dgl->dwClearColorPF; - IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL, - DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); - - // - // Now that we have a zbuffer we can create the 3D device - // - hResult = IDirect3D3_CreateDevice(dgl->lpD3D3, - bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice, - dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4, - &dgl->lpDev3, - NULL); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult); - goto cleanup_and_return_with_error; - } - - // We must do this as soon as the device is created - dglInitStateCaches(dgl); - - // - // Viewport - // - hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult); - goto cleanup_and_return_with_error; - } - - // Initialise the viewport - dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport); - dgl->d3dViewport.dwX = 0; - dgl->d3dViewport.dwY = 0; - dgl->d3dViewport.dwWidth = dgl->dwWidth; - dgl->d3dViewport.dwHeight = dgl->dwHeight; - dgl->d3dViewport.dvClipX = 0; - dgl->d3dViewport.dvClipY = 0; - dgl->d3dViewport.dvClipWidth = dgl->dwWidth; - dgl->d3dViewport.dvClipHeight = dgl->dwHeight; -// dgl->d3dViewport.dvMinZ = 0.0f; -// dgl->d3dViewport.dvMaxZ = 1.0f; - TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport), - "dglResize: SetViewport2"); - - hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3); - if (FAILED(hResult)) { - ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult); - goto cleanup_and_return_with_error; - } - - // (Re)Initialise all the Direct3D renderstates - dglInitStateD3D(ctx); - - // Now we have to recreate all of our textures (+ mipmaps). - // Walk over all textures in hash table - // XXX what about the default texture objects (id=0)? - { - struct _mesa_HashTable *textures = ctx->Shared->TexObjects; - GLuint id; - for (id = _mesa_HashFirstEntry(textures); - id; - id = _mesa_HashNextEntry(textures, id)) { - tObj = (struct gl_texture_object *) _mesa_HashLookup(textures, id); - if (tObj->DriverData) { - // We could call our TexImage function directly, but it's - // safer to use the driver pointer. - for (i=0; i<MAX_TEXTURE_LEVELS; i++) { - image = tObj->Image[i]; - if (image) { - switch (tObj->Dimensions){ - case 1: - if (ctx->Driver.TexImage) - (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image); - break; - case 2: - if (ctx->Driver.TexImage) - (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image); - break; - default: - break; - } - } - } - } - } - } - - // Re-Bind each texture Unit - for (i=0; i<glb.wMaxSimultaneousTextures; i++) { - tObj = ctx->Texture.Unit[i].Current; - if (tObj) { - DGL_texture *lpTex = (DGL_texture *)tObj->DriverData; - hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL); - if (FAILED(hResult)) { - ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult); - } - } - } -#endif // _USE_GLD3_WGL - - dgl->bCanRender = TRUE; - -#ifdef GLD_THREADS - // Release serialized access - if (glb.bMultiThreaded) - LeaveCriticalSection(&CriticalSection); -#endif - - // SUCCESS. - return TRUE; - -cleanup_and_return_with_error: - // Relase all interfaces before returning. -#ifdef _USE_GLD3_WGL - _gldDriver.DestroyDrawable(dgl); -#else // _USE_GLD3_WGL - RELEASE(dgl->lpDev3); - RELEASE(dgl->lpDepth4); - RELEASE(dgl->lpBack4); - if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) - ; - else - RELEASE(dgl->lpFront4); - -#undef DDLOG_CRITICAL_OR_WARN -#endif // _USE_GLD3_WGL - - // Mark context as not being able to render - dgl->bCanRender = FALSE; - -#ifdef GLD_THREADS - // Release serialized access - if (glb.bMultiThreaded) - LeaveCriticalSection(&CriticalSection); -#endif - - return FALSE; -} - -// *********************************************************************** -// *********************************************************************** -// Support for bitmap fonts. -// *********************************************************************** -// *********************************************************************** - -/***************************************************************************** -** -** InvertGlyphBitmap. -** -** Invert the bitmap so that it suits OpenGL's representation. -** Each row starts on a double word boundary. -** -*****************************************************************************/ - -static void InvertGlyphBitmap( - int w, - int h, - DWORD *fptr, - DWORD *tptr) -{ - int dWordsInRow = (w+31)/32; - int i, j; - DWORD *tmp = tptr; - - if (w <= 0 || h <= 0) { - return; - } - - tptr += ((h-1)*dWordsInRow); - for (i = 0; i < h; i++) { - for (j = 0; j < dWordsInRow; j++) { - *(tptr + j) = *(fptr + j); - } - tptr -= dWordsInRow; - fptr += dWordsInRow; - } -} - -// *********************************************************************** - -/***************************************************************************** - * wglUseFontBitmaps - * - * Converts a subrange of the glyphs in a GDI font to OpenGL display - * lists. - * - * Extended to support any GDI font, not just TrueType fonts. (DaveM) - * - *****************************************************************************/ - -BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)( - HDC hDC, - DWORD first, - DWORD count, - DWORD listBase) -{ - int i, ox, oy, ix, iy; - int w, h; - int iBufSize, iCurBufSize = 0; - DWORD *bitmapBuffer = NULL; - DWORD *invertedBitmapBuffer = NULL; - BOOL bSuccessOrFail = TRUE; - BOOL bTrueType = FALSE; - TEXTMETRIC tm; - GLYPHMETRICS gm; - RASTERIZER_STATUS rs; - MAT2 mat; - SIZE size; - RECT rect; - HDC hDCMem; - HBITMAP hBitmap; - BITMAPINFO bmi; - HFONT hFont; - - // Validate SciTech DirectGL license - if (!dglValidate()) - return FALSE; - - // Set up a unity matrix. - ZeroMemory(&mat, sizeof(mat)); - mat.eM11.value = 1; - mat.eM22.value = 1; - - // Test to see if selected font is TrueType or not - ZeroMemory(&tm, sizeof(tm)); - if (!GetTextMetrics(hDC, &tm)) { - ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Font metrics error\n"); - return (FALSE); - } - bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE; - - // Test to see if TRUE-TYPE capabilities are installed - // (only necessary if TrueType font selected) - ZeroMemory(&rs, sizeof(rs)); - if (bTrueType) { - if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) { - ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n"); - return (FALSE); - } - if (!(rs.wFlags & TT_ENABLED)) { - ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n"); - return (FALSE); - } - } - - // Trick to get the current font handle - hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT)); - SelectObject(hDC, hFont); - - // Have memory device context available for holding bitmaps of font glyphs - hDCMem = CreateCompatibleDC(hDC); - SelectObject(hDCMem, hFont); - SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF)); - SetBkColor(hDCMem, 0); - - for (i = first; (DWORD) i < (first + count); i++) { - // Find out how much space is needed for the bitmap so we can - // Set the buffer size correctly. - if (bTrueType) { - // Use TrueType support to get bitmap size of glyph - iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm, - 0, NULL, &mat); - if (iBufSize == GDI_ERROR) { - bSuccessOrFail = FALSE; - break; - } - } - else { - // Use generic GDI support to compute bitmap size of glyph - w = tm.tmMaxCharWidth; - h = tm.tmHeight; - if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) { - w = size.cx; - h = size.cy; - } - iBufSize = w * h; - // Use DWORD multiple for compatibility - iBufSize += 3; - iBufSize /= 4; - iBufSize *= 4; - } - - // If we need to allocate Larger Buffers, then do so - but allocate - // An extra 50 % so that we don't do too many mallocs ! - if (iBufSize > iCurBufSize) { - if (bitmapBuffer) { - __wglFree(bitmapBuffer); - } - if (invertedBitmapBuffer) { - __wglFree(invertedBitmapBuffer); - } - - iCurBufSize = iBufSize * 2; - bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize); - invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize); - - if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) { - bSuccessOrFail = FALSE; - break; - } - } - - // If we fail to get the Glyph data, delete the display lists - // Created so far and return FALSE. - if (bTrueType) { - // Use TrueType support to get bitmap of glyph - if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm, - iBufSize, bitmapBuffer, &mat) == GDI_ERROR) { - bSuccessOrFail = FALSE; - break; - } - - // Setup glBitmap parameters for current font glyph - w = gm.gmBlackBoxX; - h = gm.gmBlackBoxY; - ox = gm.gmptGlyphOrigin.x; - oy = gm.gmptGlyphOrigin.y; - ix = gm.gmCellIncX; - iy = gm.gmCellIncY; - } - else { - // Use generic GDI support to create bitmap of glyph - ZeroMemory(bitmapBuffer, iBufSize); - - if (i >= tm.tmFirstChar && i <= tm.tmLastChar) { - // Only create bitmaps for actual font glyphs - hBitmap = CreateBitmap(w, h, 1, 1, NULL); - SelectObject(hDCMem, hBitmap); - // Make bitmap of current font glyph - SetRect(&rect, 0, 0, w, h); - DrawText(hDCMem, (LPCTSTR)&i, 1, &rect, - DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP); - // Make copy of bitmap in our local buffer - ZeroMemory(&bmi, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = w; - bmi.bmiHeader.biHeight = -h; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 1; - bmi.bmiHeader.biCompression = BI_RGB; - GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0); - DeleteObject(hBitmap); - } - else { - // Otherwise use empty display list for non-existing glyph - iBufSize = 0; - } - - // Setup glBitmap parameters for current font glyph - ox = 0; - oy = tm.tmDescent; - ix = w; - iy = 0; - } - - // Create an OpenGL display list. - _GLD_glNewList((listBase + i), GL_COMPILE); - - // Some fonts have no data for the space character, yet advertise - // a non-zero size. - if (0 == iBufSize) { - _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL); - } else { - // Invert the Glyph data. - InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer); - - // Render an OpenGL bitmap and invert the origin. - _GLD_glBitmap(w, h, - (GLfloat) ox, (GLfloat) (h-oy), - (GLfloat) ix, (GLfloat) iy, - (GLubyte *) invertedBitmapBuffer); - } - - // Close this display list. - _GLD_glEndList(); - } - - if (bSuccessOrFail == FALSE) { - ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n"); - _GLD_glDeleteLists((i+listBase), (i-first)); - } - - // Release resources used - DeleteObject(hFont); - DeleteDC(hDCMem); - - if (bitmapBuffer) - __wglFree(bitmapBuffer); - if (invertedBitmapBuffer) - __wglFree(invertedBitmapBuffer); - - return(bSuccessOrFail); -} - -// *********************************************************************** - -BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)( - HDC a, - DWORD b, - DWORD c, - DWORD d) -{ - // Validate license - if (!dglValidate()) - return FALSE; - - return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d); -} - -// *********************************************************************** -// *********************************************************************** -// Support for outline TrueType fonts. -// *********************************************************************** -// *********************************************************************** - -void * __wglRealloc( - void *oldPtr, - size_t newSize) -{ - void *newPtr = NULL; - - if (newSize != 0) { - newPtr = (void *) GlobalAlloc(GPTR, newSize); - if (oldPtr && newPtr) { - DWORD oldSize = GlobalSize(oldPtr); - - memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize)); - GlobalFree(oldPtr); - } - } else if (oldPtr) { - GlobalFree(oldPtr); - } - if (newPtr == NULL) { - return NULL; /* XXX out of memory error */ - } - return newPtr; -} - -// *********************************************************************** - - -/***************************************************************************** - * wglUseFontOutlinesW - * - * Converts a subrange of the glyphs in a TrueType font to OpenGL display - * lists. - *****************************************************************************/ - -BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)( - IN HDC hDC, - IN DWORD first, - IN DWORD count, - IN DWORD listBase, - IN FLOAT chordalDeviation, - IN FLOAT extrusion, - IN INT format, - OUT LPGLYPHMETRICSFLOAT lpgmf) -{ - return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase, - chordalDeviation, extrusion, format, lpgmf); -} - -/***************************************************************************** - * wglUseFontOutlinesA - * - * Converts a subrange of the glyphs in a TrueType font to OpenGL display - * lists. - *****************************************************************************/ - -BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)( - IN HDC hDC, - IN DWORD first, - IN DWORD count, - IN DWORD listBase, - IN FLOAT chordalDeviation, - IN FLOAT extrusion, - IN INT format, - OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray) - { - DWORD glyphIndex; - UCHAR* glyphBuf; - DWORD glyphBufSize; - - - /* - * Flush any previous OpenGL errors. This allows us to check for - * new errors so they can be reported via the function return value. - */ - while (_GLD_glGetError() != GL_NO_ERROR) - ; - - /* - * Make sure that the current font can be sampled accurately. - */ - hNewFont = CreateHighResolutionFont(hDC); - if (!hNewFont) - return FALSE; - - hOldFont = SelectObject(hDC, hNewFont); - if (!hOldFont) - return FALSE; - - /* - * Preallocate a buffer for the outline data, and track its size: - */ - glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240); - if (!glyphBuf) - return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/ - - /* - * Process each glyph in the given range: - */ - for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex) - { - GLYPHMETRICS glyphMetrics; - DWORD glyphSize; - static MAT2 matrix = - { - {0, 1}, {0, 0}, - {0, 0}, {0, 1} - }; - LPGLYPHMETRICSFLOAT glyphMetricsFloat = - &glyphMetricsFloatArray[glyphIndex - first]; - - - /* - * Determine how much space is needed to store the glyph's - * outlines. If our glyph buffer isn't large enough, - * resize it. - */ - glyphSize = GetGlyphOutline( hDC, - glyphIndex, - GGO_NATIVE, - &glyphMetrics, - 0, - NULL, - &matrix - ); - if (glyphSize < 0) - return FALSE; /*WGL_STATUS_FAILURE*/ - if (glyphSize > glyphBufSize) - { - __wglFree(glyphBuf); - glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize); - if (!glyphBuf) - return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/ - } - - - /* - * Get the glyph's outlines. - */ - if (GetGlyphOutline( hDC, - glyphIndex, - GGO_NATIVE, - &glyphMetrics, - glyphBufSize, - glyphBuf, - &matrix - ) < 0) - { - __wglFree(glyphBuf); - return FALSE; /*WGL_STATUS_FAILURE*/ - } - - glyphMetricsFloat->gmfBlackBoxX = - (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor; - glyphMetricsFloat->gmfBlackBoxY = - (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor; - glyphMetricsFloat->gmfptGlyphOrigin.x = - (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor; - glyphMetricsFloat->gmfptGlyphOrigin.y = - (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor; - glyphMetricsFloat->gmfCellIncX = - (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor; - glyphMetricsFloat->gmfCellIncY = - (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor; - - /* - * Turn the glyph into a display list: - */ - if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase, - glyphBuf, - glyphSize, - glyphMetricsFloat, - chordalDeviation + ScaleFactor, - extrusion, - format)) - { - __wglFree(glyphBuf); - return FALSE; /*WGL_STATUS_FAILURE*/ - } - } - - - /* - * Clean up temporary storage and return. If an error occurred, - * clear all OpenGL error flags and return FAILURE status; - * otherwise just return SUCCESS. - */ - __wglFree(glyphBuf); - - SelectObject(hDC, hOldFont); - - if (_GLD_glGetError() == GL_NO_ERROR) - return TRUE; /*WGL_STATUS_SUCCESS*/ - else - { - while (_GLD_glGetError() != GL_NO_ERROR) - ; - return FALSE; /*WGL_STATUS_FAILURE*/ - } - } - - - -/***************************************************************************** - * CreateHighResolutionFont - * - * Gets metrics for the current font and creates an equivalent font - * scaled to the design units of the font. - * - *****************************************************************************/ - -static HFONT -CreateHighResolutionFont(HDC hDC) - { - UINT otmSize; - OUTLINETEXTMETRIC *otm; - LONG fontHeight, fontWidth, fontUnits; - LOGFONT logFont; - - otmSize = GetOutlineTextMetrics(hDC, 0, NULL); - if (otmSize == 0) - return NULL; - - otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize); - if (otm == NULL) - return NULL; - - otm->otmSize = otmSize; - if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0) - return NULL; - - fontHeight = otm->otmTextMetrics.tmHeight - - otm->otmTextMetrics.tmInternalLeading; - fontWidth = otm->otmTextMetrics.tmAveCharWidth; - fontUnits = (LONG) otm->otmEMSquare; - - ScaleFactor = 1.0F / (FLOAT) fontUnits; - - logFont.lfHeight = - ((LONG) fontUnits); - logFont.lfWidth = (LONG) - ((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight); - logFont.lfEscapement = 0; - logFont.lfOrientation = 0; - logFont.lfWeight = otm->otmTextMetrics.tmWeight; - logFont.lfItalic = otm->otmTextMetrics.tmItalic; - logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined; - logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut; - logFont.lfCharSet = otm->otmTextMetrics.tmCharSet; - logFont.lfOutPrecision = OUT_OUTLINE_PRECIS; - logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; - logFont.lfQuality = DEFAULT_QUALITY; - logFont.lfPitchAndFamily = - otm->otmTextMetrics.tmPitchAndFamily & 0xf0; - strcpy(logFont.lfFaceName, - (char *)otm + (int)otm->otmpFaceName); - - hNewFont = CreateFontIndirect(&logFont); - if (hNewFont == NULL) - return NULL; - - __wglFree(otm); - - return hNewFont; - } - - - -/***************************************************************************** - * MakeDisplayListFromGlyph - * - * Converts the outline of a glyph to an OpenGL display list. - * - * Return value is nonzero for success, zero for failure. - * - * Does not check for OpenGL errors, so if the caller needs to know about them, - * it should call glGetError(). - *****************************************************************************/ - -static int -MakeDisplayListFromGlyph( IN DWORD listName, - IN UCHAR* glyphBuf, - IN DWORD glyphSize, - IN LPGLYPHMETRICSFLOAT glyphMetricsFloat, - IN FLOAT chordalDeviation, - IN FLOAT extrusion, - IN INT format) - { - int status; - - _GLD_glNewList(listName, GL_COMPILE); - status = DrawGlyph( glyphBuf, - glyphSize, - chordalDeviation, - extrusion, - format); - - _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX, - glyphMetricsFloat->gmfCellIncY, - 0.0F); - _GLD_glEndList(); - - return status; - } - - - -/***************************************************************************** - * DrawGlyph - * - * Converts the outline of a glyph to OpenGL drawing primitives, tessellating - * as needed, and then draws the glyph. Tessellation of the quadratic splines - * in the outline is controlled by "chordalDeviation", and the drawing - * primitives (lines or polygons) are selected by "format". - * - * Return value is nonzero for success, zero for failure. - * - * Does not check for OpenGL errors, so if the caller needs to know about them, - * it should call glGetError(). - *****************************************************************************/ - -static int -DrawGlyph( IN UCHAR* glyphBuf, - IN DWORD glyphSize, - IN FLOAT chordalDeviation, - IN FLOAT extrusion, - IN INT format) - { - INT status = 0; - FLOAT* p; - DWORD loop; - DWORD point; - GLUtesselator* tess = NULL; - - - /* - * Initialize the global buffer into which we place the outlines: - */ - if (!InitLineBuf()) - goto exit; - - - /* - * Convert the glyph outlines to a set of polyline loops. - * (See MakeLinesFromGlyph() for the format of the loop data - * structure.) - */ - if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation)) - goto exit; - p = LineBuf; - - - /* - * Now draw the loops in the appropriate format: - */ - if (format == WGL_FONT_LINES) - { - /* - * This is the easy case. Just draw the outlines. - */ - for (loop = (DWORD) *p++; loop; --loop) - { - _GLD_glBegin(GL_LINE_LOOP); - for (point = (DWORD) *p++; point; --point) - { - _GLD_glVertex2fv(p); - p += 2; - } - _GLD_glEnd(); - } - status = 1; - } - - else if (format == WGL_FONT_POLYGONS) - { - double v[3]; - FLOAT *save_p = p; - GLfloat z_value; - - /* - * This is the hard case. We have to set up a tessellator - * to convert the outlines into a set of polygonal - * primitives, which the tessellator passes to some - * auxiliary routines for drawing. - */ - if (!LoadGLUTesselator()) - goto exit; - if (!InitVertBuf()) - goto exit; - if (!(tess = gluNewTessProc())) - goto exit; - gluTessCallbackProc(tess, GLU_BEGIN, (void(CALLBACK *)()) _GLD_glBegin); - gluTessCallbackProc(tess, GLU_TESS_VERTEX_DATA, - (void(CALLBACK *)()) TessVertexOutData); - gluTessCallbackProc(tess, GLU_END, (void(CALLBACK *)()) _GLD_glEnd); - gluTessCallbackProc(tess, GLU_ERROR, (void(CALLBACK *)()) TessError); - gluTessCallbackProc(tess, GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine); - gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F); - - TessErrorOccurred = 0; - _GLD_glNormal3f(0.0f, 0.0f, 1.0f); - v[2] = 0.0; - z_value = 0.0f; - - gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value); - for (loop = (DWORD) *p++; loop; --loop) - { - gluTessBeginContourProc(tess); - - for (point = (DWORD) *p++; point; --point) - { - v[0] = p[0]; - v[1] = p[1]; - gluTessVertexProc(tess, v, p); - p += 2; - } - - gluTessEndContourProc(tess); - } - gluTessEndPolygonProc(tess); - - status = !TessErrorOccurred; - - /* Extrusion code */ - if (extrusion) { - DWORD loops; - GLfloat thickness = (GLfloat) -extrusion; - FLOAT *vert, *vert2; - DWORD count; - - p = save_p; - loops = (DWORD) *p++; - - for (loop = 0; loop < loops; loop++) { - GLfloat dx, dy, len; - DWORD last; - - count = (DWORD) *p++; - _GLD_glBegin(GL_QUAD_STRIP); - - /* Check if the first and last vertex are identical - * so we don't draw the same quad twice. - */ - vert = p + (count-1)*2; - last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count; - - for (point = 0; point <= last; point++) { - vert = p + 2 * (point % last); - vert2 = p + 2 * ((point+1) % last); - - dx = vert[0] - vert2[0]; - dy = vert[1] - vert2[1]; - len = (GLfloat)sqrt(dx * dx + dy * dy); - - _GLD_glNormal3f(dy / len, -dx / len, 0.0f); - _GLD_glVertex3f((GLfloat) vert[0], - (GLfloat) vert[1], thickness); - _GLD_glVertex3f((GLfloat) vert[0], - (GLfloat) vert[1], 0.0f); - } - - _GLD_glEnd(); - p += count*2; - } - - /* Draw the back face */ - p = save_p; - v[2] = thickness; - _GLD_glNormal3f(0.0f, 0.0f, -1.0f); - gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F); - - gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness); - - for (loop = (DWORD) *p++; loop; --loop) - { - count = (DWORD) *p++; - - gluTessBeginContourProc(tess); - - for (point = 0; point < count; point++) - { - vert = p + ((count-point-1)<<1); - v[0] = vert[0]; - v[1] = vert[1]; - gluTessVertexProc(tess, v, vert); - } - p += count*2; - - gluTessEndContourProc(tess); - } - gluTessEndPolygonProc(tess); - } - -#if DEBUG - if (TessErrorOccurred) - printf("Tessellation error %s\n", - gluErrorString(TessErrorOccurred)); -#endif - } - - -exit: - FreeLineBuf(); - if (tess) - gluDeleteTessProc(tess); - // UnloadGLUTesselator(); - FreeVertBuf(); - return status; - } - - - -/***************************************************************************** - * LoadGLUTesselator - * - * Maps the glu32.dll module and gets function pointers for the - * tesselator functions. - *****************************************************************************/ - -static BOOL -LoadGLUTesselator(void) - { - if (gluModuleHandle != NULL) - return TRUE; - - { - extern HINSTANCE hInstanceOpenGL; - char *gluName = "GLU32.DLL"; -// char name[256]; -// char *ptr; -// int len; - -/* - len = GetModuleFileName(hInstanceOpenGL, name, 255); - if (len != 0) - { - ptr = name+len-1; - while (ptr > name && *ptr != '\\') - ptr--; - if (*ptr == '\\') - ptr++; - if (!stricmp(ptr, "cosmogl.dll")) - { - gluName = "COSMOGLU.DLL"; - } - else if (!stricmp(ptr, "opengl32.dll")) - { - gluName = "GLU32.DLL"; - } - } -*/ - if ((gluModuleHandle = LoadLibrary(gluName)) == NULL) - return FALSE; - } - - if ((gluNewTessProc = (gluNewTessProto) - GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL) - return FALSE; - - if ((gluDeleteTessProc = (gluDeleteTessProto) - GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL) - return FALSE; - - if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto) - GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL) - return FALSE; - - if ((gluTessBeginContourProc = (gluTessBeginContourProto) - GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL) - return FALSE; - - if ((gluTessVertexProc = (gluTessVertexProto) - GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL) - return FALSE; - - if ((gluTessEndContourProc = (gluTessEndContourProto) - GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL) - return FALSE; - - if ((gluTessEndPolygonProc = (gluTessEndPolygonProto) - GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL) - return FALSE; - - if ((gluTessPropertyProc = (gluTessPropertyProto) - GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL) - return FALSE; - - if ((gluTessNormalProc = (gluTessNormalProto) - GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL) - return FALSE; - - if ((gluTessCallbackProc = (gluTessCallbackProto) - GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL) - return FALSE; - - return TRUE; - } - - - -/***************************************************************************** - * UnloadGLUTesselator - * - * Unmaps the glu32.dll module. - *****************************************************************************/ - -static BOOL -UnloadGLUTesselator(void) - { - if (gluModuleHandle != NULL) - if (FreeLibrary(gluModuleHandle) == FALSE) - return FALSE; - gluModuleHandle = NULL; - } - - - -/***************************************************************************** - * TessVertexOut - * - * Used by tessellator to handle output vertexes. - *****************************************************************************/ - -static void CALLBACK -TessVertexOut(FLOAT p[3]) - { - GLfloat v[2]; - - v[0] = p[0] * ScaleFactor; - v[1] = p[1] * ScaleFactor; - _GLD_glVertex2fv(v); - } - -static void CALLBACK -TessVertexOutData(FLOAT p[3], GLfloat z) -{ - GLfloat v[3]; - - v[0] = (GLfloat) p[0]; - v[1] = (GLfloat) p[1]; - v[2] = z; - _GLD_glVertex3fv(v); -} - - -/***************************************************************************** - * TessCombine - * - * Used by tessellator to handle self-intersecting contours and degenerate - * geometry. - *****************************************************************************/ - -static void CALLBACK -TessCombine(double coords[3], - void* vertex_data[4], - FLOAT weight[4], - void** outData) - { - if (!AppendToVertBuf((FLOAT) coords[0]) - || !AppendToVertBuf((FLOAT) coords[1]) - || !AppendToVertBuf((FLOAT) coords[2])) - TessErrorOccurred = GL_OUT_OF_MEMORY; - *outData = VertBuf + (VertBufIndex - 3); - } - - - -/***************************************************************************** - * TessError - * - * Saves the last tessellator error code in the global TessErrorOccurred. - *****************************************************************************/ - -static void CALLBACK -TessError(GLenum error) - { - TessErrorOccurred = error; - } - - - -/***************************************************************************** - * MakeLinesFromGlyph - * - * Converts the outline of a glyph from the TTPOLYGON format to a simple - * array of floating-point values containing one or more loops. - * - * The first element of the output array is a count of the number of loops. - * The loop data follows this count. Each loop consists of a count of the - * number of vertices it contains, followed by the vertices. Each vertex - * is an X and Y coordinate. For example, a single triangle might be - * described by this array: - * - * 1., 3., 0., 0., 1., 0., 0., 1. - * ^ ^ ^ ^ ^ ^ ^ ^ - * #loops #verts x1 y1 x2 y2 x3 y3 - * - * A two-loop glyph would look like this: - * - * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4 - * - * Line segments from the TTPOLYGON are transferred to the output array in - * the obvious way. Quadratic splines in the TTPOLYGON are converted to - * collections of line segments - *****************************************************************************/ - -static int -MakeLinesFromGlyph(IN UCHAR* glyphBuf, - IN DWORD glyphSize, - IN FLOAT chordalDeviation) - { - UCHAR* p; - int status = 0; - - - /* - * Pick up all the polygons (aka loops) that make up the glyph: - */ - if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */ - goto exit; - - p = glyphBuf; - while (p < glyphBuf + glyphSize) - { - if (!MakeLinesFromTTPolygon(&p, chordalDeviation)) - goto exit; - LineBuf[0] += 1.0F; /* increment loop count */ - } - - status = 1; - -exit: - return status; - } - - - -/***************************************************************************** - * MakeLinesFromTTPolygon - * - * Converts a TTPOLYGONHEADER and its associated curve structures into a - * single polyline loop in the global LineBuf. - *****************************************************************************/ - -static int -MakeLinesFromTTPolygon( IN OUT UCHAR** pp, - IN FLOAT chordalDeviation) - { - DWORD polySize; - UCHAR* polyStart; - DWORD vertexCountIndex; - - /* - * Record where the polygon data begins, and where the loop's - * vertex count resides: - */ - polyStart = *pp; - vertexCountIndex = LineBufIndex; - if (!AppendToLineBuf(0.0F)) - return 0; - - /* - * Extract relevant data from the TTPOLYGONHEADER: - */ - polySize = GetDWord(pp); - if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */ - return 0; - if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */ - return 0; - if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */ - return 0; - LineBuf[vertexCountIndex] += 1.0F; - - /* - * Process each of the TTPOLYCURVE structures in the polygon: - */ - while (*pp < polyStart + polySize) - if (!MakeLinesFromTTPolycurve( pp, - vertexCountIndex, - chordalDeviation)) - return 0; - - return 1; - } - - - -/***************************************************************************** - * MakeLinesFromTTPolyCurve - * - * Converts the lines and splines in a single TTPOLYCURVE structure to points - * in the global LineBuf. - *****************************************************************************/ - -static int -MakeLinesFromTTPolycurve( IN OUT UCHAR** pp, - IN DWORD vertexCountIndex, - IN FLOAT chordalDeviation) - { - WORD type; - WORD pointCount; - - - /* - * Pick up the relevant fields of the TTPOLYCURVE structure: - */ - type = (WORD) GetWord(pp); - pointCount = (WORD) GetWord(pp); - - /* - * Convert the "curve" to line segments: - */ - if (type == TT_PRIM_LINE) - return MakeLinesFromTTLine( pp, - vertexCountIndex, - pointCount); - else if (type == TT_PRIM_QSPLINE) - return MakeLinesFromTTQSpline( pp, - vertexCountIndex, - pointCount, - chordalDeviation); - else - return 0; - } - - - -/***************************************************************************** - * MakeLinesFromTTLine - * - * Converts points from the polyline in a TT_PRIM_LINE structure to - * equivalent points in the global LineBuf. - *****************************************************************************/ -static int -MakeLinesFromTTLine( IN OUT UCHAR** pp, - IN DWORD vertexCountIndex, - IN WORD pointCount) - { - /* - * Just copy the line segments into the line buffer (converting - * type as we go): - */ - LineBuf[vertexCountIndex] += pointCount; - while (pointCount--) - { - if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */ - || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */ - return 0; - } - - return 1; - } - - - -/***************************************************************************** - * MakeLinesFromTTQSpline - * - * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE - * structure to polyline points in the global LineBuf. - *****************************************************************************/ - -static int -MakeLinesFromTTQSpline( IN OUT UCHAR** pp, - IN DWORD vertexCountIndex, - IN WORD pointCount, - IN FLOAT chordalDeviation) - { - FLOAT x0, y0, x1, y1, x2, y2; - WORD point; - - /* - * Process each of the non-interpolated points in the outline. - * To do this, we need to generate two interpolated points (the - * start and end of the arc) for each non-interpolated point. - * The first interpolated point is always the one most recently - * stored in LineBuf, so we just extract it from there. The - * second interpolated point is either the average of the next - * two points in the QSpline, or the last point in the QSpline - * if only one remains. - */ - for (point = 0; point < pointCount - 1; ++point) - { - x0 = LineBuf[LineBufIndex - 2]; - y0 = LineBuf[LineBufIndex - 1]; - - x1 = (FLOAT) GetFixed(pp); - y1 = (FLOAT) GetFixed(pp); - - if (point == pointCount - 2) - { - /* - * This is the last arc in the QSpline. The final - * point is the end of the arc. - */ - x2 = (FLOAT) GetFixed(pp); - y2 = (FLOAT) GetFixed(pp); - } - else - { - /* - * Peek at the next point in the input to compute - * the end of the arc: - */ - x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp)); - y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp)); - /* - * Push the point back onto the input so it will - * be reused as the next off-curve point: - */ - *pp -= 8; - } - - if (!MakeLinesFromArc( x0, y0, - x1, y1, - x2, y2, - vertexCountIndex, - chordalDeviation * chordalDeviation)) - return 0; - } - - return 1; - } - - - -/***************************************************************************** - * MakeLinesFromArc - * - * Subdivides one arc of a quadratic spline until the chordal deviation - * tolerance requirement is met, then places the resulting set of line - * segments in the global LineBuf. - *****************************************************************************/ - -static int -MakeLinesFromArc( IN FLOAT x0, - IN FLOAT y0, - IN FLOAT x1, - IN FLOAT y1, - IN FLOAT x2, - IN FLOAT y2, - IN DWORD vertexCountIndex, - IN FLOAT chordalDeviationSquared) - { - FLOAT x01; - FLOAT y01; - FLOAT x12; - FLOAT y12; - FLOAT midPointX; - FLOAT midPointY; - FLOAT deltaX; - FLOAT deltaY; - - /* - * Calculate midpoint of the curve by de Casteljau: - */ - x01 = 0.5F * (x0 + x1); - y01 = 0.5F * (y0 + y1); - x12 = 0.5F * (x1 + x2); - y12 = 0.5F * (y1 + y2); - midPointX = 0.5F * (x01 + x12); - midPointY = 0.5F * (y01 + y12); - - - /* - * Estimate chordal deviation by the distance from the midpoint - * of the curve to its non-interpolated control point. If this - * distance is greater than the specified chordal deviation - * constraint, then subdivide. Otherwise, generate polylines - * from the three control points. - */ - deltaX = midPointX - x1; - deltaY = midPointY - y1; - if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared) - { - MakeLinesFromArc( x0, y0, - x01, y01, - midPointX, midPointY, - vertexCountIndex, - chordalDeviationSquared); - - MakeLinesFromArc( midPointX, midPointY, - x12, y12, - x2, y2, - vertexCountIndex, - chordalDeviationSquared); - } - else - { - /* - * The "pen" is already at (x0, y0), so we don't need to - * add that point to the LineBuf. - */ - if (!AppendToLineBuf(x1) - || !AppendToLineBuf(y1) - || !AppendToLineBuf(x2) - || !AppendToLineBuf(y2)) - return 0; - LineBuf[vertexCountIndex] += 2.0F; - } - - return 1; - } - - - -/***************************************************************************** - * InitLineBuf - * - * Initializes the global LineBuf and its associated size and current-element - * counters. - *****************************************************************************/ - -static int -InitLineBuf(void) - { - if (!(LineBuf = (FLOAT*) - __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT)))) - return 0; - LineBufIndex = 0; - return 1; - } - - - -/***************************************************************************** - * InitVertBuf - * - * Initializes the global VertBuf and its associated size and current-element - * counters. - *****************************************************************************/ - -static int -InitVertBuf(void) - { - if (!(VertBuf = (FLOAT*) - __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT)))) - return 0; - VertBufIndex = 0; - return 1; - } - - - -/***************************************************************************** - * AppendToLineBuf - * - * Appends one floating-point value to the global LineBuf array. Return value - * is non-zero for success, zero for failure. - *****************************************************************************/ - -static int -AppendToLineBuf(FLOAT value) - { - if (LineBufIndex >= LineBufSize) - { - FLOAT* f; - - f = (FLOAT*) __wglRealloc(LineBuf, - (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT)); - if (!f) - return 0; - LineBuf = f; - } - LineBuf[LineBufIndex++] = value; - return 1; - } - - - -/***************************************************************************** - * AppendToVertBuf - * - * Appends one floating-point value to the global VertBuf array. Return value - * is non-zero for success, zero for failure. - * - * Note that we can't realloc this one, because the tessellator is using - * pointers into it. - *****************************************************************************/ - -static int -AppendToVertBuf(FLOAT value) - { - if (VertBufIndex >= VertBufSize) - return 0; - VertBuf[VertBufIndex++] = value; - return 1; - } - - - -/***************************************************************************** - * FreeLineBuf - * - * Cleans up vertex buffer structure. - *****************************************************************************/ - -static void -FreeLineBuf(void) - { - if (LineBuf) - { - __wglFree(LineBuf); - LineBuf = NULL; - } - } - - - -/***************************************************************************** - * FreeVertBuf - * - * Cleans up vertex buffer structure. - *****************************************************************************/ - -static void -FreeVertBuf(void) - { - if (VertBuf) - { - __wglFree(VertBuf); - VertBuf = NULL; - } - } - - - -/***************************************************************************** - * GetWord - * - * Fetch the next 16-bit word from a little-endian byte stream, and increment - * the stream pointer to the next unscanned byte. - *****************************************************************************/ - -static long GetWord(UCHAR** p) - { - long value; - - value = ((*p)[1] << 8) + (*p)[0]; - *p += 2; - return value; - } - - - -/***************************************************************************** - * GetDWord - * - * Fetch the next 32-bit word from a little-endian byte stream, and increment - * the stream pointer to the next unscanned byte. - *****************************************************************************/ - -static long GetDWord(UCHAR** p) - { - long value; - - value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0]; - *p += 4; - return value; - } - - - - -/***************************************************************************** - * GetFixed - * - * Fetch the next 32-bit fixed-point value from a little-endian byte stream, - * convert it to floating-point, and increment the stream pointer to the next - * unscanned byte. - *****************************************************************************/ - -static double GetFixed( - UCHAR** p) -{ - long hiBits, loBits; - double value; - - loBits = GetWord(p); - hiBits = GetWord(p); - value = (double) ((hiBits << 16) | loBits) / 65536.0; - - return value * ScaleFactor; -} - -// *********************************************************************** - +/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, 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, sublicense,
+* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#include "dglwgl.h"
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+#endif
+
+#include "gl/glu.h" // MUST USE MICROSOFT'S GLU32!
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+// Need to export wgl* functions if using GLD3,
+// otherwise export GLD2 DGL_* functions.
+#ifdef _USE_GLD3_WGL
+#define _GLD_WGL_EXPORT(a) wgl##a
+#else
+#define _GLD_WGL_EXPORT(a) DGL_##a
+#endif
+
+// Calls into Mesa 4.x are different
+#ifdef _USE_GLD3_WGL
+#include "dlist.h"
+#include "drawpix.h"
+#include "get.h"
+#include "matrix.h"
+// NOTE: All the _GLD* macros now call the gl* functions direct.
+// This ensures that the correct internal pathway is taken. KeithH
+#define _GLD_glNewList glNewList
+#define _GLD_glBitmap glBitmap
+#define _GLD_glEndList glEndList
+#define _GLD_glDeleteLists glDeleteLists
+#define _GLD_glGetError glGetError
+#define _GLD_glTranslatef glTranslatef
+#define _GLD_glBegin glBegin
+#define _GLD_glVertex2fv glVertex2fv
+#define _GLD_glEnd glEnd
+#define _GLD_glNormal3f glNormal3f
+#define _GLD_glVertex3f glVertex3f
+#define _GLD_glVertex3fv glVertex3fv
+#else // _USE_GLD3_WGL
+#define _GLD_glNewList (*mesaFuncs.glNewList)
+#define _GLD_glBitmap (*mesaFuncs.glBitmap)
+#define _GLD_glEndList (*mesaFuncs.glEndList)
+#define _GLD_glDeleteLists (*mesaFuncs.glDeleteLists)
+#define _GLD_glGetError (*mesaFuncs.glGetError)
+#define _GLD_glTranslatef (*mesaFuncs.glTranslatef)
+#define _GLD_glBegin (*mesaFuncs.glBegin)
+#define _GLD_glVertex2fv (*mesaFuncs.glVertex2fv)
+#define _GLD_glEnd (*mesaFuncs.glEnd)
+#define _GLD_glNormal3f (*mesaFuncs.glNormal3f)
+#define _GLD_glVertex3f (*mesaFuncs.glVertex3f)
+#define _GLD_glVertex3fv (*mesaFuncs.glVertex3fv)
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+// Emulate SGI DDK calls.
+#define __wglMalloc(a) GlobalAlloc(GPTR, (a))
+#define __wglFree(a) GlobalFree((a))
+
+// ***********************************************************************
+
+// Mesa glu.h and MS glu.h call these different things...
+//#define GLUtesselator GLUtriangulatorObj
+//#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA
+
+// For wglFontOutlines
+
+typedef GLUtesselator *(APIENTRY *gluNewTessProto)(void);
+typedef void (APIENTRY *gluDeleteTessProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessBeginPolygonProto)(GLUtesselator *tess, void *polygon_data);
+typedef void (APIENTRY *gluTessBeginContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessVertexProto)(GLUtesselator *tess, GLdouble coords[3], void *data);
+typedef void (APIENTRY *gluTessEndContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessEndPolygonProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessPropertyProto)(GLUtesselator *tess, GLenum which, GLdouble value);
+typedef void (APIENTRY *gluTessNormalProto)(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY *gluTessCallbackProto)(GLUtesselator *tess, GLenum which, void (CALLBACK *)());
+
+static HINSTANCE gluModuleHandle;
+static gluNewTessProto gluNewTessProc;
+static gluDeleteTessProto gluDeleteTessProc;
+static gluTessBeginPolygonProto gluTessBeginPolygonProc;
+static gluTessBeginContourProto gluTessBeginContourProc;
+static gluTessVertexProto gluTessVertexProc;
+static gluTessEndContourProto gluTessEndContourProc;
+static gluTessEndPolygonProto gluTessEndPolygonProc;
+static gluTessPropertyProto gluTessPropertyProc;
+static gluTessNormalProto gluTessNormalProc;
+static gluTessCallbackProto gluTessCallbackProc;
+
+static HFONT hNewFont, hOldFont;
+static FLOAT ScaleFactor;
+
+#define LINE_BUF_QUANT 4000
+#define VERT_BUF_QUANT 4000
+
+static FLOAT* LineBuf;
+static DWORD LineBufSize;
+static DWORD LineBufIndex;
+static FLOAT* VertBuf;
+static DWORD VertBufSize;
+static DWORD VertBufIndex;
+static GLenum TessErrorOccurred;
+
+static int AppendToLineBuf(
+ FLOAT value);
+
+static int AppendToVertBuf(
+ FLOAT value);
+
+static int DrawGlyph(
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static void FreeLineBuf(void);
+
+static void FreeVertBuf(void);
+
+static long GetWord(
+ UCHAR** p);
+
+static long GetDWord(
+ UCHAR** p);
+
+static double GetFixed(
+ UCHAR** p);
+
+static int InitLineBuf(void);
+
+static int InitVertBuf(void);
+
+static HFONT CreateHighResolutionFont(
+ HDC hDC);
+
+static int MakeDisplayListFromGlyph(
+ DWORD listName,
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static BOOL LoadGLUTesselator(void);
+static BOOL UnloadGLUTesselator(void);
+
+static int MakeLinesFromArc(
+ FLOAT x0,
+ FLOAT y0,
+ FLOAT x1,
+ FLOAT y1,
+ FLOAT x2,
+ FLOAT y2,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviationSquared);
+
+static int MakeLinesFromGlyph( UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTLine( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount);
+
+static int MakeLinesFromTTPolycurve( UCHAR** pp,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTPolygon( UCHAR** pp,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTQSpline( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount,
+ FLOAT chordalDeviation);
+
+static void CALLBACK TessCombine( double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData);
+
+static void CALLBACK TessError( GLenum error);
+
+static void CALLBACK TessVertexOutData( FLOAT p[3],
+ GLfloat z);
+
+// ***********************************************************************
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLWGL.C vars for multi-threaded support")
+extern CRITICAL_SECTION CriticalSection;
+extern DWORD dwTLSPixelFormat; // TLS index for current pixel format
+#endif
+int curPFD = 0; // Current PFD (static)
+
+// ***********************************************************************
+
+int dglGetPixelFormat(void)
+{
+#ifdef GLD_THREADS
+ int iPixelFormat;
+ // get thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iPixelFormat = curPFD;
+ }
+ }
+ // get global static var
+ else {
+ iPixelFormat = curPFD;
+ }
+ return iPixelFormat;
+#else
+ return curPFD;
+#endif
+}
+
+// ***********************************************************************
+
+void dglSetPixelFormat(int iPixelFormat)
+{
+#ifdef GLD_THREADS
+ // set thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ curPFD = iPixelFormat;
+ }
+ }
+ // set global static var
+ else {
+ curPFD = iPixelFormat;
+ }
+#else
+ curPFD = iPixelFormat;
+#endif
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)(
+ HDC a,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ DGL_pixelFormat *lpPF = glb.lpPF;
+
+ PIXELFORMATDESCRIPTOR ppfdBest;
+ int i;
+ int bestIndex = -1;
+ int numPixelFormats;
+ DWORD dwFlags;
+
+ char buf[128];
+ char cat[8];
+
+ DWORD dwAllFlags =
+ PFD_DRAW_TO_WINDOW |
+ PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI |
+ PFD_SUPPORT_OPENGL |
+ PFD_GENERIC_FORMAT |
+ PFD_NEED_PALETTE |
+ PFD_NEED_SYSTEM_PALETTE |
+ PFD_DOUBLEBUFFER |
+ PFD_STEREO |
+ /*PFD_SWAP_LAYER_BUFFERS |*/
+ PFD_DOUBLEBUFFER_DONTCARE |
+ PFD_STEREO_DONTCARE |
+ PFD_SWAP_COPY |
+ PFD_SWAP_EXCHANGE |
+ PFD_GENERIC_ACCELERATED |
+ 0;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // List may not be built until dglValidate() is called! KeithH
+ lpPF = glb.lpPF;
+
+ //
+ // Lets print the input pixel format to the log
+ // ** Based on "wglinfo" by Nate Robins **
+ //
+ ddlogMessage(DDLOG_SYSTEM, "ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO, "Input pixel format for ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO,
+ " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
+ ddlogMessage(DDLOG_INFO,
+ " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ sprintf(buf, " . ");
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+ if(ppfd->dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
+ else if(ppfd->dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
+ else sprintf(cat, ". ");
+ strcat(buf, cat);
+
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+
+ /* bReserved field indicates number of over/underlays */
+ if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ strcat(buf, cat);
+
+ sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.');
+ strcat(buf, cat);
+
+ if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAuxBuffers) sprintf(cat, "%2d ", ppfd->cAuxBuffers);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cDepthBits) sprintf(cat, "%2d ", ppfd->cDepthBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cStencilBits) sprintf(cat, "%2d ", ppfd->cStencilBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumRedBits) sprintf(cat, "%2d ", ppfd->cAccumRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumBlueBits) sprintf(cat, "%2d ", ppfd->cAccumBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ /* no multisample in Win32 */
+ sprintf(cat, " . .\n");
+ strcat(buf, cat);
+
+ ddlogMessage(DDLOG_INFO, buf);
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ ddlogMessage(DDLOG_INFO, "\n");
+
+ //
+ // Examine the flags for correctness
+ //
+ dwFlags = ppfd->dwFlags;
+ if (dwFlags != (dwFlags & dwAllFlags))
+ {
+ /* error: bad dwFlags */
+ ddlogPrintf(DDLOG_WARN,
+ "ChoosePixelFormat: bad flags (0x%x)",
+ dwFlags & (~dwAllFlags));
+ // Mask illegal flags and continue
+ dwFlags = dwFlags & dwAllFlags;
+ }
+
+ switch (ppfd->iPixelType) {
+ case PFD_TYPE_RGBA:
+ case PFD_TYPE_COLORINDEX:
+ break;
+ default:
+ /* error: bad iPixelType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n");
+ return 0;
+ }
+
+ switch (ppfd->iLayerType) {
+ case PFD_MAIN_PLANE:
+ case PFD_OVERLAY_PLANE:
+ case PFD_UNDERLAY_PLANE:
+ break;
+ default:
+ /* error: bad iLayerType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n");
+ return 0;
+ }
+
+ numPixelFormats = glb.nPixelFormatCount;
+
+ /* loop through candidate pixel format descriptors */
+ for (i=0; i<numPixelFormats; ++i) {
+ PIXELFORMATDESCRIPTOR ppfdCandidate;
+
+ memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR));
+
+ /*
+ ** Check attributes which must match
+ */
+ if (ppfd->iPixelType != ppfdCandidate.iPixelType) {
+ continue;
+ }
+
+ if (ppfd->iLayerType != ppfdCandidate.iLayerType) {
+ continue;
+ }
+
+ if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) &
+ (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL))
+ {
+ continue;
+ }
+
+ if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
+ if ((dwFlags & PFD_DOUBLEBUFFER) !=
+ (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER))
+ {
+ continue;
+ }
+ }
+
+// if (!(dwFlags & PFD_STEREO_DONTCARE)) {
+ if ((dwFlags & PFD_STEREO) !=
+ (ppfdCandidate.dwFlags & PFD_STEREO))
+ {
+ continue;
+ }
+// }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) {
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) {
+ continue;
+ }
+
+ if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) {
+ continue;
+ }
+
+ if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) {
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) {
+ continue;
+ }
+
+ /*
+ ** See if candidate is better than the previous best choice
+ */
+ if (bestIndex == -1) {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cColorBits > ppfdBest.cColorBits &&
+ ppfdCandidate.cColorBits > ppfdBest.cColorBits) ||
+ (ppfd->cColorBits <= ppfdCandidate.cColorBits &&
+ ppfdCandidate.cColorBits < ppfdBest.cColorBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits
+ && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits
+ && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cDepthBits > ppfdBest.cDepthBits &&
+ ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) ||
+ (ppfd->cDepthBits <= ppfdCandidate.cDepthBits &&
+ ppfdCandidate.cDepthBits < ppfdBest.cDepthBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cStencilBits &&
+ ppfdCandidate.cStencilBits > ppfdBest.cStencilBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers &&
+ ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+ }
+
+ if (bestIndex != -1) {
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1);
+ return bestIndex + 1;
+ }
+
+ // Return the pixelformat that has the most capabilities.
+ // ** NOTE: This is only possible due to the way the list
+ // of pixelformats is built. **
+ // Now picks best pixelformat. KeithH
+ bestIndex = numPixelFormats; // most capable double buffer format
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen by default", bestIndex);
+ return (bestIndex);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)(
+ HGLRC a,
+ HGLRC b,
+ UINT c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+ UNSUPPORTED("wglCopyContext")
+ return FALSE; // Failed
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)(
+ HDC a)
+{
+ int ipf;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // Check that the current PFD is valid
+ ipf = dglGetPixelFormat();
+ if (!IsValidPFD(ipf))
+ return (HGLRC)0;
+
+ return dglCreateContext(a, &glb.lpPF[ipf-1]);
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)(
+ HDC a,
+ int b)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("wglCreateLayerContext")
+ return NULL; // Failed
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)(
+ HGLRC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglDeleteContext(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)(
+ HDC hDC,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_DescribeLayerPlane")
+
+// gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)(
+ HDC a,
+ int b,
+ UINT c,
+ LPPIXELFORMATDESCRIPTOR d)
+{
+ UINT nSize;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ if (d == NULL) // Calling app requires max number of PF's
+ return glb.nPixelFormatCount;
+
+ // The supplied buffer may be larger than the info that we
+ // will be copying.
+ if (c > sizeof(PIXELFORMATDESCRIPTOR))
+ nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ else
+ nSize = c;
+
+ // Setup an empty PFD before doing validation check
+ memset(d, 0, nSize);
+ d->nSize = nSize;
+ d->nVersion = 1;
+
+ if (!IsValidPFD(b))
+ return 0; // Bail if PFD index is invalid
+
+ memcpy(d, &glb.lpPF[b-1].pfd, nSize);
+
+ return glb.nPixelFormatCount;
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentContext();
+}
+
+// ***********************************************************************
+
+HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentDC();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)(
+ LPCSTR a)
+{
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ UNSUPPORTED("DGL_GetDefaultProcAddress")
+ return NULL;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_GetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetPixelFormat();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)(
+ LPCSTR a)
+{
+ PROC dglGetProcAddressD3D(LPCSTR a);
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+#ifdef _USE_GLD3_WGL
+ return _gldDriver.wglGetProcAddress(a);
+#else
+ return dglGetProcAddressD3D(a);
+#endif
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)(
+ HDC a,
+ HGLRC b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglMakeCurrent(a, b);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)(
+ HDC a,
+ int b,
+ BOOL c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_RealizeLayerPalette")
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ CONST COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_SetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)(
+ HDC a,
+ int b,
+ CONST PIXELFORMATDESCRIPTOR *c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ if (IsValidPFD(b)) {
+ ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b);
+ dglSetPixelFormat(b);
+ return TRUE;
+ } else {
+ ddlogPrintf(DDLOG_ERROR,
+ "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b);
+ return FALSE;
+ }
+}
+
+// ***********************************************************************
+/*
+ * Share lists between two gl_context structures.
+ * This was added for WIN32 WGL function support, since wglShareLists()
+ * must be called *after* wglCreateContext() with valid GLRCs. (DaveM)
+ */
+//
+// Copied from GLD2.x. KeithH
+//
+static GLboolean _gldShareLists(
+ struct gl_context *ctx1,
+ struct gl_context *ctx2)
+{
+ /* Sanity check context pointers */
+ if (ctx1 == NULL || ctx2 == NULL)
+ return GL_FALSE;
+ /* Sanity check shared list pointers */
+ if (ctx1->Shared == NULL || ctx2->Shared == NULL)
+ return GL_FALSE;
+ /* Decrement reference count on sharee to release previous list */
+ ctx2->Shared->RefCount--;
+#if 0 /* 3DStudio exits on this memory release */
+ if (ctx2->Shared->RefCount == 0)
+ free_shared_state(ctx2, ctx2->Shared);
+#endif
+ /* Re-assign list from sharer to sharee and increment reference count */
+ ctx2->Shared = ctx1->Shared;
+ ctx1->Shared->RefCount++;
+ return GL_TRUE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)(
+ HGLRC a,
+ HGLRC b)
+{
+ DGL_ctx *dgl1, *dgl2;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Mesa supports shared lists, but you need to supply the shared
+ // GL context info when calling gl_create_context(). An auxiliary
+ // function gl_share_lists() has been added to update the shared
+ // list info after the GL contexts have been created. (DaveM)
+ dgl1 = dglGetContextAddress(a);
+ dgl2 = dglGetContextAddress(b);
+ if (dgl1->bAllocated && dgl2->bAllocated) {
+#ifdef _USE_GLD3_WGL
+ return _gldShareLists(dgl1->glCtx, dgl2->glCtx);
+#else
+ return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx);
+#endif
+ }
+ return FALSE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)(
+ HDC a,
+ UINT b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+// ***********************************************************************
+// Note: This ResizeBuffers() function may be called from
+// either MESA glViewport() or GLD wglMakeCurrent().
+
+BOOL dglWglResizeBuffers(
+ struct gl_context *ctx,
+ BOOL bDefaultDriver)
+{
+ DGL_ctx *dgl = NULL;
+ RECT rcScreenRect;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ IDirectDrawClipper *lpddClipper = NULL;
+ DWORD dwFlags;
+ HRESULT hResult;
+
+ DWORD dwMemoryType;
+
+ int i;
+ struct gl_texture_object *tObj;
+ struct gl_texture_image *image;
+
+ BOOL bWasFullscreen;
+ BOOL bSaveDesktop;
+ BOOL bFullScrnWin = FALSE;
+ DDSURFACEDESC2 ddsd2DisplayMode;
+
+ DDBLTFX ddbltfx;
+ POINT pt;
+ RECT rcDst;
+#ifdef _USE_GLD3_WGL
+ GLD_displayMode glddm;
+#endif
+
+#define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Sanity checks
+ if (ctx == NULL)
+ return FALSE;
+ dgl = ctx->DriverCtx;
+ if (dgl == NULL)
+ return FALSE;
+
+ // Get the window size and calculate its dimensions
+ if (dgl->hWnd == NULL) {
+ // Check for non-window DC = memory DC ?
+ if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR)
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ }
+ else if (!GetClientRect(dgl->hWnd, &rcScreenRect))
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ dwWidth = rcScreenRect.right - rcScreenRect.left;
+ dwHeight = rcScreenRect.bottom - rcScreenRect.top;
+ CopyRect(&dgl->rcScreenRect, &rcScreenRect);
+
+ // This will occur on Alt-Tab
+ if ((dwWidth == 0) && (dwHeight == 0)) {
+ //dgl->bCanRender = FALSE;
+ return TRUE; // No resize possible!
+ }
+
+ // Some apps zero only 1 dimension for non-visible window... (DaveM)
+ if ((dwWidth == 0) || (dwHeight == 0)) {
+ dwWidth = 8;
+ dwHeight = 8;
+ }
+
+ // Test to see if a resize is required.
+ // Note that the dimensions will be the same if a prior resize attempt failed.
+ if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) {
+ return TRUE; // No resize required
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight);
+#ifndef _USE_GLD3_WGL
+ // Work out where we want our surfaces created
+ dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY;
+#endif // _USE_GLD3_WGL
+
+ // Note previous fullscreen vs window display status
+ bWasFullscreen = dgl->bFullscreen;
+
+#ifdef _USE_GLD3_WGL
+ if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
+ if ( (dwWidth == glddm.Width) &&
+ (dwHeight == glddm.Height) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = glddm.Width;
+ dgl->dwModeHeight = glddm.Height;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > glddm.Width)
+ dgl->dwWidth = glddm.Width;
+ if (dgl->dwHeight > glddm.Height)
+ dgl->dwHeight = glddm.Height;
+#else // _USE_GLD3_WGL
+ // Window resize may have changed to fullscreen
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ dgl->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ dgl->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > ddsd2DisplayMode.dwWidth)
+ dgl->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (dgl->dwHeight > ddsd2DisplayMode.dwHeight)
+ dgl->dwHeight = ddsd2DisplayMode.dwHeight;
+#endif // _USE_GLD3_WGL
+
+ // Note if fullscreen vs window display has changed?
+ bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE;
+ // Save the desktop primary surface from being destroyed
+ // whenever remaining in windowed mode, since the stereo mode
+ // switches are expensive...
+
+#ifndef _USE_GLD3_WGL
+ // Don't need to re-allocate persistant buffers. (DaveM)
+ // Though we should clear the back buffers to hide artifacts.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+ return TRUE;
+ }
+
+ // Ensure all rendering is complete
+ if (ctx->Driver.Finish)
+ (*ctx->Driver.Finish)(ctx);
+ if (dgl->bSceneStarted == TRUE) {
+ IDirect3DDevice3_EndScene(dgl->lpDev3);
+ dgl->bSceneStarted = FALSE;
+ }
+#endif // _USE_GLD3_WGL
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw and DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifndef _USE_GLD3_WGL
+ // Release existing surfaces
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+#endif // _USE_GLD3_WGL
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+
+ // Set defaults
+ dgl->dwModeWidth = dgl->dwWidth;
+ dgl->dwModeHeight = dgl->dwHeight;
+
+#ifdef _USE_GLD3_WGL
+ if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers))
+ goto cleanup_and_return_with_error;
+#else // _USE_GLD3_WGL
+
+ if (dgl->bFullscreen) {
+ //
+ // FULLSCREEN
+ //
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release the persistant DirectDraw primary surface
+ // if switching to fullscreen mode. So if application wants
+ // persistant display in fullscreen mode, a fullscreen-size
+ // window should be used instead via fullscreen-blit option.
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
+ dgl->dwModeWidth,
+ dgl->dwModeHeight,
+ dgl->dwBPP,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (dgl->bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ dgl->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ // Ditto if persistant DirectDraw primary
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ goto DoClipperOnly;
+
+ // WINDOWED
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
+ dgl->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Cache the primary surface for persistant DirectDraw state
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = dgl->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+DoClipperOnly:
+ // Update the window for the original clipper
+ if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) {
+ IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ RELEASE(lpddClipper);
+ }
+
+ if (dgl->bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ } else {
+ dgl->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Zbuffer
+ //
+ if (dgl->bDepthBuffer) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[dgl->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Create a z-buffer
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ dgl->lpDepth4),
+ "dglResize: Attach Zbuffer");
+
+ }
+
+ // Clear the newly resized back buffers for the window client area.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+
+ //
+ // Now that we have a zbuffer we can create the 3D device
+ //
+ hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
+ bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ &dgl->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(dgl);
+
+ //
+ // Viewport
+ //
+ hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Initialise the viewport
+ dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport);
+ dgl->d3dViewport.dwX = 0;
+ dgl->d3dViewport.dwY = 0;
+ dgl->d3dViewport.dwWidth = dgl->dwWidth;
+ dgl->d3dViewport.dwHeight = dgl->dwHeight;
+ dgl->d3dViewport.dvClipX = 0;
+ dgl->d3dViewport.dvClipY = 0;
+ dgl->d3dViewport.dvClipWidth = dgl->dwWidth;
+ dgl->d3dViewport.dvClipHeight = dgl->dwHeight;
+// dgl->d3dViewport.dvMinZ = 0.0f;
+// dgl->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport),
+ "dglResize: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // (Re)Initialise all the Direct3D renderstates
+ dglInitStateD3D(ctx);
+
+ // Now we have to recreate all of our textures (+ mipmaps).
+ // Walk over all textures in hash table
+ // XXX what about the default texture objects (id=0)?
+ {
+ struct _mesa_HashTable *textures = ctx->Shared->TexObjects;
+ GLuint id;
+ for (id = _mesa_HashFirstEntry(textures);
+ id;
+ id = _mesa_HashNextEntry(textures, id)) {
+ tObj = (struct gl_texture_object *) _mesa_HashLookup(textures, id);
+ if (tObj->DriverData) {
+ // We could call our TexImage function directly, but it's
+ // safer to use the driver pointer.
+ for (i=0; i<MAX_TEXTURE_LEVELS; i++) {
+ image = tObj->Image[i];
+ if (image) {
+ switch (tObj->Dimensions){
+ case 1:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
+ break;
+ case 2:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Re-Bind each texture Unit
+ for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
+ tObj = ctx->Texture.Unit[i].Current;
+ if (tObj) {
+ DGL_texture *lpTex = (DGL_texture *)tObj->DriverData;
+ hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult);
+ }
+ }
+ }
+#endif // _USE_GLD3_WGL
+
+ dgl->bCanRender = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // SUCCESS.
+ return TRUE;
+
+cleanup_and_return_with_error:
+ // Relase all interfaces before returning.
+#ifdef _USE_GLD3_WGL
+ _gldDriver.DestroyDrawable(dgl);
+#else // _USE_GLD3_WGL
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+
+#undef DDLOG_CRITICAL_OR_WARN
+#endif // _USE_GLD3_WGL
+
+ // Mark context as not being able to render
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for bitmap fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+/*****************************************************************************
+**
+** InvertGlyphBitmap.
+**
+** Invert the bitmap so that it suits OpenGL's representation.
+** Each row starts on a double word boundary.
+**
+*****************************************************************************/
+
+static void InvertGlyphBitmap(
+ int w,
+ int h,
+ DWORD *fptr,
+ DWORD *tptr)
+{
+ int dWordsInRow = (w+31)/32;
+ int i, j;
+ DWORD *tmp = tptr;
+
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ tptr += ((h-1)*dWordsInRow);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < dWordsInRow; j++) {
+ *(tptr + j) = *(fptr + j);
+ }
+ tptr -= dWordsInRow;
+ fptr += dWordsInRow;
+ }
+}
+
+// ***********************************************************************
+
+/*****************************************************************************
+ * wglUseFontBitmaps
+ *
+ * Converts a subrange of the glyphs in a GDI font to OpenGL display
+ * lists.
+ *
+ * Extended to support any GDI font, not just TrueType fonts. (DaveM)
+ *
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
+ HDC hDC,
+ DWORD first,
+ DWORD count,
+ DWORD listBase)
+{
+ int i, ox, oy, ix, iy;
+ int w, h;
+ int iBufSize, iCurBufSize = 0;
+ DWORD *bitmapBuffer = NULL;
+ DWORD *invertedBitmapBuffer = NULL;
+ BOOL bSuccessOrFail = TRUE;
+ BOOL bTrueType = FALSE;
+ TEXTMETRIC tm;
+ GLYPHMETRICS gm;
+ RASTERIZER_STATUS rs;
+ MAT2 mat;
+ SIZE size;
+ RECT rect;
+ HDC hDCMem;
+ HBITMAP hBitmap;
+ BITMAPINFO bmi;
+ HFONT hFont;
+
+ // Validate SciTech DirectGL license
+ if (!dglValidate())
+ return FALSE;
+
+ // Set up a unity matrix.
+ ZeroMemory(&mat, sizeof(mat));
+ mat.eM11.value = 1;
+ mat.eM22.value = 1;
+
+ // Test to see if selected font is TrueType or not
+ ZeroMemory(&tm, sizeof(tm));
+ if (!GetTextMetrics(hDC, &tm)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Font metrics error\n");
+ return (FALSE);
+ }
+ bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
+
+ // Test to see if TRUE-TYPE capabilities are installed
+ // (only necessary if TrueType font selected)
+ ZeroMemory(&rs, sizeof(rs));
+ if (bTrueType) {
+ if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
+ return (FALSE);
+ }
+ if (!(rs.wFlags & TT_ENABLED)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
+ return (FALSE);
+ }
+ }
+
+ // Trick to get the current font handle
+ hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+ SelectObject(hDC, hFont);
+
+ // Have memory device context available for holding bitmaps of font glyphs
+ hDCMem = CreateCompatibleDC(hDC);
+ SelectObject(hDCMem, hFont);
+ SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
+ SetBkColor(hDCMem, 0);
+
+ for (i = first; (DWORD) i < (first + count); i++) {
+ // Find out how much space is needed for the bitmap so we can
+ // Set the buffer size correctly.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap size of glyph
+ iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ 0, NULL, &mat);
+ if (iBufSize == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+ else {
+ // Use generic GDI support to compute bitmap size of glyph
+ w = tm.tmMaxCharWidth;
+ h = tm.tmHeight;
+ if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
+ w = size.cx;
+ h = size.cy;
+ }
+ iBufSize = w * h;
+ // Use DWORD multiple for compatibility
+ iBufSize += 3;
+ iBufSize /= 4;
+ iBufSize *= 4;
+ }
+
+ // If we need to allocate Larger Buffers, then do so - but allocate
+ // An extra 50 % so that we don't do too many mallocs !
+ if (iBufSize > iCurBufSize) {
+ if (bitmapBuffer) {
+ __wglFree(bitmapBuffer);
+ }
+ if (invertedBitmapBuffer) {
+ __wglFree(invertedBitmapBuffer);
+ }
+
+ iCurBufSize = iBufSize * 2;
+ bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+ invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+
+ if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+
+ // If we fail to get the Glyph data, delete the display lists
+ // Created so far and return FALSE.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap of glyph
+ if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ iBufSize, bitmapBuffer, &mat) == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ w = gm.gmBlackBoxX;
+ h = gm.gmBlackBoxY;
+ ox = gm.gmptGlyphOrigin.x;
+ oy = gm.gmptGlyphOrigin.y;
+ ix = gm.gmCellIncX;
+ iy = gm.gmCellIncY;
+ }
+ else {
+ // Use generic GDI support to create bitmap of glyph
+ ZeroMemory(bitmapBuffer, iBufSize);
+
+ if (i >= tm.tmFirstChar && i <= tm.tmLastChar) {
+ // Only create bitmaps for actual font glyphs
+ hBitmap = CreateBitmap(w, h, 1, 1, NULL);
+ SelectObject(hDCMem, hBitmap);
+ // Make bitmap of current font glyph
+ SetRect(&rect, 0, 0, w, h);
+ DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
+ DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
+ // Make copy of bitmap in our local buffer
+ ZeroMemory(&bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = w;
+ bmi.bmiHeader.biHeight = -h;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
+ DeleteObject(hBitmap);
+ }
+ else {
+ // Otherwise use empty display list for non-existing glyph
+ iBufSize = 0;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ ox = 0;
+ oy = tm.tmDescent;
+ ix = w;
+ iy = 0;
+ }
+
+ // Create an OpenGL display list.
+ _GLD_glNewList((listBase + i), GL_COMPILE);
+
+ // Some fonts have no data for the space character, yet advertise
+ // a non-zero size.
+ if (0 == iBufSize) {
+ _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
+ } else {
+ // Invert the Glyph data.
+ InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
+
+ // Render an OpenGL bitmap and invert the origin.
+ _GLD_glBitmap(w, h,
+ (GLfloat) ox, (GLfloat) (h-oy),
+ (GLfloat) ix, (GLfloat) iy,
+ (GLubyte *) invertedBitmapBuffer);
+ }
+
+ // Close this display list.
+ _GLD_glEndList();
+ }
+
+ if (bSuccessOrFail == FALSE) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
+ _GLD_glDeleteLists((i+listBase), (i-first));
+ }
+
+ // Release resources used
+ DeleteObject(hFont);
+ DeleteDC(hDCMem);
+
+ if (bitmapBuffer)
+ __wglFree(bitmapBuffer);
+ if (invertedBitmapBuffer)
+ __wglFree(invertedBitmapBuffer);
+
+ return(bSuccessOrFail);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
+ HDC a,
+ DWORD b,
+ DWORD c,
+ DWORD d)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for outline TrueType fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+void * __wglRealloc(
+ void *oldPtr,
+ size_t newSize)
+{
+ void *newPtr = NULL;
+
+ if (newSize != 0) {
+ newPtr = (void *) GlobalAlloc(GPTR, newSize);
+ if (oldPtr && newPtr) {
+ DWORD oldSize = GlobalSize(oldPtr);
+
+ memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
+ GlobalFree(oldPtr);
+ }
+ } else if (oldPtr) {
+ GlobalFree(oldPtr);
+ }
+ if (newPtr == NULL) {
+ return NULL; /* XXX out of memory error */
+ }
+ return newPtr;
+}
+
+// ***********************************************************************
+
+
+/*****************************************************************************
+ * wglUseFontOutlinesW
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT lpgmf)
+{
+ return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
+ chordalDeviation, extrusion, format, lpgmf);
+}
+
+/*****************************************************************************
+ * wglUseFontOutlinesA
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
+ {
+ DWORD glyphIndex;
+ UCHAR* glyphBuf;
+ DWORD glyphBufSize;
+
+
+ /*
+ * Flush any previous OpenGL errors. This allows us to check for
+ * new errors so they can be reported via the function return value.
+ */
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+
+ /*
+ * Make sure that the current font can be sampled accurately.
+ */
+ hNewFont = CreateHighResolutionFont(hDC);
+ if (!hNewFont)
+ return FALSE;
+
+ hOldFont = SelectObject(hDC, hNewFont);
+ if (!hOldFont)
+ return FALSE;
+
+ /*
+ * Preallocate a buffer for the outline data, and track its size:
+ */
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+
+ /*
+ * Process each glyph in the given range:
+ */
+ for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
+ {
+ GLYPHMETRICS glyphMetrics;
+ DWORD glyphSize;
+ static MAT2 matrix =
+ {
+ {0, 1}, {0, 0},
+ {0, 0}, {0, 1}
+ };
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat =
+ &glyphMetricsFloatArray[glyphIndex - first];
+
+
+ /*
+ * Determine how much space is needed to store the glyph's
+ * outlines. If our glyph buffer isn't large enough,
+ * resize it.
+ */
+ glyphSize = GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ 0,
+ NULL,
+ &matrix
+ );
+ if (glyphSize < 0)
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ if (glyphSize > glyphBufSize)
+ {
+ __wglFree(glyphBuf);
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+ }
+
+
+ /*
+ * Get the glyph's outlines.
+ */
+ if (GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ glyphBufSize,
+ glyphBuf,
+ &matrix
+ ) < 0)
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+
+ glyphMetricsFloat->gmfBlackBoxX =
+ (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
+ glyphMetricsFloat->gmfBlackBoxY =
+ (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.x =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.y =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncX =
+ (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncY =
+ (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
+
+ /*
+ * Turn the glyph into a display list:
+ */
+ if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
+ glyphBuf,
+ glyphSize,
+ glyphMetricsFloat,
+ chordalDeviation + ScaleFactor,
+ extrusion,
+ format))
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+ /*
+ * Clean up temporary storage and return. If an error occurred,
+ * clear all OpenGL error flags and return FAILURE status;
+ * otherwise just return SUCCESS.
+ */
+ __wglFree(glyphBuf);
+
+ SelectObject(hDC, hOldFont);
+
+ if (_GLD_glGetError() == GL_NO_ERROR)
+ return TRUE; /*WGL_STATUS_SUCCESS*/
+ else
+ {
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+
+/*****************************************************************************
+ * CreateHighResolutionFont
+ *
+ * Gets metrics for the current font and creates an equivalent font
+ * scaled to the design units of the font.
+ *
+ *****************************************************************************/
+
+static HFONT
+CreateHighResolutionFont(HDC hDC)
+ {
+ UINT otmSize;
+ OUTLINETEXTMETRIC *otm;
+ LONG fontHeight, fontWidth, fontUnits;
+ LOGFONT logFont;
+
+ otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
+ if (otmSize == 0)
+ return NULL;
+
+ otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
+ if (otm == NULL)
+ return NULL;
+
+ otm->otmSize = otmSize;
+ if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
+ return NULL;
+
+ fontHeight = otm->otmTextMetrics.tmHeight -
+ otm->otmTextMetrics.tmInternalLeading;
+ fontWidth = otm->otmTextMetrics.tmAveCharWidth;
+ fontUnits = (LONG) otm->otmEMSquare;
+
+ ScaleFactor = 1.0F / (FLOAT) fontUnits;
+
+ logFont.lfHeight = - ((LONG) fontUnits);
+ logFont.lfWidth = (LONG)
+ ((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
+ logFont.lfEscapement = 0;
+ logFont.lfOrientation = 0;
+ logFont.lfWeight = otm->otmTextMetrics.tmWeight;
+ logFont.lfItalic = otm->otmTextMetrics.tmItalic;
+ logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
+ logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
+ logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
+ logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
+ logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ logFont.lfQuality = DEFAULT_QUALITY;
+ logFont.lfPitchAndFamily =
+ otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
+ strcpy(logFont.lfFaceName,
+ (char *)otm + (int)otm->otmpFaceName);
+
+ hNewFont = CreateFontIndirect(&logFont);
+ if (hNewFont == NULL)
+ return NULL;
+
+ __wglFree(otm);
+
+ return hNewFont;
+ }
+
+
+
+/*****************************************************************************
+ * MakeDisplayListFromGlyph
+ *
+ * Converts the outline of a glyph to an OpenGL display list.
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+MakeDisplayListFromGlyph( IN DWORD listName,
+ IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ int status;
+
+ _GLD_glNewList(listName, GL_COMPILE);
+ status = DrawGlyph( glyphBuf,
+ glyphSize,
+ chordalDeviation,
+ extrusion,
+ format);
+
+ _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
+ glyphMetricsFloat->gmfCellIncY,
+ 0.0F);
+ _GLD_glEndList();
+
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * DrawGlyph
+ *
+ * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
+ * as needed, and then draws the glyph. Tessellation of the quadratic splines
+ * in the outline is controlled by "chordalDeviation", and the drawing
+ * primitives (lines or polygons) are selected by "format".
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+DrawGlyph( IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ INT status = 0;
+ FLOAT* p;
+ DWORD loop;
+ DWORD point;
+ GLUtesselator* tess = NULL;
+
+
+ /*
+ * Initialize the global buffer into which we place the outlines:
+ */
+ if (!InitLineBuf())
+ goto exit;
+
+
+ /*
+ * Convert the glyph outlines to a set of polyline loops.
+ * (See MakeLinesFromGlyph() for the format of the loop data
+ * structure.)
+ */
+ if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
+ goto exit;
+ p = LineBuf;
+
+
+ /*
+ * Now draw the loops in the appropriate format:
+ */
+ if (format == WGL_FONT_LINES)
+ {
+ /*
+ * This is the easy case. Just draw the outlines.
+ */
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ _GLD_glBegin(GL_LINE_LOOP);
+ for (point = (DWORD) *p++; point; --point)
+ {
+ _GLD_glVertex2fv(p);
+ p += 2;
+ }
+ _GLD_glEnd();
+ }
+ status = 1;
+ }
+
+ else if (format == WGL_FONT_POLYGONS)
+ {
+ double v[3];
+ FLOAT *save_p = p;
+ GLfloat z_value;
+
+ /*
+ * This is the hard case. We have to set up a tessellator
+ * to convert the outlines into a set of polygonal
+ * primitives, which the tessellator passes to some
+ * auxiliary routines for drawing.
+ */
+ if (!LoadGLUTesselator())
+ goto exit;
+ if (!InitVertBuf())
+ goto exit;
+ if (!(tess = gluNewTessProc()))
+ goto exit;
+ gluTessCallbackProc(tess, GLU_BEGIN, (void(CALLBACK *)()) _GLD_glBegin);
+ gluTessCallbackProc(tess, GLU_TESS_VERTEX_DATA,
+ (void(CALLBACK *)()) TessVertexOutData);
+ gluTessCallbackProc(tess, GLU_END, (void(CALLBACK *)()) _GLD_glEnd);
+ gluTessCallbackProc(tess, GLU_ERROR, (void(CALLBACK *)()) TessError);
+ gluTessCallbackProc(tess, GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine);
+ gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F);
+
+ TessErrorOccurred = 0;
+ _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
+ v[2] = 0.0;
+ z_value = 0.0f;
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ gluTessBeginContourProc(tess);
+
+ for (point = (DWORD) *p++; point; --point)
+ {
+ v[0] = p[0];
+ v[1] = p[1];
+ gluTessVertexProc(tess, v, p);
+ p += 2;
+ }
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+
+ status = !TessErrorOccurred;
+
+ /* Extrusion code */
+ if (extrusion) {
+ DWORD loops;
+ GLfloat thickness = (GLfloat) -extrusion;
+ FLOAT *vert, *vert2;
+ DWORD count;
+
+ p = save_p;
+ loops = (DWORD) *p++;
+
+ for (loop = 0; loop < loops; loop++) {
+ GLfloat dx, dy, len;
+ DWORD last;
+
+ count = (DWORD) *p++;
+ _GLD_glBegin(GL_QUAD_STRIP);
+
+ /* Check if the first and last vertex are identical
+ * so we don't draw the same quad twice.
+ */
+ vert = p + (count-1)*2;
+ last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
+
+ for (point = 0; point <= last; point++) {
+ vert = p + 2 * (point % last);
+ vert2 = p + 2 * ((point+1) % last);
+
+ dx = vert[0] - vert2[0];
+ dy = vert[1] - vert2[1];
+ len = (GLfloat)sqrt(dx * dx + dy * dy);
+
+ _GLD_glNormal3f(dy / len, -dx / len, 0.0f);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], thickness);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], 0.0f);
+ }
+
+ _GLD_glEnd();
+ p += count*2;
+ }
+
+ /* Draw the back face */
+ p = save_p;
+ v[2] = thickness;
+ _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
+ gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
+
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ count = (DWORD) *p++;
+
+ gluTessBeginContourProc(tess);
+
+ for (point = 0; point < count; point++)
+ {
+ vert = p + ((count-point-1)<<1);
+ v[0] = vert[0];
+ v[1] = vert[1];
+ gluTessVertexProc(tess, v, vert);
+ }
+ p += count*2;
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+ }
+
+#if DEBUG
+ if (TessErrorOccurred)
+ printf("Tessellation error %s\n",
+ gluErrorString(TessErrorOccurred));
+#endif
+ }
+
+
+exit:
+ FreeLineBuf();
+ if (tess)
+ gluDeleteTessProc(tess);
+ // UnloadGLUTesselator();
+ FreeVertBuf();
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * LoadGLUTesselator
+ *
+ * Maps the glu32.dll module and gets function pointers for the
+ * tesselator functions.
+ *****************************************************************************/
+
+static BOOL
+LoadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ return TRUE;
+
+ {
+ extern HINSTANCE hInstanceOpenGL;
+ char *gluName = "GLU32.DLL";
+// char name[256];
+// char *ptr;
+// int len;
+
+/*
+ len = GetModuleFileName(hInstanceOpenGL, name, 255);
+ if (len != 0)
+ {
+ ptr = name+len-1;
+ while (ptr > name && *ptr != '\\')
+ ptr--;
+ if (*ptr == '\\')
+ ptr++;
+ if (!stricmp(ptr, "cosmogl.dll"))
+ {
+ gluName = "COSMOGLU.DLL";
+ }
+ else if (!stricmp(ptr, "opengl32.dll"))
+ {
+ gluName = "GLU32.DLL";
+ }
+ }
+*/
+ if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
+ return FALSE;
+ }
+
+ if ((gluNewTessProc = (gluNewTessProto)
+ GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
+ return FALSE;
+
+ if ((gluDeleteTessProc = (gluDeleteTessProto)
+ GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginContourProc = (gluTessBeginContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessVertexProc = (gluTessVertexProto)
+ GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndContourProc = (gluTessEndContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessPropertyProc = (gluTessPropertyProto)
+ GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
+ return FALSE;
+
+ if ((gluTessNormalProc = (gluTessNormalProto)
+ GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
+ return FALSE;
+
+ if ((gluTessCallbackProc = (gluTessCallbackProto)
+ GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
+ return FALSE;
+
+ return TRUE;
+ }
+
+
+
+/*****************************************************************************
+ * UnloadGLUTesselator
+ *
+ * Unmaps the glu32.dll module.
+ *****************************************************************************/
+
+static BOOL
+UnloadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ if (FreeLibrary(gluModuleHandle) == FALSE)
+ return FALSE;
+ gluModuleHandle = NULL;
+ }
+
+
+
+/*****************************************************************************
+ * TessVertexOut
+ *
+ * Used by tessellator to handle output vertexes.
+ *****************************************************************************/
+
+static void CALLBACK
+TessVertexOut(FLOAT p[3])
+ {
+ GLfloat v[2];
+
+ v[0] = p[0] * ScaleFactor;
+ v[1] = p[1] * ScaleFactor;
+ _GLD_glVertex2fv(v);
+ }
+
+static void CALLBACK
+TessVertexOutData(FLOAT p[3], GLfloat z)
+{
+ GLfloat v[3];
+
+ v[0] = (GLfloat) p[0];
+ v[1] = (GLfloat) p[1];
+ v[2] = z;
+ _GLD_glVertex3fv(v);
+}
+
+
+/*****************************************************************************
+ * TessCombine
+ *
+ * Used by tessellator to handle self-intersecting contours and degenerate
+ * geometry.
+ *****************************************************************************/
+
+static void CALLBACK
+TessCombine(double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData)
+ {
+ if (!AppendToVertBuf((FLOAT) coords[0])
+ || !AppendToVertBuf((FLOAT) coords[1])
+ || !AppendToVertBuf((FLOAT) coords[2]))
+ TessErrorOccurred = GL_OUT_OF_MEMORY;
+ *outData = VertBuf + (VertBufIndex - 3);
+ }
+
+
+
+/*****************************************************************************
+ * TessError
+ *
+ * Saves the last tessellator error code in the global TessErrorOccurred.
+ *****************************************************************************/
+
+static void CALLBACK
+TessError(GLenum error)
+ {
+ TessErrorOccurred = error;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromGlyph
+ *
+ * Converts the outline of a glyph from the TTPOLYGON format to a simple
+ * array of floating-point values containing one or more loops.
+ *
+ * The first element of the output array is a count of the number of loops.
+ * The loop data follows this count. Each loop consists of a count of the
+ * number of vertices it contains, followed by the vertices. Each vertex
+ * is an X and Y coordinate. For example, a single triangle might be
+ * described by this array:
+ *
+ * 1., 3., 0., 0., 1., 0., 0., 1.
+ * ^ ^ ^ ^ ^ ^ ^ ^
+ * #loops #verts x1 y1 x2 y2 x3 y3
+ *
+ * A two-loop glyph would look like this:
+ *
+ * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
+ *
+ * Line segments from the TTPOLYGON are transferred to the output array in
+ * the obvious way. Quadratic splines in the TTPOLYGON are converted to
+ * collections of line segments
+ *****************************************************************************/
+
+static int
+MakeLinesFromGlyph(IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation)
+ {
+ UCHAR* p;
+ int status = 0;
+
+
+ /*
+ * Pick up all the polygons (aka loops) that make up the glyph:
+ */
+ if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
+ goto exit;
+
+ p = glyphBuf;
+ while (p < glyphBuf + glyphSize)
+ {
+ if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
+ goto exit;
+ LineBuf[0] += 1.0F; /* increment loop count */
+ }
+
+ status = 1;
+
+exit:
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolygon
+ *
+ * Converts a TTPOLYGONHEADER and its associated curve structures into a
+ * single polyline loop in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolygon( IN OUT UCHAR** pp,
+ IN FLOAT chordalDeviation)
+ {
+ DWORD polySize;
+ UCHAR* polyStart;
+ DWORD vertexCountIndex;
+
+ /*
+ * Record where the polygon data begins, and where the loop's
+ * vertex count resides:
+ */
+ polyStart = *pp;
+ vertexCountIndex = LineBufIndex;
+ if (!AppendToLineBuf(0.0F))
+ return 0;
+
+ /*
+ * Extract relevant data from the TTPOLYGONHEADER:
+ */
+ polySize = GetDWord(pp);
+ if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
+ return 0;
+ LineBuf[vertexCountIndex] += 1.0F;
+
+ /*
+ * Process each of the TTPOLYCURVE structures in the polygon:
+ */
+ while (*pp < polyStart + polySize)
+ if (!MakeLinesFromTTPolycurve( pp,
+ vertexCountIndex,
+ chordalDeviation))
+ return 0;
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolyCurve
+ *
+ * Converts the lines and splines in a single TTPOLYCURVE structure to points
+ * in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolycurve( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviation)
+ {
+ WORD type;
+ WORD pointCount;
+
+
+ /*
+ * Pick up the relevant fields of the TTPOLYCURVE structure:
+ */
+ type = (WORD) GetWord(pp);
+ pointCount = (WORD) GetWord(pp);
+
+ /*
+ * Convert the "curve" to line segments:
+ */
+ if (type == TT_PRIM_LINE)
+ return MakeLinesFromTTLine( pp,
+ vertexCountIndex,
+ pointCount);
+ else if (type == TT_PRIM_QSPLINE)
+ return MakeLinesFromTTQSpline( pp,
+ vertexCountIndex,
+ pointCount,
+ chordalDeviation);
+ else
+ return 0;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTLine
+ *
+ * Converts points from the polyline in a TT_PRIM_LINE structure to
+ * equivalent points in the global LineBuf.
+ *****************************************************************************/
+static int
+MakeLinesFromTTLine( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount)
+ {
+ /*
+ * Just copy the line segments into the line buffer (converting
+ * type as we go):
+ */
+ LineBuf[vertexCountIndex] += pointCount;
+ while (pointCount--)
+ {
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
+ || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTQSpline
+ *
+ * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
+ * structure to polyline points in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTQSpline( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount,
+ IN FLOAT chordalDeviation)
+ {
+ FLOAT x0, y0, x1, y1, x2, y2;
+ WORD point;
+
+ /*
+ * Process each of the non-interpolated points in the outline.
+ * To do this, we need to generate two interpolated points (the
+ * start and end of the arc) for each non-interpolated point.
+ * The first interpolated point is always the one most recently
+ * stored in LineBuf, so we just extract it from there. The
+ * second interpolated point is either the average of the next
+ * two points in the QSpline, or the last point in the QSpline
+ * if only one remains.
+ */
+ for (point = 0; point < pointCount - 1; ++point)
+ {
+ x0 = LineBuf[LineBufIndex - 2];
+ y0 = LineBuf[LineBufIndex - 1];
+
+ x1 = (FLOAT) GetFixed(pp);
+ y1 = (FLOAT) GetFixed(pp);
+
+ if (point == pointCount - 2)
+ {
+ /*
+ * This is the last arc in the QSpline. The final
+ * point is the end of the arc.
+ */
+ x2 = (FLOAT) GetFixed(pp);
+ y2 = (FLOAT) GetFixed(pp);
+ }
+ else
+ {
+ /*
+ * Peek at the next point in the input to compute
+ * the end of the arc:
+ */
+ x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
+ y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
+ /*
+ * Push the point back onto the input so it will
+ * be reused as the next off-curve point:
+ */
+ *pp -= 8;
+ }
+
+ if (!MakeLinesFromArc( x0, y0,
+ x1, y1,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviation * chordalDeviation))
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromArc
+ *
+ * Subdivides one arc of a quadratic spline until the chordal deviation
+ * tolerance requirement is met, then places the resulting set of line
+ * segments in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromArc( IN FLOAT x0,
+ IN FLOAT y0,
+ IN FLOAT x1,
+ IN FLOAT y1,
+ IN FLOAT x2,
+ IN FLOAT y2,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviationSquared)
+ {
+ FLOAT x01;
+ FLOAT y01;
+ FLOAT x12;
+ FLOAT y12;
+ FLOAT midPointX;
+ FLOAT midPointY;
+ FLOAT deltaX;
+ FLOAT deltaY;
+
+ /*
+ * Calculate midpoint of the curve by de Casteljau:
+ */
+ x01 = 0.5F * (x0 + x1);
+ y01 = 0.5F * (y0 + y1);
+ x12 = 0.5F * (x1 + x2);
+ y12 = 0.5F * (y1 + y2);
+ midPointX = 0.5F * (x01 + x12);
+ midPointY = 0.5F * (y01 + y12);
+
+
+ /*
+ * Estimate chordal deviation by the distance from the midpoint
+ * of the curve to its non-interpolated control point. If this
+ * distance is greater than the specified chordal deviation
+ * constraint, then subdivide. Otherwise, generate polylines
+ * from the three control points.
+ */
+ deltaX = midPointX - x1;
+ deltaY = midPointY - y1;
+ if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
+ {
+ MakeLinesFromArc( x0, y0,
+ x01, y01,
+ midPointX, midPointY,
+ vertexCountIndex,
+ chordalDeviationSquared);
+
+ MakeLinesFromArc( midPointX, midPointY,
+ x12, y12,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviationSquared);
+ }
+ else
+ {
+ /*
+ * The "pen" is already at (x0, y0), so we don't need to
+ * add that point to the LineBuf.
+ */
+ if (!AppendToLineBuf(x1)
+ || !AppendToLineBuf(y1)
+ || !AppendToLineBuf(x2)
+ || !AppendToLineBuf(y2))
+ return 0;
+ LineBuf[vertexCountIndex] += 2.0F;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitLineBuf
+ *
+ * Initializes the global LineBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitLineBuf(void)
+ {
+ if (!(LineBuf = (FLOAT*)
+ __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ LineBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitVertBuf
+ *
+ * Initializes the global VertBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitVertBuf(void)
+ {
+ if (!(VertBuf = (FLOAT*)
+ __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ VertBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToLineBuf
+ *
+ * Appends one floating-point value to the global LineBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *****************************************************************************/
+
+static int
+AppendToLineBuf(FLOAT value)
+ {
+ if (LineBufIndex >= LineBufSize)
+ {
+ FLOAT* f;
+
+ f = (FLOAT*) __wglRealloc(LineBuf,
+ (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
+ if (!f)
+ return 0;
+ LineBuf = f;
+ }
+ LineBuf[LineBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToVertBuf
+ *
+ * Appends one floating-point value to the global VertBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *
+ * Note that we can't realloc this one, because the tessellator is using
+ * pointers into it.
+ *****************************************************************************/
+
+static int
+AppendToVertBuf(FLOAT value)
+ {
+ if (VertBufIndex >= VertBufSize)
+ return 0;
+ VertBuf[VertBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * FreeLineBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeLineBuf(void)
+ {
+ if (LineBuf)
+ {
+ __wglFree(LineBuf);
+ LineBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * FreeVertBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeVertBuf(void)
+ {
+ if (VertBuf)
+ {
+ __wglFree(VertBuf);
+ VertBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * GetWord
+ *
+ * Fetch the next 16-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[1] << 8) + (*p)[0];
+ *p += 2;
+ return value;
+ }
+
+
+
+/*****************************************************************************
+ * GetDWord
+ *
+ * Fetch the next 32-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetDWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
+ *p += 4;
+ return value;
+ }
+
+
+
+
+/*****************************************************************************
+ * GetFixed
+ *
+ * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
+ * convert it to floating-point, and increment the stream pointer to the next
+ * unscanned byte.
+ *****************************************************************************/
+
+static double GetFixed(
+ UCHAR** p)
+{
+ long hiBits, loBits;
+ double value;
+
+ loBits = GetWord(p);
+ hiBits = GetWord(p);
+ value = (double) ((hiBits << 16) | loBits) / 65536.0;
+
+ return value * ScaleFactor;
+}
+
+// ***********************************************************************
+
|