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