mingw changes (Nolan Leake)
[mesa.git] / src / mesa / drivers / windows / gdi / wgl.c
1 /* $Id: wgl.c,v 1.8 2005/06/13 14:07:15 brianp Exp $ */
2
3 /*
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.
8 *
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.
13 *
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.
17 *
18 */
19
20 /*
21 * File name : wgl.c
22 * WGL stuff. Added by Oleg Letsinsky, ajl@ultersys.ru
23 * Some things originated from the 3Dfx WGL functions
24 */
25
26 /*
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.
30 */
31
32
33 /* We're essentially building part of GDI here, so define this so that
34 * we get the right export linkage. */
35 #define _GDI32_
36 #include <windows.h>
37
38 #include "GL/wmesa.h" /* protos for wmesa* functions */
39
40 typedef struct wmesa_context *PWMC;
41
42 /*
43 * Pixel Format Descriptors
44 */
45
46 /* Extend the PFD to include DB flag */
47 struct __pixelformat__
48 {
49 PIXELFORMATDESCRIPTOR pfd;
50 GLboolean doubleBuffered;
51 };
52
53 /* These are the PFD's supported by this driver. */
54 struct __pixelformat__ pfd[] =
55 {
56 #if 0
57 /* Double Buffer, alpha */
58 {
59 {
60 sizeof(PIXELFORMATDESCRIPTOR), 1,
61 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
62 PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
63 PFD_TYPE_RGBA,
64 24,
65 8, 0,
66 8, 8,
67 8, 16,
68 8, 24,
69 0, 0, 0, 0, 0,
70 16, 8,
71 0, 0, 0,
72 0, 0, 0
73 },
74 GL_TRUE
75 },
76 /* Single Buffer, alpha */
77 {
78 {
79 sizeof(PIXELFORMATDESCRIPTOR), 1,
80 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
81 PFD_GENERIC_FORMAT,
82 PFD_TYPE_RGBA,
83 24,
84 8, 0,
85 8, 8,
86 8, 16,
87 8, 24,
88 0, 0, 0, 0, 0,
89 16, 8,
90 0, 0, 0,
91 0, 0, 0
92 },
93 GL_FALSE
94 },
95 #endif
96 /* Double Buffer, no alpha */
97 {
98 {
99 sizeof(PIXELFORMATDESCRIPTOR), 1,
100 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
101 PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
102 PFD_TYPE_RGBA,
103 24,
104 8, 0,
105 8, 8,
106 8, 16,
107 0, 0,
108 0, 0, 0, 0, 0,
109 16, 8,
110 0, 0, 0,
111 0, 0, 0
112 },
113 GL_TRUE
114 },
115 /* Single Buffer, no alpha */
116 {
117 {
118 sizeof(PIXELFORMATDESCRIPTOR), 1,
119 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
120 PFD_GENERIC_FORMAT,
121 PFD_TYPE_RGBA,
122 24,
123 8, 0,
124 8, 8,
125 8, 16,
126 0, 0,
127 0, 0, 0, 0, 0,
128 16, 8,
129 0, 0, 0,
130 0, 0, 0
131 },
132 GL_FALSE
133 },
134 };
135
136 int npfd = sizeof(pfd) / sizeof(pfd[0]);
137
138
139 /*
140 * Contexts
141 */
142
143 typedef struct {
144 WMesaContext ctx;
145 HDC hdc;
146 } MesaWglCtx;
147
148 #define MESAWGL_CTX_MAX_COUNT 20
149
150 static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT];
151
152 static unsigned ctx_count = 0;
153 static int ctx_current = -1;
154 static unsigned curPFD = 0;
155
156 WINGDIAPI HGLRC GLAPIENTRY wglCreateContext(HDC hdc)
157 {
158 HWND hWnd;
159 int i = 0;
160 if(!(hWnd = WindowFromDC(hdc))) {
161 SetLastError(0);
162 return(NULL);
163 }
164 if (!ctx_count) {
165 for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++) {
166 wgl_ctx[i].ctx = NULL;
167 wgl_ctx[i].hdc = NULL;
168 }
169 }
170 for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) {
171 if ( wgl_ctx[i].ctx == NULL ) {
172 wgl_ctx[i].ctx =
173 WMesaCreateContext(hWnd, NULL, GL_TRUE,
174 pfd[curPFD-1].doubleBuffered,
175 pfd[curPFD-1].pfd.cAlphaBits ?
176 GL_TRUE : GL_FALSE);
177 if (wgl_ctx[i].ctx == NULL)
178 break;
179 wgl_ctx[i].hdc = hdc;
180 ctx_count++;
181 return ((HGLRC)wgl_ctx[i].ctx);
182 }
183 }
184 SetLastError(0);
185 return(NULL);
186 }
187
188 WINGDIAPI BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc)
189 {
190 int i;
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;
197 ctx_count--;
198 return(TRUE);
199 }
200 }
201 SetLastError(0);
202 return(FALSE);
203 }
204
205 WINGDIAPI HGLRC GLAPIENTRY wglGetCurrentContext(VOID)
206 {
207 if (ctx_current < 0)
208 return 0;
209 else
210 return (HGLRC) wgl_ctx[ctx_current].ctx;
211 }
212
213 WINGDIAPI HDC GLAPIENTRY wglGetCurrentDC(VOID)
214 {
215 if (ctx_current < 0)
216 return 0;
217 else
218 return wgl_ctx[ctx_current].hdc;
219 }
220
221 WINGDIAPI BOOL GLAPIENTRY wglMakeCurrent(HDC hdc,HGLRC hglrc)
222 {
223 int i;
224
225 if (!hdc || !hglrc) {
226 WMesaMakeCurrent(NULL);
227 ctx_current = -1;
228 return TRUE;
229 }
230
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 );
235 ctx_current = i;
236 return TRUE;
237 }
238 }
239 return FALSE;
240 }
241
242
243 WINGDIAPI int GLAPIENTRY wglChoosePixelFormat(HDC hdc,
244 CONST
245 PIXELFORMATDESCRIPTOR *ppfd)
246 {
247 int i,best = -1,bestdelta = 0x7FFFFFFF,delta;
248 (void) hdc;
249
250 if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1)
251 {
252 SetLastError(0);
253 return(0);
254 }
255 for(i = 0; i < npfd;i++)
256 {
257 delta = 0;
258 if(
259 (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) &&
260 !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW))
261 continue;
262 if(
263 (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) &&
264 !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP))
265 continue;
266 if(
267 (ppfd->dwFlags & PFD_SUPPORT_GDI) &&
268 !(pfd[i].pfd.dwFlags & PFD_SUPPORT_GDI))
269 continue;
270 if(
271 (ppfd->dwFlags & PFD_SUPPORT_OPENGL) &&
272 !(pfd[i].pfd.dwFlags & PFD_SUPPORT_OPENGL))
273 continue;
274 if(
275 !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
276 ((ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
277 (pfd[i].pfd.dwFlags & PFD_DOUBLEBUFFER)))
278 continue;
279 if(
280 !(ppfd->dwFlags & PFD_STEREO_DONTCARE) &&
281 ((ppfd->dwFlags & PFD_STEREO) !=
282 (pfd[i].pfd.dwFlags & PFD_STEREO)))
283 continue;
284 if(ppfd->iPixelType != pfd[i].pfd.iPixelType)
285 delta++;
286 if(ppfd->cAlphaBits != pfd[i].pfd.cAlphaBits)
287 delta++;
288 if(delta < bestdelta)
289 {
290 best = i + 1;
291 bestdelta = delta;
292 if(bestdelta == 0)
293 break;
294 }
295 }
296 if(best == -1)
297 {
298 SetLastError(0);
299 return(0);
300 }
301 return(best);
302 }
303
304 WGLAPI int GLAPIENTRY wglDescribePixelFormat(HDC hdc,
305 int iPixelFormat,
306 UINT nBytes,
307 LPPIXELFORMATDESCRIPTOR ppfd)
308 {
309 (void) hdc;
310
311 if(ppfd == NULL)
312 return(npfd);
313 if(iPixelFormat < 1 || iPixelFormat > npfd ||
314 nBytes != sizeof(PIXELFORMATDESCRIPTOR))
315 {
316 SetLastError(0);
317 return(0);
318 }
319 *ppfd = pfd[iPixelFormat - 1].pfd;
320 return(npfd);
321 }
322
323 WINGDIAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc)
324 {
325 PROC p = (PROC) _glapi_get_proc_address((const char *) lpszProc);
326 if (p)
327 return p;
328
329 SetLastError(0);
330 return(NULL);
331 }
332
333 WINGDIAPI int GLAPIENTRY wglGetPixelFormat(HDC hdc)
334 {
335 (void) hdc;
336 if(curPFD == 0) {
337 SetLastError(0);
338 return(0);
339 }
340 return(curPFD);
341 }
342
343 WINGDIAPI BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat,
344 PIXELFORMATDESCRIPTOR *ppfd)
345 {
346 (void) hdc;
347
348 if(iPixelFormat < 1 || iPixelFormat > npfd ||
349 ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
350 SetLastError(0);
351 return(FALSE);
352 }
353 curPFD = iPixelFormat;
354 return(TRUE);
355 }
356
357 WINGDIAPI BOOL GLAPIENTRY wglSwapBuffers(HDC hdc)
358 {
359 (void) hdc;
360 if (ctx_current < 0)
361 return FALSE;
362
363 if(wgl_ctx[ctx_current].ctx == NULL) {
364 SetLastError(0);
365 return(FALSE);
366 }
367 WMesaSwapBuffers();
368 return(TRUE);
369 }
370
371 static FIXED FixedFromDouble(double d)
372 {
373 long l = (long) (d * 65536L);
374 return *(FIXED *) (void *) &l;
375 }
376
377
378 /*
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.
383 */
384 static BOOL wglUseFontBitmaps_FX(HDC fontDevice, DWORD firstChar,
385 DWORD numChars, DWORD listBase)
386 {
387 #define VERIFY(a) a
388
389 TEXTMETRIC metric;
390 BITMAPINFO *dibInfo;
391 HDC bitDevice;
392 COLORREF tempColor;
393 int i;
394
395 VERIFY(GetTextMetrics(fontDevice, &metric));
396
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;
402
403 bitDevice = CreateCompatibleDC(fontDevice);
404
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);
409
410 // Place chars based on base line
411 VERIFY(SetTextAlign(bitDevice, TA_BASELINE) != GDI_ERROR ? 1 : 0);
412
413 for(i = 0; i < (int)numChars; i++) {
414 SIZE size;
415 char curChar;
416 int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res;
417 HBITMAP bitObject;
418 HGDIOBJ origBmap;
419 unsigned char *bmap;
420
421 curChar = i + firstChar;
422
423 // Find how high/wide this character is
424 VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size));
425
426 // Create the output bitmap
427 charWidth = size.cx;
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,
433 bmapWidth,
434 bmapHeight);
435 //VERIFY(bitObject);
436
437 // Assign the output bitmap to the device
438 origBmap = SelectObject(bitDevice, bitObject);
439 (void) VERIFY(origBmap);
440
441 VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) );
442
443 // Use our source font on the device
444 VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT)));
445
446 // Draw the character
447 VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1));
448
449 // Unselect our bmap object
450 VERIFY(SelectObject(bitDevice, origBmap));
451
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,
458 dibInfo,
459 DIB_RGB_COLORS);
460 //VERIFY(res);
461
462 // Create the GL object
463 glNewList(i + listBase, GL_COMPILE);
464 glBitmap(bmapWidth, bmapHeight, 0.0, metric.tmDescent,
465 charWidth, 0.0,
466 bmap);
467 glEndList();
468 // CheckGL();
469
470 // Destroy the bmap object
471 DeleteObject(bitObject);
472
473 // Deallocate the bitmap data
474 free(bmap);
475 }
476
477 // Destroy the DC
478 VERIFY(DeleteDC(bitDevice));
479
480 free(dibInfo);
481
482 return TRUE;
483 #undef VERIFY
484 }
485
486 WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsA(HDC hdc, DWORD first,
487 DWORD count, DWORD listBase)
488 {
489 int i;
490 GLuint font_list;
491 DWORD size;
492 GLYPHMETRICS gm;
493 HANDLE hBits;
494 LPSTR lpBits;
495 MAT2 mat;
496 int success = TRUE;
497
498 if (count == 0)
499 return FALSE;
500
501 font_list = listBase;
502
503 mat.eM11 = FixedFromDouble(1);
504 mat.eM12 = FixedFromDouble(0);
505 mat.eM21 = FixedFromDouble(0);
506 mat.eM22 = FixedFromDouble(-1);
507
508 memset(&gm,0,sizeof(gm));
509
510 /*
511 ** If we can't get the glyph outline, it may be because this is a fixed
512 ** font. Try processing it that way.
513 */
514 if( GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat)
515 == GDI_ERROR ) {
516 return wglUseFontBitmaps_FX( hdc, first, count, listBase );
517 }
518
519 /*
520 ** Otherwise process all desired characters.
521 */
522 for (i = 0; i < (int)count; i++) {
523 DWORD err;
524
525 glNewList( font_list+i, GL_COMPILE );
526
527 /* allocate space for the bitmap/outline */
528 size = GetGlyphOutline(hdc, first + i, GGO_BITMAP,
529 &gm, 0, NULL, &mat);
530 if (size == GDI_ERROR) {
531 glEndList( );
532 err = GetLastError();
533 success = FALSE;
534 continue;
535 }
536
537 hBits = GlobalAlloc(GHND, size+1);
538 lpBits = GlobalLock(hBits);
539
540 err =
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 */
549 );
550
551 if (err == GDI_ERROR) {
552 GlobalUnlock(hBits);
553 GlobalFree(hBits);
554
555 glEndList( );
556 err = GetLastError();
557 success = FALSE;
558 continue;
559 }
560
561 glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY,
562 -gm.gmptGlyphOrigin.x,
563 gm.gmptGlyphOrigin.y,
564 gm.gmCellIncX,gm.gmCellIncY,
565 (const GLubyte * )lpBits);
566
567 GlobalUnlock(hBits);
568 GlobalFree(hBits);
569
570 glEndList( );
571 }
572
573 return success;
574 }
575
576
577
578 /* NOT IMPLEMENTED YET */
579 WINGDIAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc,
580 HGLRC hglrcDst,
581 UINT mask)
582 {
583 (void) hglrcSrc; (void) hglrcDst; (void) mask;
584 return(FALSE);
585 }
586
587 WINGDIAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,
588 int iLayerPlane)
589 {
590 (void) hdc; (void) iLayerPlane;
591 SetLastError(0);
592 return(NULL);
593 }
594
595 WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,
596 HGLRC hglrc2)
597 {
598 (void) hglrc1; (void) hglrc2;
599 return(TRUE);
600 }
601
602
603 WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc,
604 DWORD first,
605 DWORD count,
606 DWORD listBase)
607 {
608 (void) hdc; (void) first; (void) count; (void) listBase;
609 return FALSE;
610 }
611
612 WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc,
613 DWORD first,
614 DWORD count,
615 DWORD listBase,
616 FLOAT deviation,
617 FLOAT extrusion,
618 int format,
619 LPGLYPHMETRICSFLOAT lpgmf)
620 {
621 (void) hdc; (void) first; (void) count;
622 (void) listBase; (void) deviation; (void) extrusion; (void) format;
623 (void) lpgmf;
624 SetLastError(0);
625 return(FALSE);
626 }
627
628 WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc,
629 DWORD first,
630 DWORD count,
631 DWORD listBase,
632 FLOAT deviation,
633 FLOAT extrusion,
634 int format,
635 LPGLYPHMETRICSFLOAT lpgmf)
636 {
637 (void) hdc; (void) first; (void) count;
638 (void) listBase; (void) deviation; (void) extrusion; (void) format;
639 (void) lpgmf;
640 SetLastError(0);
641 return(FALSE);
642 }
643
644 WINGDIAPI BOOL GLAPIENTRY wglDescribeLayerPlane(HDC hdc,
645 int iPixelFormat,
646 int iLayerPlane,
647 UINT nBytes,
648 LPLAYERPLANEDESCRIPTOR plpd)
649 {
650 (void) hdc; (void) iPixelFormat; (void) iLayerPlane;
651 (void) nBytes; (void) plpd;
652 SetLastError(0);
653 return(FALSE);
654 }
655
656 WINGDIAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC hdc,
657 int iLayerPlane,
658 int iStart,
659 int cEntries,
660 CONST COLORREF *pcr)
661 {
662 (void) hdc; (void) iLayerPlane; (void) iStart;
663 (void) cEntries; (void) pcr;
664 SetLastError(0);
665 return(0);
666 }
667
668 WINGDIAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC hdc,
669 int iLayerPlane,
670 int iStart,
671 int cEntries,
672 COLORREF *pcr)
673 {
674 (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr;
675 SetLastError(0);
676 return(0);
677 }
678
679 WINGDIAPI BOOL GLAPIENTRY wglRealizeLayerPalette(HDC hdc,
680 int iLayerPlane,
681 BOOL bRealize)
682 {
683 (void) hdc; (void) iLayerPlane; (void) bRealize;
684 SetLastError(0);
685 return(FALSE);
686 }
687
688 WINGDIAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc,
689 UINT fuPlanes)
690 {
691 (void) hdc; (void) fuPlanes;
692 SetLastError(0);
693 return(FALSE);
694 }
695