/* $Id: fxwgl.c,v 1.18 2003/10/02 17:36:45 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 4.0 * * Copyright (C) 1999-2001 Brian Paul 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 * BRIAN PAUL 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. */ /* Authors: * David Bucciarelli * Brian Paul * Keith Whitwell */ /* fxwgl.c - Microsoft wgl functions emulation for * 3Dfx VooDoo/Mesa interface */ #ifdef _WIN32 #ifdef __cplusplus extern "C" { #endif #include #define GL_GLEXT_PROTOTYPES #include "GL/gl.h" #include "GL/glext.h" #ifdef __cplusplus } #endif #include "GL/fxmesa.h" #include "glheader.h" #include "glapi.h" #include "imports.h" #include "fxdrv.h" #define MAX_MESA_ATTRS 20 struct __extensions__ { PROC proc; char *name; }; struct __pixelformat__ { PIXELFORMATDESCRIPTOR pfd; GLint mesaAttr[MAX_MESA_ATTRS]; }; //WINGDIAPI void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *); struct __pixelformat__ pix[] = { /* 16bit RGB565 single buffer with depth */ { {sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 16, 5, 0, 6, 5, 5, 11, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0} , {FXMESA_COLORDEPTH, 16, FXMESA_ALPHA_SIZE, 0, FXMESA_DEPTH_SIZE, 16, FXMESA_STENCIL_SIZE, 0, FXMESA_ACCUM_SIZE, 0, FXMESA_NONE} } , /* 16bit RGB565 double buffer with depth */ { {sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_COPY, PFD_TYPE_RGBA, 16, 5, 0, 6, 5, 5, 11, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0} , {FXMESA_COLORDEPTH, 16, FXMESA_DOUBLEBUFFER, FXMESA_ALPHA_SIZE, 0, FXMESA_DEPTH_SIZE, 16, FXMESA_STENCIL_SIZE, 0, FXMESA_ACCUM_SIZE, 0, FXMESA_NONE} } , /* 16bit ARGB1555 single buffer with depth */ { {sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 16, 5, 0, 5, 5, 5, 10, 1, 15, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0} , {FXMESA_COLORDEPTH, 15, FXMESA_ALPHA_SIZE, 1, FXMESA_DEPTH_SIZE, 16, FXMESA_STENCIL_SIZE, 0, FXMESA_ACCUM_SIZE, 0, FXMESA_NONE} } , /* 16bit ARGB1555 double buffer with depth */ { {sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_COPY, PFD_TYPE_RGBA, 16, 5, 0, 5, 5, 5, 10, 1, 15, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0} , {FXMESA_COLORDEPTH, 15, FXMESA_DOUBLEBUFFER, FXMESA_ALPHA_SIZE, 1, FXMESA_DEPTH_SIZE, 16, FXMESA_STENCIL_SIZE, 0, FXMESA_ACCUM_SIZE, 0, FXMESA_NONE} } , #if 1 /* 24bit RGB888 single buffer with depth */ { {sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 24, 8, 0, 8, 8, 8, 16, 0, 0, 0, 0, 0, 0, 0, 24, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0} , {FXMESA_COLORDEPTH, 32, FXMESA_ALPHA_SIZE, 8, FXMESA_DEPTH_SIZE, 24, FXMESA_STENCIL_SIZE, 8, FXMESA_ACCUM_SIZE, 0, FXMESA_NONE} } , /* 24bit RGB888 double buffer with depth */ { {sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_COPY, PFD_TYPE_RGBA, 24, 8, 0, 8, 8, 8, 16, 0, 0, 0, 0, 0, 0, 0, 24, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0} , {FXMESA_COLORDEPTH, 32, FXMESA_DOUBLEBUFFER, FXMESA_ALPHA_SIZE, 8, FXMESA_DEPTH_SIZE, 24, FXMESA_STENCIL_SIZE, 8, FXMESA_ACCUM_SIZE, 0, FXMESA_NONE} }, #endif /* 32bit ARGB8888 single buffer with depth */ { {sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 32, 8, 0, 8, 8, 8, 16, 8, 24, 0, 0, 0, 0, 0, 24, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0} , {FXMESA_COLORDEPTH, 32, FXMESA_ALPHA_SIZE, 8, FXMESA_DEPTH_SIZE, 24, FXMESA_STENCIL_SIZE, 8, FXMESA_ACCUM_SIZE, 0, FXMESA_NONE} } , /* 32bit ARGB8888 double buffer with depth */ { {sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_COPY, PFD_TYPE_RGBA, 32, 8, 0, 8, 8, 8, 16, 8, 24, 0, 0, 0, 0, 0, 24, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0} , {FXMESA_COLORDEPTH, 32, FXMESA_DOUBLEBUFFER, FXMESA_ALPHA_SIZE, 8, FXMESA_DEPTH_SIZE, 24, FXMESA_STENCIL_SIZE, 8, FXMESA_ACCUM_SIZE, 0, FXMESA_NONE} } }; static int qt_pix = sizeof(pix) / sizeof(pix[0]); static fxMesaContext ctx = NULL; static WNDPROC hWNDOldProc; static int curPFD = 0; static HDC hDC; static HWND hWND; static GLboolean haveDualHead; /* For the in-window-rendering hack */ #ifndef GR_CONTROL_RESIZE /* Apparently GR_CONTROL_RESIZE can be ignored. OK? */ #define GR_CONTROL_RESIZE -1 #endif static GLboolean gdiWindowHack; static void *dibSurfacePtr; static BITMAPINFO *dibBMI; static HBITMAP dibHBM; static HWND dibWnd; static LRESULT APIENTRY __wglMonitor(HWND hwnd, UINT message, UINT wParam, LONG lParam) { long ret; /* Now gives the resized window at the end to hWNDOldProc */ if (ctx && hwnd == hWND) { switch (message) { case WM_PAINT: case WM_MOVE: break; case WM_DISPLAYCHANGE: case WM_SIZE: #if 0 if (wParam != SIZE_MINIMIZED) { static int moving = 0; if (!moving) { if (!FX_grSstControl(GR_CONTROL_RESIZE)) { moving = 1; SetWindowPos(hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE | SWP_NOZORDER); moving = 0; if (!FX_grSstControl(GR_CONTROL_RESIZE)) { /*MessageBox(0,_T("Error changing windowsize"),_T("fxMESA"),MB_OK); */ PostMessage(hWND, WM_CLOSE, 0, 0); } } /* Do the clipping in the glide library */ grClipWindow(0, 0, FX_grSstScreenWidth(), FX_grSstScreenHeight()); /* And let the new size set in the context */ fxMesaUpdateScreenSize(ctx); } } #endif break; case WM_ACTIVATE: break; case WM_SHOWWINDOW: break; case WM_SYSKEYDOWN: case WM_SYSCHAR: break; } } /* Finaly call the hWNDOldProc, which handles the resize witch the now changed window sizes */ ret = CallWindowProc(hWNDOldProc, hwnd, message, wParam, lParam); return (ret); } GLAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) { return (FALSE); } GLAPI HGLRC GLAPIENTRY wglCreateContext(HDC hdc) { HWND hWnd; WNDPROC oldProc; int error; if (ctx) { SetLastError(0); return (NULL); } if (!(hWnd = WindowFromDC(hdc))) { SetLastError(0); return (NULL); } if (curPFD == 0) { SetLastError(0); return (NULL); } if ((oldProc = (WNDPROC) GetWindowLong(hWnd, GWL_WNDPROC)) != __wglMonitor) { hWNDOldProc = oldProc; SetWindowLong(hWnd, GWL_WNDPROC, (LONG) __wglMonitor); } #ifdef FX_DEBUG freopen("MESA.LOG", "w", stderr); #endif { RECT cliRect; ShowWindow(hWnd, SW_SHOWNORMAL); SetForegroundWindow(hWnd); Sleep(100); /* a hack for win95 */ GetClientRect(hWnd, &cliRect); error = !(ctx = fxMesaCreateBestContext((GLuint) hWnd, cliRect.right, cliRect.bottom, pix[curPFD - 1].mesaAttr)); } /*if (getenv("SST_DUALHEAD")) haveDualHead = ((atoi(getenv("SST_DUALHEAD")) == 1) ? GL_TRUE : GL_FALSE); else haveDualHead = GL_FALSE;*/ if (error) { SetLastError(0); return (NULL); } hDC = hdc; hWND = hWnd; /* Required by the OpenGL Optimizer 1.1 (is it a Optimizer bug ?) */ wglMakeCurrent(hdc, (HGLRC) 1); return ((HGLRC) 1); } GLAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc, int iLayerPlane) { SetLastError(0); return (NULL); } GLAPI BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc) { if (ctx && hglrc == (HGLRC) 1) { fxMesaDestroyContext(ctx); SetWindowLong(WindowFromDC(hDC), GWL_WNDPROC, (LONG) hWNDOldProc); ctx = NULL; hDC = 0; return (TRUE); } SetLastError(0); return (FALSE); } GLAPI HGLRC GLAPIENTRY wglGetCurrentContext(VOID) { if (ctx) return ((HGLRC) 1); SetLastError(0); return (NULL); } GLAPI HDC GLAPIENTRY wglGetCurrentDC(VOID) { if (ctx) return (hDC); SetLastError(0); return (NULL); } GLAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc) { PROC p = (PROC) _glapi_get_proc_address((const char *) lpszProc); if (p) return p; SetLastError(0); return (NULL); } GLAPI BOOL GLAPIENTRY wglMakeCurrent(HDC hdc, HGLRC hglrc) { if ((hdc == NULL) && (hglrc == NULL)) return (TRUE); if (!ctx || hglrc != (HGLRC) 1 || WindowFromDC(hdc) != hWND) { SetLastError(0); return (FALSE); } hDC = hdc; fxMesaMakeCurrent(ctx); return (TRUE); } GLAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { if (!ctx || hglrc1 != (HGLRC) 1 || hglrc1 != hglrc2) { SetLastError(0); return (FALSE); } return (TRUE); } static BOOL wglUseFontBitmaps_FX(HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase) { TEXTMETRIC metric; BITMAPINFO *dibInfo; HDC bitDevice; COLORREF tempColor; int i; GetTextMetrics(fontDevice, &metric); dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1); dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); dibInfo->bmiHeader.biPlanes = 1; dibInfo->bmiHeader.biBitCount = 1; dibInfo->bmiHeader.biCompression = BI_RGB; bitDevice = CreateCompatibleDC(fontDevice); // Swap fore and back colors so the bitmap has the right polarity tempColor = GetBkColor(bitDevice); SetBkColor(bitDevice, GetTextColor(bitDevice)); SetTextColor(bitDevice, tempColor); // Place chars based on base line SetTextAlign(bitDevice, TA_BASELINE); for (i = 0; i < (int)numChars; i++) { SIZE size; char curChar; int charWidth, charHeight, bmapWidth, bmapHeight, numBytes, res; HBITMAP bitObject; HGDIOBJ origBmap; unsigned char *bmap; curChar = (char)(i + firstChar); // [koolsmoky] explicit cast // Find how high/wide this character is GetTextExtentPoint32(bitDevice, &curChar, 1, &size); // Create the output bitmap charWidth = size.cx; charHeight = size.cy; bmapWidth = ((charWidth + 31) / 32) * 32; // Round up to the next multiple of 32 bits bmapHeight = charHeight; bitObject = CreateCompatibleBitmap(bitDevice, bmapWidth, bmapHeight); //VERIFY(bitObject); // Assign the output bitmap to the device origBmap = SelectObject(bitDevice, bitObject); PatBlt(bitDevice, 0, 0, bmapWidth, bmapHeight, BLACKNESS); // Use our source font on the device SelectObject(bitDevice, GetCurrentObject(fontDevice, OBJ_FONT)); // Draw the character TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1); // Unselect our bmap object SelectObject(bitDevice, origBmap); // Convert the display dependant representation to a 1 bit deep DIB numBytes = (bmapWidth * bmapHeight) / 8; bmap = MALLOC(numBytes); dibInfo->bmiHeader.biWidth = bmapWidth; dibInfo->bmiHeader.biHeight = bmapHeight; res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap, dibInfo, DIB_RGB_COLORS); // Create the GL object glNewList(i + listBase, GL_COMPILE); glBitmap(bmapWidth, bmapHeight, 0.0, metric.tmDescent, charWidth, 0.0, bmap); glEndList(); // CheckGL(); // Destroy the bmap object DeleteObject(bitObject); // Deallocate the bitmap data FREE(bmap); } // Destroy the DC DeleteDC(bitDevice); FREE(dibInfo); return TRUE; } GLAPI BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase) { return (FALSE); } GLAPI BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf) { SetLastError(0); return (FALSE); } GLAPI BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf) { SetLastError(0); return (FALSE); } GLAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc, UINT fuPlanes) { if (ctx && WindowFromDC(hdc) == hWND) { fxMesaSwapBuffers(); return (TRUE); } SetLastError(0); return (FALSE); } GLAPI int GLAPIENTRY wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR * ppfd) { int i, best = -1, qt_valid_pix; #if 0 FILE *pix_file; pix_file = fopen("pix_log.txt", "a"); if (pix_file) { fprintf(pix_file, "wglChoosePixelFormat\n"); fprintf(pix_file, "nSize = %d\n",ppfd->nSize); fprintf(pix_file, "nVersion = %d\n",ppfd->nVersion); fprintf(pix_file, "dwFlags = %d\n",ppfd->dwFlags); fprintf(pix_file, "iPixelType = %d\n",ppfd->iPixelType); fprintf(pix_file, "cColorBits = %d\n",ppfd->cColorBits); fprintf(pix_file, "cRedBits = %d\n",ppfd->cRedBits); fprintf(pix_file, "cRedShift = %d\n",ppfd->cRedShift); fprintf(pix_file, "cGreenBits = %d\n",ppfd->cGreenBits); fprintf(pix_file, "cGreenShift = %d\n",ppfd->cGreenShift); fprintf(pix_file, "cBlueBits = %d\n",ppfd->cBlueBits); fprintf(pix_file, "cBlueShift = %d\n",ppfd->cBlueShift); fprintf(pix_file, "cAlphaBits = %d\n",ppfd->cAlphaBits); fprintf(pix_file, "cAlphaShift = %d\n",ppfd->cAlphaShift); fprintf(pix_file, "cAccumBits = %d\n",ppfd->cAccumBits); fprintf(pix_file, "cAccumRedBits = %d\n",ppfd->cAccumRedBits); fprintf(pix_file, "cAccumGreenBits = %d\n",ppfd->cAccumGreenBits); fprintf(pix_file, "cAccumBlueBits = %d\n",ppfd->cAccumBlueBits); fprintf(pix_file, "cAccumAlphaBits = %d\n",ppfd->cAccumAlphaBits); fprintf(pix_file, "cDepthBits = %d\n",ppfd->cDepthBits); fprintf(pix_file, "cStencilBits = %d\n",ppfd->cStencilBits); fprintf(pix_file, "cAuxBuffers = %d\n",ppfd->cAuxBuffers); fprintf(pix_file, "iLayerType = %d\n",ppfd->iLayerType); fprintf(pix_file, "bReserved = %d\n",ppfd->bReserved); fprintf(pix_file, "dwLayerMask = %d\n",ppfd->dwLayerMask); fprintf(pix_file, "dwVisibleMask = %d\n",ppfd->dwVisibleMask); fprintf(pix_file, "dwDamageMask = %d\n",ppfd->dwDamageMask); } fclose(pix_file); #endif qt_valid_pix = qt_pix; if (ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1) { SetLastError(0); return (0); } for (i = 0; i < qt_valid_pix; i++) { if (ppfd->cColorBits > 0 && pix[i].pfd.cColorBits != ppfd->cColorBits) continue; if ((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) continue; if ((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) continue; if ((ppfd->dwFlags & PFD_SUPPORT_GDI) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI)) continue; if ((ppfd->dwFlags & PFD_SUPPORT_OPENGL) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) continue; if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO))) continue; if (ppfd->cDepthBits > 0 && pix[i].pfd.cDepthBits == 0) continue; /* need depth buffer */ if (ppfd->cAlphaBits > 0 && pix[i].pfd.cAlphaBits == 0) continue; /* need alpha buffer */ #if 0 if ((ppfd->cColorBits == 32) && (ppfd->cStencilBits > 0 && pix[i].pfd.cStencilBits == 0)) continue; /* need stencil */ #endif if (ppfd->iPixelType == pix[i].pfd.iPixelType) { best = i + 1; break; } } if (best == -1) { SetLastError(0); return (0); } return (best); } GLAPI int GLAPIENTRY ChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR * ppfd) { return wglChoosePixelFormat(hdc, ppfd); } GLAPI int GLAPIENTRY wglDescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd) { int qt_valid_pix; qt_valid_pix = qt_pix; if (iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ((nBytes != sizeof(PIXELFORMATDESCRIPTOR)) && (nBytes != 0))) { SetLastError(0); return (0); } if (nBytes != 0) *ppfd = pix[iPixelFormat - 1].pfd; return (qt_valid_pix); } GLAPI int GLAPIENTRY DescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd) { return wglDescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd); } GLAPI int GLAPIENTRY wglGetPixelFormat(HDC hdc) { if (curPFD == 0) { SetLastError(0); return (0); } return (curPFD); } GLAPI int GLAPIENTRY GetPixelFormat(HDC hdc) { return wglGetPixelFormat(hdc); } GLAPI BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR * ppfd) { int qt_valid_pix; qt_valid_pix = qt_pix; if (iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) { SetLastError(0); return (FALSE); } curPFD = iPixelFormat; return (TRUE); } GLAPI BOOL GLAPIENTRY wglSwapBuffers(HDC hdc) { if (!ctx) { SetLastError(0); return (FALSE); } fxMesaSwapBuffers(); return (TRUE); } GLAPI BOOL GLAPIENTRY SetPixelFormat(HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR * ppfd) { return wglSetPixelFormat(hdc, iPixelFormat, ppfd); } GLAPI BOOL GLAPIENTRY SwapBuffers(HDC hdc) { return wglSwapBuffers(hdc); } static FIXED FixedFromDouble(double d) { long l = (long) (d * 65536L); return *(FIXED *)&l; } /* ** This was yanked from windows/gdi/wgl.c */ GLAPI BOOL GLAPIENTRY wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase) { int i; GLuint font_list; DWORD size; GLYPHMETRICS gm; HANDLE hBits; LPSTR lpBits; MAT2 mat; int success = TRUE; if (first<0) return FALSE; if (count<0) return FALSE; if (listBase<0) return FALSE; font_list = listBase; mat.eM11 = FixedFromDouble(1); mat.eM12 = FixedFromDouble(0); mat.eM21 = FixedFromDouble(0); mat.eM22 = FixedFromDouble(-1); memset(&gm,0,sizeof(gm)); /* ** If we can't get the glyph outline, it may be because this is a fixed ** font. Try processing it that way. */ if( GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat) == GDI_ERROR ) { return wglUseFontBitmaps_FX( hdc, first, count, listBase ); } /* ** Otherwise process all desired characters. */ for (i = 0; i < count; i++) { DWORD err; glNewList( font_list+i, GL_COMPILE ); /* allocate space for the bitmap/outline */ size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, 0, NULL, &mat); if (size == GDI_ERROR) { glEndList( ); err = GetLastError(); success = FALSE; continue; } hBits = GlobalAlloc(GHND, size+1); lpBits = GlobalLock(hBits); err = GetGlyphOutline(hdc, /* handle to device context */ first + i, /* character to query */ GGO_BITMAP, /* format of data to return */ &gm, /* pointer to structure for metrics*/ size, /* size of buffer for data */ lpBits, /* pointer to buffer for data */ &mat /* pointer to transformation */ /* matrix structure */ ); if (err == GDI_ERROR) { GlobalUnlock(hBits); GlobalFree(hBits); glEndList( ); err = GetLastError(); success = FALSE; continue; } glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY, -gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y, gm.gmCellIncX,gm.gmCellIncY, (const GLubyte * )lpBits); GlobalUnlock(hBits); GlobalFree(hBits); glEndList( ); } return success; } GLAPI BOOL GLAPIENTRY wglDescribeLayerPlane(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR ppfd) { SetLastError(0); return (FALSE); } GLAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, CONST COLORREF *pcr) { SetLastError(0); return (FALSE); } GLAPI BOOL GLAPIENTRY wglRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize) { SetLastError(0); return(FALSE); } GLAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC hdc,int iLayerPlane, int iStart, int cEntries, CONST COLORREF *pcr) { SetLastError(0); return(FALSE); } #endif /* FX */