| /* |
| * 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 |
| * Hiroshi Morii |
| * Daniel Borca |
| */ |
| |
| /* fxwgl.c - Microsoft wgl functions emulation for |
| * 3Dfx VooDoo/Mesa interface |
| */ |
| |
| |
| #ifdef _WIN32 |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include <windows.h> |
| #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 "../../glide/fxdrv.h" |
| |
| #define MAX_MESA_ATTRS 20 |
| |
| #if (_MSC_VER >= 1200) |
| #pragma warning( push ) |
| #pragma warning( disable : 4273 ) |
| #endif |
| |
| struct __extensions__ { |
| PROC proc; |
| char *name; |
| }; |
| |
| struct __pixelformat__ { |
| PIXELFORMATDESCRIPTOR pfd; |
| GLint mesaAttr[MAX_MESA_ATTRS]; |
| }; |
| |
| WINGDIAPI void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *); |
| static GLushort gammaTable[3 * 256]; |
| |
| 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} |
| } |
| , |
| /* 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 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 int |
| env_check (const char *var, int val) |
| { |
| const char *env = getenv(var); |
| return (env && (env[0] == val)); |
| } |
| |
| 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; |
| } |
| } |
| |
| /* Finally call the hWNDOldProc, which handles the resize with the |
| * now changed window sizes */ |
| ret = CallWindowProc(hWNDOldProc, hwnd, message, wParam, lParam); |
| |
| return ret; |
| } |
| |
| static void |
| wgl_error (long error) |
| { |
| #define WGL_INVALID_PIXELFORMAT ERROR_INVALID_PIXEL_FORMAT |
| SetLastError(0xC0000000 /* error severity */ |
| |0x00070000 /* error facility (who we are) */ |
| |error); |
| } |
| |
| 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) { |
| wgl_error(WGL_INVALID_PIXELFORMAT); |
| return NULL; |
| } |
| |
| if ((oldProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC)) != __wglMonitor) { |
| hWNDOldProc = oldProc; |
| SetWindowLong(hWnd, GWL_WNDPROC, (LONG)__wglMonitor); |
| } |
| |
| /* always log when debugging, or if user demands */ |
| if (TDFX_DEBUG || env_check("MESA_FX_INFO", 'r')) { |
| freopen("MESA.LOG", "w", stderr); |
| } |
| |
| { |
| RECT cliRect; |
| ShowWindow(hWnd, SW_SHOWNORMAL); |
| SetForegroundWindow(hWnd); |
| Sleep(100); /* a hack for win95 */ |
| if (env_check("MESA_GLX_FX", 'w') && !(GetWindowLong(hWnd, GWL_STYLE) & WS_POPUP)) { |
| /* XXX todo - windowed modes */ |
| error = !(ctx = fxMesaCreateContext((GLuint) hWnd, GR_RESOLUTION_NONE, GR_REFRESH_NONE, pix[curPFD - 1].mesaAttr)); |
| } else { |
| 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 BOOL GLAPIENTRY |
| wglSwapIntervalEXT (int interval) |
| { |
| if (ctx == NULL) { |
| return FALSE; |
| } |
| if (interval < 0) { |
| interval = 0; |
| } else if (interval > 3) { |
| interval = 3; |
| } |
| ctx->swapInterval = interval; |
| return TRUE; |
| } |
| |
| GLAPI int GLAPIENTRY |
| wglGetSwapIntervalEXT (void) |
| { |
| return (ctx == NULL) ? -1 : ctx->swapInterval; |
| } |
| |
| GLAPI BOOL GLAPIENTRY |
| wglGetDeviceGammaRamp3DFX (HDC hdc, LPVOID arrays) |
| { |
| /* gammaTable should be per-context */ |
| memcpy(arrays, gammaTable, 3 * 256 * sizeof(GLushort)); |
| return TRUE; |
| } |
| |
| GLAPI BOOL GLAPIENTRY |
| wglSetDeviceGammaRamp3DFX (HDC hdc, LPVOID arrays) |
| { |
| GLint i, tableSize, inc, index; |
| GLushort *red, *green, *blue; |
| FxU32 gammaTableR[256], gammaTableG[256], gammaTableB[256]; |
| |
| /* gammaTable should be per-context */ |
| memcpy(gammaTable, arrays, 3 * 256 * sizeof(GLushort)); |
| |
| tableSize = FX_grGetInteger(GR_GAMMA_TABLE_ENTRIES); |
| inc = 256 / tableSize; |
| red = (GLushort *)arrays; |
| green = (GLushort *)arrays + 256; |
| blue = (GLushort *)arrays + 512; |
| for (i = 0, index = 0; i < tableSize; i++, index += inc) { |
| gammaTableR[i] = red[index] >> 8; |
| gammaTableG[i] = green[index] >> 8; |
| gammaTableB[i] = blue[index] >> 8; |
| } |
| |
| grLoadGammaTable(tableSize, gammaTableR, gammaTableG, gammaTableB); |
| |
| return TRUE; |
| } |
| |
| typedef void *HPBUFFERARB; |
| |
| /* WGL_ARB_pixel_format */ |
| GLAPI BOOL GLAPIENTRY |
| wglGetPixelFormatAttribivARB (HDC hdc, |
| int iPixelFormat, |
| int iLayerPlane, |
| UINT nAttributes, |
| const int *piAttributes, |
| int *piValues) |
| { |
| SetLastError(0); |
| return FALSE; |
| } |
| |
| GLAPI BOOL GLAPIENTRY |
| wglGetPixelFormatAttribfvARB (HDC hdc, |
| int iPixelFormat, |
| int iLayerPlane, |
| UINT nAttributes, |
| const int *piAttributes, |
| FLOAT *pfValues) |
| { |
| SetLastError(0); |
| return FALSE; |
| } |
| |
| GLAPI BOOL GLAPIENTRY |
| wglChoosePixelFormatARB (HDC hdc, |
| const int *piAttribIList, |
| const FLOAT *pfAttribFList, |
| UINT nMaxFormats, |
| int *piFormats, |
| UINT *nNumFormats) |
| { |
| SetLastError(0); |
| return FALSE; |
| } |
| |
| /* WGL_ARB_render_texture */ |
| GLAPI BOOL GLAPIENTRY |
| wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer) |
| { |
| SetLastError(0); |
| return FALSE; |
| } |
| |
| GLAPI BOOL GLAPIENTRY |
| wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer) |
| { |
| SetLastError(0); |
| return FALSE; |
| } |
| |
| GLAPI BOOL GLAPIENTRY |
| wglSetPbufferAttribARB (HPBUFFERARB hPbuffer, |
| const int *piAttribList) |
| { |
| SetLastError(0); |
| return FALSE; |
| } |
| |
| /* WGL_ARB_pbuffer */ |
| GLAPI HPBUFFERARB GLAPIENTRY |
| wglCreatePbufferARB (HDC hDC, |
| int iPixelFormat, |
| int iWidth, |
| int iHeight, |
| const int *piAttribList) |
| { |
| SetLastError(0); |
| return NULL; |
| } |
| |
| GLAPI HDC GLAPIENTRY |
| wglGetPbufferDCARB (HPBUFFERARB hPbuffer) |
| { |
| SetLastError(0); |
| return NULL; |
| } |
| |
| GLAPI int GLAPIENTRY |
| wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC) |
| { |
| SetLastError(0); |
| return -1; |
| } |
| |
| GLAPI BOOL GLAPIENTRY |
| wglDestroyPbufferARB (HPBUFFERARB hPbuffer) |
| { |
| SetLastError(0); |
| return FALSE; |
| } |
| |
| GLAPI BOOL GLAPIENTRY |
| wglQueryPbufferARB (HPBUFFERARB hPbuffer, |
| int iAttribute, |
| int *piValue) |
| { |
| SetLastError(0); |
| return FALSE; |
| } |
| |
| GLAPI const char * GLAPIENTRY |
| wglGetExtensionsStringEXT (void) |
| { |
| return "WGL_3DFX_gamma_control " |
| "WGL_EXT_swap_control " |
| "WGL_EXT_extensions_string WGL_ARB_extensions_string" |
| /*WGL_ARB_pixel_format WGL_ARB_render_texture WGL_ARB_pbuffer*/; |
| } |
| |
| GLAPI const char * GLAPIENTRY |
| wglGetExtensionsStringARB (HDC hdc) |
| { |
| return wglGetExtensionsStringEXT(); |
| } |
| |
| static struct { |
| const char *name; |
| PROC func; |
| } wgl_ext[] = { |
| {"wglGetExtensionsStringARB", (PROC)wglGetExtensionsStringARB}, |
| {"wglGetExtensionsStringEXT", (PROC)wglGetExtensionsStringEXT}, |
| {"wglSwapIntervalEXT", (PROC)wglSwapIntervalEXT}, |
| {"wglGetSwapIntervalEXT", (PROC)wglGetSwapIntervalEXT}, |
| {"wglGetDeviceGammaRamp3DFX", (PROC)wglGetDeviceGammaRamp3DFX}, |
| {"wglSetDeviceGammaRamp3DFX", (PROC)wglSetDeviceGammaRamp3DFX}, |
| /* WGL_ARB_pixel_format */ |
| {"wglGetPixelFormatAttribivARB", (PROC)wglGetPixelFormatAttribivARB}, |
| {"wglGetPixelFormatAttribfvARB", (PROC)wglGetPixelFormatAttribfvARB}, |
| {"wglChoosePixelFormatARB", (PROC)wglChoosePixelFormatARB}, |
| /* WGL_ARB_render_texture */ |
| {"wglBindTexImageARB", (PROC)wglBindTexImageARB}, |
| {"wglReleaseTexImageARB", (PROC)wglReleaseTexImageARB}, |
| {"wglSetPbufferAttribARB", (PROC)wglSetPbufferAttribARB}, |
| /* WGL_ARB_pbuffer */ |
| {"wglCreatePbufferARB", (PROC)wglCreatePbufferARB}, |
| {"wglGetPbufferDCARB", (PROC)wglGetPbufferDCARB}, |
| {"wglReleasePbufferDCARB", (PROC)wglReleasePbufferDCARB}, |
| {"wglDestroyPbufferARB", (PROC)wglDestroyPbufferARB}, |
| {"wglQueryPbufferARB", (PROC)wglQueryPbufferARB}, |
| {NULL, NULL} |
| }; |
| |
| GLAPI PROC GLAPIENTRY |
| wglGetProcAddress (LPCSTR lpszProc) |
| { |
| int i; |
| PROC p = (PROC)_glapi_get_proc_address((const char *)lpszProc); |
| |
| /* we can't BlendColor. work around buggy applications */ |
| if (p && strcmp(lpszProc, "glBlendColor") |
| && strcmp(lpszProc, "glBlendColorEXT")) |
| return p; |
| |
| for (i = 0; wgl_ext[i].name; i++) { |
| if (!strcmp(lpszProc, wgl_ext[i].name)) { |
| return wgl_ext[i].func; |
| } |
| } |
| |
| SetLastError(0); |
| return NULL; |
| } |
| |
| GLAPI PROC GLAPIENTRY |
| wglGetDefaultProcAddress (LPCSTR lpszProc) |
| { |
| 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; |
| } |
| |
| static int |
| pfd_tablen (void) |
| { |
| /* we should take an envvar for `fxMesaSelectCurrentBoard' */ |
| return (fxMesaSelectCurrentBoard(0) < GR_SSTTYPE_Voodoo4) |
| ? 2 /* only 16bit entries */ |
| : sizeof(pix) / sizeof(pix[0]); /* full table */ |
| } |
| |
| GLAPI int GLAPIENTRY |
| wglChoosePixelFormat (HDC hdc, const PIXELFORMATDESCRIPTOR *ppfd) |
| { |
| int i, best = -1, qt_valid_pix; |
| PIXELFORMATDESCRIPTOR pfd = *ppfd; |
| |
| qt_valid_pix = pfd_tablen(); |
| |
| #if 1 || QUAKE2 || GORE |
| /* QUAKE2: 24+32 */ |
| /* GORE : 24+16 */ |
| if ((pfd.cColorBits == 24) || (pfd.cColorBits == 32)) { |
| /* the first 2 entries are 16bit */ |
| pfd.cColorBits = (qt_valid_pix > 2) ? 32 : 16; |
| } |
| if (pfd.cColorBits == 32) { |
| pfd.cDepthBits = 24; |
| } else if (pfd.cColorBits == 16) { |
| pfd.cDepthBits = 16; |
| } |
| #endif |
| |
| if (pfd.nSize != sizeof(PIXELFORMATDESCRIPTOR) || pfd.nVersion != 1) { |
| SetLastError(0); |
| return 0; |
| } |
| |
| for (i = 0; i < qt_valid_pix; i++) { |
| if (pfd.cColorBits > 0 && pix[i].pfd.cColorBits != pfd.cColorBits) |
| continue; |
| |
| if ((pfd.dwFlags & PFD_DRAW_TO_WINDOW) |
| && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) continue; |
| if ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) |
| && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) continue; |
| if ((pfd.dwFlags & PFD_SUPPORT_GDI) |
| && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI)) continue; |
| if ((pfd.dwFlags & PFD_SUPPORT_OPENGL) |
| && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) continue; |
| if (!(pfd.dwFlags & PFD_DOUBLEBUFFER_DONTCARE) |
| && ((pfd.dwFlags & PFD_DOUBLEBUFFER) != |
| (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; |
| #if 1 /* Doom3 fails here! */ |
| if (!(pfd.dwFlags & PFD_STEREO_DONTCARE) |
| && ((pfd.dwFlags & PFD_STEREO) != |
| (pix[i].pfd.dwFlags & PFD_STEREO))) continue; |
| #endif |
| |
| if (pfd.cDepthBits > 0 && pix[i].pfd.cDepthBits == 0) |
| continue; /* need depth buffer */ |
| |
| if (pfd.cAlphaBits > 0 && pix[i].pfd.cAlphaBits == 0) |
| continue; /* need alpha buffer */ |
| |
| #if 0 /* regression bug? */ |
| if (pfd.cStencilBits > 0 && pix[i].pfd.cStencilBits == 0) |
| continue; /* need stencil buffer */ |
| #endif |
| |
| if (pfd.iPixelType == pix[i].pfd.iPixelType) { |
| best = i + 1; |
| break; |
| } |
| } |
| |
| if (best == -1) { |
| FILE *err = fopen("MESA.LOG", "w"); |
| if (err != NULL) { |
| fprintf(err, "wglChoosePixelFormat failed\n"); |
| fprintf(err, "\tnSize = %d\n", ppfd->nSize); |
| fprintf(err, "\tnVersion = %d\n", ppfd->nVersion); |
| fprintf(err, "\tdwFlags = %lu\n", ppfd->dwFlags); |
| fprintf(err, "\tiPixelType = %d\n", ppfd->iPixelType); |
| fprintf(err, "\tcColorBits = %d\n", ppfd->cColorBits); |
| fprintf(err, "\tcRedBits = %d\n", ppfd->cRedBits); |
| fprintf(err, "\tcRedShift = %d\n", ppfd->cRedShift); |
| fprintf(err, "\tcGreenBits = %d\n", ppfd->cGreenBits); |
| fprintf(err, "\tcGreenShift = %d\n", ppfd->cGreenShift); |
| fprintf(err, "\tcBlueBits = %d\n", ppfd->cBlueBits); |
| fprintf(err, "\tcBlueShift = %d\n", ppfd->cBlueShift); |
| fprintf(err, "\tcAlphaBits = %d\n", ppfd->cAlphaBits); |
| fprintf(err, "\tcAlphaShift = %d\n", ppfd->cAlphaShift); |
| fprintf(err, "\tcAccumBits = %d\n", ppfd->cAccumBits); |
| fprintf(err, "\tcAccumRedBits = %d\n", ppfd->cAccumRedBits); |
| fprintf(err, "\tcAccumGreenBits = %d\n", ppfd->cAccumGreenBits); |
| fprintf(err, "\tcAccumBlueBits = %d\n", ppfd->cAccumBlueBits); |
| fprintf(err, "\tcAccumAlphaBits = %d\n", ppfd->cAccumAlphaBits); |
| fprintf(err, "\tcDepthBits = %d\n", ppfd->cDepthBits); |
| fprintf(err, "\tcStencilBits = %d\n", ppfd->cStencilBits); |
| fprintf(err, "\tcAuxBuffers = %d\n", ppfd->cAuxBuffers); |
| fprintf(err, "\tiLayerType = %d\n", ppfd->iLayerType); |
| fprintf(err, "\tbReserved = %d\n", ppfd->bReserved); |
| fprintf(err, "\tdwLayerMask = %lu\n", ppfd->dwLayerMask); |
| fprintf(err, "\tdwVisibleMask = %lu\n", ppfd->dwVisibleMask); |
| fprintf(err, "\tdwDamageMask = %lu\n", ppfd->dwDamageMask); |
| fclose(err); |
| } |
| |
| 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 = pfd_tablen(); |
| |
| if (iPixelFormat < 1 || iPixelFormat > qt_valid_pix || |
| ((nBytes != sizeof(PIXELFORMATDESCRIPTOR)) && (nBytes != 0))) { |
| SetLastError(0); |
| return qt_valid_pix; |
| } |
| |
| 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 = pfd_tablen(); |
| |
| if (iPixelFormat < 1 || iPixelFormat > qt_valid_pix) { |
| if (ppfd == NULL) { |
| PIXELFORMATDESCRIPTOR my_pfd; |
| if (!wglDescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &my_pfd)) { |
| SetLastError(0); |
| return FALSE; |
| } |
| } else if (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) |
| { |
| struct { |
| FIXED f; |
| long l; |
| } pun; |
| pun.l = (long)(d * 65536L); |
| return pun.f; |
| } |
| |
| /* |
| ** 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; |
| |
| 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, 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; |
| } |
| |
| |
| /*************************************************************************** |
| * [dBorca] simplistic ICD implementation, based on ICD code by Gregor Anich |
| */ |
| |
| typedef struct _icdTable { |
| DWORD size; |
| PROC table[336]; |
| } ICDTABLE, *PICDTABLE; |
| |
| #ifdef USE_MGL_NAMESPACE |
| #define GL_FUNC(func) mgl##func |
| #else |
| #define GL_FUNC(func) gl##func |
| #endif |
| |
| static ICDTABLE icdTable = { 336, { |
| #define ICD_ENTRY(func) (PROC)GL_FUNC(func), |
| #include "../icd/icdlist.h" |
| #undef ICD_ENTRY |
| } }; |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvCopyContext (HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) |
| { |
| return wglCopyContext(hglrcSrc, hglrcDst, mask); |
| } |
| |
| |
| GLAPI HGLRC GLAPIENTRY |
| DrvCreateContext (HDC hdc) |
| { |
| return wglCreateContext(hdc); |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvDeleteContext (HGLRC hglrc) |
| { |
| return wglDeleteContext(hglrc); |
| } |
| |
| |
| GLAPI HGLRC GLAPIENTRY |
| DrvCreateLayerContext (HDC hdc, int iLayerPlane) |
| { |
| return wglCreateContext(hdc); |
| } |
| |
| |
| GLAPI PICDTABLE GLAPIENTRY |
| DrvSetContext (HDC hdc, HGLRC hglrc, void *callback) |
| { |
| return wglMakeCurrent(hdc, hglrc) ? &icdTable : NULL; |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvReleaseContext (HGLRC hglrc) |
| { |
| return TRUE; |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvShareLists (HGLRC hglrc1, HGLRC hglrc2) |
| { |
| return wglShareLists(hglrc1, hglrc2); |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvDescribeLayerPlane (HDC hdc, int iPixelFormat, |
| int iLayerPlane, UINT nBytes, |
| LPLAYERPLANEDESCRIPTOR plpd) |
| { |
| return wglDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd); |
| } |
| |
| |
| GLAPI int GLAPIENTRY |
| DrvSetLayerPaletteEntries (HDC hdc, int iLayerPlane, |
| int iStart, int cEntries, CONST COLORREF *pcr) |
| { |
| return wglSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); |
| } |
| |
| |
| GLAPI int GLAPIENTRY |
| DrvGetLayerPaletteEntries (HDC hdc, int iLayerPlane, |
| int iStart, int cEntries, COLORREF *pcr) |
| { |
| return wglGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvRealizeLayerPalette (HDC hdc, int iLayerPlane, BOOL bRealize) |
| { |
| return wglRealizeLayerPalette(hdc, iLayerPlane, bRealize); |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvSwapLayerBuffers (HDC hdc, UINT fuPlanes) |
| { |
| return wglSwapLayerBuffers(hdc, fuPlanes); |
| } |
| |
| GLAPI int GLAPIENTRY |
| DrvDescribePixelFormat (HDC hdc, int iPixelFormat, UINT nBytes, |
| LPPIXELFORMATDESCRIPTOR ppfd) |
| { |
| return wglDescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd); |
| } |
| |
| |
| GLAPI PROC GLAPIENTRY |
| DrvGetProcAddress (LPCSTR lpszProc) |
| { |
| return wglGetProcAddress(lpszProc); |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvSetPixelFormat (HDC hdc, int iPixelFormat) |
| { |
| return wglSetPixelFormat(hdc, iPixelFormat, NULL); |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvSwapBuffers (HDC hdc) |
| { |
| return wglSwapBuffers(hdc); |
| } |
| |
| |
| GLAPI BOOL GLAPIENTRY |
| DrvValidateVersion (DWORD version) |
| { |
| (void)version; |
| return TRUE; |
| } |
| |
| |
| #if (_MSC_VER >= 1200) |
| #pragma warning( pop ) |
| #endif |
| |
| #endif /* FX */ |