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