blob: ce76ecd15689a6116561fb973f52206c4268f2de [file] [log] [blame]
/*
* 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 */