Tizen 2.0 Release
[profile/ivi/osmesa.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 }