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