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