1 /* $Id: wgl.c,v 1.8 2005/06/13 14:07:15 brianp Exp $ */
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * WGL stuff. Added by Oleg Letsinsky, ajl@ultersys.ru
23 * Some things originated from the 3Dfx WGL functions
27 * This file contains the implementation of the wgl* functions for
28 * Mesa on Windows. Since these functions are provided by Windows in
29 * GDI/OpenGL, we must supply our versions that work with Mesa here.
33 /* We're essentially building part of GDI here, so define this so that
34 * we get the right export linkage. */
38 #include "GL/wmesa.h" /* protos for wmesa* functions */
40 typedef struct wmesa_context
*PWMC
;
43 * Pixel Format Descriptors
46 /* Extend the PFD to include DB flag */
47 struct __pixelformat__
49 PIXELFORMATDESCRIPTOR pfd
;
50 GLboolean doubleBuffered
;
53 /* These are the PFD's supported by this driver. */
54 struct __pixelformat__ pfd
[] =
57 /* Double Buffer, alpha */
60 sizeof(PIXELFORMATDESCRIPTOR
), 1,
61 PFD_DRAW_TO_WINDOW
|PFD_SUPPORT_OPENGL
|
62 PFD_GENERIC_FORMAT
|PFD_DOUBLEBUFFER
|PFD_SWAP_COPY
,
76 /* Single Buffer, alpha */
79 sizeof(PIXELFORMATDESCRIPTOR
), 1,
80 PFD_DRAW_TO_WINDOW
|PFD_SUPPORT_OPENGL
|
96 /* Double Buffer, no alpha */
99 sizeof(PIXELFORMATDESCRIPTOR
), 1,
100 PFD_DRAW_TO_WINDOW
|PFD_SUPPORT_OPENGL
|
101 PFD_GENERIC_FORMAT
|PFD_DOUBLEBUFFER
|PFD_SWAP_COPY
,
115 /* Single Buffer, no alpha */
118 sizeof(PIXELFORMATDESCRIPTOR
), 1,
119 PFD_DRAW_TO_WINDOW
|PFD_SUPPORT_OPENGL
|
136 int npfd
= sizeof(pfd
) / sizeof(pfd
[0]);
148 #define MESAWGL_CTX_MAX_COUNT 20
150 static MesaWglCtx wgl_ctx
[MESAWGL_CTX_MAX_COUNT
];
152 static unsigned ctx_count
= 0;
153 static int ctx_current
= -1;
154 static unsigned curPFD
= 0;
156 WINGDIAPI HGLRC GLAPIENTRY
wglCreateContext(HDC hdc
)
160 if(!(hWnd
= WindowFromDC(hdc
))) {
165 for(i
=0;i
<MESAWGL_CTX_MAX_COUNT
;i
++) {
166 wgl_ctx
[i
].ctx
= NULL
;
167 wgl_ctx
[i
].hdc
= NULL
;
170 for( i
= 0; i
< MESAWGL_CTX_MAX_COUNT
; i
++ ) {
171 if ( wgl_ctx
[i
].ctx
== NULL
) {
173 WMesaCreateContext(hWnd
, NULL
, GL_TRUE
,
174 pfd
[curPFD
-1].doubleBuffered
,
175 pfd
[curPFD
-1].pfd
.cAlphaBits
?
177 if (wgl_ctx
[i
].ctx
== NULL
)
179 wgl_ctx
[i
].hdc
= hdc
;
181 return ((HGLRC
)wgl_ctx
[i
].ctx
);
188 WINGDIAPI BOOL GLAPIENTRY
wglDeleteContext(HGLRC hglrc
)
191 for ( i
= 0; i
< MESAWGL_CTX_MAX_COUNT
; i
++ ) {
192 if ( wgl_ctx
[i
].ctx
== (PWMC
) hglrc
){
193 WMesaMakeCurrent((PWMC
) hglrc
);
194 WMesaDestroyContext();
195 wgl_ctx
[i
].ctx
= NULL
;
196 wgl_ctx
[i
].hdc
= NULL
;
205 WINGDIAPI HGLRC GLAPIENTRY
wglGetCurrentContext(VOID
)
210 return (HGLRC
) wgl_ctx
[ctx_current
].ctx
;
213 WINGDIAPI HDC GLAPIENTRY
wglGetCurrentDC(VOID
)
218 return wgl_ctx
[ctx_current
].hdc
;
221 WINGDIAPI BOOL GLAPIENTRY
wglMakeCurrent(HDC hdc
,HGLRC hglrc
)
225 if (!hdc
|| !hglrc
) {
226 WMesaMakeCurrent(NULL
);
231 for ( i
= 0; i
< MESAWGL_CTX_MAX_COUNT
; i
++ ) {
232 if ( wgl_ctx
[i
].ctx
== (PWMC
) hglrc
) {
233 wgl_ctx
[i
].hdc
= hdc
;
234 WMesaMakeCurrent( (WMesaContext
) hglrc
);
243 WINGDIAPI
int GLAPIENTRY
wglChoosePixelFormat(HDC hdc
,
245 PIXELFORMATDESCRIPTOR
*ppfd
)
247 int i
,best
= -1,bestdelta
= 0x7FFFFFFF,delta
;
250 if(ppfd
->nSize
!= sizeof(PIXELFORMATDESCRIPTOR
) || ppfd
->nVersion
!= 1)
255 for(i
= 0; i
< npfd
;i
++)
259 (ppfd
->dwFlags
& PFD_DRAW_TO_WINDOW
) &&
260 !(pfd
[i
].pfd
.dwFlags
& PFD_DRAW_TO_WINDOW
))
263 (ppfd
->dwFlags
& PFD_DRAW_TO_BITMAP
) &&
264 !(pfd
[i
].pfd
.dwFlags
& PFD_DRAW_TO_BITMAP
))
267 (ppfd
->dwFlags
& PFD_SUPPORT_GDI
) &&
268 !(pfd
[i
].pfd
.dwFlags
& PFD_SUPPORT_GDI
))
271 (ppfd
->dwFlags
& PFD_SUPPORT_OPENGL
) &&
272 !(pfd
[i
].pfd
.dwFlags
& PFD_SUPPORT_OPENGL
))
275 !(ppfd
->dwFlags
& PFD_DOUBLEBUFFER_DONTCARE
) &&
276 ((ppfd
->dwFlags
& PFD_DOUBLEBUFFER
) !=
277 (pfd
[i
].pfd
.dwFlags
& PFD_DOUBLEBUFFER
)))
280 !(ppfd
->dwFlags
& PFD_STEREO_DONTCARE
) &&
281 ((ppfd
->dwFlags
& PFD_STEREO
) !=
282 (pfd
[i
].pfd
.dwFlags
& PFD_STEREO
)))
284 if(ppfd
->iPixelType
!= pfd
[i
].pfd
.iPixelType
)
286 if(ppfd
->cAlphaBits
!= pfd
[i
].pfd
.cAlphaBits
)
288 if(delta
< bestdelta
)
304 WGLAPI
int GLAPIENTRY
wglDescribePixelFormat(HDC hdc
,
307 LPPIXELFORMATDESCRIPTOR ppfd
)
313 if(iPixelFormat
< 1 || iPixelFormat
> npfd
||
314 nBytes
!= sizeof(PIXELFORMATDESCRIPTOR
))
319 *ppfd
= pfd
[iPixelFormat
- 1].pfd
;
323 WINGDIAPI PROC GLAPIENTRY
wglGetProcAddress(LPCSTR lpszProc
)
325 PROC p
= (PROC
) _glapi_get_proc_address((const char *) lpszProc
);
333 WINGDIAPI
int GLAPIENTRY
wglGetPixelFormat(HDC hdc
)
343 WINGDIAPI BOOL GLAPIENTRY
wglSetPixelFormat(HDC hdc
,int iPixelFormat
,
344 PIXELFORMATDESCRIPTOR
*ppfd
)
348 if(iPixelFormat
< 1 || iPixelFormat
> npfd
||
349 ppfd
->nSize
!= sizeof(PIXELFORMATDESCRIPTOR
)) {
353 curPFD
= iPixelFormat
;
357 WINGDIAPI BOOL GLAPIENTRY
wglSwapBuffers(HDC hdc
)
363 if(wgl_ctx
[ctx_current
].ctx
== NULL
) {
371 static FIXED
FixedFromDouble(double d
)
373 long l
= (long) (d
* 65536L);
374 return *(FIXED
*) (void *) &l
;
379 ** This is cribbed from FX/fxwgl.c, and seems to implement support
380 ** for bitmap fonts where the wglUseFontBitmapsA() code implements
381 ** support for outline fonts. In combination they hopefully give
382 ** fairly generic support for fonts.
384 static BOOL
wglUseFontBitmaps_FX(HDC fontDevice
, DWORD firstChar
,
385 DWORD numChars
, DWORD listBase
)
395 VERIFY(GetTextMetrics(fontDevice
, &metric
));
397 dibInfo
= (BITMAPINFO
*) calloc(sizeof(BITMAPINFO
) + sizeof(RGBQUAD
), 1);
398 dibInfo
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
399 dibInfo
->bmiHeader
.biPlanes
= 1;
400 dibInfo
->bmiHeader
.biBitCount
= 1;
401 dibInfo
->bmiHeader
.biCompression
= BI_RGB
;
403 bitDevice
= CreateCompatibleDC(fontDevice
);
405 // Swap fore and back colors so the bitmap has the right polarity
406 tempColor
= GetBkColor(bitDevice
);
407 SetBkColor(bitDevice
, GetTextColor(bitDevice
));
408 SetTextColor(bitDevice
, tempColor
);
410 // Place chars based on base line
411 VERIFY(SetTextAlign(bitDevice
, TA_BASELINE
) != GDI_ERROR
? 1 : 0);
413 for(i
= 0; i
< (int)numChars
; i
++) {
416 int charWidth
,charHeight
,bmapWidth
,bmapHeight
,numBytes
,res
;
421 curChar
= i
+ firstChar
;
423 // Find how high/wide this character is
424 VERIFY(GetTextExtentPoint32(bitDevice
, &curChar
, 1, &size
));
426 // Create the output bitmap
428 charHeight
= size
.cy
;
429 // Round up to the next multiple of 32 bits
430 bmapWidth
= ((charWidth
+ 31) / 32) * 32;
431 bmapHeight
= charHeight
;
432 bitObject
= CreateCompatibleBitmap(bitDevice
,
437 // Assign the output bitmap to the device
438 origBmap
= SelectObject(bitDevice
, bitObject
);
439 (void) VERIFY(origBmap
);
441 VERIFY( PatBlt( bitDevice
, 0, 0, bmapWidth
, bmapHeight
,BLACKNESS
) );
443 // Use our source font on the device
444 VERIFY(SelectObject(bitDevice
, GetCurrentObject(fontDevice
,OBJ_FONT
)));
446 // Draw the character
447 VERIFY(TextOut(bitDevice
, 0, metric
.tmAscent
, &curChar
, 1));
449 // Unselect our bmap object
450 VERIFY(SelectObject(bitDevice
, origBmap
));
452 // Convert the display dependant representation to a 1 bit deep DIB
453 numBytes
= (bmapWidth
* bmapHeight
) / 8;
454 bmap
= malloc(numBytes
);
455 dibInfo
->bmiHeader
.biWidth
= bmapWidth
;
456 dibInfo
->bmiHeader
.biHeight
= bmapHeight
;
457 res
= GetDIBits(bitDevice
, bitObject
, 0, bmapHeight
, bmap
,
462 // Create the GL object
463 glNewList(i
+ listBase
, GL_COMPILE
);
464 glBitmap(bmapWidth
, bmapHeight
, 0.0, metric
.tmDescent
,
470 // Destroy the bmap object
471 DeleteObject(bitObject
);
473 // Deallocate the bitmap data
478 VERIFY(DeleteDC(bitDevice
));
486 WINGDIAPI BOOL GLAPIENTRY
wglUseFontBitmapsA(HDC hdc
, DWORD first
,
487 DWORD count
, DWORD listBase
)
501 font_list
= listBase
;
503 mat
.eM11
= FixedFromDouble(1);
504 mat
.eM12
= FixedFromDouble(0);
505 mat
.eM21
= FixedFromDouble(0);
506 mat
.eM22
= FixedFromDouble(-1);
508 memset(&gm
,0,sizeof(gm
));
511 ** If we can't get the glyph outline, it may be because this is a fixed
512 ** font. Try processing it that way.
514 if( GetGlyphOutline(hdc
, first
, GGO_BITMAP
, &gm
, 0, NULL
, &mat
)
516 return wglUseFontBitmaps_FX( hdc
, first
, count
, listBase
);
520 ** Otherwise process all desired characters.
522 for (i
= 0; i
< (int)count
; i
++) {
525 glNewList( font_list
+i
, GL_COMPILE
);
527 /* allocate space for the bitmap/outline */
528 size
= GetGlyphOutline(hdc
, first
+ i
, GGO_BITMAP
,
530 if (size
== GDI_ERROR
) {
532 err
= GetLastError();
537 hBits
= GlobalAlloc(GHND
, size
+1);
538 lpBits
= GlobalLock(hBits
);
541 GetGlyphOutline(hdc
, /* handle to device context */
542 first
+ i
, /* character to query */
543 GGO_BITMAP
, /* format of data to return */
544 &gm
, /* ptr to structure for metrics*/
545 size
, /* size of buffer for data */
546 lpBits
, /* pointer to buffer for data */
547 &mat
/* pointer to transformation */
548 /* matrix structure */
551 if (err
== GDI_ERROR
) {
556 err
= GetLastError();
561 glBitmap(gm
.gmBlackBoxX
,gm
.gmBlackBoxY
,
562 -gm
.gmptGlyphOrigin
.x
,
563 gm
.gmptGlyphOrigin
.y
,
564 gm
.gmCellIncX
,gm
.gmCellIncY
,
565 (const GLubyte
* )lpBits
);
578 /* NOT IMPLEMENTED YET */
579 WINGDIAPI BOOL GLAPIENTRY
wglCopyContext(HGLRC hglrcSrc
,
583 (void) hglrcSrc
; (void) hglrcDst
; (void) mask
;
587 WINGDIAPI HGLRC GLAPIENTRY
wglCreateLayerContext(HDC hdc
,
590 (void) hdc
; (void) iLayerPlane
;
595 WINGDIAPI BOOL GLAPIENTRY
wglShareLists(HGLRC hglrc1
,
598 (void) hglrc1
; (void) hglrc2
;
603 WINGDIAPI BOOL GLAPIENTRY
wglUseFontBitmapsW(HDC hdc
,
608 (void) hdc
; (void) first
; (void) count
; (void) listBase
;
612 WINGDIAPI BOOL GLAPIENTRY
wglUseFontOutlinesA(HDC hdc
,
619 LPGLYPHMETRICSFLOAT lpgmf
)
621 (void) hdc
; (void) first
; (void) count
;
622 (void) listBase
; (void) deviation
; (void) extrusion
; (void) format
;
628 WINGDIAPI BOOL GLAPIENTRY
wglUseFontOutlinesW(HDC hdc
,
635 LPGLYPHMETRICSFLOAT lpgmf
)
637 (void) hdc
; (void) first
; (void) count
;
638 (void) listBase
; (void) deviation
; (void) extrusion
; (void) format
;
644 WINGDIAPI BOOL GLAPIENTRY
wglDescribeLayerPlane(HDC hdc
,
648 LPLAYERPLANEDESCRIPTOR plpd
)
650 (void) hdc
; (void) iPixelFormat
; (void) iLayerPlane
;
651 (void) nBytes
; (void) plpd
;
656 WINGDIAPI
int GLAPIENTRY
wglSetLayerPaletteEntries(HDC hdc
,
662 (void) hdc
; (void) iLayerPlane
; (void) iStart
;
663 (void) cEntries
; (void) pcr
;
668 WINGDIAPI
int GLAPIENTRY
wglGetLayerPaletteEntries(HDC hdc
,
674 (void) hdc
; (void) iLayerPlane
; (void) iStart
; (void) cEntries
; (void) pcr
;
679 WINGDIAPI BOOL GLAPIENTRY
wglRealizeLayerPalette(HDC hdc
,
683 (void) hdc
; (void) iLayerPlane
; (void) bRealize
;
688 WINGDIAPI BOOL GLAPIENTRY
wglSwapLayerBuffers(HDC hdc
,
691 (void) hdc
; (void) fuPlanes
;