/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * File name : wgl.c * WGL stuff. Added by Oleg Letsinsky, ajl@ultersys.ru * Some things originated from the 3Dfx WGL functions */ /* * This file contains the implementation of the wgl* functions for * Mesa on Windows. Since these functions are provided by Windows in * GDI/OpenGL, we must supply our versions that work with Mesa here. */ #include <windows.h> #include "main/config.h" #include "glapi/glapi.h" #include "swrast/swrast.h" #include "GL/wmesa.h" /* protos for wmesa* functions */ /* * Pixel Format Descriptors */ /* Extend the PFD to include DB flag */ struct __pixelformat__ { PIXELFORMATDESCRIPTOR pfd; GLboolean doubleBuffered; }; /* These are the PFD's supported by this driver. */ struct __pixelformat__ pfd[] = { #if 0 /* Double Buffer, alpha */ { { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY, PFD_TYPE_RGBA, 24, 8, 0, 8, 8, 8, 16, 8, 24, 0, 0, 0, 0, 0, DEFAULT_SOFTWARE_DEPTH_BITS, 8, 0, 0, 0, 0, 0, 0 }, GL_TRUE }, /* Single Buffer, alpha */ { { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| PFD_GENERIC_FORMAT, PFD_TYPE_RGBA, 24, 8, 0, 8, 8, 8, 16, 8, 24, 0, 0, 0, 0, 0, DEFAULT_SOFTWARE_DEPTH_BITS, 8, 0, 0, 0, 0, 0, 0 }, GL_FALSE }, #endif /* Double Buffer, no alpha */ { { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY, PFD_TYPE_RGBA, 24, 8, 0, 8, 8, 8, 16, 0, 0, 0, 0, 0, 0, 0, DEFAULT_SOFTWARE_DEPTH_BITS, 8, 0, 0, 0, 0, 0, 0 }, GL_TRUE }, /* Single Buffer, no alpha */ { { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| PFD_GENERIC_FORMAT, PFD_TYPE_RGBA, 24, 8, 0, 8, 8, 8, 16, 0, 0, 0, 0, 0, 0, 0, DEFAULT_SOFTWARE_DEPTH_BITS, 8, 0, 0, 0, 0, 0, 0 }, GL_FALSE }, }; int npfd = sizeof(pfd) / sizeof(pfd[0]); /* * Contexts */ typedef struct { WMesaContext ctx; } MesaWglCtx; #define MESAWGL_CTX_MAX_COUNT 20 static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT]; static unsigned ctx_count = 0; static int ctx_current = -1; static unsigned curPFD = 0; static HDC CurrentHDC = 0; WINGDIAPI HGLRC GLAPIENTRY wglCreateContext(HDC hdc) { int i = 0; if (!ctx_count) { for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++) { wgl_ctx[i].ctx = NULL; } } for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { if ( wgl_ctx[i].ctx == NULL ) { wgl_ctx[i].ctx = WMesaCreateContext(hdc, NULL, (GLboolean)GL_TRUE, (GLboolean) (pfd[curPFD-1].doubleBuffered ? GL_TRUE : GL_FALSE), (GLboolean)(pfd[curPFD-1].pfd.cAlphaBits ? GL_TRUE : GL_FALSE) ); if (wgl_ctx[i].ctx == NULL) break; ctx_count++; return ((HGLRC)wgl_ctx[i].ctx); } } SetLastError(0); return(NULL); } WINGDIAPI BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc) { int i; for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { if ( wgl_ctx[i].ctx == (WMesaContext) hglrc ){ WMesaMakeCurrent((WMesaContext) hglrc, NULL); WMesaDestroyContext(wgl_ctx[i].ctx); wgl_ctx[i].ctx = NULL; ctx_count--; return(TRUE); } } SetLastError(0); return(FALSE); } WINGDIAPI HGLRC GLAPIENTRY wglGetCurrentContext(VOID) { if (ctx_current < 0) return 0; else return (HGLRC) wgl_ctx[ctx_current].ctx; } WINGDIAPI HDC GLAPIENTRY wglGetCurrentDC(VOID) { return CurrentHDC; } WINGDIAPI BOOL GLAPIENTRY wglMakeCurrent(HDC hdc, HGLRC hglrc) { int i; CurrentHDC = hdc; if (!hdc || !hglrc) { WMesaMakeCurrent(NULL, NULL); ctx_current = -1; return TRUE; } for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { if ( wgl_ctx[i].ctx == (WMesaContext) hglrc ) { WMesaMakeCurrent( (WMesaContext) hglrc, hdc ); ctx_current = i; return TRUE; } } return FALSE; } WINGDIAPI int GLAPIENTRY wglChoosePixelFormat(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd) { int i,best = -1,bestdelta = 0x7FFFFFFF,delta; (void) hdc; if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1) { SetLastError(0); return(0); } for(i = 0; i < npfd;i++) { delta = 0; if( (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) continue; if( (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) continue; if( (ppfd->dwFlags & PFD_SUPPORT_GDI) && !(pfd[i].pfd.dwFlags & PFD_SUPPORT_GDI)) continue; if( (ppfd->dwFlags & PFD_SUPPORT_OPENGL) && !(pfd[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) continue; if( !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pfd[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; if( !(ppfd->dwFlags & PFD_STEREO_DONTCARE) && ((ppfd->dwFlags & PFD_STEREO) != (pfd[i].pfd.dwFlags & PFD_STEREO))) continue; if(ppfd->iPixelType != pfd[i].pfd.iPixelType) delta++; if(ppfd->cAlphaBits != pfd[i].pfd.cAlphaBits) delta++; if(delta < bestdelta) { best = i + 1; bestdelta = delta; if(bestdelta == 0) break; } } if(best == -1) { SetLastError(0); return(0); } return(best); } WINGDIAPI int GLAPIENTRY wglDescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd) { (void) hdc; if(ppfd == NULL) return(npfd); if(iPixelFormat < 1 || iPixelFormat > npfd || nBytes != sizeof(PIXELFORMATDESCRIPTOR)) { SetLastError(0); return(0); } *ppfd = pfd[iPixelFormat - 1].pfd; return(npfd); } WINGDIAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc) { PROC p = (PROC) _glapi_get_proc_address((const char *) lpszProc); if (p) return p; SetLastError(0); return(NULL); } WINGDIAPI int GLAPIENTRY wglGetPixelFormat(HDC hdc) { (void) hdc; if(curPFD == 0) { SetLastError(0); return(0); } return(curPFD); } WINGDIAPI BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd) { (void) hdc; /* SetPixelFormat (hence wglSetPixelFormat) must not touch ppfd, per * http://msdn.microsoft.com/en-us/library/dd369049(v=vs.85).aspx */ (void) ppfd; if(iPixelFormat < 1 || iPixelFormat > npfd) { SetLastError(0); return(FALSE); } curPFD = iPixelFormat; return(TRUE); } WINGDIAPI BOOL GLAPIENTRY wglSwapBuffers(HDC hdc) { WMesaSwapBuffers(hdc); return TRUE; } static FIXED FixedFromDouble(double d) { long l = (long) (d * 65536L); return *(FIXED *) (void *) &l; } /* ** This is cribbed from FX/fxwgl.c, and seems to implement support ** for bitmap fonts where the wglUseFontBitmapsA() code implements ** support for outline fonts. In combination they hopefully give ** fairly generic support for fonts. */ static BOOL wglUseFontBitmaps_FX(HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase) { #define VERIFY(a) (void)(a) TEXTMETRIC metric; BITMAPINFO *dibInfo; HDC bitDevice; COLORREF tempColor; int i; VERIFY(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 */ VERIFY(SetTextAlign(bitDevice, TA_BASELINE) != GDI_ERROR ? 1 : 0); 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); /* Find how high/wide this character is */ VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size)); /* Create the output bitmap */ charWidth = size.cx; charHeight = size.cy; /* Round up to the next multiple of 32 bits */ bmapWidth = ((charWidth + 31) / 32) * 32; bmapHeight = charHeight; bitObject = CreateCompatibleBitmap(bitDevice, bmapWidth, bmapHeight); /* VERIFY(bitObject); */ /* Assign the output bitmap to the device */ origBmap = SelectObject(bitDevice, bitObject); (void) VERIFY(origBmap); VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) ); /* Use our source font on the device */ VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT))); /* Draw the character */ VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1)); /* Unselect our bmap object */ VERIFY(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); /* VERIFY(res); */ /* Create the GL object */ glNewList(i + listBase, GL_COMPILE); glBitmap(bmapWidth, bmapHeight, 0.0, (GLfloat)metric.tmDescent, (GLfloat)charWidth, 0.0, bmap); glEndList(); /* CheckGL(); */ /* Destroy the bmap object */ DeleteObject(bitObject); /* Deallocate the bitmap data */ free(bmap); } /* Destroy the DC */ VERIFY(DeleteDC(bitDevice)); free(dibInfo); return TRUE; #undef VERIFY } WINGDIAPI 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 (count == 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 < (int)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, /* ptr 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, (GLfloat)-gm.gmptGlyphOrigin.x, (GLfloat)gm.gmptGlyphOrigin.y, (GLfloat)gm.gmCellIncX, (GLfloat)gm.gmCellIncY, (const GLubyte * )lpBits); GlobalUnlock(hBits); GlobalFree(hBits); glEndList( ); } return success; } WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { WMesaShareLists((WMesaContext)hglrc1, (WMesaContext)hglrc2); return(TRUE); } /* NOT IMPLEMENTED YET */ WINGDIAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) { (void) hglrcSrc; (void) hglrcDst; (void) mask; return(FALSE); } WINGDIAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc, int iLayerPlane) { SetLastError(0); if (iLayerPlane == 0) return wglCreateContext( hdc ); return(NULL); } WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase) { (void) hdc; (void) first; (void) count; (void) listBase; return FALSE; } WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf) { (void) hdc; (void) first; (void) count; (void) listBase; (void) deviation; (void) extrusion; (void) format; (void) lpgmf; SetLastError(0); return(FALSE); } WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf) { (void) hdc; (void) first; (void) count; (void) listBase; (void) deviation; (void) extrusion; (void) format; (void) lpgmf; SetLastError(0); return(FALSE); } WINGDIAPI BOOL GLAPIENTRY wglDescribeLayerPlane(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd) { (void) hdc; (void) iPixelFormat; (void) iLayerPlane; (void) nBytes; (void) plpd; SetLastError(0); return(FALSE); } WINGDIAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, CONST COLORREF *pcr) { (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr; SetLastError(0); return(0); } WINGDIAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, COLORREF *pcr) { (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr; SetLastError(0); return(0); } WINGDIAPI BOOL GLAPIENTRY wglRealizeLayerPalette(HDC hdc, int iLayerPlane, BOOL bRealize) { (void) hdc; (void) iLayerPlane; (void) bRealize; SetLastError(0); return(FALSE); } WINGDIAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc, UINT fuPlanes) { (void) hdc; (void) fuPlanes; SetLastError(0); return(FALSE); } WINGDIAPI const char * GLAPIENTRY wglGetExtensionsStringARB(HDC hdc) { return "WGL_ARB_extensions_string"; }