1 /*
2  * File: indirect.c
3  * Purpose: A GLX implementation that uses Windows OpenGL library
4  *
5  * Authors: Alexander Gottwald
6  *          Jon TURNEY
7  *
8  * Copyright (c) Jon TURNEY 2009
9  * Copyright (c) Alexander Gottwald 2004
10  *
11  * Portions of this file are copied from GL/apple/indirect.c,
12  * which contains the following copyright:
13  *
14  * Copyright (c) 2007, 2008, 2009 Apple Inc.
15  * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
16  * Copyright (c) 2002 Greg Parker. All Rights Reserved.
17  *
18  * Portions of this file are copied from Mesa's xf86glx.c,
19  * which contains the following copyright:
20  *
21  * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
22  * All Rights Reserved.
23  *
24  *
25  * Permission is hereby granted, free of charge, to any person obtaining a
26  * copy of this software and associated documentation files (the "Software"),
27  * to deal in the Software without restriction, including without limitation
28  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
29  * and/or sell copies of the Software, and to permit persons to whom the
30  * Software is furnished to do so, subject to the following conditions:
31  *
32  * The above copyright notice and this permission notice shall be included in
33  * all copies or substantial portions of the Software.
34  *
35  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
39  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
40  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
41  * DEALINGS IN THE SOFTWARE.
42  */
43 
44 /*
45   TODO:
46   - hook up remaining unimplemented extensions
47   - research what guarantees glXWaitX, glXWaitGL are supposed to offer, and implement then
48     using GdiFlush and/or glFinish
49   - pbuffer clobbering: we don't get async notification, but can we arrange to emit the
50     event when we notice it's been clobbered? at the very least, check if it's been clobbered
51     before using it?
52   - XGetImage() doesn't work on pixmaps; need to do more work to make the format and location
53     of the native pixmap compatible
54   - implement GLX_EXT_texture_from_pixmap in terms of WGL_ARB_render_texture
55     (not quite straightforward as we will have to create a pbuffer and copy the pixmap texture
56      into it)
57 */
58 
59 /*
60   Assumptions:
61   - the __GLXConfig * we get handed back ones we are made (so we can extend the structure
62     with privates) and never get created inside the GLX core
63 */
64 
65 /*
66   MSDN clarifications:
67 
68   It says SetPixelFormat()'s PIXELFORMATDESCRIPTOR pointer argument has no effect
69   except on metafiles, this seems to mean that as it's ok to supply NULL if the DC
70   is not for a metafile
71 
72   wglMakeCurrent ignores the hdc if hglrc is NULL, so wglMakeCurrent(NULL, NULL)
73   is used to make no context current
74 
75 */
76 
77 #ifdef HAVE_XWIN_CONFIG_H
78 #include <xwin-config.h>
79 #endif
80 
81 #include "glwindows.h"
82 #include <glx/glxserver.h>
83 #include <glx/glxutil.h>
84 #include <GL/glxtokens.h>
85 
86 #include <winpriv.h>
87 #include <wgl_ext_api.h>
88 #include <winglobals.h>
89 #include <indirect.h>
90 
91 /* Not yet in w32api */
92 #ifndef PFD_SUPPORT_DIRECTDRAW
93 #define PFD_SUPPORT_DIRECTDRAW   0x00002000
94 #endif
95 #ifndef PFD_DIRECT3D_ACCELERATED
96 #define PFD_DIRECT3D_ACCELERATED 0x00004000
97 #endif
98 #ifndef PFD_SUPPORT_COMPOSITION
99 #define PFD_SUPPORT_COMPOSITION  0x00008000
100 #endif
101 
102 
103 typedef struct  {
104     int notOpenGL;
105     int unknownPixelType;
106     int unaccelerated;
107 } PixelFormatRejectStats;
108 
109 /* ---------------------------------------------------------------------- */
110 /*
111  * Various debug helpers
112  */
113 
114 #define GLWIN_DEBUG_HWND(hwnd)  \
115     if (glxWinDebugSettings.dumpHWND) { \
116         char buffer[1024]; \
117         if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; \
118         GLWIN_DEBUG_MSG("Got HWND %p for window '%s'", hwnd, buffer); \
119     }
120 
121 glxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0 };
122 
123 static void
glxWinInitDebugSettings(void)124 glxWinInitDebugSettings(void)
125 {
126     char *envptr;
127 
128     envptr = getenv("GLWIN_ENABLE_DEBUG");
129     if (envptr != NULL)
130         glxWinDebugSettings.enableDebug = (atoi(envptr) == 1);
131 
132     envptr = getenv("GLWIN_ENABLE_TRACE");
133     if (envptr != NULL)
134         glxWinDebugSettings.enableTrace = (atoi(envptr) == 1);
135 
136     envptr = getenv("GLWIN_DUMP_PFD");
137     if (envptr != NULL)
138         glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1);
139 
140     envptr = getenv("GLWIN_DUMP_HWND");
141     if (envptr != NULL)
142         glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1);
143 
144     envptr = getenv("GLWIN_DUMP_DC");
145     if (envptr != NULL)
146         glxWinDebugSettings.dumpDC = (atoi(envptr) == 1);
147 
148     envptr = getenv("GLWIN_ENABLE_GLCALL_TRACE");
149     if (envptr != NULL)
150         glxWinDebugSettings.enableGLcallTrace = (atoi(envptr) == 1);
151 
152     envptr = getenv("GLWIN_ENABLE_WGLCALL_TRACE");
153     if (envptr != NULL)
154         glxWinDebugSettings.enableWGLcallTrace = (atoi(envptr) == 1);
155 
156     envptr = getenv("GLWIN_DEBUG_ALL");
157     if (envptr != NULL) {
158         glxWinDebugSettings.enableDebug = 1;
159         glxWinDebugSettings.enableTrace = 1;
160         glxWinDebugSettings.dumpPFD = 1;
161         glxWinDebugSettings.dumpHWND = 1;
162         glxWinDebugSettings.dumpDC = 1;
163         glxWinDebugSettings.enableGLcallTrace = 1;
164         glxWinDebugSettings.enableWGLcallTrace = 1;
165     }
166 }
167 
168 static
169 const char *
glxWinErrorMessage(void)170 glxWinErrorMessage(void)
171 {
172     static char errorbuffer[1024];
173     unsigned int last_error = GetLastError();
174 
175     if (!FormatMessage
176         (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
177          FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, last_error, 0,
178          (LPTSTR) &errorbuffer, sizeof(errorbuffer), NULL)) {
179         snprintf(errorbuffer, sizeof(errorbuffer), "Unknown error");
180     }
181 
182     if ((errorbuffer[strlen(errorbuffer) - 1] == '\n') ||
183         (errorbuffer[strlen(errorbuffer) - 1] == '\r'))
184         errorbuffer[strlen(errorbuffer) - 1] = 0;
185 
186     sprintf(errorbuffer + strlen(errorbuffer), " (%08x)", last_error);
187 
188     return errorbuffer;
189 }
190 
191 static void pfdOut(const PIXELFORMATDESCRIPTOR * pfd);
192 
193 #define DUMP_PFD_FLAG(flag) \
194     if (pfd->dwFlags & flag) { \
195         ErrorF("%s%s", pipesym, #flag); \
196         pipesym = " | "; \
197     }
198 
199 static void
pfdOut(const PIXELFORMATDESCRIPTOR * pfd)200 pfdOut(const PIXELFORMATDESCRIPTOR * pfd)
201 {
202     const char *pipesym = "";   /* will be set after first flag dump */
203 
204     ErrorF("PIXELFORMATDESCRIPTOR:\n");
205     ErrorF("nSize = %u\n", pfd->nSize);
206     ErrorF("nVersion = %u\n", pfd->nVersion);
207     ErrorF("dwFlags = %u = {", (unsigned int)pfd->dwFlags);
208     DUMP_PFD_FLAG(PFD_DOUBLEBUFFER);
209     DUMP_PFD_FLAG(PFD_STEREO);
210     DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW);
211     DUMP_PFD_FLAG(PFD_DRAW_TO_BITMAP);
212     DUMP_PFD_FLAG(PFD_SUPPORT_GDI);
213     DUMP_PFD_FLAG(PFD_SUPPORT_OPENGL);
214     DUMP_PFD_FLAG(PFD_GENERIC_FORMAT);
215     DUMP_PFD_FLAG(PFD_NEED_PALETTE);
216     DUMP_PFD_FLAG(PFD_NEED_SYSTEM_PALETTE);
217     DUMP_PFD_FLAG(PFD_SWAP_EXCHANGE);
218     DUMP_PFD_FLAG(PFD_SWAP_COPY);
219     DUMP_PFD_FLAG(PFD_SWAP_LAYER_BUFFERS);
220     DUMP_PFD_FLAG(PFD_GENERIC_ACCELERATED);
221     DUMP_PFD_FLAG(PFD_SUPPORT_DIRECTDRAW);
222     DUMP_PFD_FLAG(PFD_DIRECT3D_ACCELERATED);
223     DUMP_PFD_FLAG(PFD_SUPPORT_COMPOSITION);
224     DUMP_PFD_FLAG(PFD_DEPTH_DONTCARE);
225     DUMP_PFD_FLAG(PFD_DOUBLEBUFFER_DONTCARE);
226     DUMP_PFD_FLAG(PFD_STEREO_DONTCARE);
227     ErrorF("}\n");
228 
229     ErrorF("iPixelType = %hu = %s\n", pfd->iPixelType,
230            (pfd->iPixelType ==
231             PFD_TYPE_RGBA ? "PFD_TYPE_RGBA" : "PFD_TYPE_COLORINDEX"));
232     ErrorF("cColorBits = %hhu\n", pfd->cColorBits);
233     ErrorF("cRedBits = %hhu\n", pfd->cRedBits);
234     ErrorF("cRedShift = %hhu\n", pfd->cRedShift);
235     ErrorF("cGreenBits = %hhu\n", pfd->cGreenBits);
236     ErrorF("cGreenShift = %hhu\n", pfd->cGreenShift);
237     ErrorF("cBlueBits = %hhu\n", pfd->cBlueBits);
238     ErrorF("cBlueShift = %hhu\n", pfd->cBlueShift);
239     ErrorF("cAlphaBits = %hhu\n", pfd->cAlphaBits);
240     ErrorF("cAlphaShift = %hhu\n", pfd->cAlphaShift);
241     ErrorF("cAccumBits = %hhu\n", pfd->cAccumBits);
242     ErrorF("cAccumRedBits = %hhu\n", pfd->cAccumRedBits);
243     ErrorF("cAccumGreenBits = %hhu\n", pfd->cAccumGreenBits);
244     ErrorF("cAccumBlueBits = %hhu\n", pfd->cAccumBlueBits);
245     ErrorF("cAccumAlphaBits = %hhu\n", pfd->cAccumAlphaBits);
246     ErrorF("cDepthBits = %hhu\n", pfd->cDepthBits);
247     ErrorF("cStencilBits = %hhu\n", pfd->cStencilBits);
248     ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers);
249     ErrorF("iLayerType = %hhu\n", pfd->iLayerType);
250     ErrorF("bReserved = %hhu\n", pfd->bReserved);
251     ErrorF("dwLayerMask = %u\n", (unsigned int)pfd->dwLayerMask);
252     ErrorF("dwVisibleMask = %u\n", (unsigned int)pfd->dwVisibleMask);
253     ErrorF("dwDamageMask = %u\n", (unsigned int)pfd->dwDamageMask);
254     ErrorF("\n");
255 }
256 
257 static const char *
visual_class_name(int cls)258 visual_class_name(int cls)
259 {
260     switch (cls) {
261     case GLX_STATIC_COLOR:
262         return "StaticColor";
263     case GLX_PSEUDO_COLOR:
264         return "PseudoColor";
265     case GLX_STATIC_GRAY:
266         return "StaticGray";
267     case GLX_GRAY_SCALE:
268         return "GrayScale";
269     case GLX_TRUE_COLOR:
270         return "TrueColor";
271     case GLX_DIRECT_COLOR:
272         return "DirectColor";
273     default:
274         return "-none-";
275     }
276 }
277 
278 static const char *
swap_method_name(int mthd)279 swap_method_name(int mthd)
280 {
281     switch (mthd) {
282     case GLX_SWAP_EXCHANGE_OML:
283         return "xchg";
284     case GLX_SWAP_COPY_OML:
285         return "copy";
286     case GLX_SWAP_UNDEFINED_OML:
287         return "    ";
288     default:
289         return "????";
290     }
291 }
292 
293 static void
fbConfigsDump(unsigned int n,__GLXconfig * c,PixelFormatRejectStats * rejects)294 fbConfigsDump(unsigned int n, __GLXconfig * c, PixelFormatRejectStats *rejects)
295 {
296     LogMessage(X_INFO, "%d fbConfigs\n", n);
297     LogMessage(X_INFO, "ignored pixel formats: %d not OpenGL, %d unknown pixel type, %d unaccelerated\n",
298                rejects->notOpenGL, rejects->unknownPixelType, rejects->unaccelerated);
299 
300     if (g_iLogVerbose < 3)
301         return;
302 
303     ErrorF
304         ("pxf vis  fb                      render         Ste                     aux    accum        MS    drawable             Group/ sRGB\n");
305     ErrorF
306         ("idx  ID  ID VisualType Depth Lvl RGB CI DB Swap reo  R  G  B  A   Z  S  buf AR AG AB AA  bufs num  W P Pb  Float Trans Caveat cap \n");
307     ErrorF
308         ("----------------------------------------------------------------------------------------------------------------------------------\n");
309 
310     while (c != NULL) {
311         unsigned int i = ((GLXWinConfig *) c)->pixelFormatIndex;
312 
313         const char *float_col = ".";
314         if (c->renderType & GLX_RGBA_FLOAT_BIT_ARB) float_col = "s";
315         if (c->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) float_col = "u";
316 
317         ErrorF("%3d %3x %3x "
318                "%-11s"
319                " %3d %3d   %s   %s  %s %s  %s  "
320                "%2d %2d %2d %2d  "
321                "%2d %2d  "
322                "%2d  "
323                "%2d %2d %2d %2d"
324                "   %2d   %2d"
325                "  %s %s %s "
326                "    %s   "
327                "  %s   "
328                "  %d %s "
329                "  %s"
330                "\n",
331                i, c->visualID, c->fbconfigID,
332                visual_class_name(c->visualType),
333                c->rgbBits ? c->rgbBits : c->indexBits,
334                c->level,
335                (c->renderType & GLX_RGBA_BIT) ? "y" : ".",
336                (c->renderType & GLX_COLOR_INDEX_BIT) ? "y" : ".",
337                c->doubleBufferMode ? "y" : ".",
338                swap_method_name(c->swapMethod),
339                c->stereoMode ? "y" : ".",
340                c->redBits, c->greenBits, c->blueBits, c->alphaBits,
341                c->depthBits, c->stencilBits,
342                c->numAuxBuffers,
343                c->accumRedBits, c->accumGreenBits, c->accumBlueBits,
344                c->accumAlphaBits, c->sampleBuffers, c->samples,
345                (c->drawableType & GLX_WINDOW_BIT) ? "y" : ".",
346                (c->drawableType & GLX_PIXMAP_BIT) ? "y" : ".",
347                (c->drawableType & GLX_PBUFFER_BIT) ? "y" : ".",
348                float_col,
349                (c->transparentPixel != GLX_NONE_EXT) ? "y" : ".",
350                c->visualSelectGroup,
351                (c->visualRating == GLX_SLOW_VISUAL_EXT) ? "*" : " ",
352                c->sRGBCapable ? "y" : ".");
353 
354         c = c->next;
355     }
356 }
357 
358 /* ---------------------------------------------------------------------- */
359 /*
360  * Forward declarations
361  */
362 
363 static __GLXscreen *glxWinScreenProbe(ScreenPtr pScreen);
364 static __GLXcontext *glxWinCreateContext(__GLXscreen * screen,
365                                          __GLXconfig * modes,
366                                          __GLXcontext * baseShareContext,
367                                          unsigned num_attribs,
368                                          const uint32_t * attribs, int *error);
369 static __GLXdrawable *glxWinCreateDrawable(ClientPtr client,
370                                            __GLXscreen * screen,
371                                            DrawablePtr pDraw,
372                                            XID drawId,
373                                            int type,
374                                            XID glxDrawId, __GLXconfig * conf);
375 
376 static Bool glxWinRealizeWindow(WindowPtr pWin);
377 static Bool glxWinUnrealizeWindow(WindowPtr pWin);
378 static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg,
379                              RegionPtr prgnSrc);
380 static Bool glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride,
381                                  __GLXscreen *screen, __GLXconfig *config);
382 static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw,
383                         HDC * hdc, HWND * hwnd);
384 static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw);
385 
386 static void glxWinCreateConfigs(HDC dc, glxWinScreen * screen);
387 static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen,
388                                    PixelFormatRejectStats * rejects);
389 static int fbConfigToPixelFormat(__GLXconfig * mode,
390                                  PIXELFORMATDESCRIPTOR * pfdret,
391                                  int drawableTypeOverride);
392 static int fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig * mode,
393                                       int drawableTypeOverride,
394                                       glxWinScreen * winScreen);
395 
396 /* ---------------------------------------------------------------------- */
397 /*
398  * The GLX provider
399  */
400 
401 __GLXprovider __glXWGLProvider = {
402     glxWinScreenProbe,
403     "Win32 native WGL",
404     NULL
405 };
406 
407 void
glxWinPushNativeProvider(void)408 glxWinPushNativeProvider(void)
409 {
410     GlxPushProvider(&__glXWGLProvider);
411 }
412 
413 /* ---------------------------------------------------------------------- */
414 /*
415  * Screen functions
416  */
417 
418 static void
glxWinScreenDestroy(__GLXscreen * screen)419 glxWinScreenDestroy(__GLXscreen * screen)
420 {
421     GLWIN_DEBUG_MSG("glxWinScreenDestroy(%p)", screen);
422     __glXScreenDestroy(screen);
423     free(screen);
424 }
425 
426 static int
glxWinScreenSwapInterval(__GLXdrawable * drawable,int interval)427 glxWinScreenSwapInterval(__GLXdrawable * drawable, int interval)
428 {
429     BOOL ret = wglSwapIntervalEXTWrapper(interval);
430 
431     if (!ret) {
432         ErrorF("wglSwapIntervalEXT interval %d failed:%s\n", interval,
433                glxWinErrorMessage());
434     }
435     return ret;
436 }
437 
438 /*
439   Report the extensions split and formatted to avoid overflowing a line
440  */
441 static void
glxLogExtensions(const char * prefix,const char * extensions)442 glxLogExtensions(const char *prefix, const char *extensions)
443 {
444     int length = 0;
445     const char *strl;
446     char *str = strdup(extensions);
447 
448     if (str == NULL) {
449         ErrorF("glxLogExtensions: xalloc error\n");
450         return;
451     }
452 
453     strl = strtok(str, " ");
454     if (strl == NULL)
455         strl = "";
456     ErrorF("%s%s", prefix, strl);
457     length = strlen(prefix) + strlen(strl);
458 
459     while (1) {
460         strl = strtok(NULL, " ");
461         if (strl == NULL)
462             break;
463 
464         if (length + strlen(strl) + 1 > 120) {
465             ErrorF("\n");
466             ErrorF("%s", prefix);
467             length = strlen(prefix);
468         }
469         else {
470             ErrorF(" ");
471             length++;
472         }
473 
474         ErrorF("%s", strl);
475         length = length + strlen(strl);
476     }
477 
478     ErrorF("\n");
479 
480     free(str);
481 }
482 
483 /* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */
484 static __GLXscreen *
glxWinScreenProbe(ScreenPtr pScreen)485 glxWinScreenProbe(ScreenPtr pScreen)
486 {
487     glxWinScreen *screen;
488     const char *gl_extensions;
489     const char *gl_renderer;
490     const char *wgl_extensions;
491     HWND hwnd;
492     HDC hdc;
493     HGLRC hglrc;
494     PixelFormatRejectStats rejects;
495 
496     GLWIN_DEBUG_MSG("glxWinScreenProbe");
497 
498     glxWinInitDebugSettings();
499 
500     if (pScreen == NULL)
501         return NULL;
502 
503     if (!winCheckScreenAiglxIsSupported(pScreen)) {
504         LogMessage(X_ERROR,
505                    "AIGLX: No native OpenGL in modes with a root window\n");
506         return NULL;
507     }
508 
509     screen = calloc(1, sizeof(glxWinScreen));
510 
511     if (NULL == screen)
512         return NULL;
513 
514     // Select the native GL implementation (WGL)
515     if (glWinSelectImplementation(1)) {
516         free(screen);
517         return NULL;
518     }
519 
520     // create window class
521 #define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest"
522     {
523         static wATOM glTestWndClass = 0;
524 
525         if (glTestWndClass == 0) {
526             WNDCLASSEX wc;
527 
528             wc.cbSize = sizeof(WNDCLASSEX);
529             wc.style = CS_HREDRAW | CS_VREDRAW;
530             wc.lpfnWndProc = DefWindowProc;
531             wc.cbClsExtra = 0;
532             wc.cbWndExtra = 0;
533             wc.hInstance = GetModuleHandle(NULL);
534             wc.hIcon = 0;
535             wc.hCursor = 0;
536             wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
537             wc.lpszMenuName = NULL;
538             wc.lpszClassName = WIN_GL_TEST_WINDOW_CLASS;
539             wc.hIconSm = 0;
540             RegisterClassEx(&wc);
541         }
542     }
543 
544     // create an invisible window for a scratch DC
545     hwnd = CreateWindowExA(0,
546                            WIN_GL_TEST_WINDOW_CLASS,
547                            "XWin GL Renderer Capabilities Test Window",
548                            0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL),
549                            NULL);
550     if (hwnd == NULL)
551         LogMessage(X_ERROR,
552                    "AIGLX: Couldn't create a window for render capabilities testing\n");
553 
554     hdc = GetDC(hwnd);
555 
556     // we must set a pixel format before we can create a context, just use the first one...
557     SetPixelFormat(hdc, 1, NULL);
558     hglrc = wglCreateContext(hdc);
559     wglMakeCurrent(hdc, hglrc);
560 
561     // initialize wgl extension proc pointers (don't call them before here...)
562     // (but we need to have a current context for them to be resolvable)
563     wglResolveExtensionProcs();
564 
565     /* Dump out some useful information about the native renderer */
566     ErrorF("GL_VERSION:     %s\n", glGetString(GL_VERSION));
567     ErrorF("GL_VENDOR:      %s\n", glGetString(GL_VENDOR));
568     gl_renderer = (const char *) glGetString(GL_RENDERER);
569     ErrorF("GL_RENDERER:    %s\n", gl_renderer);
570     gl_extensions = (const char *) glGetString(GL_EXTENSIONS);
571     wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
572     if (!wgl_extensions)
573         wgl_extensions = "";
574 
575     if (g_iLogVerbose >= 3) {
576         glxLogExtensions("GL_EXTENSIONS:  ", gl_extensions);
577         glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions);
578     }
579 
580     if (strcasecmp(gl_renderer, "GDI Generic") == 0) {
581         free(screen);
582         LogMessage(X_ERROR,
583                    "AIGLX: Won't use generic native renderer as it is not accelerated\n");
584         goto error;
585     }
586 
587     // Can you see the problem here?  The extensions string is DC specific
588     // Different DCs for windows on a multimonitor system driven by multiple cards
589     // might have completely different capabilities.  Of course, good luck getting
590     // those screens to be accelerated in XP and earlier...
591 
592 
593     {
594         int i;
595 
596         const struct
597         {
598             const char *wglext;
599             const char *glxext;
600             Bool mandatory;
601         } extensionMap[] = {
602             { "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 1 },
603             { "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 },
604             { "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 },
605             //      { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 },
606             // Sufficiently different that it's not obvious if this can be done...
607             { "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 },
608             { "WGL_ARB_multisample", "GLX_ARB_multisample", 1 },
609             { "WGL_ARB_multisample", "GLX_SGIS_multisample", 0 },
610             { "WGL_ARB_pixel_format_float", "GLX_ARB_fbconfig_float", 0 },
611             { "WGL_EXT_pixel_format_packed_float", "GLX_EXT_fbconfig_packed_float", 0 },
612             { "WGL_ARB_create_context", "GLX_ARB_create_context", 0 },
613             { "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 },
614             { "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 },
615             { "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 },
616             { "WGL_ARB_framebuffer_sRGB", "GLX_ARB_framebuffer_sRGB", 0 },
617         };
618 
619         //
620         // Based on the WGL extensions available, enable various GLX extensions
621         //
622         __glXInitExtensionEnableBits(screen->base.glx_enable_bits);
623 
624         for (i = 0; i < sizeof(extensionMap)/sizeof(extensionMap[0]); i++) {
625             if (strstr(wgl_extensions, extensionMap[i].wglext)) {
626                 __glXEnableExtension(screen->base.glx_enable_bits, extensionMap[i].glxext);
627                 LogMessage(X_INFO, "GLX: enabled %s\n", extensionMap[i].glxext);
628             }
629             else if (extensionMap[i].mandatory) {
630                 LogMessage(X_ERROR, "required WGL extension %s is missing\n", extensionMap[i].wglext);
631             }
632         }
633 
634         // Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might
635         // only be in GL_EXTENSIONS
636         if (strstr(gl_extensions, "GL_WIN_swap_hint")) {
637             __glXEnableExtension(screen->base.glx_enable_bits,
638                                  "GLX_MESA_copy_sub_buffer");
639             LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
640         }
641 
642         if (strstr(wgl_extensions, "WGL_ARB_make_current_read"))
643             screen->has_WGL_ARB_make_current_read = TRUE;
644 
645         if (strstr(wgl_extensions, "WGL_ARB_pbuffer"))
646             screen->has_WGL_ARB_pbuffer = TRUE;
647 
648         if (strstr(wgl_extensions, "WGL_ARB_multisample"))
649             screen->has_WGL_ARB_multisample = TRUE;
650 
651         if (strstr(wgl_extensions, "WGL_ARB_framebuffer_sRGB")) {
652             screen->has_WGL_ARB_framebuffer_sRGB = TRUE;
653         }
654 
655         screen->base.destroy = glxWinScreenDestroy;
656         screen->base.createContext = glxWinCreateContext;
657         screen->base.createDrawable = glxWinCreateDrawable;
658         screen->base.swapInterval = glxWinScreenSwapInterval;
659         screen->base.pScreen = pScreen;
660 
661         // Creating the fbConfigs initializes screen->base.fbconfigs and screen->base.numFBConfigs
662         memset(&rejects, 0, sizeof(rejects));
663         if (strstr(wgl_extensions, "WGL_ARB_pixel_format")) {
664             glxWinCreateConfigsExt(hdc, screen, &rejects);
665 
666             /*
667                Some graphics drivers appear to advertise WGL_ARB_pixel_format,
668                but it doesn't work usefully, so we have to be prepared for it
669                to fail and fall back to using DescribePixelFormat()
670              */
671             if (screen->base.numFBConfigs > 0) {
672                 screen->has_WGL_ARB_pixel_format = TRUE;
673             }
674         }
675 
676         if (screen->base.numFBConfigs <= 0) {
677             memset(&rejects, 0, sizeof(rejects));
678             glxWinCreateConfigs(hdc, screen);
679             screen->has_WGL_ARB_pixel_format = FALSE;
680         }
681 
682         /*
683            If we still didn't get any fbConfigs, we can't provide GLX for this screen
684          */
685         if (screen->base.numFBConfigs <= 0) {
686             free(screen);
687             LogMessage(X_ERROR,
688                        "AIGLX: No fbConfigs could be made from native OpenGL pixel formats\n");
689             goto error;
690         }
691 
692         /* These will be set by __glXScreenInit */
693         screen->base.visuals = NULL;
694         screen->base.numVisuals = 0;
695 
696         __glXScreenInit(&screen->base, pScreen);
697     }
698 
699     wglMakeCurrent(NULL, NULL);
700     wglDeleteContext(hglrc);
701     ReleaseDC(hwnd, hdc);
702     DestroyWindow(hwnd);
703 
704     // dump out fbConfigs now fbConfigIds and visualIDs have been assigned
705     fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs, &rejects);
706 
707     /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */
708     screen->RealizeWindow = pScreen->RealizeWindow;
709     pScreen->RealizeWindow = glxWinRealizeWindow;
710     screen->UnrealizeWindow = pScreen->UnrealizeWindow;
711     pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
712     screen->CopyWindow = pScreen->CopyWindow;
713     pScreen->CopyWindow = glxWinCopyWindow;
714 
715     // Note that WGL is active on this screen
716     winSetScreenAiglxIsActive(pScreen);
717 
718     return &screen->base;
719 
720  error:
721     // Something went wrong and we can't use the native GL implementation
722     // so make sure the mesa GL implementation is selected instead
723     glWinSelectImplementation(0);
724 
725     return NULL;
726 }
727 
728 /* ---------------------------------------------------------------------- */
729 /*
730  * Window functions
731  */
732 
733 static Bool
glxWinRealizeWindow(WindowPtr pWin)734 glxWinRealizeWindow(WindowPtr pWin)
735 {
736     Bool result;
737     ScreenPtr pScreen = pWin->drawable.pScreen;
738     glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
739 
740     GLWIN_DEBUG_MSG("glxWinRealizeWindow");
741 
742     /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */
743     pScreen->RealizeWindow = screenPriv->RealizeWindow;
744     result = pScreen->RealizeWindow(pWin);
745     pScreen->RealizeWindow = glxWinRealizeWindow;
746 
747     return result;
748 }
749 
750 static void
glxWinCopyWindow(WindowPtr pWindow,DDXPointRec ptOldOrg,RegionPtr prgnSrc)751 glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
752 {
753     __GLXWinDrawable *pGlxDraw;
754     ScreenPtr pScreen = pWindow->drawable.pScreen;
755     glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
756 
757     GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow);
758 
759     dixLookupResourceByType((void *) &pGlxDraw, pWindow->drawable.id,
760                             __glXDrawableRes, NullClient, DixUnknownAccess);
761 
762     /*
763        Discard any CopyWindow requests if a GL drawing context is pointing at the window
764 
765        For regions which are being drawn by GL, the shadow framebuffer doesn't have the
766        correct bits, so we wish to avoid shadow framebuffer damage occurring, which will
767        cause those incorrect bits to be transferred to the display....
768      */
769     if (pGlxDraw && pGlxDraw->drawContext) {
770         GLWIN_DEBUG_MSG("glxWinCopyWindow: discarding");
771         return;
772     }
773 
774     GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer");
775 
776     pScreen->CopyWindow = screenPriv->CopyWindow;
777     pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
778     pScreen->CopyWindow = glxWinCopyWindow;
779 }
780 
781 static Bool
glxWinUnrealizeWindow(WindowPtr pWin)782 glxWinUnrealizeWindow(WindowPtr pWin)
783 {
784     Bool result;
785     ScreenPtr pScreen = pWin->drawable.pScreen;
786     glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
787 
788     GLWIN_DEBUG_MSG("glxWinUnrealizeWindow");
789 
790     pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow;
791     result = pScreen->UnrealizeWindow(pWin);
792     pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
793 
794     return result;
795 }
796 
797 /* ---------------------------------------------------------------------- */
798 /*
799  * Drawable functions
800  */
801 
802 static GLboolean
glxWinDrawableSwapBuffers(ClientPtr client,__GLXdrawable * base)803 glxWinDrawableSwapBuffers(ClientPtr client, __GLXdrawable * base)
804 {
805     HDC dc;
806     HWND hwnd;
807     BOOL ret;
808     __GLXWinDrawable *draw = (__GLXWinDrawable *) base;
809 
810     /* Swap buffers on the last active context for drawing on the drawable */
811     if (draw->drawContext == NULL) {
812         GLWIN_TRACE_MSG("glxWinSwapBuffers - no context for drawable");
813         return GL_FALSE;
814     }
815 
816     GLWIN_TRACE_MSG
817         ("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)",
818          base, draw->drawContext, draw->drawContext->ctx);
819 
820     dc = glxWinMakeDC(draw->drawContext, draw, &dc, &hwnd);
821     if (dc == NULL)
822         return GL_FALSE;
823 
824     ret = wglSwapLayerBuffers(dc, WGL_SWAP_MAIN_PLANE);
825 
826     glxWinReleaseDC(hwnd, dc, draw);
827 
828     if (!ret) {
829         ErrorF("wglSwapBuffers failed: %s\n", glxWinErrorMessage());
830         return GL_FALSE;
831     }
832 
833     return GL_TRUE;
834 }
835 
836 static void
glxWinDrawableCopySubBuffer(__GLXdrawable * drawable,int x,int y,int w,int h)837 glxWinDrawableCopySubBuffer(__GLXdrawable * drawable,
838                             int x, int y, int w, int h)
839 {
840     glAddSwapHintRectWINWrapper(x, y, w, h);
841     glxWinDrawableSwapBuffers(NULL, drawable);
842 }
843 
844 static void
glxWinDrawableDestroy(__GLXdrawable * base)845 glxWinDrawableDestroy(__GLXdrawable * base)
846 {
847     __GLXWinDrawable *glxPriv = (__GLXWinDrawable *) base;
848 
849     if (glxPriv->hPbuffer)
850         if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer)) {
851             ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage());
852         }
853 
854     if (glxPriv->dibDC) {
855         // restore the default DIB
856         SelectObject(glxPriv->dibDC, glxPriv->hOldDIB);
857 
858         if (!DeleteDC(glxPriv->dibDC)) {
859             ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage());
860         }
861     }
862 
863     if (glxPriv->hDIB) {
864         if (!CloseHandle(glxPriv->hSection)) {
865             ErrorF("CloseHandle failed: %s\n", glxWinErrorMessage());
866         }
867 
868         if (!DeleteObject(glxPriv->hDIB)) {
869             ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
870         }
871 
872         ((PixmapPtr) glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits;
873     }
874 
875     GLWIN_DEBUG_MSG("glxWinDestroyDrawable");
876     free(glxPriv);
877 }
878 
879 static __GLXdrawable *
glxWinCreateDrawable(ClientPtr client,__GLXscreen * screen,DrawablePtr pDraw,XID drawId,int type,XID glxDrawId,__GLXconfig * conf)880 glxWinCreateDrawable(ClientPtr client,
881                      __GLXscreen * screen,
882                      DrawablePtr pDraw,
883                      XID drawId, int type, XID glxDrawId, __GLXconfig * conf)
884 {
885     __GLXWinDrawable *glxPriv;
886 
887     glxPriv = malloc(sizeof *glxPriv);
888 
889     if (glxPriv == NULL)
890         return NULL;
891 
892     memset(glxPriv, 0, sizeof *glxPriv);
893 
894     if (!__glXDrawableInit
895         (&glxPriv->base, screen, pDraw, type, glxDrawId, conf)) {
896         free(glxPriv);
897         return NULL;
898     }
899 
900     glxPriv->base.destroy = glxWinDrawableDestroy;
901     glxPriv->base.swapBuffers = glxWinDrawableSwapBuffers;
902     glxPriv->base.copySubBuffer = glxWinDrawableCopySubBuffer;
903     // glxPriv->base.waitX  what are these for?
904     // glxPriv->base.waitGL
905 
906     GLWIN_DEBUG_MSG("glxWinCreateDrawable %p", glxPriv);
907 
908     return &glxPriv->base;
909 }
910 
911 void
glxWinDeferredCreateDrawable(__GLXWinDrawable * draw,__GLXconfig * config)912 glxWinDeferredCreateDrawable(__GLXWinDrawable *draw, __GLXconfig *config)
913 {
914     switch (draw->base.type) {
915     case GLX_DRAWABLE_WINDOW:
916     {
917         WindowPtr pWin = (WindowPtr) draw->base.pDraw;
918 
919         if (!(config->drawableType & GLX_WINDOW_BIT)) {
920             ErrorF
921                 ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_WINDOW drawable with a fbConfig which doesn't have drawableType GLX_WINDOW_BIT\n");
922         }
923 
924         if (pWin == NULL) {
925             GLWIN_DEBUG_MSG("Deferring until X window is created");
926             return;
927         }
928 
929         GLWIN_DEBUG_MSG("glxWinDeferredCreateDrawable: pWin %p", pWin);
930 
931         if (winGetWindowInfo(pWin) == NULL) {
932             GLWIN_DEBUG_MSG("Deferring until native window is created");
933             return;
934         }
935     }
936     break;
937 
938     case GLX_DRAWABLE_PBUFFER:
939     {
940         if (draw->hPbuffer == NULL) {
941             __GLXscreen *screen;
942             glxWinScreen *winScreen;
943             int pixelFormat;
944 
945             // XXX: which DC are we supposed to use???
946             HDC screenDC = GetDC(NULL);
947 
948             if (!(config->drawableType & GLX_PBUFFER_BIT)) {
949                 ErrorF
950                     ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PBUFFER drawable with a fbConfig which doesn't have drawableType GLX_PBUFFER_BIT\n");
951             }
952 
953             screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]);
954             winScreen = (glxWinScreen *) screen;
955 
956             pixelFormat =
957                 fbConfigToPixelFormatIndex(screenDC, config,
958                                            GLX_PBUFFER_BIT, winScreen);
959             if (pixelFormat == 0) {
960                 return;
961             }
962 
963             draw->hPbuffer =
964                 wglCreatePbufferARBWrapper(screenDC, pixelFormat,
965                                            draw->base.pDraw->width,
966                                            draw->base.pDraw->height, NULL);
967             ReleaseDC(NULL, screenDC);
968 
969             if (draw->hPbuffer == NULL) {
970                 ErrorF("wglCreatePbufferARBWrapper error: %s\n",
971                        glxWinErrorMessage());
972                 return;
973             }
974 
975             GLWIN_DEBUG_MSG
976                 ("glxWinDeferredCreateDrawable: pBuffer %p created for drawable %p",
977                  draw->hPbuffer, draw);
978         }
979     }
980     break;
981 
982     case GLX_DRAWABLE_PIXMAP:
983     {
984         if (draw->dibDC == NULL) {
985             BITMAPINFOHEADER bmpHeader;
986             void *pBits;
987             __GLXscreen *screen;
988             DWORD size;
989             char name[MAX_PATH];
990 
991             memset(&bmpHeader, 0, sizeof(BITMAPINFOHEADER));
992             bmpHeader.biSize = sizeof(BITMAPINFOHEADER);
993             bmpHeader.biWidth = draw->base.pDraw->width;
994             bmpHeader.biHeight = draw->base.pDraw->height;
995             bmpHeader.biPlanes = 1;
996             bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel;
997             bmpHeader.biCompression = BI_RGB;
998 
999             if (!(config->drawableType & GLX_PIXMAP_BIT)) {
1000                 ErrorF
1001                     ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PIXMAP drawable with a fbConfig which doesn't have drawableType GLX_PIXMAP_BIT\n");
1002             }
1003 
1004             draw->dibDC = CreateCompatibleDC(NULL);
1005             if (draw->dibDC == NULL) {
1006                 ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
1007                 return;
1008             }
1009 
1010 #define RASTERWIDTHBYTES(bmi) (((((bmi)->biWidth*(bmi)->biBitCount)+31)&~31)>>3)
1011             size = bmpHeader.biHeight * RASTERWIDTHBYTES(&bmpHeader);
1012             GLWIN_DEBUG_MSG("shared memory region size %zu + %u\n", sizeof(BITMAPINFOHEADER), (unsigned int)size);
1013 
1014             // Create unique name for mapping based on XID
1015             //
1016             // XXX: not quite unique as potentially this name could be used in
1017             // another server instance.  Not sure how to deal with that.
1018             snprintf(name, sizeof(name), "Local\\CYGWINX_WINDOWSDRI_%08x", (unsigned int)draw->base.pDraw->id);
1019             GLWIN_DEBUG_MSG("shared memory region name %s\n", name);
1020 
1021             // Create a file mapping backed by the pagefile
1022             draw->hSection = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
1023                                                PAGE_READWRITE, 0, sizeof(BITMAPINFOHEADER) + size, name);
1024             if (draw->hSection == NULL) {
1025                 ErrorF("CreateFileMapping error: %s\n", glxWinErrorMessage());
1026                 return;
1027                 }
1028 
1029             draw->hDIB =
1030                 CreateDIBSection(draw->dibDC, (BITMAPINFO *) &bmpHeader,
1031                                  DIB_RGB_COLORS, &pBits, draw->hSection, sizeof(BITMAPINFOHEADER));
1032             if (draw->dibDC == NULL) {
1033                 ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage());
1034                 return;
1035             }
1036 
1037             // Store a copy of the BITMAPINFOHEADER at the start of the shared
1038             // memory for the information of the receiving process
1039             {
1040                 LPVOID pData = MapViewOfFile(draw->hSection, FILE_MAP_WRITE, 0, 0, 0);
1041                 memcpy(pData, (void *)&bmpHeader, sizeof(BITMAPINFOHEADER));
1042                 UnmapViewOfFile(pData);
1043             }
1044 
1045             // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to
1046             // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits
1047             // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are
1048             // even compatible ...
1049             draw->pOldBits = ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr;
1050             ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr = pBits;
1051 
1052             // Select the DIB into the DC
1053             draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB);
1054             if (!draw->hOldDIB) {
1055                 ErrorF("SelectObject error: %s\n", glxWinErrorMessage());
1056             }
1057 
1058             screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]);
1059 
1060             // Set the pixel format of the bitmap
1061             glxWinSetPixelFormat(draw->dibDC,
1062                                  draw->base.pDraw->bitsPerPixel,
1063                                  GLX_PIXMAP_BIT,
1064                                  screen,
1065                                  config);
1066 
1067             GLWIN_DEBUG_MSG
1068                 ("glxWinDeferredCreateDrawable: DIB bitmap %p created for drawable %p",
1069                  draw->hDIB, draw);
1070         }
1071     }
1072     break;
1073 
1074     default:
1075     {
1076         ErrorF
1077             ("glxWinDeferredCreateDrawable: tried to attach unhandled drawable type %d\n",
1078              draw->base.type);
1079         return;
1080     }
1081     }
1082 }
1083 
1084 /* ---------------------------------------------------------------------- */
1085 /*
1086  * Texture functions
1087  */
1088 
1089 static
1090     int
glxWinBindTexImage(__GLXcontext * baseContext,int buffer,__GLXdrawable * pixmap)1091 glxWinBindTexImage(__GLXcontext * baseContext,
1092                    int buffer, __GLXdrawable * pixmap)
1093 {
1094     ErrorF("glxWinBindTexImage: not implemented\n");
1095     return FALSE;
1096 }
1097 
1098 static
1099     int
glxWinReleaseTexImage(__GLXcontext * baseContext,int buffer,__GLXdrawable * pixmap)1100 glxWinReleaseTexImage(__GLXcontext * baseContext,
1101                       int buffer, __GLXdrawable * pixmap)
1102 {
1103     ErrorF(" glxWinReleaseTexImage: not implemented\n");
1104     return FALSE;
1105 }
1106 
1107 /* ---------------------------------------------------------------------- */
1108 /*
1109  * Lazy update context implementation
1110  *
1111  * WGL contexts are created for a specific HDC, so we cannot create the WGL
1112  * context in glxWinCreateContext(), we must defer creation until the context
1113  * is actually used on a specific drawable which is connected to a native window,
1114  * pbuffer or DIB
1115  *
1116  * The WGL context may be used on other, compatible HDCs, so we don't need to
1117  * recreate it for every new native window
1118  *
1119  * XXX: I wonder why we can't create the WGL context on the screen HDC ?
1120  * Basically we assume all HDCs are compatible at the moment: if they are not
1121  * we are in a muddle, there was some code in the old implementation to attempt
1122  * to transparently migrate a context to a new DC by copying state and sharing
1123  * lists with the old one...
1124  */
1125 
1126 static Bool
glxWinSetPixelFormat(HDC hdc,int bppOverride,int drawableTypeOverride,__GLXscreen * screen,__GLXconfig * config)1127 glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride,
1128                      __GLXscreen *screen, __GLXconfig *config)
1129 {
1130     glxWinScreen *winScreen = (glxWinScreen *) screen;
1131     GLXWinConfig *winConfig = (GLXWinConfig *) config;
1132 
1133     GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d",
1134                     winConfig->pixelFormatIndex);
1135 
1136     /*
1137        Normally, we can just use the the pixelFormatIndex corresponding
1138        to the fbconfig which has been specified by the client
1139      */
1140 
1141     if (!
1142         ((bppOverride &&
1143           (bppOverride !=
1144            (config->redBits + config->greenBits + config->blueBits)))
1145          || ((config->drawableType & drawableTypeOverride) == 0))) {
1146         if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL)) {
1147             ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
1148             return FALSE;
1149         }
1150 
1151         return TRUE;
1152     }
1153 
1154     /*
1155        However, in certain special cases this pixel format will be incompatible with the
1156        use we are going to put it to, so we need to re-evaluate the pixel format to use:
1157 
1158        1) When PFD_DRAW_TO_BITMAP is set, ChoosePixelFormat() always returns a format with
1159        the cColorBits we asked for, so we need to ensure it matches the bpp of the bitmap
1160 
1161        2) Applications may assume that visuals selected with glXChooseVisual() work with
1162        pixmap drawables (there is no attribute to explicitly query for pixmap drawable
1163        support as there is for glXChooseFBConfig())
1164        (it's arguable this is an error in the application, but we try to make it work)
1165 
1166        pixmap rendering is always slow for us, so we don't want to choose those visuals
1167        by default, but if the actual drawable type we're trying to select the context
1168        on (drawableTypeOverride) isn't supported by the selected fbConfig, reconsider
1169        and see if we can find a suitable one...
1170      */
1171     ErrorF
1172         ("glxWinSetPixelFormat: having second thoughts: cColorbits %d, bppOveride %d; config->drawableType %d, drawableTypeOverride %d\n",
1173          (config->redBits + config->greenBits + config->blueBits), bppOverride,
1174          config->drawableType, drawableTypeOverride);
1175 
1176     if (winScreen->has_WGL_ARB_pixel_format) {
1177         int pixelFormat =
1178             fbConfigToPixelFormatIndex(hdc, config,
1179                                        drawableTypeOverride, winScreen);
1180         if (pixelFormat != 0) {
1181             GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d",
1182                             pixelFormat);
1183             ErrorF
1184                 ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n",
1185                  pixelFormat, winConfig->pixelFormatIndex);
1186 
1187             if (!SetPixelFormat(hdc, pixelFormat, NULL)) {
1188                 ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
1189                 return FALSE;
1190             }
1191         }
1192     }
1193 
1194     /*
1195       For some drivers, wglChoosePixelFormatARB() can fail when the provided
1196       DC doesn't belong to the driver (e.g. it's a compatible DC for a bitmap,
1197       so allow fallback to ChoosePixelFormat()
1198      */
1199     {
1200         PIXELFORMATDESCRIPTOR pfd;
1201         int pixelFormat;
1202 
1203         /* convert fbConfig to PFD */
1204         if (fbConfigToPixelFormat(config, &pfd, drawableTypeOverride)) {
1205             ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n");
1206             return FALSE;
1207         }
1208 
1209         if (glxWinDebugSettings.dumpPFD)
1210             pfdOut(&pfd);
1211 
1212         if (bppOverride) {
1213             GLWIN_DEBUG_MSG("glxWinSetPixelFormat: Forcing bpp from %d to %d\n",
1214                             pfd.cColorBits, bppOverride);
1215             pfd.cColorBits = bppOverride;
1216         }
1217 
1218         pixelFormat = ChoosePixelFormat(hdc, &pfd);
1219         if (pixelFormat == 0) {
1220             ErrorF("ChoosePixelFormat error: %s\n", glxWinErrorMessage());
1221             return FALSE;
1222         }
1223 
1224         GLWIN_DEBUG_MSG("ChoosePixelFormat: chose pixelFormatIndex %d",
1225                         pixelFormat);
1226         ErrorF
1227             ("ChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n",
1228              pixelFormat, winConfig->pixelFormatIndex);
1229 
1230         if (!SetPixelFormat(hdc, pixelFormat, &pfd)) {
1231             ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
1232             return FALSE;
1233         }
1234     }
1235 
1236     return TRUE;
1237 }
1238 
1239 static HDC
glxWinMakeDC(__GLXWinContext * gc,__GLXWinDrawable * draw,HDC * hdc,HWND * hwnd)1240 glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, HDC * hdc,
1241              HWND * hwnd)
1242 {
1243     *hdc = NULL;
1244     *hwnd = NULL;
1245 
1246     if (draw == NULL) {
1247         GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc,
1248                         gc->ctx);
1249         return NULL;
1250     }
1251 
1252     switch (draw->base.type) {
1253     case GLX_DRAWABLE_WINDOW:
1254     {
1255         WindowPtr pWin;
1256 
1257         pWin = (WindowPtr) draw->base.pDraw;
1258         if (pWin == NULL) {
1259             GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin);
1260             return NULL;
1261         }
1262 
1263         *hwnd = winGetWindowInfo(pWin);
1264 
1265         if (*hwnd == NULL) {
1266             ErrorF("No HWND error: %s\n", glxWinErrorMessage());
1267             return NULL;
1268         }
1269 
1270         *hdc = GetDC(*hwnd);
1271 
1272         if (*hdc == NULL)
1273             ErrorF("GetDC error: %s\n", glxWinErrorMessage());
1274 
1275         /* Check if the hwnd has changed... */
1276         if (*hwnd != gc->hwnd) {
1277             if (glxWinDebugSettings.enableTrace)
1278                 GLWIN_DEBUG_HWND(*hwnd);
1279 
1280             GLWIN_TRACE_MSG
1281                 ("for context %p (native ctx %p), hWnd changed from %p to %p",
1282                  gc, gc->ctx, gc->hwnd, *hwnd);
1283             gc->hwnd = *hwnd;
1284 
1285             /* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */
1286             if (!glxWinSetPixelFormat(*hdc, 0, GLX_WINDOW_BIT, gc->base.pGlxScreen, gc->base.config)) {
1287                 ErrorF("glxWinSetPixelFormat error: %s\n",
1288                        glxWinErrorMessage());
1289                 ReleaseDC(*hwnd, *hdc);
1290                 *hdc = NULL;
1291                 return NULL;
1292             }
1293         }
1294     }
1295         break;
1296 
1297     case GLX_DRAWABLE_PBUFFER:
1298     {
1299         *hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer);
1300 
1301         if (*hdc == NULL)
1302             ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage());
1303     }
1304         break;
1305 
1306     case GLX_DRAWABLE_PIXMAP:
1307     {
1308         *hdc = draw->dibDC;
1309     }
1310         break;
1311 
1312     default:
1313     {
1314         ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n",
1315                draw->base.type);
1316     }
1317     }
1318 
1319     if (glxWinDebugSettings.dumpDC)
1320         GLWIN_DEBUG_MSG("Got HDC %p", *hdc);
1321 
1322     return *hdc;
1323 }
1324 
1325 static void
glxWinReleaseDC(HWND hwnd,HDC hdc,__GLXWinDrawable * draw)1326 glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw)
1327 {
1328     switch (draw->base.type) {
1329     case GLX_DRAWABLE_WINDOW:
1330     {
1331         ReleaseDC(hwnd, hdc);
1332     }
1333         break;
1334 
1335     case GLX_DRAWABLE_PBUFFER:
1336     {
1337         if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc)) {
1338             ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage());
1339         }
1340     }
1341         break;
1342 
1343     case GLX_DRAWABLE_PIXMAP:
1344     {
1345         // don't release DC, the memory DC lives as long as the bitmap
1346 
1347         // We must ensure that all GDI drawing into the bitmap has completed
1348         // in case we subsequently access the bits from it
1349         GdiFlush();
1350     }
1351         break;
1352 
1353     default:
1354     {
1355         ErrorF
1356             ("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n",
1357              draw->base.type);
1358     }
1359     }
1360 }
1361 
1362 static void
glxWinDeferredCreateContext(__GLXWinContext * gc,__GLXWinDrawable * draw)1363 glxWinDeferredCreateContext(__GLXWinContext * gc, __GLXWinDrawable * draw)
1364 {
1365     HDC dc;
1366     HWND hwnd;
1367 
1368     GLWIN_DEBUG_MSG
1369         ("glxWinDeferredCreateContext: attach context %p to drawable %p", gc,
1370          draw);
1371 
1372     glxWinDeferredCreateDrawable(draw, gc->base.config);
1373 
1374     dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
1375     gc->ctx = wglCreateContext(dc);
1376     glxWinReleaseDC(hwnd, dc, draw);
1377 
1378     if (gc->ctx == NULL) {
1379         ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage());
1380         return;
1381     }
1382 
1383     GLWIN_DEBUG_MSG
1384         ("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p",
1385          gc, gc->ctx, draw);
1386 
1387     // if the native context was created successfully, shareLists if needed
1388     if (gc->ctx && gc->shareContext) {
1389         GLWIN_DEBUG_MSG
1390             ("glxWinCreateContextReal shareLists with context %p (native ctx %p)",
1391              gc->shareContext, gc->shareContext->ctx);
1392 
1393         if (!wglShareLists(gc->shareContext->ctx, gc->ctx)) {
1394             ErrorF("wglShareLists error: %s\n", glxWinErrorMessage());
1395         }
1396     }
1397 }
1398 
1399 /* ---------------------------------------------------------------------- */
1400 /*
1401  * Context functions
1402  */
1403 
1404 /* Context manipulation routines should return TRUE on success, FALSE on failure */
1405 static int
glxWinContextMakeCurrent(__GLXcontext * base)1406 glxWinContextMakeCurrent(__GLXcontext * base)
1407 {
1408     __GLXWinContext *gc = (__GLXWinContext *) base;
1409     glxWinScreen *scr = (glxWinScreen *)base->pGlxScreen;
1410     BOOL ret;
1411     HDC drawDC;
1412     HDC readDC = NULL;
1413     __GLXdrawable *drawPriv;
1414     __GLXdrawable *readPriv = NULL;
1415     HWND hDrawWnd;
1416     HWND hReadWnd;
1417 
1418     GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc,
1419                     gc->ctx);
1420 
1421     /* Keep a note of the last active context in the drawable */
1422     drawPriv = gc->base.drawPriv;
1423     ((__GLXWinDrawable *) drawPriv)->drawContext = gc;
1424 
1425     if (gc->ctx == NULL) {
1426         glxWinDeferredCreateContext(gc, (__GLXWinDrawable *) drawPriv);
1427     }
1428 
1429     if (gc->ctx == NULL) {
1430         ErrorF("glxWinContextMakeCurrent: Native context is NULL\n");
1431         return FALSE;
1432     }
1433 
1434     drawDC =
1435         glxWinMakeDC(gc, (__GLXWinDrawable *) drawPriv, &drawDC, &hDrawWnd);
1436     if (drawDC == NULL) {
1437         ErrorF("glxWinMakeDC failed for drawDC\n");
1438         return FALSE;
1439     }
1440 
1441     if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv)) {
1442         /*
1443          * We enable GLX_SGI_make_current_read unconditionally, but the
1444          * renderer might not support it. It's fairly rare to use this
1445          * feature so just error out if it can't work.
1446          */
1447         if (!scr->has_WGL_ARB_make_current_read)
1448             return FALSE;
1449 
1450         /*
1451            If there is a separate read drawable, create a separate read DC, and
1452            use the wglMakeContextCurrent extension to make the context current drawing
1453            to one DC and reading from the other
1454          */
1455         readPriv = gc->base.readPriv;
1456         readDC =
1457             glxWinMakeDC(gc, (__GLXWinDrawable *) readPriv, &readDC, &hReadWnd);
1458         if (readDC == NULL) {
1459             ErrorF("glxWinMakeDC failed for readDC\n");
1460             glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *) drawPriv);
1461             return FALSE;
1462         }
1463 
1464         ret = wglMakeContextCurrentARBWrapper(drawDC, readDC, gc->ctx);
1465         if (!ret) {
1466             ErrorF("wglMakeContextCurrentARBWrapper error: %s\n",
1467                    glxWinErrorMessage());
1468         }
1469     }
1470     else {
1471         /* Otherwise, just use wglMakeCurrent */
1472         ret = wglMakeCurrent(drawDC, gc->ctx);
1473         if (!ret) {
1474             ErrorF("wglMakeCurrent error: %s\n", glxWinErrorMessage());
1475         }
1476     }
1477 
1478     // apparently make current could fail if the context is current in a different thread,
1479     // but that shouldn't be able to happen in the current server...
1480 
1481     glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *) drawPriv);
1482     if (readDC)
1483         glxWinReleaseDC(hReadWnd, readDC, (__GLXWinDrawable *) readPriv);
1484 
1485     return ret;
1486 }
1487 
1488 static int
glxWinContextLoseCurrent(__GLXcontext * base)1489 glxWinContextLoseCurrent(__GLXcontext * base)
1490 {
1491     BOOL ret;
1492     __GLXWinContext *gc = (__GLXWinContext *) base;
1493 
1494     GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc,
1495                     gc->ctx);
1496 
1497     /*
1498        An error seems to be reported if we try to make no context current
1499        if there is already no current context, so avoid doing that...
1500      */
1501     if (wglGetCurrentContext() != NULL) {
1502         ret = wglMakeCurrent(NULL, NULL);       /* We don't need a DC when setting no current context */
1503         if (!ret)
1504             ErrorF("glxWinContextLoseCurrent error: %s\n",
1505                    glxWinErrorMessage());
1506     }
1507 
1508     return TRUE;
1509 }
1510 
1511 static int
glxWinContextCopy(__GLXcontext * dst_base,__GLXcontext * src_base,unsigned long mask)1512 glxWinContextCopy(__GLXcontext * dst_base, __GLXcontext * src_base,
1513                   unsigned long mask)
1514 {
1515     __GLXWinContext *dst = (__GLXWinContext *) dst_base;
1516     __GLXWinContext *src = (__GLXWinContext *) src_base;
1517     BOOL ret;
1518 
1519     GLWIN_DEBUG_MSG("glxWinContextCopy");
1520 
1521     ret = wglCopyContext(src->ctx, dst->ctx, mask);
1522     if (!ret) {
1523         ErrorF("wglCopyContext error: %s\n", glxWinErrorMessage());
1524     }
1525 
1526     return ret;
1527 }
1528 
1529 static void
glxWinContextDestroy(__GLXcontext * base)1530 glxWinContextDestroy(__GLXcontext * base)
1531 {
1532     __GLXWinContext *gc = (__GLXWinContext *) base;
1533 
1534     if (gc != NULL) {
1535         GLWIN_DEBUG_MSG("GLXcontext %p destroyed (native ctx %p)", base,
1536                         gc->ctx);
1537 
1538         if (gc->ctx) {
1539             /* It's bad style to delete the context while it's still current */
1540             if (wglGetCurrentContext() == gc->ctx) {
1541                 wglMakeCurrent(NULL, NULL);
1542             }
1543 
1544             {
1545                 BOOL ret = wglDeleteContext(gc->ctx);
1546 
1547                 if (!ret)
1548                     ErrorF("wglDeleteContext error: %s\n",
1549                            glxWinErrorMessage());
1550             }
1551 
1552             gc->ctx = NULL;
1553         }
1554 
1555         free(gc);
1556     }
1557 }
1558 
1559 static __GLXcontext *
glxWinCreateContext(__GLXscreen * screen,__GLXconfig * modes,__GLXcontext * baseShareContext,unsigned num_attribs,const uint32_t * attribs,int * error)1560 glxWinCreateContext(__GLXscreen * screen,
1561                     __GLXconfig * modes, __GLXcontext * baseShareContext,
1562                     unsigned num_attribs, const uint32_t * attribs, int *error)
1563 {
1564     __GLXWinContext *context;
1565     __GLXWinContext *shareContext = (__GLXWinContext *) baseShareContext;
1566 
1567     context = calloc(1, sizeof(__GLXWinContext));
1568 
1569     if (!context)
1570         return NULL;
1571 
1572     memset(context, 0, sizeof *context);
1573     context->base.destroy = glxWinContextDestroy;
1574     context->base.makeCurrent = glxWinContextMakeCurrent;
1575     context->base.loseCurrent = glxWinContextLoseCurrent;
1576     context->base.copy = glxWinContextCopy;
1577     context->base.bindTexImage = glxWinBindTexImage;
1578     context->base.releaseTexImage = glxWinReleaseTexImage;
1579     context->base.config = modes;
1580     context->base.pGlxScreen = screen;
1581 
1582     // actual native GL context creation is deferred until attach()
1583     context->ctx = NULL;
1584     context->shareContext = shareContext;
1585 
1586     GLWIN_DEBUG_MSG("GLXcontext %p created", context);
1587 
1588     return &(context->base);
1589 }
1590 
1591 /* ---------------------------------------------------------------------- */
1592 /*
1593  * Utility functions
1594  */
1595 
1596 static int
GetShift(int mask)1597 GetShift(int mask)
1598 {
1599     int shift = 0;
1600     while (mask > 1) {
1601         shift++;
1602         mask >>=1;
1603     }
1604     return shift;
1605 }
1606 
1607 static int
fbConfigToPixelFormat(__GLXconfig * mode,PIXELFORMATDESCRIPTOR * pfdret,int drawableTypeOverride)1608 fbConfigToPixelFormat(__GLXconfig * mode, PIXELFORMATDESCRIPTOR * pfdret,
1609                       int drawableTypeOverride)
1610 {
1611     PIXELFORMATDESCRIPTOR pfd = {
1612         sizeof(PIXELFORMATDESCRIPTOR),  /* size of this pfd */
1613         1,                      /* version number */
1614         PFD_SUPPORT_OPENGL,     /* support OpenGL */
1615         PFD_TYPE_RGBA,          /* RGBA type */
1616         24,                     /* 24-bit color depth */
1617         0, 0, 0, 0, 0, 0,       /* color bits ignored */
1618         0,                      /* no alpha buffer */
1619         0,                      /* shift bit ignored */
1620         0,                      /* no accumulation buffer */
1621         0, 0, 0, 0,             /* accum bits ignored */
1622         32,                     /* 32-bit z-buffer */
1623         0,                      /* no stencil buffer */
1624         0,                      /* no auxiliary buffer */
1625         PFD_MAIN_PLANE,         /* main layer */
1626         0,                      /* reserved */
1627         0, 0, 0                 /* layer masks ignored */
1628     };
1629 
1630     if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
1631         pfd.dwFlags |= PFD_DRAW_TO_WINDOW;      /* support window */
1632 
1633     if ((mode->drawableType | drawableTypeOverride) & GLX_PIXMAP_BIT)
1634         pfd.dwFlags |= (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI);  /* supports software rendering to bitmap */
1635 
1636     if (mode->stereoMode) {
1637         pfd.dwFlags |= PFD_STEREO;
1638     }
1639     if (mode->doubleBufferMode) {
1640         pfd.dwFlags |= PFD_DOUBLEBUFFER;
1641     }
1642 
1643     pfd.cColorBits = mode->redBits + mode->greenBits + mode->blueBits;
1644     pfd.cRedBits = mode->redBits;
1645     pfd.cRedShift = GetShift(mode->redMask);
1646     pfd.cGreenBits = mode->greenBits;
1647     pfd.cGreenShift = GetShift(mode->greenMask);
1648     pfd.cBlueBits = mode->blueBits;
1649     pfd.cBlueShift = GetShift(mode->blueMask);
1650     pfd.cAlphaBits = mode->alphaBits;
1651     pfd.cAlphaShift = GetShift(mode->alphaMask);
1652 
1653     if (mode->visualType == GLX_TRUE_COLOR) {
1654         pfd.iPixelType = PFD_TYPE_RGBA;
1655         pfd.dwVisibleMask =
1656             (pfd.cRedBits << pfd.cRedShift) | (pfd.cGreenBits << pfd.cGreenShift) |
1657             (pfd.cBlueBits << pfd.cBlueShift) | (pfd.cAlphaBits << pfd.cAlphaShift);
1658     }
1659     else {
1660         pfd.iPixelType = PFD_TYPE_COLORINDEX;
1661         pfd.dwVisibleMask = mode->transparentIndex;
1662     }
1663 
1664     pfd.cAccumBits =
1665         mode->accumRedBits + mode->accumGreenBits + mode->accumBlueBits +
1666         mode->accumAlphaBits;
1667     pfd.cAccumRedBits = mode->accumRedBits;
1668     pfd.cAccumGreenBits = mode->accumGreenBits;
1669     pfd.cAccumBlueBits = mode->accumBlueBits;
1670     pfd.cAccumAlphaBits = mode->accumAlphaBits;
1671 
1672     pfd.cDepthBits = mode->depthBits;
1673     pfd.cStencilBits = mode->stencilBits;
1674     pfd.cAuxBuffers = mode->numAuxBuffers;
1675 
1676     /* mode->level ? */
1677 
1678     *pfdret = pfd;
1679 
1680     return 0;
1681 }
1682 
1683 #define SET_ATTR_VALUE(attr, value) { attribList[i++] = attr; attribList[i++] = value; assert(i < ARRAY_SIZE(attribList)); }
1684 
1685 static int
fbConfigToPixelFormatIndex(HDC hdc,__GLXconfig * mode,int drawableTypeOverride,glxWinScreen * winScreen)1686 fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig * mode,
1687                            int drawableTypeOverride, glxWinScreen * winScreen)
1688 {
1689     UINT numFormats;
1690     unsigned int i = 0;
1691 
1692     /* convert fbConfig to attr-value list  */
1693     int attribList[60];
1694 
1695     SET_ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, TRUE);
1696 
1697     switch (mode->renderType)
1698         {
1699         case GLX_COLOR_INDEX_BIT:
1700         case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT:
1701             SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_COLORINDEX_ARB);
1702             SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->indexBits);
1703             break;
1704 
1705         default:
1706             ErrorF("unexpected renderType %x\n", mode->renderType);
1707             /* fall-through */
1708         case GLX_RGBA_BIT:
1709             SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB);
1710             SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits);
1711             break;
1712 
1713         case GLX_RGBA_FLOAT_BIT_ARB:
1714             SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ARB);
1715             SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits);
1716             break;
1717 
1718         case GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT:
1719             SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT);
1720             SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits);
1721             break;
1722         }
1723 
1724     SET_ATTR_VALUE(WGL_RED_BITS_ARB, mode->redBits);
1725     SET_ATTR_VALUE(WGL_GREEN_BITS_ARB, mode->greenBits);
1726     SET_ATTR_VALUE(WGL_BLUE_BITS_ARB, mode->blueBits);
1727     SET_ATTR_VALUE(WGL_ALPHA_BITS_ARB, mode->alphaBits);
1728     SET_ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, mode->accumRedBits);
1729     SET_ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, mode->accumGreenBits);
1730     SET_ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, mode->accumBlueBits);
1731     SET_ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, mode->accumAlphaBits);
1732     SET_ATTR_VALUE(WGL_DEPTH_BITS_ARB, mode->depthBits);
1733     SET_ATTR_VALUE(WGL_STENCIL_BITS_ARB, mode->stencilBits);
1734     SET_ATTR_VALUE(WGL_AUX_BUFFERS_ARB, mode->numAuxBuffers);
1735 
1736     if (mode->doubleBufferMode)
1737         SET_ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, TRUE);
1738 
1739     if (mode->stereoMode)
1740         SET_ATTR_VALUE(WGL_STEREO_ARB, TRUE);
1741 
1742     // Some attributes are only added to the list if the value requested is not 'don't care', as exactly matching that is daft..
1743     if (mode->swapMethod == GLX_SWAP_EXCHANGE_OML)
1744         SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB);
1745 
1746     if (mode->swapMethod == GLX_SWAP_COPY_OML)
1747         SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_COPY_ARB);
1748 
1749     // XXX: this should probably be the other way around, but that messes up drawableTypeOverride
1750     if (mode->visualRating == GLX_SLOW_VISUAL_EXT)
1751         SET_ATTR_VALUE(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB);
1752 
1753     if (winScreen->has_WGL_ARB_multisample) {
1754         SET_ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, mode->sampleBuffers);
1755         SET_ATTR_VALUE(WGL_SAMPLES_ARB, mode->samples);
1756     }
1757 
1758     // must support all the drawable types the mode supports
1759     if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
1760         SET_ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, TRUE);
1761 
1762     // XXX: this is a horrible hacky heuristic, in fact this whole drawableTypeOverride thing is a bad idea
1763     // try to avoid asking for formats which don't exist (by not asking for all when adjusting the config to include the drawableTypeOverride)
1764     if (drawableTypeOverride == GLX_WINDOW_BIT) {
1765         if (mode->drawableType & GLX_PIXMAP_BIT)
1766             SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE);
1767 
1768         if (mode->drawableType & GLX_PBUFFER_BIT)
1769             if (winScreen->has_WGL_ARB_pbuffer)
1770                 SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
1771     }
1772     else {
1773         if (drawableTypeOverride & GLX_PIXMAP_BIT)
1774             SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE);
1775 
1776         if (drawableTypeOverride & GLX_PBUFFER_BIT)
1777             if (winScreen->has_WGL_ARB_pbuffer)
1778                 SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
1779     }
1780 
1781     if (winScreen->has_WGL_ARB_framebuffer_sRGB)
1782         SET_ATTR_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE);
1783 
1784     SET_ATTR_VALUE(0, 0);       // terminator
1785 
1786     /* choose the first match */
1787     {
1788         int pixelFormatIndex;
1789 
1790         if (!wglChoosePixelFormatARBWrapper
1791             (hdc, attribList, NULL, 1, &pixelFormatIndex, &numFormats)) {
1792             ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
1793         }
1794         else {
1795             if (numFormats > 0) {
1796                 GLWIN_DEBUG_MSG
1797                     ("wglChoosePixelFormat: chose pixelFormatIndex %d)",
1798                      pixelFormatIndex);
1799                 return pixelFormatIndex;
1800             }
1801             else
1802                 ErrorF("wglChoosePixelFormat couldn't decide\n");
1803         }
1804     }
1805 
1806     return 0;
1807 }
1808 
1809 /* ---------------------------------------------------------------------- */
1810 
1811 #define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask))
1812 
1813 //
1814 // Create the GLXconfigs using DescribePixelFormat()
1815 //
1816 static void
glxWinCreateConfigs(HDC hdc,glxWinScreen * screen)1817 glxWinCreateConfigs(HDC hdc, glxWinScreen * screen)
1818 {
1819     GLXWinConfig *first = NULL, *prev = NULL;
1820     int numConfigs = 0;
1821     int i = 0;
1822     int n = 0;
1823     PIXELFORMATDESCRIPTOR pfd;
1824 
1825     GLWIN_DEBUG_MSG("glxWinCreateConfigs");
1826 
1827     screen->base.numFBConfigs = 0;
1828     screen->base.fbconfigs = NULL;
1829 
1830     // get the number of pixelformats
1831     numConfigs =
1832         DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
1833     LogMessage(X_INFO, "%d pixel formats reported by DescribePixelFormat\n",
1834                numConfigs);
1835 
1836     n = 0;
1837 
1838     /* fill in configs */
1839     for (i = 0; i < numConfigs; i++) {
1840         int rc;
1841         GLXWinConfig temp;
1842         GLXWinConfig *c = &temp;
1843         GLXWinConfig *work;
1844         memset(c, 0, sizeof(GLXWinConfig));
1845 
1846         c->pixelFormatIndex = i + 1;
1847 
1848         rc = DescribePixelFormat(hdc, i + 1, sizeof(PIXELFORMATDESCRIPTOR),
1849                                  &pfd);
1850 
1851         if (!rc) {
1852             ErrorF("DescribePixelFormat failed for index %d, error %s\n", i + 1,
1853                    glxWinErrorMessage());
1854             break;
1855         }
1856 
1857         if (glxWinDebugSettings.dumpPFD)
1858             pfdOut(&pfd);
1859 
1860         if (!(pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP)) ||
1861             !(pfd.dwFlags & PFD_SUPPORT_OPENGL)) {
1862             GLWIN_DEBUG_MSG
1863                 ("pixelFormat %d has unsuitable flags 0x%08x, skipping", i + 1,
1864                  (unsigned int)pfd.dwFlags);
1865             continue;
1866         }
1867 
1868         c->base.doubleBufferMode =
1869             (pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
1870         c->base.stereoMode = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE;
1871 
1872         c->base.redBits = pfd.cRedBits;
1873         c->base.greenBits = pfd.cGreenBits;
1874         c->base.blueBits = pfd.cBlueBits;
1875         c->base.alphaBits = pfd.cAlphaBits;
1876 
1877         c->base.redMask = BITS_AND_SHIFT_TO_MASK(pfd.cRedBits, pfd.cRedShift);
1878         c->base.greenMask =
1879             BITS_AND_SHIFT_TO_MASK(pfd.cGreenBits, pfd.cGreenShift);
1880         c->base.blueMask =
1881             BITS_AND_SHIFT_TO_MASK(pfd.cBlueBits, pfd.cBlueShift);
1882         c->base.alphaMask =
1883             BITS_AND_SHIFT_TO_MASK(pfd.cAlphaBits, pfd.cAlphaShift);
1884 
1885         c->base.rgbBits = pfd.cColorBits;
1886 
1887         if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
1888             c->base.indexBits = pfd.cColorBits;
1889         }
1890         else {
1891             c->base.indexBits = 0;
1892         }
1893 
1894         c->base.accumRedBits = pfd.cAccumRedBits;
1895         c->base.accumGreenBits = pfd.cAccumGreenBits;
1896         c->base.accumBlueBits = pfd.cAccumBlueBits;
1897         c->base.accumAlphaBits = pfd.cAccumAlphaBits;
1898         //  pfd.cAccumBits;
1899 
1900         c->base.depthBits = pfd.cDepthBits;
1901         c->base.stencilBits = pfd.cStencilBits;
1902         c->base.numAuxBuffers = pfd.cAuxBuffers;
1903 
1904         // pfd.iLayerType; // ignored
1905         c->base.level = 0;
1906         // pfd.dwLayerMask; // ignored
1907         // pfd.dwDamageMask;  // ignored
1908 
1909         c->base.visualID = -1;  // will be set by __glXScreenInit()
1910 
1911         /* EXT_visual_rating / GLX 1.2 */
1912         if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
1913             c->base.visualRating = GLX_SLOW_VISUAL_EXT;
1914             GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1);
1915             continue;
1916         }
1917         else {
1918             // PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD accelerated...
1919             c->base.visualRating = GLX_NONE_EXT;
1920         }
1921 
1922         /* EXT_visual_info / GLX 1.2 */
1923         if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
1924             c->base.visualType = GLX_STATIC_COLOR;
1925             c->base.transparentRed = GLX_NONE;
1926             c->base.transparentGreen = GLX_NONE;
1927             c->base.transparentBlue = GLX_NONE;
1928             c->base.transparentAlpha = GLX_NONE;
1929             c->base.transparentIndex = pfd.dwVisibleMask;
1930             c->base.transparentPixel = GLX_TRANSPARENT_INDEX;
1931         }
1932         else {
1933             c->base.visualType = GLX_TRUE_COLOR;
1934             c->base.transparentRed =
1935                 (pfd.dwVisibleMask & c->base.redMask) >> pfd.cRedShift;
1936             c->base.transparentGreen =
1937                 (pfd.dwVisibleMask & c->base.greenMask) >> pfd.cGreenShift;
1938             c->base.transparentBlue =
1939                 (pfd.dwVisibleMask & c->base.blueMask) >> pfd.cBlueShift;
1940             c->base.transparentAlpha =
1941                 (pfd.dwVisibleMask & c->base.alphaMask) >> pfd.cAlphaShift;
1942             c->base.transparentIndex = GLX_NONE;
1943             c->base.transparentPixel = GLX_TRANSPARENT_RGB;
1944         }
1945 
1946         /* ARB_multisample / SGIS_multisample */
1947         c->base.sampleBuffers = 0;
1948         c->base.samples = 0;
1949 
1950         /* SGIX_fbconfig / GLX 1.3 */
1951         c->base.drawableType =
1952             (((pfd.dwFlags & PFD_DRAW_TO_WINDOW) ? GLX_WINDOW_BIT : 0)
1953              | ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) ? GLX_PIXMAP_BIT : 0));
1954 
1955         if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
1956             c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT;
1957         }
1958         else {
1959             c->base.renderType = GLX_RGBA_BIT;
1960         }
1961 
1962         c->base.fbconfigID = -1;        // will be set by __glXScreenInit()
1963 
1964         /* SGIX_pbuffer / GLX 1.3 */
1965         // XXX: How can we find these values out ???
1966         c->base.maxPbufferWidth = -1;
1967         c->base.maxPbufferHeight = -1;
1968         c->base.maxPbufferPixels = -1;
1969         c->base.optimalPbufferWidth = 0;        // there is no optimal value
1970         c->base.optimalPbufferHeight = 0;
1971 
1972         /* SGIX_visual_select_group */
1973         // arrange for visuals with the best acceleration to be preferred in selection
1974         switch (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) {
1975         case 0:
1976             c->base.visualSelectGroup = 2;
1977             break;
1978 
1979         case PFD_GENERIC_ACCELERATED:
1980             c->base.visualSelectGroup = 1;
1981             break;
1982 
1983         case PFD_GENERIC_FORMAT:
1984             c->base.visualSelectGroup = 0;
1985             break;
1986 
1987         default:
1988             ;
1989             // "can't happen"
1990         }
1991 
1992         /* OML_swap_method */
1993         if (pfd.dwFlags & PFD_SWAP_EXCHANGE)
1994             c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
1995         else if (pfd.dwFlags & PFD_SWAP_COPY)
1996             c->base.swapMethod = GLX_SWAP_COPY_OML;
1997         else
1998             c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
1999 
2000         /* EXT_texture_from_pixmap */
2001         c->base.bindToTextureRgb = -1;
2002         c->base.bindToTextureRgba = -1;
2003         c->base.bindToMipmapTexture = -1;
2004         c->base.bindToTextureTargets = -1;
2005         c->base.yInverted = -1;
2006         c->base.sRGBCapable = 0;
2007 
2008         n++;
2009 
2010         // allocate and save
2011         work = malloc(sizeof(GLXWinConfig));
2012         if (NULL == work) {
2013             ErrorF("Failed to allocate GLXWinConfig\n");
2014             break;
2015         }
2016         *work = temp;
2017 
2018         // note the first config
2019         if (!first)
2020             first = work;
2021 
2022         // update previous config to point to this config
2023         if (prev)
2024             prev->base.next = &(work->base);
2025         prev = work;
2026     }
2027 
2028     GLWIN_DEBUG_MSG
2029         ("found %d pixelFormats suitable for conversion to fbConfigs", n);
2030 
2031     screen->base.numFBConfigs = n;
2032     screen->base.fbconfigs = first ? &(first->base) : NULL;
2033 }
2034 
2035 // helper function to access an attribute value from an attribute value array by attribute
2036 static
2037     int
getAttrValue(const int attrs[],int values[],unsigned int num,int attr,int fallback)2038 getAttrValue(const int attrs[], int values[], unsigned int num, int attr,
2039              int fallback)
2040 {
2041     unsigned int i;
2042 
2043     for (i = 0; i < num; i++) {
2044         if (attrs[i] == attr) {
2045             GLWIN_TRACE_MSG("getAttrValue attr 0x%x, value %d", attr,
2046                             values[i]);
2047             return values[i];
2048         }
2049     }
2050 
2051     ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n",
2052            attr, fallback);
2053     return fallback;
2054 }
2055 
2056 //
2057 // Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
2058 //
2059 static void
glxWinCreateConfigsExt(HDC hdc,glxWinScreen * screen,PixelFormatRejectStats * rejects)2060 glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen, PixelFormatRejectStats * rejects)
2061 {
2062     GLXWinConfig *first = NULL, *prev = NULL;
2063     int i = 0;
2064     int n = 0;
2065 
2066     const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB;
2067     int numConfigs;
2068 
2069     int attrs[50];
2070     unsigned int num_attrs = 0;
2071 
2072     GLWIN_DEBUG_MSG("glxWinCreateConfigsExt");
2073 
2074     screen->base.numFBConfigs = 0;
2075     screen->base.fbconfigs = NULL;
2076 
2077     if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs)) {
2078         ErrorF
2079             ("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n",
2080              glxWinErrorMessage());
2081         return;
2082     }
2083 
2084     LogMessage(X_INFO,
2085                "%d pixel formats reported by wglGetPixelFormatAttribivARB\n",
2086                numConfigs);
2087 
2088     n = 0;
2089 
2090 #define ADD_ATTR(a) { attrs[num_attrs++] = a; assert(num_attrs < ARRAY_SIZE(attrs)); }
2091 
2092     ADD_ATTR(WGL_DRAW_TO_WINDOW_ARB);
2093     ADD_ATTR(WGL_DRAW_TO_BITMAP_ARB);
2094     ADD_ATTR(WGL_ACCELERATION_ARB);
2095     ADD_ATTR(WGL_SWAP_LAYER_BUFFERS_ARB);
2096     ADD_ATTR(WGL_NUMBER_OVERLAYS_ARB);
2097     ADD_ATTR(WGL_NUMBER_UNDERLAYS_ARB);
2098     ADD_ATTR(WGL_TRANSPARENT_ARB);
2099     ADD_ATTR(WGL_TRANSPARENT_RED_VALUE_ARB);
2100     ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB);
2101     ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB);
2102     ADD_ATTR(WGL_TRANSPARENT_ALPHA_VALUE_ARB);
2103     ADD_ATTR(WGL_SUPPORT_OPENGL_ARB);
2104     ADD_ATTR(WGL_DOUBLE_BUFFER_ARB);
2105     ADD_ATTR(WGL_STEREO_ARB);
2106     ADD_ATTR(WGL_PIXEL_TYPE_ARB);
2107     ADD_ATTR(WGL_COLOR_BITS_ARB);
2108     ADD_ATTR(WGL_RED_BITS_ARB);
2109     ADD_ATTR(WGL_RED_SHIFT_ARB);
2110     ADD_ATTR(WGL_GREEN_BITS_ARB);
2111     ADD_ATTR(WGL_GREEN_SHIFT_ARB);
2112     ADD_ATTR(WGL_BLUE_BITS_ARB);
2113     ADD_ATTR(WGL_BLUE_SHIFT_ARB);
2114     ADD_ATTR(WGL_ALPHA_BITS_ARB);
2115     ADD_ATTR(WGL_ALPHA_SHIFT_ARB);
2116     ADD_ATTR(WGL_ACCUM_RED_BITS_ARB);
2117     ADD_ATTR(WGL_ACCUM_GREEN_BITS_ARB);
2118     ADD_ATTR(WGL_ACCUM_BLUE_BITS_ARB);
2119     ADD_ATTR(WGL_ACCUM_ALPHA_BITS_ARB);
2120     ADD_ATTR(WGL_DEPTH_BITS_ARB);
2121     ADD_ATTR(WGL_STENCIL_BITS_ARB);
2122     ADD_ATTR(WGL_AUX_BUFFERS_ARB);
2123     ADD_ATTR(WGL_SWAP_METHOD_ARB);
2124 
2125     if (screen->has_WGL_ARB_multisample) {
2126         // we may not query these attrs if WGL_ARB_multisample is not offered
2127         ADD_ATTR(WGL_SAMPLE_BUFFERS_ARB);
2128         ADD_ATTR(WGL_SAMPLES_ARB);
2129     }
2130 
2131     if (screen->has_WGL_ARB_render_texture) {
2132         // we may not query these attrs if WGL_ARB_render_texture is not offered
2133         ADD_ATTR(WGL_BIND_TO_TEXTURE_RGB_ARB);
2134         ADD_ATTR(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2135     }
2136 
2137     if (screen->has_WGL_ARB_pbuffer) {
2138         // we may not query these attrs if WGL_ARB_pbuffer is not offered
2139         ADD_ATTR(WGL_DRAW_TO_PBUFFER_ARB);
2140         ADD_ATTR(WGL_MAX_PBUFFER_PIXELS_ARB);
2141         ADD_ATTR(WGL_MAX_PBUFFER_WIDTH_ARB);
2142         ADD_ATTR(WGL_MAX_PBUFFER_HEIGHT_ARB);
2143     }
2144 
2145     if (screen->has_WGL_ARB_framebuffer_sRGB) {
2146         // we may not query these attrs if WGL_ARB_framebuffer_sRGB is not offered
2147         ADD_ATTR(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
2148     }
2149 
2150     /* fill in configs */
2151     for (i = 0; i < numConfigs; i++) {
2152         int values[num_attrs];
2153         GLXWinConfig temp;
2154         GLXWinConfig *c = &temp;
2155         GLXWinConfig *work;
2156         memset(c, 0, sizeof(GLXWinConfig));
2157 
2158         c->pixelFormatIndex = i + 1;
2159 
2160         if (!wglGetPixelFormatAttribivARBWrapper
2161             (hdc, i + 1, 0, num_attrs, attrs, values)) {
2162             ErrorF
2163                 ("wglGetPixelFormatAttribivARB failed for index %d, error %s\n",
2164                  i + 1, glxWinErrorMessage());
2165             break;
2166         }
2167 
2168 #define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
2169 
2170         if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0)) {
2171             rejects->notOpenGL++;
2172             GLWIN_DEBUG_MSG
2173                 ("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping",
2174                  i + 1);
2175             continue;
2176         }
2177 
2178         c->base.doubleBufferMode =
2179             ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, 0) ? GL_TRUE : GL_FALSE;
2180         c->base.stereoMode = ATTR_VALUE(WGL_STEREO_ARB, 0) ? GL_TRUE : GL_FALSE;
2181 
2182         c->base.redBits = ATTR_VALUE(WGL_RED_BITS_ARB, 0);
2183         c->base.greenBits = ATTR_VALUE(WGL_GREEN_BITS_ARB, 0);
2184         c->base.blueBits = ATTR_VALUE(WGL_BLUE_BITS_ARB, 0);
2185         c->base.alphaBits = ATTR_VALUE(WGL_ALPHA_BITS_ARB, 0);
2186 
2187         c->base.redMask =
2188             BITS_AND_SHIFT_TO_MASK(c->base.redBits,
2189                                    ATTR_VALUE(WGL_RED_SHIFT_ARB, 0));
2190         c->base.greenMask =
2191             BITS_AND_SHIFT_TO_MASK(c->base.greenBits,
2192                                    ATTR_VALUE(WGL_GREEN_SHIFT_ARB, 0));
2193         c->base.blueMask =
2194             BITS_AND_SHIFT_TO_MASK(c->base.blueBits,
2195                                    ATTR_VALUE(WGL_BLUE_SHIFT_ARB, 0));
2196         c->base.alphaMask =
2197             BITS_AND_SHIFT_TO_MASK(c->base.alphaBits,
2198                                    ATTR_VALUE(WGL_ALPHA_SHIFT_ARB, 0));
2199 
2200         switch (ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)) {
2201         case WGL_TYPE_COLORINDEX_ARB:
2202             c->base.indexBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
2203             c->base.rgbBits = 0;
2204             c->base.visualType = GLX_STATIC_COLOR;
2205             c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT;
2206 
2207             /*
2208               Assume RGBA rendering is available on all single-channel visuals
2209               (it is specified to render to red component in single-channel
2210               visuals, if supported, but there doesn't seem to be any mechanism
2211               to check if it is supported)
2212 
2213               Color index rendering is only supported on single-channel visuals
2214             */
2215 
2216             break;
2217 
2218         case WGL_TYPE_RGBA_ARB:
2219             c->base.indexBits = 0;
2220             c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
2221             c->base.visualType = GLX_TRUE_COLOR;
2222             c->base.renderType = GLX_RGBA_BIT;
2223             break;
2224 
2225         case WGL_TYPE_RGBA_FLOAT_ARB:
2226             c->base.indexBits = 0;
2227             c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
2228             c->base.visualType = GLX_TRUE_COLOR;
2229             c->base.renderType = GLX_RGBA_FLOAT_BIT_ARB;
2230             // assert pbuffer drawable
2231             // assert WGL_ARB_pixel_format_float
2232             break;
2233 
2234         case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
2235             c->base.indexBits = 0;
2236             c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
2237             c->base.visualType = GLX_TRUE_COLOR;
2238             c->base.renderType = GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT;
2239             // assert pbuffer drawable
2240             // assert WGL_EXT_pixel_format_packed_float
2241             break;
2242 
2243         default:
2244             rejects->unknownPixelType++;
2245             ErrorF
2246                 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n",
2247                  ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0));
2248             continue;
2249         }
2250 
2251         c->base.accumRedBits = ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, 0);
2252         c->base.accumGreenBits = ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, 0);
2253         c->base.accumBlueBits = ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, 0);
2254         c->base.accumAlphaBits = ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, 0);
2255 
2256         c->base.depthBits = ATTR_VALUE(WGL_DEPTH_BITS_ARB, 0);
2257         c->base.stencilBits = ATTR_VALUE(WGL_STENCIL_BITS_ARB, 0);
2258         c->base.numAuxBuffers = ATTR_VALUE(WGL_AUX_BUFFERS_ARB, 0);
2259 
2260         {
2261             int layers =
2262                 ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,
2263                            0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0);
2264 
2265             if (layers > 0) {
2266                 ErrorF
2267                     ("pixelFormat %d: has %d overlay, %d underlays which aren't currently handled\n",
2268                      i, ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB, 0),
2269                      ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0));
2270                 // XXX: need to iterate over layers?
2271             }
2272         }
2273         c->base.level = 0;
2274 
2275         c->base.visualID = -1;  // will be set by __glXScreenInit()
2276 
2277         /* EXT_visual_rating / GLX 1.2 */
2278         switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) {
2279         default:
2280             ErrorF
2281                 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_ACCELERATION_ARB\n",
2282                  ATTR_VALUE(WGL_ACCELERATION_ARB, 0));
2283 
2284         case WGL_NO_ACCELERATION_ARB:
2285             rejects->unaccelerated++;
2286             c->base.visualRating = GLX_SLOW_VISUAL_EXT;
2287             GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1);
2288             continue;
2289             break;
2290 
2291         case WGL_GENERIC_ACCELERATION_ARB:
2292         case WGL_FULL_ACCELERATION_ARB:
2293             c->base.visualRating = GLX_NONE_EXT;
2294             break;
2295         }
2296 
2297         /* EXT_visual_info / GLX 1.2 */
2298         // c->base.visualType is set above
2299         if (ATTR_VALUE(WGL_TRANSPARENT_ARB, 0)) {
2300             c->base.transparentPixel =
2301                 (c->base.visualType ==
2302                  GLX_TRUE_COLOR) ? GLX_TRANSPARENT_RGB_EXT :
2303                 GLX_TRANSPARENT_INDEX_EXT;
2304             c->base.transparentRed =
2305                 ATTR_VALUE(WGL_TRANSPARENT_RED_VALUE_ARB, 0);
2306             c->base.transparentGreen =
2307                 ATTR_VALUE(WGL_TRANSPARENT_GREEN_VALUE_ARB, 0);
2308             c->base.transparentBlue =
2309                 ATTR_VALUE(WGL_TRANSPARENT_BLUE_VALUE_ARB, 0);
2310             c->base.transparentAlpha =
2311                 ATTR_VALUE(WGL_TRANSPARENT_ALPHA_VALUE_ARB, 0);
2312             c->base.transparentIndex =
2313                 ATTR_VALUE(WGL_TRANSPARENT_INDEX_VALUE_ARB, 0);
2314         }
2315         else {
2316             c->base.transparentPixel = GLX_NONE_EXT;
2317             c->base.transparentRed = GLX_NONE;
2318             c->base.transparentGreen = GLX_NONE;
2319             c->base.transparentBlue = GLX_NONE;
2320             c->base.transparentAlpha = GLX_NONE;
2321             c->base.transparentIndex = GLX_NONE;
2322         }
2323 
2324         /* ARB_multisample / SGIS_multisample */
2325         if (screen->has_WGL_ARB_multisample) {
2326             c->base.sampleBuffers = ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, 0);
2327             c->base.samples = ATTR_VALUE(WGL_SAMPLES_ARB, 0);
2328         }
2329         else {
2330             c->base.sampleBuffers = 0;
2331             c->base.samples = 0;
2332         }
2333 
2334         /* SGIX_fbconfig / GLX 1.3 */
2335         c->base.drawableType =
2336             ((ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, 0) ? GLX_WINDOW_BIT : 0)
2337              | (ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, 0) ? GLX_PIXMAP_BIT : 0)
2338              | (ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, 0) ? GLX_PBUFFER_BIT : 0));
2339 
2340         c->base.fbconfigID = -1;        // will be set by __glXScreenInit()
2341 
2342         /* SGIX_pbuffer / GLX 1.3 */
2343         if (screen->has_WGL_ARB_pbuffer) {
2344             c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1);
2345             c->base.maxPbufferHeight =
2346                 ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1);
2347             c->base.maxPbufferPixels =
2348                 ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1);
2349         }
2350         else {
2351             c->base.maxPbufferWidth = -1;
2352             c->base.maxPbufferHeight = -1;
2353             c->base.maxPbufferPixels = -1;
2354         }
2355         c->base.optimalPbufferWidth = 0;        // there is no optimal value
2356         c->base.optimalPbufferHeight = 0;
2357 
2358         /* SGIX_visual_select_group */
2359         // arrange for visuals with the best acceleration to be preferred in selection
2360         switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) {
2361         case WGL_FULL_ACCELERATION_ARB:
2362             c->base.visualSelectGroup = 2;
2363             break;
2364 
2365         case WGL_GENERIC_ACCELERATION_ARB:
2366             c->base.visualSelectGroup = 1;
2367             break;
2368 
2369         default:
2370         case WGL_NO_ACCELERATION_ARB:
2371             c->base.visualSelectGroup = 0;
2372             break;
2373         }
2374 
2375         /* OML_swap_method */
2376         switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0)) {
2377         case WGL_SWAP_EXCHANGE_ARB:
2378             c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
2379             break;
2380 
2381         case WGL_SWAP_COPY_ARB:
2382             c->base.swapMethod = GLX_SWAP_COPY_OML;
2383             break;
2384 
2385         default:
2386             ErrorF
2387                 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n",
2388                  ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0));
2389 
2390         case WGL_SWAP_UNDEFINED_ARB:
2391             c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
2392         }
2393 
2394         /* EXT_texture_from_pixmap */
2395         /*
2396            Mesa's DRI configs always have bindToTextureRgb/Rgba TRUE (see driCreateConfigs(), so setting
2397            bindToTextureRgb/bindToTextureRgba to FALSE means that swrast can't find any fbConfigs to use,
2398            so setting these to 0, even if we know bindToTexture isn't available, isn't a good idea...
2399          */
2400         if (screen->has_WGL_ARB_render_texture) {
2401             c->base.bindToTextureRgb =
2402                 ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGB_ARB, -1);
2403             c->base.bindToTextureRgba =
2404                 ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGBA_ARB, -1);
2405         }
2406         else {
2407             c->base.bindToTextureRgb = -1;
2408             c->base.bindToTextureRgba = -1;
2409         }
2410         c->base.bindToMipmapTexture = -1;
2411         c->base.bindToTextureTargets =
2412             GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT |
2413             GLX_TEXTURE_RECTANGLE_BIT_EXT;
2414         c->base.yInverted = -1;
2415 
2416         /* WGL_ARB_framebuffer_sRGB */
2417         if (screen->has_WGL_ARB_framebuffer_sRGB)
2418             c->base.sRGBCapable = ATTR_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, 0);
2419         else
2420             c->base.sRGBCapable = 0;
2421 
2422         n++;
2423 
2424         // allocate and save
2425         work = malloc(sizeof(GLXWinConfig));
2426         if (NULL == work) {
2427             ErrorF("Failed to allocate GLXWinConfig\n");
2428             break;
2429         }
2430         *work = temp;
2431 
2432         // note the first config
2433         if (!first)
2434             first = work;
2435 
2436         // update previous config to point to this config
2437         if (prev)
2438             prev->base.next = &(work->base);
2439         prev = work;
2440     }
2441 
2442     screen->base.numFBConfigs = n;
2443     screen->base.fbconfigs = first ? &(first->base) : NULL;
2444 }
2445