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