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