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