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