1706f2543Smrg/*
2706f2543Smrg * File: indirect.c
3706f2543Smrg * Purpose: A GLX implementation that uses Windows OpenGL library
4706f2543Smrg *
5706f2543Smrg * Authors: Alexander Gottwald
6706f2543Smrg *          Jon TURNEY
7706f2543Smrg *
8706f2543Smrg * Copyright (c) Jon TURNEY 2009
9706f2543Smrg * Copyright (c) Alexander Gottwald 2004
10706f2543Smrg *
11706f2543Smrg * Portions of this file are copied from GL/apple/indirect.c,
12706f2543Smrg * which contains the following copyright:
13706f2543Smrg *
14706f2543Smrg * Copyright (c) 2007, 2008, 2009 Apple Inc.
15706f2543Smrg * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
16706f2543Smrg * Copyright (c) 2002 Greg Parker. All Rights Reserved.
17706f2543Smrg *
18706f2543Smrg * Portions of this file are copied from Mesa's xf86glx.c,
19706f2543Smrg * which contains the following copyright:
20706f2543Smrg *
21706f2543Smrg * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
22706f2543Smrg * All Rights Reserved.
23706f2543Smrg *
24706f2543Smrg *
25706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
26706f2543Smrg * copy of this software and associated documentation files (the "Software"),
27706f2543Smrg * to deal in the Software without restriction, including without limitation
28706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
29706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
30706f2543Smrg * Software is furnished to do so, subject to the following conditions:
31706f2543Smrg *
32706f2543Smrg * The above copyright notice and this permission notice shall be included in
33706f2543Smrg * all copies or substantial portions of the Software.
34706f2543Smrg *
35706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
39706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
40706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
41706f2543Smrg * DEALINGS IN THE SOFTWARE.
42706f2543Smrg */
43706f2543Smrg
44706f2543Smrg/*
45706f2543Smrg  TODO:
46706f2543Smrg  - hook up remaining unimplemented extensions
47706f2543Smrg  - research what guarantees glXWaitX, glXWaitGL are supposed to offer, and implement then
48706f2543Smrg    using GdiFlush and/or glFinish
49706f2543Smrg  - pbuffer clobbering: we don't get async notification, but can we arrange to emit the
50706f2543Smrg    event when we notice it's been clobbered? at the very least, check if it's been clobbered
51706f2543Smrg    before using it?
52706f2543Smrg  - are the __GLXConfig * we get handed back ones we are made (so we can extend the structure
53706f2543Smrg    with privates?) Or are they created inside the GLX core as well?
54706f2543Smrg*/
55706f2543Smrg
56706f2543Smrg/*
57706f2543Smrg  MSDN clarifications:
58706f2543Smrg
59706f2543Smrg  It says SetPixelFormat()'s PIXELFORMATDESCRIPTOR pointer argument has no effect
60706f2543Smrg  except on metafiles, this seems to mean that as it's ok to supply NULL if the DC
61706f2543Smrg  is not for a metafile
62706f2543Smrg
63706f2543Smrg  wglMakeCurrent ignores the hdc if hglrc is NULL, so wglMakeCurrent(NULL, NULL)
64706f2543Smrg  is used to make no context current
65706f2543Smrg
66706f2543Smrg*/
67706f2543Smrg
68706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H
69706f2543Smrg#include <xwin-config.h>
70706f2543Smrg#endif
71706f2543Smrg
72706f2543Smrg#include "glwindows.h"
73706f2543Smrg#include <glx/glxserver.h>
74706f2543Smrg#include <glx/glxutil.h>
75706f2543Smrg#include <glx/extension_string.h>
76706f2543Smrg#include <GL/glxtokens.h>
77706f2543Smrg
78706f2543Smrg#include <winpriv.h>
79706f2543Smrg#include <wgl_ext_api.h>
80706f2543Smrg
81706f2543Smrg#define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1]))
82706f2543Smrg
83706f2543Smrg/* ---------------------------------------------------------------------- */
84706f2543Smrg/*
85706f2543Smrg *   structure definitions
86706f2543Smrg */
87706f2543Smrg
88706f2543Smrgtypedef struct __GLXWinContext  __GLXWinContext;
89706f2543Smrgtypedef struct __GLXWinDrawable __GLXWinDrawable;
90706f2543Smrgtypedef struct __GLXWinScreen glxWinScreen;
91706f2543Smrgtypedef struct __GLXWinConfig GLXWinConfig;
92706f2543Smrg
93706f2543Smrgstruct __GLXWinContext {
94706f2543Smrg  __GLXcontext base;
95706f2543Smrg  HGLRC ctx;                         /* Windows GL Context */
96706f2543Smrg  __GLXWinContext *shareContext;     /* Context with which we will share display lists and textures */
97706f2543Smrg  HWND hwnd;                         /* For detecting when HWND has changed */
98706f2543Smrg};
99706f2543Smrg
100706f2543Smrgstruct __GLXWinDrawable
101706f2543Smrg{
102706f2543Smrg  __GLXdrawable base;
103706f2543Smrg  __GLXWinContext *drawContext;
104706f2543Smrg  __GLXWinContext *readContext;
105706f2543Smrg
106706f2543Smrg  /* If this drawable is GLX_DRAWABLE_PBUFFER */
107706f2543Smrg  HPBUFFERARB hPbuffer;
108706f2543Smrg
109706f2543Smrg  /* If this drawable is GLX_DRAWABLE_PIXMAP */
110706f2543Smrg  HDC dibDC;
111706f2543Smrg  HBITMAP hDIB;
112706f2543Smrg  HBITMAP hOldDIB; /* original DIB for DC */
113706f2543Smrg  void *pOldBits; /* original pBits for this drawable's pixmap */
114706f2543Smrg};
115706f2543Smrg
116706f2543Smrgstruct __GLXWinScreen
117706f2543Smrg{
118706f2543Smrg  __GLXscreen base;
119706f2543Smrg
120706f2543Smrg  /* Supported GLX extensions */
121706f2543Smrg  unsigned char glx_enable_bits[__GLX_EXT_BYTES];
122706f2543Smrg
123706f2543Smrg  Bool has_WGL_ARB_multisample;
124706f2543Smrg  Bool has_WGL_ARB_pixel_format;
125706f2543Smrg  Bool has_WGL_ARB_pbuffer;
126706f2543Smrg  Bool has_WGL_ARB_render_texture;
127706f2543Smrg
128706f2543Smrg  /* wrapped screen functions */
129706f2543Smrg  RealizeWindowProcPtr RealizeWindow;
130706f2543Smrg  UnrealizeWindowProcPtr UnrealizeWindow;
131706f2543Smrg  CopyWindowProcPtr CopyWindow;
132706f2543Smrg};
133706f2543Smrg
134706f2543Smrgstruct __GLXWinConfig
135706f2543Smrg{
136706f2543Smrg  __GLXconfig base;
137706f2543Smrg  int pixelFormatIndex;
138706f2543Smrg};
139706f2543Smrg
140706f2543Smrg/* ---------------------------------------------------------------------- */
141706f2543Smrg/*
142706f2543Smrg * Various debug helpers
143706f2543Smrg */
144706f2543Smrg
145706f2543Smrg#define GLWIN_DEBUG_HWND(hwnd)  \
146706f2543Smrg    if (glxWinDebugSettings.dumpHWND) { \
147706f2543Smrg        char buffer[1024]; \
148706f2543Smrg        if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; \
149706f2543Smrg        GLWIN_DEBUG_MSG("Got HWND %p for window '%s'", hwnd, buffer); \
150706f2543Smrg    }
151706f2543Smrg
152706f2543SmrgglxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0};
153706f2543Smrg
154706f2543Smrgstatic void glxWinInitDebugSettings(void)
155706f2543Smrg{
156706f2543Smrg    char *envptr;
157706f2543Smrg
158706f2543Smrg    envptr = getenv("GLWIN_ENABLE_DEBUG");
159706f2543Smrg    if (envptr != NULL)
160706f2543Smrg        glxWinDebugSettings.enableDebug = (atoi(envptr) == 1);
161706f2543Smrg
162706f2543Smrg    envptr = getenv("GLWIN_ENABLE_TRACE");
163706f2543Smrg    if (envptr != NULL)
164706f2543Smrg        glxWinDebugSettings.enableTrace = (atoi(envptr) == 1);
165706f2543Smrg
166706f2543Smrg    envptr = getenv("GLWIN_DUMP_PFD");
167706f2543Smrg    if (envptr != NULL)
168706f2543Smrg        glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1);
169706f2543Smrg
170706f2543Smrg    envptr = getenv("GLWIN_DUMP_HWND");
171706f2543Smrg    if (envptr != NULL)
172706f2543Smrg        glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1);
173706f2543Smrg
174706f2543Smrg    envptr = getenv("GLWIN_DUMP_DC");
175706f2543Smrg    if (envptr != NULL)
176706f2543Smrg        glxWinDebugSettings.dumpDC = (atoi(envptr) == 1);
177706f2543Smrg
178706f2543Smrg    envptr = getenv("GLWIN_ENABLE_GLCALL_TRACE");
179706f2543Smrg    if (envptr != NULL)
180706f2543Smrg        glxWinDebugSettings.enableGLcallTrace = (atoi(envptr) == 1);
181706f2543Smrg
182706f2543Smrg    envptr = getenv("GLWIN_ENABLE_WGLCALL_TRACE");
183706f2543Smrg    if (envptr != NULL)
184706f2543Smrg        glxWinDebugSettings.enableWGLcallTrace = (atoi(envptr) == 1);
185706f2543Smrg
186706f2543Smrg    envptr = getenv("GLWIN_DEBUG_ALL");
187706f2543Smrg    if (envptr != NULL)
188706f2543Smrg      {
189706f2543Smrg        glxWinDebugSettings.enableDebug = 1;
190706f2543Smrg        glxWinDebugSettings.enableTrace = 1;
191706f2543Smrg        glxWinDebugSettings.dumpPFD = 1;
192706f2543Smrg        glxWinDebugSettings.dumpHWND = 1;
193706f2543Smrg        glxWinDebugSettings.dumpDC = 1;
194706f2543Smrg        glxWinDebugSettings.enableGLcallTrace = 1;
195706f2543Smrg        glxWinDebugSettings.enableWGLcallTrace = 1;
196706f2543Smrg      }
197706f2543Smrg}
198706f2543Smrg
199706f2543Smrgstatic
200706f2543Smrgconst char *glxWinErrorMessage(void)
201706f2543Smrg{
202706f2543Smrg  static char errorbuffer[1024];
203706f2543Smrg
204706f2543Smrg  if (!FormatMessage(
205706f2543Smrg                     FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
206706f2543Smrg                     NULL,
207706f2543Smrg                     GetLastError(),
208706f2543Smrg                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
209706f2543Smrg                     (LPTSTR) &errorbuffer,
210706f2543Smrg                     sizeof(errorbuffer),
211706f2543Smrg                     NULL ))
212706f2543Smrg    {
213706f2543Smrg      snprintf(errorbuffer, sizeof(errorbuffer), "Unknown error in FormatMessage: %08x!", (unsigned)GetLastError());
214706f2543Smrg    }
215706f2543Smrg
216706f2543Smrg  if (errorbuffer[strlen(errorbuffer)-1] == '\n')
217706f2543Smrg    errorbuffer[strlen(errorbuffer)-1] = 0;
218706f2543Smrg
219706f2543Smrg  return errorbuffer;
220706f2543Smrg}
221706f2543Smrg
222706f2543Smrgstatic void pfdOut(const PIXELFORMATDESCRIPTOR *pfd);
223706f2543Smrg
224706f2543Smrg#define DUMP_PFD_FLAG(flag) \
225706f2543Smrg    if (pfd->dwFlags & flag) { \
226706f2543Smrg        ErrorF("%s%s", pipesym, #flag); \
227706f2543Smrg        pipesym = " | "; \
228706f2543Smrg    }
229706f2543Smrg
230706f2543Smrgstatic void pfdOut(const PIXELFORMATDESCRIPTOR *pfd)
231706f2543Smrg{
232706f2543Smrg    const char *pipesym = ""; /* will be set after first flag dump */
233706f2543Smrg    ErrorF("PIXELFORMATDESCRIPTOR:\n");
234706f2543Smrg    ErrorF("nSize = %u\n", pfd->nSize);
235706f2543Smrg    ErrorF("nVersion = %u\n", pfd->nVersion);
236706f2543Smrg    ErrorF("dwFlags = %lu = {", pfd->dwFlags);
237706f2543Smrg        DUMP_PFD_FLAG(PFD_DOUBLEBUFFER);
238706f2543Smrg        DUMP_PFD_FLAG(PFD_STEREO);
239706f2543Smrg        DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW);
240706f2543Smrg        DUMP_PFD_FLAG(PFD_DRAW_TO_BITMAP);
241706f2543Smrg        DUMP_PFD_FLAG(PFD_SUPPORT_GDI);
242706f2543Smrg        DUMP_PFD_FLAG(PFD_SUPPORT_OPENGL);
243706f2543Smrg        DUMP_PFD_FLAG(PFD_GENERIC_FORMAT);
244706f2543Smrg        DUMP_PFD_FLAG(PFD_NEED_PALETTE);
245706f2543Smrg        DUMP_PFD_FLAG(PFD_NEED_SYSTEM_PALETTE);
246706f2543Smrg        DUMP_PFD_FLAG(PFD_SWAP_EXCHANGE);
247706f2543Smrg        DUMP_PFD_FLAG(PFD_SWAP_COPY);
248706f2543Smrg        DUMP_PFD_FLAG(PFD_SWAP_LAYER_BUFFERS);
249706f2543Smrg        DUMP_PFD_FLAG(PFD_GENERIC_ACCELERATED);
250706f2543Smrg        DUMP_PFD_FLAG(PFD_DEPTH_DONTCARE);
251706f2543Smrg        DUMP_PFD_FLAG(PFD_DOUBLEBUFFER_DONTCARE);
252706f2543Smrg        DUMP_PFD_FLAG(PFD_STEREO_DONTCARE);
253706f2543Smrg    ErrorF("}\n");
254706f2543Smrg
255706f2543Smrg    ErrorF("iPixelType = %hu = %s\n", pfd->iPixelType,
256706f2543Smrg            (pfd->iPixelType == PFD_TYPE_RGBA ? "PFD_TYPE_RGBA" : "PFD_TYPE_COLORINDEX"));
257706f2543Smrg    ErrorF("cColorBits = %hhu\n", pfd->cColorBits);
258706f2543Smrg    ErrorF("cRedBits = %hhu\n", pfd->cRedBits);
259706f2543Smrg    ErrorF("cRedShift = %hhu\n", pfd->cRedShift);
260706f2543Smrg    ErrorF("cGreenBits = %hhu\n", pfd->cGreenBits);
261706f2543Smrg    ErrorF("cGreenShift = %hhu\n", pfd->cGreenShift);
262706f2543Smrg    ErrorF("cBlueBits = %hhu\n", pfd->cBlueBits);
263706f2543Smrg    ErrorF("cBlueShift = %hhu\n", pfd->cBlueShift);
264706f2543Smrg    ErrorF("cAlphaBits = %hhu\n", pfd->cAlphaBits);
265706f2543Smrg    ErrorF("cAlphaShift = %hhu\n", pfd->cAlphaShift);
266706f2543Smrg    ErrorF("cAccumBits = %hhu\n", pfd->cAccumBits);
267706f2543Smrg    ErrorF("cAccumRedBits = %hhu\n", pfd->cAccumRedBits);
268706f2543Smrg    ErrorF("cAccumGreenBits = %hhu\n", pfd->cAccumGreenBits);
269706f2543Smrg    ErrorF("cAccumBlueBits = %hhu\n", pfd->cAccumBlueBits);
270706f2543Smrg    ErrorF("cAccumAlphaBits = %hhu\n", pfd->cAccumAlphaBits);
271706f2543Smrg    ErrorF("cDepthBits = %hhu\n", pfd->cDepthBits);
272706f2543Smrg    ErrorF("cStencilBits = %hhu\n", pfd->cStencilBits);
273706f2543Smrg    ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers);
274706f2543Smrg    ErrorF("iLayerType = %hhu\n", pfd->iLayerType);
275706f2543Smrg    ErrorF("bReserved = %hhu\n", pfd->bReserved);
276706f2543Smrg    ErrorF("dwLayerMask = %lu\n", pfd->dwLayerMask);
277706f2543Smrg    ErrorF("dwVisibleMask = %lu\n", pfd->dwVisibleMask);
278706f2543Smrg    ErrorF("dwDamageMask = %lu\n", pfd->dwDamageMask);
279706f2543Smrg    ErrorF("\n");
280706f2543Smrg}
281706f2543Smrg
282706f2543Smrgstatic const char *
283706f2543Smrgvisual_class_name(int cls)
284706f2543Smrg{
285706f2543Smrg  switch (cls) {
286706f2543Smrg  case GLX_STATIC_COLOR:
287706f2543Smrg    return "StaticColor";
288706f2543Smrg  case GLX_PSEUDO_COLOR:
289706f2543Smrg    return "PseudoColor";
290706f2543Smrg  case GLX_STATIC_GRAY:
291706f2543Smrg    return "StaticGray";
292706f2543Smrg  case GLX_GRAY_SCALE:
293706f2543Smrg    return "GrayScale";
294706f2543Smrg  case GLX_TRUE_COLOR:
295706f2543Smrg     return "TrueColor";
296706f2543Smrg  case GLX_DIRECT_COLOR:
297706f2543Smrg     return "DirectColor";
298706f2543Smrg  default:
299706f2543Smrg    return "-none-";
300706f2543Smrg  }
301706f2543Smrg}
302706f2543Smrg
303706f2543Smrgstatic const char *
304706f2543Smrgswap_method_name(int mthd)
305706f2543Smrg{
306706f2543Smrg  switch (mthd)
307706f2543Smrg    {
308706f2543Smrg    case GLX_SWAP_EXCHANGE_OML:
309706f2543Smrg      return "xchg";
310706f2543Smrg    case GLX_SWAP_COPY_OML:
311706f2543Smrg      return "copy";
312706f2543Smrg    case GLX_SWAP_UNDEFINED_OML:
313706f2543Smrg      return "    ";
314706f2543Smrg    default:
315706f2543Smrg      return "????";
316706f2543Smrg    }
317706f2543Smrg}
318706f2543Smrg
319706f2543Smrgstatic void
320706f2543SmrgfbConfigsDump(unsigned int n, __GLXconfig *c)
321706f2543Smrg{
322706f2543Smrg  ErrorF("%d fbConfigs\n", n);
323706f2543Smrg  ErrorF("pxf vis  fb                      render         Ste                     aux    accum        MS    drawable             Group/\n");
324706f2543Smrg  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");
325706f2543Smrg  ErrorF("-----------------------------------------------------------------------------------------------------------------------------\n");
326706f2543Smrg
327706f2543Smrg  while (c != NULL)
328706f2543Smrg    {
329706f2543Smrg      unsigned int i = ((GLXWinConfig *)c)->pixelFormatIndex;
330706f2543Smrg
331706f2543Smrg      ErrorF("%3d  %2x  %2x "
332706f2543Smrg             "%-11s"
333706f2543Smrg             " %3d %3d   %s   %s  %s %s  %s  "
334706f2543Smrg             "%2d %2d %2d %2d  "
335706f2543Smrg             "%2d %2d  "
336706f2543Smrg             "%2d  "
337706f2543Smrg             "%2d %2d %2d %2d"
338706f2543Smrg             "   %2d   %2d"
339706f2543Smrg             "  %s %s %s "
340706f2543Smrg             "    %s   "
341706f2543Smrg             "  %s   "
342706f2543Smrg             "  %d %s"
343706f2543Smrg             "\n",
344706f2543Smrg             i, c->visualID, c->fbconfigID,
345706f2543Smrg             visual_class_name(c->visualType),
346706f2543Smrg             c->rgbBits ? c->rgbBits : c->indexBits,
347706f2543Smrg             c->level,
348706f2543Smrg	     (c->renderType & GLX_RGBA_BIT) ? "y" : ".",
349706f2543Smrg	     (c->renderType & GLX_COLOR_INDEX_BIT) ? "y" : ".",
350706f2543Smrg	     c->doubleBufferMode ? "y" : ".",
351706f2543Smrg             swap_method_name(c->swapMethod),
352706f2543Smrg	     c->stereoMode ? "y" : ".",
353706f2543Smrg             c->redBits, c->greenBits, c->blueBits, c->alphaBits,
354706f2543Smrg             c->depthBits, c->stencilBits,
355706f2543Smrg             c->numAuxBuffers,
356706f2543Smrg             c->accumRedBits, c->accumGreenBits, c->accumBlueBits, c->accumAlphaBits,
357706f2543Smrg             c->sampleBuffers, c->samples,
358706f2543Smrg             (c->drawableType & GLX_WINDOW_BIT) ? "y" : ".",
359706f2543Smrg             (c->drawableType & GLX_PIXMAP_BIT) ? "y" : ".",
360706f2543Smrg             (c->drawableType & GLX_PBUFFER_BIT) ? "y" : ".",
361706f2543Smrg             ".",
362706f2543Smrg             (c->transparentPixel != GLX_NONE_EXT) ? "y" : ".",
363706f2543Smrg             c->visualSelectGroup, (c->visualRating == GLX_SLOW_VISUAL_EXT) ? "*" : " ");
364706f2543Smrg
365706f2543Smrg      c = c->next;
366706f2543Smrg    }
367706f2543Smrg}
368706f2543Smrg
369706f2543Smrg/* ---------------------------------------------------------------------- */
370706f2543Smrg/*
371706f2543Smrg * Forward declarations
372706f2543Smrg */
373706f2543Smrg
374706f2543Smrgstatic __GLXscreen *glxWinScreenProbe(ScreenPtr pScreen);
375706f2543Smrgstatic __GLXcontext *glxWinCreateContext(__GLXscreen *screen,
376706f2543Smrg                                        __GLXconfig *modes,
377706f2543Smrg                                        __GLXcontext *baseShareContext);
378706f2543Smrgstatic __GLXdrawable *glxWinCreateDrawable(ClientPtr client,
379706f2543Smrg                                          __GLXscreen *screen,
380706f2543Smrg                                          DrawablePtr pDraw,
381706f2543Smrg                                          XID drawId,
382706f2543Smrg                                          int type,
383706f2543Smrg                                          XID glxDrawId,
384706f2543Smrg                                          __GLXconfig *conf);
385706f2543Smrg
386706f2543Smrgstatic Bool glxWinRealizeWindow(WindowPtr pWin);
387706f2543Smrgstatic Bool glxWinUnrealizeWindow(WindowPtr pWin);
388706f2543Smrgstatic void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
389706f2543Smrg
390706f2543Smrgstatic HDC glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HDC *hdc, HWND *hwnd);
391706f2543Smrgstatic void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable *draw);
392706f2543Smrg
393706f2543Smrgstatic void glxWinCreateConfigs(HDC dc, glxWinScreen *screen);
394706f2543Smrgstatic void glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen);
395706f2543Smrgstatic int fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride);
396706f2543Smrgstatic int fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen);
397706f2543Smrg
398706f2543Smrg/* ---------------------------------------------------------------------- */
399706f2543Smrg/*
400706f2543Smrg * The GLX provider
401706f2543Smrg */
402706f2543Smrg
403706f2543Smrg__GLXprovider __glXWGLProvider = {
404706f2543Smrg    glxWinScreenProbe,
405706f2543Smrg    "Win32 native WGL",
406706f2543Smrg    NULL
407706f2543Smrg};
408706f2543Smrg
409706f2543Smrgvoid
410706f2543SmrgglxWinPushNativeProvider(void)
411706f2543Smrg{
412706f2543Smrg  GlxPushProvider(&__glXWGLProvider);
413706f2543Smrg}
414706f2543Smrg
415706f2543Smrg/* ---------------------------------------------------------------------- */
416706f2543Smrg/*
417706f2543Smrg * Screen functions
418706f2543Smrg */
419706f2543Smrg
420706f2543Smrgstatic void
421706f2543SmrgglxWinScreenDestroy(__GLXscreen *screen)
422706f2543Smrg{
423706f2543Smrg    GLWIN_DEBUG_MSG("glxWinScreenDestroy(%p)", screen);
424706f2543Smrg    __glXScreenDestroy(screen);
425706f2543Smrg    free(screen);
426706f2543Smrg}
427706f2543Smrg
428706f2543Smrgstatic int
429706f2543SmrgglxWinScreenSwapInterval(__GLXdrawable *drawable, int interval)
430706f2543Smrg{
431706f2543Smrg  BOOL ret = wglSwapIntervalEXTWrapper(interval);
432706f2543Smrg  if (!ret)
433706f2543Smrg    {
434706f2543Smrg      ErrorF("wglSwapIntervalEXT interval %d failed:%s\n", interval, glxWinErrorMessage());
435706f2543Smrg    }
436706f2543Smrg  return ret;
437706f2543Smrg}
438706f2543Smrg
439706f2543Smrg/*
440706f2543Smrg  Report the extensions split and formatted to avoid overflowing a line
441706f2543Smrg */
442706f2543Smrgstatic void
443706f2543SmrgglxLogExtensions(const char *prefix, const char *extensions)
444706f2543Smrg{
445706f2543Smrg  int length = 0;
446706f2543Smrg  char *strl;
447706f2543Smrg  char *str = strdup(extensions);
448706f2543Smrg
449706f2543Smrg  if (str == NULL)
450706f2543Smrg    {
451706f2543Smrg      ErrorF("glxLogExtensions: xalloc error\n");
452706f2543Smrg      return;
453706f2543Smrg    }
454706f2543Smrg
455706f2543Smrg  strl = strtok(str, " ");
456706f2543Smrg  ErrorF("%s%s", prefix, strl);
457706f2543Smrg  length = strlen(prefix) + strlen(strl);
458706f2543Smrg
459706f2543Smrg  while (1)
460706f2543Smrg    {
461706f2543Smrg      strl = strtok(NULL, " ");
462706f2543Smrg      if (strl == NULL) break;
463706f2543Smrg
464706f2543Smrg      if (length + strlen(strl) + 1 > 120)
465706f2543Smrg        {
466706f2543Smrg          ErrorF("\n");
467706f2543Smrg          ErrorF("%s",prefix);
468706f2543Smrg          length = strlen(prefix);
469706f2543Smrg        }
470706f2543Smrg      else
471706f2543Smrg        {
472706f2543Smrg          ErrorF(" ");
473706f2543Smrg          length++;
474706f2543Smrg        }
475706f2543Smrg
476706f2543Smrg      ErrorF("%s", strl);
477706f2543Smrg      length = length + strlen(strl);
478706f2543Smrg    }
479706f2543Smrg
480706f2543Smrg  ErrorF("\n");
481706f2543Smrg
482706f2543Smrg  free(str);
483706f2543Smrg}
484706f2543Smrg
485706f2543Smrg/* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */
486706f2543Smrgstatic __GLXscreen *
487706f2543SmrgglxWinScreenProbe(ScreenPtr pScreen)
488706f2543Smrg{
489706f2543Smrg    glxWinScreen *screen;
490706f2543Smrg    const char *gl_extensions;
491706f2543Smrg    const char *wgl_extensions;
492706f2543Smrg    HWND hwnd;
493706f2543Smrg    HDC hdc;
494706f2543Smrg    HGLRC hglrc;
495706f2543Smrg
496706f2543Smrg    GLWIN_DEBUG_MSG("glxWinScreenProbe");
497706f2543Smrg
498706f2543Smrg    glxWinInitDebugSettings();
499706f2543Smrg
500706f2543Smrg    if (pScreen == NULL)
501706f2543Smrg	return NULL;
502706f2543Smrg
503706f2543Smrg    if (!winCheckScreenAiglxIsSupported(pScreen))
504706f2543Smrg      {
505706f2543Smrg        LogMessage(X_ERROR,"AIGLX: No native OpenGL in modes with a root window\n");
506706f2543Smrg        return NULL;
507706f2543Smrg      }
508706f2543Smrg
509706f2543Smrg    screen = calloc(1, sizeof(glxWinScreen));
510706f2543Smrg
511706f2543Smrg    if (NULL == screen)
512706f2543Smrg	return NULL;
513706f2543Smrg
514706f2543Smrg    /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */
515706f2543Smrg    screen->RealizeWindow = pScreen->RealizeWindow;
516706f2543Smrg    pScreen->RealizeWindow = glxWinRealizeWindow;
517706f2543Smrg    screen->UnrealizeWindow = pScreen->UnrealizeWindow;
518706f2543Smrg    pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
519706f2543Smrg    screen->CopyWindow = pScreen->CopyWindow;
520706f2543Smrg    pScreen->CopyWindow = glxWinCopyWindow;
521706f2543Smrg
522706f2543Smrg    /* Dump out some useful information about the native renderer */
523706f2543Smrg
524706f2543Smrg    // create window class
525706f2543Smrg#define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest"
526706f2543Smrg    {
527706f2543Smrg      static wATOM glTestWndClass = 0;
528706f2543Smrg      if (glTestWndClass == 0)
529706f2543Smrg        {
530706f2543Smrg          WNDCLASSEX wc;
531706f2543Smrg          wc.cbSize = sizeof(WNDCLASSEX);
532706f2543Smrg          wc.style = CS_HREDRAW | CS_VREDRAW;
533706f2543Smrg          wc.lpfnWndProc = DefWindowProc;
534706f2543Smrg          wc.cbClsExtra = 0;
535706f2543Smrg          wc.cbWndExtra = 0;
536706f2543Smrg          wc.hInstance = GetModuleHandle(NULL);
537706f2543Smrg          wc.hIcon = 0;
538706f2543Smrg          wc.hCursor = 0;
539706f2543Smrg          wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
540706f2543Smrg          wc.lpszMenuName = NULL;
541706f2543Smrg          wc.lpszClassName = WIN_GL_TEST_WINDOW_CLASS;
542706f2543Smrg          wc.hIconSm = 0;
543706f2543Smrg          RegisterClassEx (&wc);
544706f2543Smrg      }
545706f2543Smrg    }
546706f2543Smrg
547706f2543Smrg    // create an invisible window for a scratch DC
548706f2543Smrg    hwnd = CreateWindowExA(0,
549706f2543Smrg                           WIN_GL_TEST_WINDOW_CLASS,
550706f2543Smrg                           "XWin GL Renderer Capabilities Test Window",
551706f2543Smrg                           0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
552706f2543Smrg    if (hwnd == NULL)
553706f2543Smrg      LogMessage(X_ERROR,"AIGLX: Couldn't create a window for render capabilities testing\n");
554706f2543Smrg
555706f2543Smrg    hdc = GetDC(hwnd);
556706f2543Smrg
557706f2543Smrg    // we must set a pixel format before we can create a context, just use the first one...
558706f2543Smrg    SetPixelFormat(hdc, 1, NULL);
559706f2543Smrg    hglrc = wglCreateContext(hdc);
560706f2543Smrg    wglMakeCurrent(hdc, hglrc);
561706f2543Smrg
562706f2543Smrg    // initialize wgl extension proc pointers (don't call them before here...)
563706f2543Smrg    // (but we need to have a current context for them to be resolvable)
564706f2543Smrg    wglResolveExtensionProcs();
565706f2543Smrg
566706f2543Smrg    ErrorF("GL_VERSION:     %s\n", glGetStringWrapperNonstatic(GL_VERSION));
567706f2543Smrg    ErrorF("GL_VENDOR:      %s\n", glGetStringWrapperNonstatic(GL_VENDOR));
568706f2543Smrg    ErrorF("GL_RENDERER:    %s\n", glGetStringWrapperNonstatic(GL_RENDERER));
569706f2543Smrg    gl_extensions = (const char *)glGetStringWrapperNonstatic(GL_EXTENSIONS);
570706f2543Smrg    glxLogExtensions("GL_EXTENSIONS:  ", gl_extensions);
571706f2543Smrg    wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
572706f2543Smrg    if (!wgl_extensions) wgl_extensions = "";
573706f2543Smrg    glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions);
574706f2543Smrg
575706f2543Smrg    // Can you see the problem here?  The extensions string is DC specific
576706f2543Smrg    // Different DCs for windows on a multimonitor system driven by multiple cards
577706f2543Smrg    // might have completely different capabilities.  Of course, good luck getting
578706f2543Smrg    // those screens to be accelerated in XP and earlier...
579706f2543Smrg
580706f2543Smrg    {
581706f2543Smrg      // testing facility to not use any WGL extensions
582706f2543Smrg      char *envptr = getenv("GLWIN_NO_WGL_EXTENSIONS");
583706f2543Smrg      if ((envptr != NULL) && (atoi(envptr) != 0))
584706f2543Smrg        {
585706f2543Smrg          ErrorF("GLWIN_NO_WGL_EXTENSIONS is set, ignoring WGL_EXTENSIONS\n");
586706f2543Smrg          wgl_extensions = "";
587706f2543Smrg        }
588706f2543Smrg    }
589706f2543Smrg
590706f2543Smrg    {
591706f2543Smrg      Bool glx_sgi_make_current_read = FALSE;
592706f2543Smrg
593706f2543Smrg      //
594706f2543Smrg      // Based on the WGL extensions available, enable various GLX extensions
595706f2543Smrg      // XXX: make this table-driven ?
596706f2543Smrg      //
597706f2543Smrg      memset(screen->glx_enable_bits, 0, __GLX_EXT_BYTES);
598706f2543Smrg
599706f2543Smrg      __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_visual_info");
600706f2543Smrg      __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_visual_rating");
601706f2543Smrg      __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_import_context");
602706f2543Smrg      __glXEnableExtension(screen->glx_enable_bits, "GLX_OML_swap_method");
603706f2543Smrg      __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIX_fbconfig");
604706f2543Smrg
605706f2543Smrg      if (strstr(wgl_extensions, "WGL_ARB_make_current_read"))
606706f2543Smrg        {
607706f2543Smrg          __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_make_current_read");
608706f2543Smrg          LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
609706f2543Smrg          glx_sgi_make_current_read = TRUE;
610706f2543Smrg        }
611706f2543Smrg
612706f2543Smrg      if (strstr(gl_extensions, "GL_WIN_swap_hint"))
613706f2543Smrg        {
614706f2543Smrg          __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
615706f2543Smrg          LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
616706f2543Smrg        }
617706f2543Smrg
618706f2543Smrg      if (strstr(wgl_extensions, "WGL_EXT_swap_control"))
619706f2543Smrg        {
620706f2543Smrg          __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control");
621706f2543Smrg          __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_swap_control");
622706f2543Smrg          LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
623706f2543Smrg        }
624706f2543Smrg
625706f2543Smrg/*       // Hmm?  screen->texOffset */
626706f2543Smrg/*       if (strstr(wgl_extensions, "WGL_ARB_render_texture")) */
627706f2543Smrg/*         { */
628706f2543Smrg/*           __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_texture_from_pixmap"); */
629706f2543Smrg/*           LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); */
630706f2543Smrg/*           screen->has_WGL_ARB_render_texture = TRUE; */
631706f2543Smrg/*         } */
632706f2543Smrg
633706f2543Smrg      if (strstr(wgl_extensions, "WGL_ARB_pbuffer"))
634706f2543Smrg        {
635706f2543Smrg          __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIX_pbuffer");
636706f2543Smrg          LogMessage(X_INFO, "AIGLX: enabled GLX_SGIX_pbuffer\n");
637706f2543Smrg          screen->has_WGL_ARB_pbuffer = TRUE;
638706f2543Smrg        }
639706f2543Smrg
640706f2543Smrg      if (strstr(wgl_extensions, "WGL_ARB_multisample"))
641706f2543Smrg        {
642706f2543Smrg          __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_multisample");
643706f2543Smrg          __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIS_multisample");
644706f2543Smrg          LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_multisample and GLX_SGIS_multisample\n");
645706f2543Smrg          screen->has_WGL_ARB_multisample = TRUE;
646706f2543Smrg        }
647706f2543Smrg
648706f2543Smrg      screen->base.destroy = glxWinScreenDestroy;
649706f2543Smrg      screen->base.createContext = glxWinCreateContext;
650706f2543Smrg      screen->base.createDrawable = glxWinCreateDrawable;
651706f2543Smrg      screen->base.swapInterval = glxWinScreenSwapInterval;
652706f2543Smrg      screen->base.pScreen = pScreen;
653706f2543Smrg
654706f2543Smrg      if (strstr(wgl_extensions, "WGL_ARB_pixel_format"))
655706f2543Smrg        {
656706f2543Smrg          glxWinCreateConfigsExt(hdc, screen);
657706f2543Smrg          screen->has_WGL_ARB_pixel_format = TRUE;
658706f2543Smrg        }
659706f2543Smrg      else
660706f2543Smrg        {
661706f2543Smrg          glxWinCreateConfigs(hdc, screen);
662706f2543Smrg          screen->has_WGL_ARB_pixel_format = FALSE;
663706f2543Smrg        }
664706f2543Smrg      // Initializes screen->base.fbconfigs and screen->base.numFBConfigs
665706f2543Smrg
666706f2543Smrg      /* These will be set by __glXScreenInit */
667706f2543Smrg      screen->base.visuals = NULL;
668706f2543Smrg      screen->base.numVisuals = 0;
669706f2543Smrg
670706f2543Smrg      __glXScreenInit(&screen->base, pScreen);
671706f2543Smrg
672706f2543Smrg      // dump out fbConfigs now fbConfigIds and visualIDs have been assigned
673706f2543Smrg      fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs);
674706f2543Smrg
675706f2543Smrg      // Override the GL extensions string set by __glXScreenInit()
676706f2543Smrg      screen->base.GLextensions = strdup(gl_extensions);
677706f2543Smrg
678706f2543Smrg      // Generate the GLX extensions string (overrides that set by __glXScreenInit())
679706f2543Smrg      {
680706f2543Smrg        unsigned int buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
681706f2543Smrg        if (buffer_size > 0)
682706f2543Smrg          {
683706f2543Smrg            free(screen->base.GLXextensions);
684706f2543Smrg
685706f2543Smrg            screen->base.GLXextensions = xnfalloc(buffer_size);
686706f2543Smrg            __glXGetExtensionString(screen->glx_enable_bits, screen->base.GLXextensions);
687706f2543Smrg          }
688706f2543Smrg      }
689706f2543Smrg
690706f2543Smrg      //
691706f2543Smrg      // Override the GLX version (__glXScreenInit() sets it to "1.2")
692706f2543Smrg      // if we have all the needed extensions to operate as a higher version
693706f2543Smrg      //
694706f2543Smrg      // SGIX_fbconfig && SGIX_pbuffer && SGI_make_current_read -> 1.3
695706f2543Smrg      // ARB_multisample -> 1.4
696706f2543Smrg      //
697706f2543Smrg      if (screen->has_WGL_ARB_pbuffer && glx_sgi_make_current_read)
698706f2543Smrg        {
699706f2543Smrg          if (screen->has_WGL_ARB_multisample)
700706f2543Smrg            {
701706f2543Smrg              screen->base.GLXmajor = 1;
702706f2543Smrg              screen->base.GLXminor = 4;
703706f2543Smrg            }
704706f2543Smrg          else
705706f2543Smrg            {
706706f2543Smrg              screen->base.GLXmajor = 1;
707706f2543Smrg              screen->base.GLXminor = 3;
708706f2543Smrg            }
709706f2543Smrg        }
710706f2543Smrg    }
711706f2543Smrg    LogMessage(X_INFO, "AIGLX: Set GLX version to %d.%d\n", screen->base.GLXmajor, screen->base.GLXminor);
712706f2543Smrg
713706f2543Smrg    wglMakeCurrent(NULL, NULL);
714706f2543Smrg    wglDeleteContext(hglrc);
715706f2543Smrg    ReleaseDC(hwnd, hdc);
716706f2543Smrg    DestroyWindow(hwnd);
717706f2543Smrg
718706f2543Smrg    return &screen->base;
719706f2543Smrg}
720706f2543Smrg
721706f2543Smrg/* ---------------------------------------------------------------------- */
722706f2543Smrg/*
723706f2543Smrg * Window functions
724706f2543Smrg */
725706f2543Smrg
726706f2543Smrgstatic Bool
727706f2543SmrgglxWinRealizeWindow(WindowPtr pWin)
728706f2543Smrg{
729706f2543Smrg    Bool result;
730706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
731706f2543Smrg    glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
732706f2543Smrg
733706f2543Smrg    GLWIN_DEBUG_MSG("glxWinRealizeWindow");
734706f2543Smrg
735706f2543Smrg    /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */
736706f2543Smrg    pScreen->RealizeWindow = screenPriv->RealizeWindow;
737706f2543Smrg    result = pScreen->RealizeWindow(pWin);
738706f2543Smrg    pScreen->RealizeWindow = glxWinRealizeWindow;
739706f2543Smrg
740706f2543Smrg    return result;
741706f2543Smrg}
742706f2543Smrg
743706f2543Smrg
744706f2543Smrgstatic void
745706f2543SmrgglxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
746706f2543Smrg{
747706f2543Smrg    __GLXWinDrawable *pGlxDraw;
748706f2543Smrg    ScreenPtr pScreen = pWindow->drawable.pScreen;
749706f2543Smrg    glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
750706f2543Smrg
751706f2543Smrg    GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow);
752706f2543Smrg
753706f2543Smrg    dixLookupResourceByType((pointer) &pGlxDraw, pWindow->drawable.id, __glXDrawableRes,
754706f2543Smrg				NullClient, DixUnknownAccess);
755706f2543Smrg
756706f2543Smrg
757706f2543Smrg    /*
758706f2543Smrg       Discard any CopyWindow requests if a GL drawing context is pointing at the window
759706f2543Smrg
760706f2543Smrg       For regions which are being drawn by GL, the shadow framebuffer doesn't have the
761706f2543Smrg       correct bits, so we wish to avoid shadow framebuffer damage occuring, which will
762706f2543Smrg       cause those incorrect bits to be transferred to the display....
763706f2543Smrg    */
764706f2543Smrg    if (pGlxDraw && pGlxDraw->drawContext)
765706f2543Smrg      {
766706f2543Smrg        GLWIN_DEBUG_MSG("glxWinCopyWindow: discarding");
767706f2543Smrg        return;
768706f2543Smrg      }
769706f2543Smrg
770706f2543Smrg    GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer");
771706f2543Smrg
772706f2543Smrg    pScreen->CopyWindow = screenPriv->CopyWindow;
773706f2543Smrg    pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
774706f2543Smrg    pScreen->CopyWindow = glxWinCopyWindow;
775706f2543Smrg}
776706f2543Smrg
777706f2543Smrgstatic Bool
778706f2543SmrgglxWinUnrealizeWindow(WindowPtr pWin)
779706f2543Smrg{
780706f2543Smrg    Bool result;
781706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
782706f2543Smrg    glxWinScreen *screenPriv = (glxWinScreen *)glxGetScreen(pScreen);
783706f2543Smrg
784706f2543Smrg    GLWIN_DEBUG_MSG("glxWinUnrealizeWindow");
785706f2543Smrg
786706f2543Smrg    pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow;
787706f2543Smrg    result = pScreen->UnrealizeWindow(pWin);
788706f2543Smrg    pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
789706f2543Smrg
790706f2543Smrg    return result;
791706f2543Smrg}
792706f2543Smrg
793706f2543Smrg/* ---------------------------------------------------------------------- */
794706f2543Smrg/*
795706f2543Smrg * Drawable functions
796706f2543Smrg */
797706f2543Smrg
798706f2543Smrgstatic GLboolean
799706f2543SmrgglxWinDrawableSwapBuffers(ClientPtr client, __GLXdrawable *base)
800706f2543Smrg{
801706f2543Smrg    HDC dc;
802706f2543Smrg    HWND hwnd;
803706f2543Smrg    BOOL ret;
804706f2543Smrg    __GLXWinDrawable *draw = (__GLXWinDrawable *)base;
805706f2543Smrg
806706f2543Smrg    /* Swap buffers on the last active context for drawing on the drawable */
807706f2543Smrg    if (draw->drawContext == NULL)
808706f2543Smrg      {
809706f2543Smrg        GLWIN_TRACE_MSG("glxWinSwapBuffers - no context for drawable");
810706f2543Smrg        return GL_FALSE;
811706f2543Smrg      }
812706f2543Smrg
813706f2543Smrg    GLWIN_TRACE_MSG("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)", base, draw->drawContext, draw->drawContext->ctx);
814706f2543Smrg
815706f2543Smrg    /*
816706f2543Smrg       draw->drawContext->base.drawPriv will not be set if the context is not current anymore,
817706f2543Smrg       but if it is, it should point to this drawable....
818706f2543Smrg    */
819706f2543Smrg    assert((draw->drawContext->base.drawPriv == NULL) || (draw->drawContext->base.drawPriv == base));
820706f2543Smrg
821706f2543Smrg    dc = glxWinMakeDC(draw->drawContext, draw, &dc, &hwnd);
822706f2543Smrg    if (dc == NULL)
823706f2543Smrg      return GL_FALSE;
824706f2543Smrg
825706f2543Smrg    ret = wglSwapLayerBuffers(dc, WGL_SWAP_MAIN_PLANE);
826706f2543Smrg
827706f2543Smrg    glxWinReleaseDC(hwnd, dc, draw);
828706f2543Smrg
829706f2543Smrg    if (!ret)
830706f2543Smrg      {
831706f2543Smrg        ErrorF("wglSwapBuffers failed: %s\n", glxWinErrorMessage());
832706f2543Smrg        return GL_FALSE;
833706f2543Smrg      }
834706f2543Smrg
835706f2543Smrg    return GL_TRUE;
836706f2543Smrg}
837706f2543Smrg
838706f2543Smrgstatic void
839706f2543SmrgglxWinDrawableCopySubBuffer(__GLXdrawable *drawable,
840706f2543Smrg                            int x, int y, int w, int h)
841706f2543Smrg{
842706f2543Smrg  glAddSwapHintRectWINWrapperNonstatic(x, y, w, h);
843706f2543Smrg  glxWinDrawableSwapBuffers(NULL, drawable);
844706f2543Smrg}
845706f2543Smrg
846706f2543Smrgstatic void
847706f2543SmrgglxWinDrawableDestroy(__GLXdrawable *base)
848706f2543Smrg{
849706f2543Smrg  __GLXWinDrawable *glxPriv = (__GLXWinDrawable *)base;
850706f2543Smrg
851706f2543Smrg  if (glxPriv->drawContext && (__glXLastContext == &((glxPriv->drawContext)->base)))
852706f2543Smrg    {
853706f2543Smrg      // if this context is current and has unflushed commands, say we have flushed them
854706f2543Smrg      // (don't actually flush them, the window is going away anyhow, and an implict flush occurs
855706f2543Smrg      // on the next context change)
856706f2543Smrg      // (GLX core considers it an error when we try to select a new current context if the old one
857706f2543Smrg      // has unflushed commands, but the window has disappeared..)
858706f2543Smrg      __GLX_NOTE_FLUSHED_CMDS(__glXLastContext);
859706f2543Smrg      __glXLastContext = NULL;
860706f2543Smrg    }
861706f2543Smrg
862706f2543Smrg  if (glxPriv->hPbuffer)
863706f2543Smrg    if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer))
864706f2543Smrg      {
865706f2543Smrg        ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage());
866706f2543Smrg      }
867706f2543Smrg
868706f2543Smrg  if (glxPriv->dibDC)
869706f2543Smrg    {
870706f2543Smrg      // restore the default DIB
871706f2543Smrg      SelectObject(glxPriv->dibDC, glxPriv->hOldDIB);
872706f2543Smrg
873706f2543Smrg      if (!DeleteDC(glxPriv->dibDC))
874706f2543Smrg        {
875706f2543Smrg          ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage());
876706f2543Smrg        }
877706f2543Smrg    }
878706f2543Smrg
879706f2543Smrg  if (glxPriv->hDIB)
880706f2543Smrg    {
881706f2543Smrg      if (!DeleteObject(glxPriv->hDIB))
882706f2543Smrg        {
883706f2543Smrg          ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
884706f2543Smrg        }
885706f2543Smrg
886706f2543Smrg      ((PixmapPtr)glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits;
887706f2543Smrg    }
888706f2543Smrg
889706f2543Smrg  GLWIN_DEBUG_MSG("glxWinDestroyDrawable");
890706f2543Smrg  free(glxPriv);
891706f2543Smrg}
892706f2543Smrg
893706f2543Smrgstatic __GLXdrawable *
894706f2543SmrgglxWinCreateDrawable(ClientPtr client,
895706f2543Smrg                    __GLXscreen *screen,
896706f2543Smrg                    DrawablePtr pDraw,
897706f2543Smrg                    XID drawId,
898706f2543Smrg                    int type,
899706f2543Smrg                    XID glxDrawId,
900706f2543Smrg                    __GLXconfig *conf)
901706f2543Smrg{
902706f2543Smrg  __GLXWinDrawable *glxPriv;
903706f2543Smrg
904706f2543Smrg  glxPriv = malloc(sizeof *glxPriv);
905706f2543Smrg
906706f2543Smrg  if (glxPriv == NULL)
907706f2543Smrg      return NULL;
908706f2543Smrg
909706f2543Smrg  memset(glxPriv, 0, sizeof *glxPriv);
910706f2543Smrg
911706f2543Smrg  if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, glxDrawId, conf)) {
912706f2543Smrg    free(glxPriv);
913706f2543Smrg    return NULL;
914706f2543Smrg  }
915706f2543Smrg
916706f2543Smrg  glxPriv->base.destroy       = glxWinDrawableDestroy;
917706f2543Smrg  glxPriv->base.swapBuffers   = glxWinDrawableSwapBuffers;
918706f2543Smrg  glxPriv->base.copySubBuffer = glxWinDrawableCopySubBuffer;
919706f2543Smrg  // glxPriv->base.waitX  what are these for?
920706f2543Smrg  // glxPriv->base.waitGL
921706f2543Smrg
922706f2543Smrg  GLWIN_DEBUG_MSG("glxWinCreateDrawable %p", glxPriv);
923706f2543Smrg
924706f2543Smrg  return &glxPriv->base;
925706f2543Smrg}
926706f2543Smrg
927706f2543Smrg/* ---------------------------------------------------------------------- */
928706f2543Smrg/*
929706f2543Smrg * Texture functions
930706f2543Smrg */
931706f2543Smrg
932706f2543Smrgstatic
933706f2543Smrgint glxWinBindTexImage(__GLXcontext  *baseContext,
934706f2543Smrg                      int            buffer,
935706f2543Smrg                      __GLXdrawable *pixmap)
936706f2543Smrg{
937706f2543Smrg  ErrorF("glxWinBindTexImage: not implemented\n");
938706f2543Smrg  return FALSE;
939706f2543Smrg}
940706f2543Smrg
941706f2543Smrgstatic
942706f2543Smrgint glxWinReleaseTexImage(__GLXcontext  *baseContext,
943706f2543Smrg                         int            buffer,
944706f2543Smrg                         __GLXdrawable *pixmap)
945706f2543Smrg{
946706f2543Smrg  ErrorF(" glxWinReleaseTexImage: not implemented\n");
947706f2543Smrg  return FALSE;
948706f2543Smrg}
949706f2543Smrg
950706f2543Smrg/* ---------------------------------------------------------------------- */
951706f2543Smrg/*
952706f2543Smrg * Lazy update context implementation
953706f2543Smrg *
954706f2543Smrg * WGL contexts are created for a specific HDC, so we cannot create the WGL
955706f2543Smrg * context in glxWinCreateContext(), we must defer creation until the context
956706f2543Smrg * is actually used on a specifc drawable which is connected to a native window,
957706f2543Smrg * pbuffer or DIB
958706f2543Smrg *
959706f2543Smrg * The WGL context may be used on other, compatible HDCs, so we don't need to
960706f2543Smrg * recreate it for every new native window
961706f2543Smrg *
962706f2543Smrg * XXX: I wonder why we can't create the WGL context on the screen HDC ?
963706f2543Smrg * Basically we assume all HDCs are compatible at the moment: if they are not
964706f2543Smrg * we are in a muddle, there was some code in the old implementation to attempt
965706f2543Smrg * to transparently migrate a context to a new DC by copying state and sharing
966706f2543Smrg * lists with the old one...
967706f2543Smrg */
968706f2543Smrg
969706f2543Smrgstatic void
970706f2543SmrgglxWinSetPixelFormat(__GLXWinContext *gc, HDC hdc, int bppOverride, int drawableTypeOverride)
971706f2543Smrg{
972706f2543Smrg  __GLXscreen *screen = gc->base.pGlxScreen;
973706f2543Smrg  glxWinScreen *winScreen = (glxWinScreen *)screen;
974706f2543Smrg
975706f2543Smrg  __GLXconfig *config = gc->base.config;
976706f2543Smrg  GLXWinConfig *winConfig = (GLXWinConfig *)config;
977706f2543Smrg
978706f2543Smrg  GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d", winConfig->pixelFormatIndex);
979706f2543Smrg
980706f2543Smrg  /*
981706f2543Smrg    Normally, we can just use the the pixelFormatIndex corresponding
982706f2543Smrg    to the fbconfig which has been specified by the client
983706f2543Smrg  */
984706f2543Smrg
985706f2543Smrg  if (!((bppOverride && (bppOverride != (config->redBits + config->greenBits + config->blueBits) ))
986706f2543Smrg        || ((config->drawableType & drawableTypeOverride) == 0)))
987706f2543Smrg    {
988706f2543Smrg      if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL))
989706f2543Smrg        {
990706f2543Smrg          ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
991706f2543Smrg          return;
992706f2543Smrg        }
993706f2543Smrg
994706f2543Smrg      return;
995706f2543Smrg    }
996706f2543Smrg
997706f2543Smrg  /*
998706f2543Smrg    However, in certain special cases this pixel format will be incompatible with the
999706f2543Smrg    use we are going to put it to, so we need to re-evaluate the pixel format to use:
1000706f2543Smrg
1001706f2543Smrg    1) When PFD_DRAW_TO_BITMAP is set, ChoosePixelFormat() always returns a format with
1002706f2543Smrg       the cColorBits we asked for, so we need to ensure it matches the bpp of the bitmap
1003706f2543Smrg
1004706f2543Smrg    2) Applications may assume that visuals selected with glXChooseVisual() work with
1005706f2543Smrg       pixmap drawables (there is no attribute to explicitly query for pixmap drawable
1006706f2543Smrg       support as there is for glXChooseFBConfig())
1007706f2543Smrg       (it's arguable this is an error in the application, but we try to make it work)
1008706f2543Smrg
1009706f2543Smrg       pixmap rendering is always slow for us, so we don't want to choose those visuals
1010706f2543Smrg       by default, but if the actual drawable type we're trying to select the context
1011706f2543Smrg       on (drawableTypeOverride) isn't supported by the selected fbConfig, reconsider
1012706f2543Smrg       and see if we can find a suitable one...
1013706f2543Smrg   */
1014706f2543Smrg  ErrorF("glxWinSetPixelFormat: having second thoughts: cColorbits %d, bppOveride %d; config->drawableType %d, drawableTypeOverride %d\n",
1015706f2543Smrg         (config->redBits + config->greenBits + config->blueBits), bppOverride, config->drawableType, drawableTypeOverride);
1016706f2543Smrg
1017706f2543Smrg  if (!winScreen->has_WGL_ARB_pixel_format)
1018706f2543Smrg    {
1019706f2543Smrg      PIXELFORMATDESCRIPTOR pfd;
1020706f2543Smrg      int pixelFormat;
1021706f2543Smrg
1022706f2543Smrg      /* convert fbConfig to PFD */
1023706f2543Smrg      if (fbConfigToPixelFormat(gc->base.config, &pfd, drawableTypeOverride))
1024706f2543Smrg        {
1025706f2543Smrg          ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n");
1026706f2543Smrg          return;
1027706f2543Smrg        }
1028706f2543Smrg
1029706f2543Smrg      if (glxWinDebugSettings.dumpPFD)
1030706f2543Smrg        pfdOut(&pfd);
1031706f2543Smrg
1032706f2543Smrg      if (bppOverride)
1033706f2543Smrg        {
1034706f2543Smrg          GLWIN_DEBUG_MSG("glxWinSetPixelFormat: Forcing bpp from %d to %d\n", pfd.cColorBits, bppOverride);
1035706f2543Smrg          pfd.cColorBits = bppOverride;
1036706f2543Smrg        }
1037706f2543Smrg
1038706f2543Smrg      pixelFormat = ChoosePixelFormat(hdc, &pfd);
1039706f2543Smrg      if (pixelFormat == 0)
1040706f2543Smrg        {
1041706f2543Smrg          ErrorF("ChoosePixelFormat error: %s\n", glxWinErrorMessage());
1042706f2543Smrg          return;
1043706f2543Smrg        }
1044706f2543Smrg
1045706f2543Smrg      GLWIN_DEBUG_MSG("ChoosePixelFormat: chose pixelFormatIndex %d", pixelFormat);
1046706f2543Smrg      ErrorF("ChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", pixelFormat, winConfig->pixelFormatIndex);
1047706f2543Smrg
1048706f2543Smrg      if (!SetPixelFormat(hdc, pixelFormat, &pfd))
1049706f2543Smrg        {
1050706f2543Smrg          ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
1051706f2543Smrg          return;
1052706f2543Smrg        }
1053706f2543Smrg    }
1054706f2543Smrg  else
1055706f2543Smrg    {
1056706f2543Smrg      int pixelFormat = fbConfigToPixelFormatIndex(hdc, gc->base.config, drawableTypeOverride, winScreen);
1057706f2543Smrg      if (pixelFormat == 0)
1058706f2543Smrg        {
1059706f2543Smrg          ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
1060706f2543Smrg          return;
1061706f2543Smrg        }
1062706f2543Smrg
1063706f2543Smrg      GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d", pixelFormat);
1064706f2543Smrg      ErrorF("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", pixelFormat, winConfig->pixelFormatIndex);
1065706f2543Smrg
1066706f2543Smrg      if (!SetPixelFormat(hdc, pixelFormat, NULL))
1067706f2543Smrg        {
1068706f2543Smrg          ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
1069706f2543Smrg          return;
1070706f2543Smrg        }
1071706f2543Smrg    }
1072706f2543Smrg}
1073706f2543Smrg
1074706f2543Smrgstatic HDC
1075706f2543SmrgglxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HDC *hdc, HWND *hwnd)
1076706f2543Smrg{
1077706f2543Smrg  *hdc = NULL;
1078706f2543Smrg  *hwnd = NULL;
1079706f2543Smrg
1080706f2543Smrg  if (draw == NULL)
1081706f2543Smrg    {
1082706f2543Smrg      GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc, gc->ctx);
1083706f2543Smrg      return NULL;
1084706f2543Smrg    }
1085706f2543Smrg
1086706f2543Smrg  switch (draw->base.type)
1087706f2543Smrg  {
1088706f2543Smrg    case GLX_DRAWABLE_WINDOW:
1089706f2543Smrg    {
1090706f2543Smrg      WindowPtr pWin;
1091706f2543Smrg
1092706f2543Smrg      pWin = (WindowPtr) draw->base.pDraw;
1093706f2543Smrg      if (pWin == NULL)
1094706f2543Smrg        {
1095706f2543Smrg          GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin);
1096706f2543Smrg          return NULL;
1097706f2543Smrg        }
1098706f2543Smrg
1099706f2543Smrg      *hwnd = winGetWindowInfo(pWin);
1100706f2543Smrg
1101706f2543Smrg      if (*hwnd == NULL)
1102706f2543Smrg        {
1103706f2543Smrg          ErrorF("No HWND error: %s\n", glxWinErrorMessage());
1104706f2543Smrg          return NULL;
1105706f2543Smrg        }
1106706f2543Smrg
1107706f2543Smrg      *hdc = GetDC(*hwnd);
1108706f2543Smrg
1109706f2543Smrg      if (*hdc == NULL)
1110706f2543Smrg        ErrorF("GetDC error: %s\n", glxWinErrorMessage());
1111706f2543Smrg
1112706f2543Smrg      /* Check if the hwnd has changed... */
1113706f2543Smrg      if (*hwnd != gc->hwnd)
1114706f2543Smrg        {
1115706f2543Smrg          if (glxWinDebugSettings.enableTrace)
1116706f2543Smrg            GLWIN_DEBUG_HWND(*hwnd);
1117706f2543Smrg
1118706f2543Smrg          GLWIN_TRACE_MSG("for context %p (native ctx %p), hWnd changed from %p to %p", gc, gc->ctx, gc->hwnd, *hwnd);
1119706f2543Smrg          gc->hwnd = *hwnd;
1120706f2543Smrg
1121706f2543Smrg          /* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */
1122706f2543Smrg          glxWinSetPixelFormat(gc, *hdc, 0, GLX_WINDOW_BIT);
1123706f2543Smrg        }
1124706f2543Smrg    }
1125706f2543Smrg    break;
1126706f2543Smrg
1127706f2543Smrg  case GLX_DRAWABLE_PBUFFER:
1128706f2543Smrg    {
1129706f2543Smrg      *hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer);
1130706f2543Smrg
1131706f2543Smrg      if (*hdc == NULL)
1132706f2543Smrg        ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage());
1133706f2543Smrg    }
1134706f2543Smrg    break;
1135706f2543Smrg
1136706f2543Smrg  case GLX_DRAWABLE_PIXMAP:
1137706f2543Smrg    {
1138706f2543Smrg      *hdc = draw->dibDC;
1139706f2543Smrg    }
1140706f2543Smrg    break;
1141706f2543Smrg
1142706f2543Smrg  default:
1143706f2543Smrg    {
1144706f2543Smrg      ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n", draw->base.type);
1145706f2543Smrg    }
1146706f2543Smrg  }
1147706f2543Smrg
1148706f2543Smrg  if (glxWinDebugSettings.dumpDC)
1149706f2543Smrg    GLWIN_DEBUG_MSG("Got HDC %p", *hdc);
1150706f2543Smrg
1151706f2543Smrg  return *hdc;
1152706f2543Smrg}
1153706f2543Smrg
1154706f2543Smrgstatic void
1155706f2543SmrgglxWinReleaseDC(HWND hwnd, HDC hdc,__GLXWinDrawable *draw)
1156706f2543Smrg{
1157706f2543Smrg  switch (draw->base.type)
1158706f2543Smrg  {
1159706f2543Smrg    case GLX_DRAWABLE_WINDOW:
1160706f2543Smrg    {
1161706f2543Smrg      ReleaseDC(hwnd, hdc);
1162706f2543Smrg    }
1163706f2543Smrg    break;
1164706f2543Smrg
1165706f2543Smrg  case GLX_DRAWABLE_PBUFFER:
1166706f2543Smrg    {
1167706f2543Smrg      if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc))
1168706f2543Smrg        {
1169706f2543Smrg          ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage());
1170706f2543Smrg        }
1171706f2543Smrg    }
1172706f2543Smrg    break;
1173706f2543Smrg
1174706f2543Smrg  case GLX_DRAWABLE_PIXMAP:
1175706f2543Smrg    {
1176706f2543Smrg      // don't release DC, the memory DC lives as long as the bitmap
1177706f2543Smrg
1178706f2543Smrg      // We must ensure that all GDI drawing into the bitmap has completed
1179706f2543Smrg      // in case we subsequently access the bits from it
1180706f2543Smrg      GdiFlush();
1181706f2543Smrg    }
1182706f2543Smrg    break;
1183706f2543Smrg
1184706f2543Smrg  default:
1185706f2543Smrg    {
1186706f2543Smrg      ErrorF("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n", draw->base.type);
1187706f2543Smrg    }
1188706f2543Smrg  }
1189706f2543Smrg}
1190706f2543Smrg
1191706f2543Smrgstatic void
1192706f2543SmrgglxWinDeferredCreateContext(__GLXWinContext *gc, __GLXWinDrawable *draw)
1193706f2543Smrg{
1194706f2543Smrg  HDC dc;
1195706f2543Smrg  HWND hwnd;
1196706f2543Smrg  GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attach context %p to drawable %p", gc, draw);
1197706f2543Smrg
1198706f2543Smrg  switch (draw->base.type)
1199706f2543Smrg  {
1200706f2543Smrg    case GLX_DRAWABLE_WINDOW:
1201706f2543Smrg    {
1202706f2543Smrg      WindowPtr pWin = (WindowPtr) draw->base.pDraw;
1203706f2543Smrg
1204706f2543Smrg      if (!(gc->base.config->drawableType & GLX_WINDOW_BIT))
1205706f2543Smrg        {
1206706f2543Smrg          ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable\n");
1207706f2543Smrg        }
1208706f2543Smrg
1209706f2543Smrg      if (pWin == NULL)
1210706f2543Smrg        {
1211706f2543Smrg          GLWIN_DEBUG_MSG("Deferring until X window is created");
1212706f2543Smrg          return;
1213706f2543Smrg        }
1214706f2543Smrg
1215706f2543Smrg      GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pWin %p", pWin);
1216706f2543Smrg
1217706f2543Smrg      if (winGetWindowInfo(pWin) == NULL)
1218706f2543Smrg        {
1219706f2543Smrg          GLWIN_DEBUG_MSG("Deferring until native window is created");
1220706f2543Smrg          return;
1221706f2543Smrg        }
1222706f2543Smrg    }
1223706f2543Smrg    break;
1224706f2543Smrg
1225706f2543Smrg    case GLX_DRAWABLE_PBUFFER:
1226706f2543Smrg    {
1227706f2543Smrg      if (draw->hPbuffer == NULL)
1228706f2543Smrg        {
1229706f2543Smrg          __GLXscreen *screen;
1230706f2543Smrg          glxWinScreen *winScreen;
1231706f2543Smrg          int pixelFormat;
1232706f2543Smrg          // XXX: which DC are supposed to use???
1233706f2543Smrg          HDC screenDC = GetDC(NULL);
1234706f2543Smrg
1235706f2543Smrg          if (!(gc->base.config->drawableType & GLX_PBUFFER_BIT))
1236706f2543Smrg            {
1237706f2543Smrg              ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable\n");
1238706f2543Smrg            }
1239706f2543Smrg
1240706f2543Smrg          screen = gc->base.pGlxScreen;
1241706f2543Smrg          winScreen = (glxWinScreen *)screen;
1242706f2543Smrg
1243706f2543Smrg          pixelFormat = fbConfigToPixelFormatIndex(screenDC, gc->base.config, GLX_DRAWABLE_PBUFFER, winScreen);
1244706f2543Smrg          if (pixelFormat == 0)
1245706f2543Smrg            {
1246706f2543Smrg              ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
1247706f2543Smrg              return;
1248706f2543Smrg            }
1249706f2543Smrg
1250706f2543Smrg          draw->hPbuffer = wglCreatePbufferARBWrapper(screenDC, pixelFormat, draw->base.pDraw->width, draw->base.pDraw->height, NULL);
1251706f2543Smrg          ReleaseDC(NULL, screenDC);
1252706f2543Smrg
1253706f2543Smrg          if (draw->hPbuffer == NULL)
1254706f2543Smrg            {
1255706f2543Smrg              ErrorF("wglCreatePbufferARBWrapper error: %s\n", glxWinErrorMessage());
1256706f2543Smrg              return;
1257706f2543Smrg            }
1258706f2543Smrg
1259706f2543Smrg          GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pBuffer %p created for drawable %p", draw->hPbuffer, draw);
1260706f2543Smrg        }
1261706f2543Smrg    }
1262706f2543Smrg    break;
1263706f2543Smrg
1264706f2543Smrg    case GLX_DRAWABLE_PIXMAP:
1265706f2543Smrg    {
1266706f2543Smrg      if (draw->dibDC == NULL)
1267706f2543Smrg        {
1268706f2543Smrg          BITMAPINFOHEADER bmpHeader;
1269706f2543Smrg          void *pBits;
1270706f2543Smrg
1271706f2543Smrg          memset (&bmpHeader, 0, sizeof(BITMAPINFOHEADER));
1272706f2543Smrg          bmpHeader.biSize = sizeof(BITMAPINFOHEADER);
1273706f2543Smrg          bmpHeader.biWidth = draw->base.pDraw->width;
1274706f2543Smrg          bmpHeader.biHeight = draw->base.pDraw->height;
1275706f2543Smrg          bmpHeader.biPlanes = 1;
1276706f2543Smrg          bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel;
1277706f2543Smrg          bmpHeader.biCompression = BI_RGB;
1278706f2543Smrg
1279706f2543Smrg          if (!(gc->base.config->drawableType & GLX_PIXMAP_BIT))
1280706f2543Smrg            {
1281706f2543Smrg              ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n");
1282706f2543Smrg            }
1283706f2543Smrg
1284706f2543Smrg          draw->dibDC = CreateCompatibleDC(NULL);
1285706f2543Smrg          if (draw->dibDC == NULL)
1286706f2543Smrg            {
1287706f2543Smrg              ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
1288706f2543Smrg              return;
1289706f2543Smrg            }
1290706f2543Smrg
1291706f2543Smrg          draw->hDIB = CreateDIBSection(draw->dibDC, (BITMAPINFO *)&bmpHeader, DIB_RGB_COLORS, &pBits, 0, 0);
1292706f2543Smrg          if (draw->dibDC == NULL)
1293706f2543Smrg            {
1294706f2543Smrg              ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage());
1295706f2543Smrg              return;
1296706f2543Smrg            }
1297706f2543Smrg
1298706f2543Smrg          // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to
1299706f2543Smrg          // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits
1300706f2543Smrg          // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are
1301706f2543Smrg          // even compatible ...
1302706f2543Smrg          draw->pOldBits = ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr;
1303706f2543Smrg          ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr = pBits;
1304706f2543Smrg
1305706f2543Smrg          // Select the DIB into the DC
1306706f2543Smrg          draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB);
1307706f2543Smrg          if (!draw->hOldDIB)
1308706f2543Smrg            {
1309706f2543Smrg              ErrorF("SelectObject error: %s\n", glxWinErrorMessage());
1310706f2543Smrg            }
1311706f2543Smrg
1312706f2543Smrg          // Set the pixel format of the bitmap
1313706f2543Smrg          glxWinSetPixelFormat(gc, draw->dibDC, draw->base.pDraw->bitsPerPixel, GLX_PIXMAP_BIT);
1314706f2543Smrg
1315706f2543Smrg          GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p", draw->hDIB, draw);
1316706f2543Smrg        }
1317706f2543Smrg    }
1318706f2543Smrg    break;
1319706f2543Smrg
1320706f2543Smrg    default:
1321706f2543Smrg    {
1322706f2543Smrg      ErrorF("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", draw->base.type);
1323706f2543Smrg      return;
1324706f2543Smrg    }
1325706f2543Smrg  }
1326706f2543Smrg
1327706f2543Smrg  dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
1328706f2543Smrg  gc->ctx = wglCreateContext(dc);
1329706f2543Smrg  glxWinReleaseDC(hwnd, dc, draw);
1330706f2543Smrg
1331706f2543Smrg  if (gc->ctx == NULL)
1332706f2543Smrg    {
1333706f2543Smrg      ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage());
1334706f2543Smrg      return;
1335706f2543Smrg    }
1336706f2543Smrg
1337706f2543Smrg  GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p", gc, gc->ctx, draw);
1338706f2543Smrg
1339706f2543Smrg  // if the native context was created successfully, shareLists if needed
1340706f2543Smrg  if (gc->ctx && gc->shareContext)
1341706f2543Smrg    {
1342706f2543Smrg      GLWIN_DEBUG_MSG("glxWinCreateContextReal shareLists with context %p (native ctx %p)", gc->shareContext, gc->shareContext->ctx);
1343706f2543Smrg
1344706f2543Smrg      if (!wglShareLists(gc->shareContext->ctx, gc->ctx))
1345706f2543Smrg        {
1346706f2543Smrg          ErrorF("wglShareLists error: %s\n", glxWinErrorMessage());
1347706f2543Smrg        }
1348706f2543Smrg    }
1349706f2543Smrg}
1350706f2543Smrg
1351706f2543Smrg/* ---------------------------------------------------------------------- */
1352706f2543Smrg/*
1353706f2543Smrg * Context functions
1354706f2543Smrg */
1355706f2543Smrg
1356706f2543Smrg
1357706f2543Smrg/* Context manipulation routines should return TRUE on success, FALSE on failure */
1358706f2543Smrgstatic int
1359706f2543SmrgglxWinContextMakeCurrent(__GLXcontext *base)
1360706f2543Smrg{
1361706f2543Smrg  __GLXWinContext *gc = (__GLXWinContext *)base;
1362706f2543Smrg  BOOL ret;
1363706f2543Smrg  HDC drawDC;
1364706f2543Smrg  HDC readDC = NULL;
1365706f2543Smrg  __GLXdrawable *drawPriv;
1366706f2543Smrg  __GLXdrawable *readPriv = NULL;
1367706f2543Smrg  HWND hDrawWnd;
1368706f2543Smrg  HWND hReadWnd;
1369706f2543Smrg
1370706f2543Smrg  GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc, gc->ctx);
1371706f2543Smrg  glWinCallDelta();
1372706f2543Smrg
1373706f2543Smrg  /* Keep a note of the last active context in the drawable */
1374706f2543Smrg  drawPriv = gc->base.drawPriv;
1375706f2543Smrg  ((__GLXWinDrawable *)drawPriv)->drawContext = gc;
1376706f2543Smrg
1377706f2543Smrg  if (gc->ctx == NULL)
1378706f2543Smrg    {
1379706f2543Smrg      glxWinDeferredCreateContext(gc, (__GLXWinDrawable *)drawPriv);
1380706f2543Smrg    }
1381706f2543Smrg
1382706f2543Smrg  if (gc->ctx == NULL)
1383706f2543Smrg    {
1384706f2543Smrg      ErrorF("glxWinContextMakeCurrent: Native context is NULL\n");
1385706f2543Smrg      return FALSE;
1386706f2543Smrg    }
1387706f2543Smrg
1388706f2543Smrg  drawDC = glxWinMakeDC(gc, (__GLXWinDrawable *)drawPriv, &drawDC, &hDrawWnd);
1389706f2543Smrg  if (drawDC == NULL)
1390706f2543Smrg    {
1391706f2543Smrg      ErrorF("glxWinMakeDC failed for drawDC\n");
1392706f2543Smrg      return FALSE;
1393706f2543Smrg    }
1394706f2543Smrg
1395706f2543Smrg  if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv))
1396706f2543Smrg    {
1397706f2543Smrg      // XXX: should only occur with WGL_ARB_make_current_read
1398706f2543Smrg      /*
1399706f2543Smrg        If there is a separate read drawable, create a separate read DC, and
1400706f2543Smrg        use the wglMakeContextCurrent extension to make the context current drawing
1401706f2543Smrg        to one DC and reading from the other
1402706f2543Smrg      */
1403706f2543Smrg      readPriv = gc->base.readPriv;
1404706f2543Smrg      readDC = glxWinMakeDC(gc, (__GLXWinDrawable *)readPriv, &readDC, &hReadWnd);
1405706f2543Smrg      if (readDC == NULL)
1406706f2543Smrg        {
1407706f2543Smrg          ErrorF("glxWinMakeDC failed for readDC\n");
1408706f2543Smrg          glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *)drawPriv);
1409706f2543Smrg          return FALSE;
1410706f2543Smrg        }
1411706f2543Smrg
1412706f2543Smrg      ret = wglMakeContextCurrentARBWrapper(drawDC, readDC, gc->ctx);
1413706f2543Smrg      if (!ret)
1414706f2543Smrg        {
1415706f2543Smrg          ErrorF("wglMakeContextCurrentARBWrapper error: %s\n", glxWinErrorMessage());
1416706f2543Smrg        }
1417706f2543Smrg    }
1418706f2543Smrg  else
1419706f2543Smrg    {
1420706f2543Smrg      /* Otherwise, just use wglMakeCurrent */
1421706f2543Smrg      ret = wglMakeCurrent(drawDC, gc->ctx);
1422706f2543Smrg      if (!ret)
1423706f2543Smrg        {
1424706f2543Smrg          ErrorF("wglMakeCurrent error: %s\n", glxWinErrorMessage());
1425706f2543Smrg        }
1426706f2543Smrg    }
1427706f2543Smrg
1428706f2543Smrg  // apparently make current could fail if the context is current in a different thread,
1429706f2543Smrg  // but that shouldn't be able to happen in the current server...
1430706f2543Smrg
1431706f2543Smrg  glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *)drawPriv);
1432706f2543Smrg  if (readDC)
1433706f2543Smrg    glxWinReleaseDC(hReadWnd, readDC, (__GLXWinDrawable *)readPriv);
1434706f2543Smrg
1435706f2543Smrg  return ret;
1436706f2543Smrg}
1437706f2543Smrg
1438706f2543Smrgstatic int
1439706f2543SmrgglxWinContextLoseCurrent(__GLXcontext *base)
1440706f2543Smrg{
1441706f2543Smrg  BOOL ret;
1442706f2543Smrg  __GLXWinContext *gc = (__GLXWinContext *)base;
1443706f2543Smrg
1444706f2543Smrg  GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc, gc->ctx);
1445706f2543Smrg  glWinCallDelta();
1446706f2543Smrg
1447706f2543Smrg  /*
1448706f2543Smrg     An error seems to be reported if we try to make no context current
1449706f2543Smrg     if there is already no current context, so avoid doing that...
1450706f2543Smrg  */
1451706f2543Smrg  if (__glXLastContext != NULL)
1452706f2543Smrg    {
1453706f2543Smrg      ret = wglMakeCurrent(NULL, NULL); /* We don't need a DC when setting no current context */
1454706f2543Smrg      if (!ret)
1455706f2543Smrg        ErrorF("glxWinContextLoseCurrent error: %s\n", glxWinErrorMessage());
1456706f2543Smrg    }
1457706f2543Smrg
1458706f2543Smrg  return TRUE;
1459706f2543Smrg}
1460706f2543Smrg
1461706f2543Smrgstatic int
1462706f2543SmrgglxWinContextCopy(__GLXcontext *dst_base, __GLXcontext *src_base, unsigned long mask)
1463706f2543Smrg{
1464706f2543Smrg  __GLXWinContext *dst = (__GLXWinContext *)dst_base;
1465706f2543Smrg  __GLXWinContext *src = (__GLXWinContext *)src_base;
1466706f2543Smrg  BOOL ret;
1467706f2543Smrg
1468706f2543Smrg  GLWIN_DEBUG_MSG("glxWinContextCopy");
1469706f2543Smrg
1470706f2543Smrg  ret = wglCopyContext(src->ctx, dst->ctx, mask);
1471706f2543Smrg  if (!ret)
1472706f2543Smrg    {
1473706f2543Smrg      ErrorF("wglCopyContext error: %s\n", glxWinErrorMessage());
1474706f2543Smrg    }
1475706f2543Smrg
1476706f2543Smrg  return ret;
1477706f2543Smrg}
1478706f2543Smrg
1479706f2543Smrgstatic int
1480706f2543SmrgglxWinContextForceCurrent(__GLXcontext *base)
1481706f2543Smrg{
1482706f2543Smrg  /* wglMakeCurrent always flushes the previous context, so this is equivalent to glxWinContextMakeCurrent */
1483706f2543Smrg  return glxWinContextMakeCurrent(base);
1484706f2543Smrg}
1485706f2543Smrg
1486706f2543Smrgstatic void
1487706f2543SmrgglxWinContextDestroy(__GLXcontext *base)
1488706f2543Smrg{
1489706f2543Smrg  __GLXWinContext *gc = (__GLXWinContext *)base;
1490706f2543Smrg
1491706f2543Smrg  if (gc != NULL)
1492706f2543Smrg    {
1493706f2543Smrg      GLWIN_DEBUG_MSG("GLXcontext %p destroyed (native ctx %p)", base, gc->ctx);
1494706f2543Smrg
1495706f2543Smrg      if (gc->ctx)
1496706f2543Smrg        {
1497706f2543Smrg          /* It's bad style to delete the context while it's still current */
1498706f2543Smrg          if (wglGetCurrentContext() == gc->ctx)
1499706f2543Smrg            {
1500706f2543Smrg              wglMakeCurrent(NULL, NULL);
1501706f2543Smrg            }
1502706f2543Smrg
1503706f2543Smrg          {
1504706f2543Smrg            BOOL ret = wglDeleteContext(gc->ctx);
1505706f2543Smrg            if (!ret)
1506706f2543Smrg              ErrorF("wglDeleteContext error: %s\n", glxWinErrorMessage());
1507706f2543Smrg          }
1508706f2543Smrg
1509706f2543Smrg          gc->ctx = NULL;
1510706f2543Smrg        }
1511706f2543Smrg
1512706f2543Smrg      free(gc);
1513706f2543Smrg    }
1514706f2543Smrg}
1515706f2543Smrg
1516706f2543Smrgstatic __GLXcontext *
1517706f2543SmrgglxWinCreateContext(__GLXscreen *screen,
1518706f2543Smrg                   __GLXconfig *modes,
1519706f2543Smrg                   __GLXcontext *baseShareContext)
1520706f2543Smrg{
1521706f2543Smrg    __GLXWinContext *context;
1522706f2543Smrg    __GLXWinContext *shareContext = (__GLXWinContext *)baseShareContext;
1523706f2543Smrg
1524706f2543Smrg    static __GLXtextureFromPixmap glxWinTextureFromPixmap =
1525706f2543Smrg      {
1526706f2543Smrg        glxWinBindTexImage,
1527706f2543Smrg        glxWinReleaseTexImage
1528706f2543Smrg      };
1529706f2543Smrg
1530706f2543Smrg    context = (__GLXWinContext *)calloc(1, sizeof(__GLXWinContext));
1531706f2543Smrg
1532706f2543Smrg    if (!context)
1533706f2543Smrg        return NULL;
1534706f2543Smrg
1535706f2543Smrg    memset(context, 0, sizeof *context);
1536706f2543Smrg    context->base.destroy        = glxWinContextDestroy;
1537706f2543Smrg    context->base.makeCurrent    = glxWinContextMakeCurrent;
1538706f2543Smrg    context->base.loseCurrent    = glxWinContextLoseCurrent;
1539706f2543Smrg    context->base.copy           = glxWinContextCopy;
1540706f2543Smrg    context->base.forceCurrent   = glxWinContextForceCurrent;
1541706f2543Smrg    context->base.textureFromPixmap = &glxWinTextureFromPixmap;
1542706f2543Smrg    context->base.config = modes;
1543706f2543Smrg    context->base.pGlxScreen = screen;
1544706f2543Smrg
1545706f2543Smrg    // actual native GL context creation is deferred until attach()
1546706f2543Smrg    context->ctx = NULL;
1547706f2543Smrg    context->shareContext = shareContext;
1548706f2543Smrg
1549706f2543Smrg    glWinSetupDispatchTable();
1550706f2543Smrg
1551706f2543Smrg    GLWIN_DEBUG_MSG("GLXcontext %p created", context);
1552706f2543Smrg
1553706f2543Smrg    return &(context->base);
1554706f2543Smrg}
1555706f2543Smrg
1556706f2543Smrg/* ---------------------------------------------------------------------- */
1557706f2543Smrg/*
1558706f2543Smrg * Utility functions
1559706f2543Smrg */
1560706f2543Smrg
1561706f2543Smrgstatic int
1562706f2543SmrgfbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride)
1563706f2543Smrg{
1564706f2543Smrg    PIXELFORMATDESCRIPTOR pfd = {
1565706f2543Smrg      sizeof(PIXELFORMATDESCRIPTOR),   /* size of this pfd */
1566706f2543Smrg      1,                     /* version number */
1567706f2543Smrg      PFD_SUPPORT_OPENGL,    /* support OpenGL */
1568706f2543Smrg      PFD_TYPE_RGBA,         /* RGBA type */
1569706f2543Smrg      24,                    /* 24-bit color depth */
1570706f2543Smrg      0, 0, 0, 0, 0, 0,      /* color bits ignored */
1571706f2543Smrg      0,                     /* no alpha buffer */
1572706f2543Smrg      0,                     /* shift bit ignored */
1573706f2543Smrg      0,                     /* no accumulation buffer */
1574706f2543Smrg      0, 0, 0, 0,            /* accum bits ignored */
1575706f2543Smrg      32,                    /* 32-bit z-buffer */
1576706f2543Smrg      0,                     /* no stencil buffer */
1577706f2543Smrg      0,                     /* no auxiliary buffer */
1578706f2543Smrg      PFD_MAIN_PLANE,        /* main layer */
1579706f2543Smrg      0,                     /* reserved */
1580706f2543Smrg      0, 0, 0                /* layer masks ignored */
1581706f2543Smrg    };
1582706f2543Smrg
1583706f2543Smrg    if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
1584706f2543Smrg      pfd.dwFlags |= PFD_DRAW_TO_WINDOW; /* support window */
1585706f2543Smrg
1586706f2543Smrg    if ((mode->drawableType | drawableTypeOverride) & GLX_PIXMAP_BIT)
1587706f2543Smrg      pfd.dwFlags |= (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI); /* supports software rendering to bitmap */
1588706f2543Smrg
1589706f2543Smrg    if (mode->stereoMode) {
1590706f2543Smrg        pfd.dwFlags |= PFD_STEREO;
1591706f2543Smrg    }
1592706f2543Smrg    if (mode->doubleBufferMode) {
1593706f2543Smrg        pfd.dwFlags |= PFD_DOUBLEBUFFER;
1594706f2543Smrg    }
1595706f2543Smrg
1596706f2543Smrg    pfd.iPixelType = PFD_TYPE_RGBA;
1597706f2543Smrg    pfd.cColorBits = mode->redBits + mode->greenBits + mode->blueBits;
1598706f2543Smrg    pfd.cRedBits = mode->redBits;
1599706f2543Smrg    pfd.cRedShift = 0; /* FIXME */
1600706f2543Smrg    pfd.cGreenBits = mode->greenBits;
1601706f2543Smrg    pfd.cGreenShift = 0; /* FIXME  */
1602706f2543Smrg    pfd.cBlueBits = mode->blueBits;
1603706f2543Smrg    pfd.cBlueShift = 0; /* FIXME */
1604706f2543Smrg    pfd.cAlphaBits = mode->alphaBits;
1605706f2543Smrg    pfd.cAlphaShift = 0; /* FIXME */
1606706f2543Smrg
1607706f2543Smrg    pfd.cAccumBits = mode->accumRedBits + mode->accumGreenBits + mode->accumBlueBits + mode->accumAlphaBits;
1608706f2543Smrg    pfd.cAccumRedBits = mode->accumRedBits;
1609706f2543Smrg    pfd.cAccumGreenBits = mode->accumGreenBits;
1610706f2543Smrg    pfd.cAccumBlueBits = mode->accumBlueBits;
1611706f2543Smrg    pfd.cAccumAlphaBits = mode->accumAlphaBits;
1612706f2543Smrg
1613706f2543Smrg    pfd.cDepthBits = mode->depthBits;
1614706f2543Smrg    pfd.cStencilBits = mode->stencilBits;
1615706f2543Smrg    pfd.cAuxBuffers = mode->numAuxBuffers;
1616706f2543Smrg
1617706f2543Smrg    /* mode->level ? */
1618706f2543Smrg    /* mode->pixmapMode ? */
1619706f2543Smrg
1620706f2543Smrg    *pfdret = pfd;
1621706f2543Smrg
1622706f2543Smrg    return 0;
1623706f2543Smrg}
1624706f2543Smrg
1625706f2543Smrg#define SET_ATTR_VALUE(attr, value) { attribList[i++] = attr; attribList[i++] = value; assert(i < NUM_ELEMENTS(attribList)); }
1626706f2543Smrg
1627706f2543Smrgstatic int
1628706f2543SmrgfbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen)
1629706f2543Smrg{
1630706f2543Smrg  UINT numFormats;
1631706f2543Smrg  unsigned int i = 0;
1632706f2543Smrg
1633706f2543Smrg  /* convert fbConfig to attr-value list  */
1634706f2543Smrg  int attribList[60];
1635706f2543Smrg
1636706f2543Smrg  SET_ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, TRUE);
1637706f2543Smrg  SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, (mode->visualType == GLX_TRUE_COLOR) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB);
1638706f2543Smrg  SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, (mode->visualType == GLX_TRUE_COLOR) ? mode->rgbBits : mode->indexBits);
1639706f2543Smrg  SET_ATTR_VALUE(WGL_RED_BITS_ARB, mode->redBits);
1640706f2543Smrg  SET_ATTR_VALUE(WGL_GREEN_BITS_ARB, mode->greenBits);
1641706f2543Smrg  SET_ATTR_VALUE(WGL_BLUE_BITS_ARB, mode->blueBits);
1642706f2543Smrg  SET_ATTR_VALUE(WGL_ALPHA_BITS_ARB, mode->alphaBits);
1643706f2543Smrg  SET_ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, mode->accumRedBits);
1644706f2543Smrg  SET_ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, mode->accumGreenBits);
1645706f2543Smrg  SET_ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, mode->accumBlueBits);
1646706f2543Smrg  SET_ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, mode->accumAlphaBits);
1647706f2543Smrg  SET_ATTR_VALUE(WGL_DEPTH_BITS_ARB, mode->depthBits);
1648706f2543Smrg  SET_ATTR_VALUE(WGL_STENCIL_BITS_ARB, mode->stencilBits);
1649706f2543Smrg  SET_ATTR_VALUE(WGL_AUX_BUFFERS_ARB, mode->numAuxBuffers);
1650706f2543Smrg
1651706f2543Smrg  if (mode->doubleBufferMode)
1652706f2543Smrg    SET_ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, TRUE);
1653706f2543Smrg
1654706f2543Smrg  if (mode->stereoMode)
1655706f2543Smrg    SET_ATTR_VALUE(WGL_STEREO_ARB, TRUE);
1656706f2543Smrg
1657706f2543Smrg  // Some attributes are only added to the list if the value requested is not 'don't care', as exactly matching that is daft..
1658706f2543Smrg  if (mode->swapMethod == GLX_SWAP_EXCHANGE_OML)
1659706f2543Smrg    SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB);
1660706f2543Smrg
1661706f2543Smrg  if (mode->swapMethod == GLX_SWAP_COPY_OML)
1662706f2543Smrg    SET_ATTR_VALUE(WGL_SWAP_COPY_ARB, TRUE);
1663706f2543Smrg
1664706f2543Smrg  // XXX: this should probably be the other way around, but that messes up drawableTypeOverride
1665706f2543Smrg  if (mode->visualRating == GLX_SLOW_VISUAL_EXT)
1666706f2543Smrg    SET_ATTR_VALUE(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB);
1667706f2543Smrg
1668706f2543Smrg  // must support all the drawable types the mode supports
1669706f2543Smrg  if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
1670706f2543Smrg    SET_ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB,TRUE);
1671706f2543Smrg
1672706f2543Smrg  // XXX: this is a horrible hacky heuristic, in fact this whole drawableTypeOverride thing is a bad idea
1673706f2543Smrg  // try to avoid asking for formats which don't exist (by not asking for all when adjusting the config to include the drawableTypeOverride)
1674706f2543Smrg  if (drawableTypeOverride == GLX_WINDOW_BIT)
1675706f2543Smrg    {
1676706f2543Smrg      if (mode->drawableType & GLX_PIXMAP_BIT)
1677706f2543Smrg        SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE);
1678706f2543Smrg
1679706f2543Smrg      if (mode->drawableType & GLX_PBUFFER_BIT)
1680706f2543Smrg        if (winScreen->has_WGL_ARB_pbuffer)
1681706f2543Smrg          SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
1682706f2543Smrg    }
1683706f2543Smrg  else
1684706f2543Smrg    {
1685706f2543Smrg      if (drawableTypeOverride & GLX_PIXMAP_BIT)
1686706f2543Smrg        SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE);
1687706f2543Smrg
1688706f2543Smrg      if (drawableTypeOverride & GLX_PBUFFER_BIT)
1689706f2543Smrg        if (winScreen->has_WGL_ARB_pbuffer)
1690706f2543Smrg          SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
1691706f2543Smrg    }
1692706f2543Smrg
1693706f2543Smrg  SET_ATTR_VALUE(0, 0); // terminator
1694706f2543Smrg
1695706f2543Smrg  /* choose the first match */
1696706f2543Smrg  {
1697706f2543Smrg    int pixelFormatIndex;
1698706f2543Smrg
1699706f2543Smrg    if (!wglChoosePixelFormatARBWrapper(hdc, attribList, NULL, 1, &pixelFormatIndex, &numFormats))
1700706f2543Smrg      {
1701706f2543Smrg        ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
1702706f2543Smrg      }
1703706f2543Smrg    else
1704706f2543Smrg      {
1705706f2543Smrg        if (numFormats > 0)
1706706f2543Smrg          {
1707706f2543Smrg            GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d)", pixelFormatIndex);
1708706f2543Smrg            return pixelFormatIndex;
1709706f2543Smrg          }
1710706f2543Smrg        else
1711706f2543Smrg          ErrorF("wglChoosePixelFormat couldn't decide\n");
1712706f2543Smrg      }
1713706f2543Smrg  }
1714706f2543Smrg
1715706f2543Smrg  return 0;
1716706f2543Smrg}
1717706f2543Smrg
1718706f2543Smrg/* ---------------------------------------------------------------------- */
1719706f2543Smrg
1720706f2543Smrg#define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask))
1721706f2543Smrg
1722706f2543Smrg//
1723706f2543Smrg// Create the GLXconfigs using DescribePixelFormat()
1724706f2543Smrg//
1725706f2543Smrgstatic void
1726706f2543SmrgglxWinCreateConfigs(HDC hdc, glxWinScreen *screen)
1727706f2543Smrg{
1728706f2543Smrg  GLXWinConfig *c, *result, *prev = NULL;
1729706f2543Smrg  int numConfigs = 0;
1730706f2543Smrg  int i = 0;
1731706f2543Smrg  int n = 0;
1732706f2543Smrg  PIXELFORMATDESCRIPTOR pfd;
1733706f2543Smrg
1734706f2543Smrg  GLWIN_DEBUG_MSG("glxWinCreateConfigs");
1735706f2543Smrg
1736706f2543Smrg  screen->base.numFBConfigs = 0;
1737706f2543Smrg  screen->base.fbconfigs = NULL;
1738706f2543Smrg
1739706f2543Smrg  // get the number of pixelformats
1740706f2543Smrg  numConfigs = DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
1741706f2543Smrg  GLWIN_DEBUG_MSG("DescribePixelFormat says %d possible pixel formats", numConfigs);
1742706f2543Smrg
1743706f2543Smrg  /* alloc */
1744706f2543Smrg  result = malloc(sizeof(GLXWinConfig) * numConfigs);
1745706f2543Smrg
1746706f2543Smrg  if (NULL == result)
1747706f2543Smrg    {
1748706f2543Smrg      return;
1749706f2543Smrg    }
1750706f2543Smrg
1751706f2543Smrg  memset(result, 0, sizeof(GLXWinConfig) * numConfigs);
1752706f2543Smrg  n = 0;
1753706f2543Smrg
1754706f2543Smrg  /* fill in configs */
1755706f2543Smrg  for (i = 0;  i < numConfigs; i++)
1756706f2543Smrg    {
1757706f2543Smrg      int rc;
1758706f2543Smrg
1759706f2543Smrg      c = &(result[i]);
1760706f2543Smrg      c->base.next = NULL;
1761706f2543Smrg      c->pixelFormatIndex = i+1;
1762706f2543Smrg
1763706f2543Smrg      rc = DescribePixelFormat(hdc, i+1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
1764706f2543Smrg
1765706f2543Smrg      if (!rc)
1766706f2543Smrg        {
1767706f2543Smrg          ErrorF("DescribePixelFormat failed for index %d, error %s\n", i+1, glxWinErrorMessage());
1768706f2543Smrg          break;
1769706f2543Smrg        }
1770706f2543Smrg
1771706f2543Smrg      if (glxWinDebugSettings.dumpPFD)
1772706f2543Smrg        pfdOut(&pfd);
1773706f2543Smrg
1774706f2543Smrg      if (!(pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP)) || !(pfd.dwFlags & PFD_SUPPORT_OPENGL))
1775706f2543Smrg        {
1776706f2543Smrg          GLWIN_DEBUG_MSG("pixelFormat %d has unsuitable flags 0x%08lx, skipping", i+1, pfd.dwFlags);
1777706f2543Smrg          continue;
1778706f2543Smrg        }
1779706f2543Smrg
1780706f2543Smrg      c->base.doubleBufferMode = (pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
1781706f2543Smrg      c->base.stereoMode = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE;
1782706f2543Smrg
1783706f2543Smrg      c->base.redBits = pfd.cRedBits;
1784706f2543Smrg      c->base.greenBits = pfd.cGreenBits;
1785706f2543Smrg      c->base.blueBits = pfd.cBlueBits;
1786706f2543Smrg      c->base.alphaBits = pfd.cAlphaBits;
1787706f2543Smrg
1788706f2543Smrg      c->base.redMask = BITS_AND_SHIFT_TO_MASK(pfd.cRedBits, pfd.cRedShift);
1789706f2543Smrg      c->base.greenMask =  BITS_AND_SHIFT_TO_MASK(pfd.cGreenBits, pfd.cGreenShift);
1790706f2543Smrg      c->base.blueMask = BITS_AND_SHIFT_TO_MASK(pfd.cBlueBits, pfd.cBlueShift);
1791706f2543Smrg      c->base.alphaMask = BITS_AND_SHIFT_TO_MASK(pfd.cAlphaBits, pfd.cAlphaShift);
1792706f2543Smrg
1793706f2543Smrg      c->base.rgbBits = pfd.cColorBits;
1794706f2543Smrg
1795706f2543Smrg      if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
1796706f2543Smrg        {
1797706f2543Smrg          c->base.indexBits = pfd.cColorBits;
1798706f2543Smrg        }
1799706f2543Smrg      else
1800706f2543Smrg        {
1801706f2543Smrg          c->base.indexBits = 0;
1802706f2543Smrg        }
1803706f2543Smrg
1804706f2543Smrg      c->base.accumRedBits = pfd.cAccumRedBits;
1805706f2543Smrg      c->base.accumGreenBits = pfd.cAccumGreenBits;
1806706f2543Smrg      c->base.accumBlueBits = pfd.cAccumBlueBits;
1807706f2543Smrg      c->base.accumAlphaBits = pfd.cAccumAlphaBits;
1808706f2543Smrg      //  pfd.cAccumBits;
1809706f2543Smrg
1810706f2543Smrg      c->base.depthBits = pfd.cDepthBits;
1811706f2543Smrg      c->base.stencilBits = pfd.cStencilBits;
1812706f2543Smrg      c->base.numAuxBuffers = pfd.cAuxBuffers;
1813706f2543Smrg
1814706f2543Smrg      // pfd.iLayerType; // ignored
1815706f2543Smrg      c->base.level = 0;
1816706f2543Smrg      // pfd.dwLayerMask; // ignored
1817706f2543Smrg      // pfd.dwDamageMask;  // ignored
1818706f2543Smrg
1819706f2543Smrg      c->base.pixmapMode = 0;
1820706f2543Smrg      c->base.visualID = -1;  // will be set by __glXScreenInit()
1821706f2543Smrg
1822706f2543Smrg      /* EXT_visual_rating / GLX 1.2 */
1823706f2543Smrg      if (pfd.dwFlags & PFD_GENERIC_FORMAT)
1824706f2543Smrg        {
1825706f2543Smrg          c->base.visualRating = GLX_SLOW_VISUAL_EXT;
1826706f2543Smrg        }
1827706f2543Smrg      else
1828706f2543Smrg        {
1829706f2543Smrg          // PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated...
1830706f2543Smrg          c->base.visualRating = GLX_NONE_EXT;
1831706f2543Smrg        }
1832706f2543Smrg
1833706f2543Smrg      /* EXT_visual_info / GLX 1.2 */
1834706f2543Smrg      if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
1835706f2543Smrg        {
1836706f2543Smrg          c->base.visualType = GLX_STATIC_COLOR;
1837706f2543Smrg
1838706f2543Smrg          if (!getenv("GLWIN_ENABLE_COLORINDEX_FBCONFIGS"))
1839706f2543Smrg            {
1840706f2543Smrg              GLWIN_DEBUG_MSG("pixelFormat %d is PFD_TYPE_COLORINDEX, skipping", i+1);
1841706f2543Smrg              continue;
1842706f2543Smrg            }
1843706f2543Smrg        }
1844706f2543Smrg      else
1845706f2543Smrg        {
1846706f2543Smrg          c->base.visualType = GLX_TRUE_COLOR;
1847706f2543Smrg        }
1848706f2543Smrg
1849706f2543Smrg      // pfd.dwVisibleMask; ???
1850706f2543Smrg      c->base.transparentPixel = GLX_NONE;
1851706f2543Smrg      c->base.transparentRed = GLX_NONE;
1852706f2543Smrg      c->base.transparentGreen = GLX_NONE;
1853706f2543Smrg      c->base.transparentBlue = GLX_NONE;
1854706f2543Smrg      c->base.transparentAlpha = GLX_NONE;
1855706f2543Smrg      c->base.transparentIndex = GLX_NONE;
1856706f2543Smrg
1857706f2543Smrg      /* ARB_multisample / SGIS_multisample */
1858706f2543Smrg      c->base.sampleBuffers = 0;
1859706f2543Smrg      c->base.samples = 0;
1860706f2543Smrg
1861706f2543Smrg      /* SGIX_fbconfig / GLX 1.3 */
1862706f2543Smrg      c->base.drawableType = (((pfd.dwFlags & PFD_DRAW_TO_WINDOW) ? GLX_WINDOW_BIT : 0)
1863706f2543Smrg                         | ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) ? GLX_PIXMAP_BIT : 0));
1864706f2543Smrg
1865706f2543Smrg      if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
1866706f2543Smrg        {
1867706f2543Smrg          c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT;
1868706f2543Smrg        }
1869706f2543Smrg      else
1870706f2543Smrg        {
1871706f2543Smrg          c->base.renderType = GLX_RGBA_BIT;
1872706f2543Smrg        }
1873706f2543Smrg
1874706f2543Smrg      c->base.xRenderable = GL_TRUE;
1875706f2543Smrg      c->base.fbconfigID = -1; // will be set by __glXScreenInit()
1876706f2543Smrg
1877706f2543Smrg      /* SGIX_pbuffer / GLX 1.3 */
1878706f2543Smrg      // XXX: How can we find these values out ???
1879706f2543Smrg      c->base.maxPbufferWidth = -1;
1880706f2543Smrg      c->base.maxPbufferHeight = -1;
1881706f2543Smrg      c->base.maxPbufferPixels = -1;
1882706f2543Smrg      c->base.optimalPbufferWidth = 0; // there is no optimal value
1883706f2543Smrg      c->base.optimalPbufferHeight = 0;
1884706f2543Smrg
1885706f2543Smrg      /* SGIX_visual_select_group */
1886706f2543Smrg      // arrange for visuals with the best acceleration to be preferred in selection
1887706f2543Smrg      switch (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
1888706f2543Smrg        {
1889706f2543Smrg        case 0:
1890706f2543Smrg          c->base.visualSelectGroup = 2;
1891706f2543Smrg          break;
1892706f2543Smrg
1893706f2543Smrg        case PFD_GENERIC_ACCELERATED:
1894706f2543Smrg          c->base.visualSelectGroup = 1;
1895706f2543Smrg          break;
1896706f2543Smrg
1897706f2543Smrg        case PFD_GENERIC_FORMAT:
1898706f2543Smrg          c->base.visualSelectGroup = 0;
1899706f2543Smrg          break;
1900706f2543Smrg
1901706f2543Smrg        default:
1902706f2543Smrg          ;
1903706f2543Smrg          // "can't happen"
1904706f2543Smrg        }
1905706f2543Smrg
1906706f2543Smrg      /* OML_swap_method */
1907706f2543Smrg      if (pfd.dwFlags & PFD_SWAP_EXCHANGE)
1908706f2543Smrg        c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
1909706f2543Smrg      else if (pfd.dwFlags & PFD_SWAP_COPY)
1910706f2543Smrg        c->base.swapMethod = GLX_SWAP_COPY_OML;
1911706f2543Smrg      else
1912706f2543Smrg        c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
1913706f2543Smrg
1914706f2543Smrg      /* EXT_import_context */
1915706f2543Smrg      c->base.screen = screen->base.pScreen->myNum;
1916706f2543Smrg
1917706f2543Smrg      /* EXT_texture_from_pixmap */
1918706f2543Smrg      c->base.bindToTextureRgb = -1;
1919706f2543Smrg      c->base.bindToTextureRgba = -1;
1920706f2543Smrg      c->base.bindToMipmapTexture = -1;
1921706f2543Smrg      c->base.bindToTextureTargets = -1;
1922706f2543Smrg      c->base.yInverted = -1;
1923706f2543Smrg
1924706f2543Smrg      n++;
1925706f2543Smrg
1926706f2543Smrg      // update previous config to point to this config
1927706f2543Smrg      if (prev)
1928706f2543Smrg        prev->base.next = &(c->base);
1929706f2543Smrg
1930706f2543Smrg      prev = c;
1931706f2543Smrg    }
1932706f2543Smrg
1933706f2543Smrg  GLWIN_DEBUG_MSG("found %d pixelFormats suitable for conversion to fbConfigs", n);
1934706f2543Smrg
1935706f2543Smrg  screen->base.numFBConfigs = n;
1936706f2543Smrg  screen->base.fbconfigs = &(result->base);
1937706f2543Smrg}
1938706f2543Smrg
1939706f2543Smrg// helper function to access an attribute value from an attribute value array by attribute
1940706f2543Smrgstatic
1941706f2543Smrgint getAttrValue(const int attrs[], int values[], unsigned int num, int attr, int fallback)
1942706f2543Smrg{
1943706f2543Smrg  unsigned int i;
1944706f2543Smrg  for (i = 0; i < num; i++)
1945706f2543Smrg    {
1946706f2543Smrg      if (attrs[i] == attr)
1947706f2543Smrg        {
1948706f2543Smrg          GLWIN_TRACE_MSG("getAttrValue attr 0x%x, value %d", attr, values[i]);
1949706f2543Smrg          return values[i];
1950706f2543Smrg        }
1951706f2543Smrg    }
1952706f2543Smrg
1953706f2543Smrg  ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n", attr, fallback);
1954706f2543Smrg  return fallback;
1955706f2543Smrg}
1956706f2543Smrg
1957706f2543Smrg//
1958706f2543Smrg// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
1959706f2543Smrg//
1960706f2543Smrgstatic void
1961706f2543SmrgglxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen)
1962706f2543Smrg{
1963706f2543Smrg  GLXWinConfig *c, *result, *prev = NULL;
1964706f2543Smrg  int i = 0;
1965706f2543Smrg  int n = 0;
1966706f2543Smrg
1967706f2543Smrg  const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB;
1968706f2543Smrg  int numConfigs;
1969706f2543Smrg
1970706f2543Smrg  int attrs[50];
1971706f2543Smrg  unsigned int num_attrs = 0;
1972706f2543Smrg
1973706f2543Smrg  GLWIN_DEBUG_MSG("glxWinCreateConfigsExt");
1974706f2543Smrg
1975706f2543Smrg  screen->base.numFBConfigs = 0;
1976706f2543Smrg  screen->base.fbconfigs = NULL;
1977706f2543Smrg
1978706f2543Smrg  if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs))
1979706f2543Smrg    {
1980706f2543Smrg      ErrorF("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n", glxWinErrorMessage());
1981706f2543Smrg      return;
1982706f2543Smrg    }
1983706f2543Smrg
1984706f2543Smrg  GLWIN_DEBUG_MSG("wglGetPixelFormatAttribivARB says %d possible pixel formats", numConfigs);
1985706f2543Smrg
1986706f2543Smrg  /* alloc */
1987706f2543Smrg  result = malloc(sizeof(GLXWinConfig) * numConfigs);
1988706f2543Smrg
1989706f2543Smrg  if (NULL == result)
1990706f2543Smrg    {
1991706f2543Smrg      return;
1992706f2543Smrg    }
1993706f2543Smrg
1994706f2543Smrg  memset(result, 0, sizeof(GLXWinConfig) * numConfigs);
1995706f2543Smrg  n = 0;
1996706f2543Smrg
1997706f2543Smrg#define ADD_ATTR(a) { attrs[num_attrs++] = a; assert(num_attrs < NUM_ELEMENTS(attrs)); }
1998706f2543Smrg
1999706f2543Smrg  ADD_ATTR(WGL_DRAW_TO_WINDOW_ARB);
2000706f2543Smrg  ADD_ATTR(WGL_DRAW_TO_BITMAP_ARB);
2001706f2543Smrg  ADD_ATTR(WGL_ACCELERATION_ARB);
2002706f2543Smrg  ADD_ATTR(WGL_SWAP_LAYER_BUFFERS_ARB);
2003706f2543Smrg  ADD_ATTR(WGL_NUMBER_OVERLAYS_ARB);
2004706f2543Smrg  ADD_ATTR(WGL_NUMBER_UNDERLAYS_ARB);
2005706f2543Smrg  ADD_ATTR(WGL_TRANSPARENT_ARB);
2006706f2543Smrg  ADD_ATTR(WGL_TRANSPARENT_RED_VALUE_ARB);
2007706f2543Smrg  ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB);
2008706f2543Smrg  ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB);
2009706f2543Smrg  ADD_ATTR(WGL_TRANSPARENT_ALPHA_VALUE_ARB);
2010706f2543Smrg  ADD_ATTR(WGL_SUPPORT_OPENGL_ARB);
2011706f2543Smrg  ADD_ATTR(WGL_DOUBLE_BUFFER_ARB);
2012706f2543Smrg  ADD_ATTR(WGL_STEREO_ARB);
2013706f2543Smrg  ADD_ATTR(WGL_PIXEL_TYPE_ARB);
2014706f2543Smrg  ADD_ATTR(WGL_COLOR_BITS_ARB);
2015706f2543Smrg  ADD_ATTR(WGL_RED_BITS_ARB);
2016706f2543Smrg  ADD_ATTR(WGL_RED_SHIFT_ARB);
2017706f2543Smrg  ADD_ATTR(WGL_GREEN_BITS_ARB);
2018706f2543Smrg  ADD_ATTR(WGL_GREEN_SHIFT_ARB);
2019706f2543Smrg  ADD_ATTR(WGL_BLUE_BITS_ARB);
2020706f2543Smrg  ADD_ATTR(WGL_BLUE_SHIFT_ARB);
2021706f2543Smrg  ADD_ATTR(WGL_ALPHA_BITS_ARB);
2022706f2543Smrg  ADD_ATTR(WGL_ALPHA_SHIFT_ARB);
2023706f2543Smrg  ADD_ATTR(WGL_ACCUM_RED_BITS_ARB);
2024706f2543Smrg  ADD_ATTR(WGL_ACCUM_GREEN_BITS_ARB);
2025706f2543Smrg  ADD_ATTR(WGL_ACCUM_BLUE_BITS_ARB);
2026706f2543Smrg  ADD_ATTR(WGL_ACCUM_ALPHA_BITS_ARB);
2027706f2543Smrg  ADD_ATTR(WGL_DEPTH_BITS_ARB);
2028706f2543Smrg  ADD_ATTR(WGL_STENCIL_BITS_ARB);
2029706f2543Smrg  ADD_ATTR(WGL_AUX_BUFFERS_ARB);
2030706f2543Smrg  ADD_ATTR(WGL_SWAP_METHOD_ARB);
2031706f2543Smrg
2032706f2543Smrg  if (screen->has_WGL_ARB_multisample)
2033706f2543Smrg    {
2034706f2543Smrg      // we may not query these attrs if WGL_ARB_multisample is not offered
2035706f2543Smrg      ADD_ATTR(WGL_SAMPLE_BUFFERS_ARB);
2036706f2543Smrg      ADD_ATTR(WGL_SAMPLES_ARB);
2037706f2543Smrg    }
2038706f2543Smrg
2039706f2543Smrg  if (screen->has_WGL_ARB_render_texture)
2040706f2543Smrg    {
2041706f2543Smrg      // we may not query these attrs if WGL_ARB_render_texture is not offered
2042706f2543Smrg      ADD_ATTR(WGL_BIND_TO_TEXTURE_RGB_ARB);
2043706f2543Smrg      ADD_ATTR(WGL_BIND_TO_TEXTURE_RGBA_ARB);
2044706f2543Smrg    }
2045706f2543Smrg
2046706f2543Smrg  if (screen->has_WGL_ARB_pbuffer)
2047706f2543Smrg    {
2048706f2543Smrg      // we may not query these attrs if WGL_ARB_pbuffer is not offered
2049706f2543Smrg      ADD_ATTR(WGL_DRAW_TO_PBUFFER_ARB);
2050706f2543Smrg      ADD_ATTR(WGL_MAX_PBUFFER_PIXELS_ARB);
2051706f2543Smrg      ADD_ATTR(WGL_MAX_PBUFFER_WIDTH_ARB);
2052706f2543Smrg      ADD_ATTR(WGL_MAX_PBUFFER_HEIGHT_ARB);
2053706f2543Smrg    }
2054706f2543Smrg
2055706f2543Smrg  /* fill in configs */
2056706f2543Smrg  for (i = 0;  i < numConfigs; i++)
2057706f2543Smrg    {
2058706f2543Smrg      int values[num_attrs];
2059706f2543Smrg
2060706f2543Smrg      c = &(result[i]);
2061706f2543Smrg      c->base.next = NULL;
2062706f2543Smrg      c->pixelFormatIndex = i+1;
2063706f2543Smrg
2064706f2543Smrg      if (!wglGetPixelFormatAttribivARBWrapper(hdc, i+1, 0, num_attrs, attrs, values))
2065706f2543Smrg        {
2066706f2543Smrg          ErrorF("wglGetPixelFormatAttribivARB failed for index %d, error %s\n", i+1, glxWinErrorMessage());
2067706f2543Smrg          break;
2068706f2543Smrg        }
2069706f2543Smrg
2070706f2543Smrg#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
2071706f2543Smrg
2072706f2543Smrg      if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0))
2073706f2543Smrg        {
2074706f2543Smrg          GLWIN_DEBUG_MSG("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping", i+1);
2075706f2543Smrg          continue;
2076706f2543Smrg        }
2077706f2543Smrg
2078706f2543Smrg      c->base.doubleBufferMode = ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, 0) ? GL_TRUE : GL_FALSE;
2079706f2543Smrg      c->base.stereoMode = ATTR_VALUE(WGL_STEREO_ARB, 0) ? GL_TRUE : GL_FALSE;
2080706f2543Smrg
2081706f2543Smrg      c->base.redBits = ATTR_VALUE(WGL_RED_BITS_ARB, 0);
2082706f2543Smrg      c->base.greenBits = ATTR_VALUE(WGL_GREEN_BITS_ARB, 0);
2083706f2543Smrg      c->base.blueBits = ATTR_VALUE(WGL_BLUE_BITS_ARB, 0);
2084706f2543Smrg      c->base.alphaBits = ATTR_VALUE(WGL_ALPHA_BITS_ARB, 0);
2085706f2543Smrg
2086706f2543Smrg      c->base.redMask = BITS_AND_SHIFT_TO_MASK(c->base.redBits, ATTR_VALUE(WGL_RED_SHIFT_ARB, 0));
2087706f2543Smrg      c->base.greenMask = BITS_AND_SHIFT_TO_MASK(c->base.greenBits, ATTR_VALUE(WGL_GREEN_SHIFT_ARB, 0));
2088706f2543Smrg      c->base.blueMask = BITS_AND_SHIFT_TO_MASK(c->base.blueBits, ATTR_VALUE(WGL_BLUE_SHIFT_ARB, 0));
2089706f2543Smrg      c->base.alphaMask = BITS_AND_SHIFT_TO_MASK(c->base.alphaBits, ATTR_VALUE(WGL_ALPHA_SHIFT_ARB, 0));
2090706f2543Smrg
2091706f2543Smrg      switch (ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0))
2092706f2543Smrg        {
2093706f2543Smrg        case WGL_TYPE_COLORINDEX_ARB:
2094706f2543Smrg          c->base.indexBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
2095706f2543Smrg          c->base.rgbBits = 0;
2096706f2543Smrg          c->base.visualType = GLX_STATIC_COLOR;
2097706f2543Smrg
2098706f2543Smrg          if (!getenv("GLWIN_ENABLE_COLORINDEX_FBCONFIGS"))
2099706f2543Smrg            {
2100706f2543Smrg              GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_COLORINDEX_ARB, skipping", i+1);
2101706f2543Smrg              continue;
2102706f2543Smrg            }
2103706f2543Smrg
2104706f2543Smrg          break;
2105706f2543Smrg
2106706f2543Smrg        case WGL_TYPE_RGBA_FLOAT_ARB:
2107706f2543Smrg          GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i+1);
2108706f2543Smrg          continue;
2109706f2543Smrg
2110706f2543Smrg        case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
2111706f2543Smrg          GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping", i+1);
2112706f2543Smrg          continue;
2113706f2543Smrg
2114706f2543Smrg        case WGL_TYPE_RGBA_ARB:
2115706f2543Smrg          c->base.indexBits = 0;
2116706f2543Smrg          c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
2117706f2543Smrg          c->base.visualType = GLX_TRUE_COLOR;
2118706f2543Smrg          break;
2119706f2543Smrg
2120706f2543Smrg        default:
2121706f2543Smrg          ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n", ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0));
2122706f2543Smrg          continue;
2123706f2543Smrg        }
2124706f2543Smrg
2125706f2543Smrg      c->base.accumRedBits = ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, 0);
2126706f2543Smrg      c->base.accumGreenBits = ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, 0);
2127706f2543Smrg      c->base.accumBlueBits = ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, 0);
2128706f2543Smrg      c->base.accumAlphaBits = ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, 0);
2129706f2543Smrg
2130706f2543Smrg      c->base.depthBits = ATTR_VALUE(WGL_DEPTH_BITS_ARB, 0);
2131706f2543Smrg      c->base.stencilBits = ATTR_VALUE(WGL_STENCIL_BITS_ARB, 0);
2132706f2543Smrg      c->base.numAuxBuffers = ATTR_VALUE(WGL_AUX_BUFFERS_ARB, 0);
2133706f2543Smrg
2134706f2543Smrg      {
2135706f2543Smrg        int layers = ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0);
2136706f2543Smrg
2137706f2543Smrg        if (layers > 0)
2138706f2543Smrg          {
2139706f2543Smrg            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));
2140706f2543Smrg            // XXX: need to iterate over layers?
2141706f2543Smrg          }
2142706f2543Smrg      }
2143706f2543Smrg      c->base.level = 0;
2144706f2543Smrg
2145706f2543Smrg      c->base.pixmapMode = 0; // ???
2146706f2543Smrg      c->base.visualID = -1;  // will be set by __glXScreenInit()
2147706f2543Smrg
2148706f2543Smrg      /* EXT_visual_rating / GLX 1.2 */
2149706f2543Smrg      switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0))
2150706f2543Smrg        {
2151706f2543Smrg        default:
2152706f2543Smrg          ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_ACCELERATION_ARB\n", ATTR_VALUE(WGL_ACCELERATION_ARB, 0));
2153706f2543Smrg
2154706f2543Smrg        case WGL_NO_ACCELERATION_ARB:
2155706f2543Smrg          c->base.visualRating = GLX_SLOW_VISUAL_EXT;
2156706f2543Smrg          break;
2157706f2543Smrg
2158706f2543Smrg        case WGL_GENERIC_ACCELERATION_ARB:
2159706f2543Smrg        case WGL_FULL_ACCELERATION_ARB:
2160706f2543Smrg          c->base.visualRating = GLX_NONE_EXT;
2161706f2543Smrg          break;
2162706f2543Smrg        }
2163706f2543Smrg
2164706f2543Smrg      /* EXT_visual_info / GLX 1.2 */
2165706f2543Smrg      // c->base.visualType is set above
2166706f2543Smrg      if (ATTR_VALUE(WGL_TRANSPARENT_ARB, 0))
2167706f2543Smrg        {
2168706f2543Smrg          c->base.transparentPixel = (c->base.visualType == GLX_TRUE_COLOR) ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
2169706f2543Smrg          c->base.transparentRed = ATTR_VALUE(WGL_TRANSPARENT_RED_VALUE_ARB, 0);
2170706f2543Smrg          c->base.transparentGreen = ATTR_VALUE(WGL_TRANSPARENT_GREEN_VALUE_ARB, 0);
2171706f2543Smrg          c->base.transparentBlue = ATTR_VALUE(WGL_TRANSPARENT_BLUE_VALUE_ARB, 0);
2172706f2543Smrg          c->base.transparentAlpha = ATTR_VALUE(WGL_TRANSPARENT_ALPHA_VALUE_ARB, 0);
2173706f2543Smrg          c->base.transparentIndex = ATTR_VALUE(WGL_TRANSPARENT_INDEX_VALUE_ARB, 0);
2174706f2543Smrg        }
2175706f2543Smrg      else
2176706f2543Smrg        {
2177706f2543Smrg          c->base.transparentPixel = GLX_NONE_EXT;
2178706f2543Smrg          c->base.transparentRed = GLX_NONE;
2179706f2543Smrg          c->base.transparentGreen = GLX_NONE;
2180706f2543Smrg          c->base.transparentBlue = GLX_NONE;
2181706f2543Smrg          c->base.transparentAlpha = GLX_NONE;
2182706f2543Smrg          c->base.transparentIndex = GLX_NONE;
2183706f2543Smrg        }
2184706f2543Smrg
2185706f2543Smrg      /* ARB_multisample / SGIS_multisample */
2186706f2543Smrg      if (screen->has_WGL_ARB_multisample)
2187706f2543Smrg        {
2188706f2543Smrg          c->base.sampleBuffers = ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, 0);
2189706f2543Smrg          c->base.samples = ATTR_VALUE(WGL_SAMPLES_ARB, 0);
2190706f2543Smrg        }
2191706f2543Smrg      else
2192706f2543Smrg        {
2193706f2543Smrg          c->base.sampleBuffers = 0;
2194706f2543Smrg          c->base.samples = 0;
2195706f2543Smrg        }
2196706f2543Smrg
2197706f2543Smrg      /* SGIX_fbconfig / GLX 1.3 */
2198706f2543Smrg      c->base.drawableType = ((ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, 0) ? GLX_WINDOW_BIT : 0)
2199706f2543Smrg                         | (ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, 0) ? GLX_PIXMAP_BIT : 0)
2200706f2543Smrg                         | (ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, 0) ? GLX_PBUFFER_BIT : 0));
2201706f2543Smrg
2202706f2543Smrg      /*
2203706f2543Smrg        Assume OpenGL RGBA rendering is available on all visuals
2204706f2543Smrg        (it is specified to render to red component in single-channel visuals,
2205706f2543Smrg        if supported, but there doesn't seem to be any mechanism to check if it
2206706f2543Smrg        is supported)
2207706f2543Smrg
2208706f2543Smrg        Color index rendering is only supported on single-channel visuals
2209706f2543Smrg      */
2210706f2543Smrg      if (c->base.visualType == GLX_STATIC_COLOR)
2211706f2543Smrg        {
2212706f2543Smrg          c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT;
2213706f2543Smrg        }
2214706f2543Smrg      else
2215706f2543Smrg        {
2216706f2543Smrg          c->base.renderType = GLX_RGBA_BIT;
2217706f2543Smrg        }
2218706f2543Smrg
2219706f2543Smrg      c->base.xRenderable = GL_TRUE;
2220706f2543Smrg      c->base.fbconfigID = -1; // will be set by __glXScreenInit()
2221706f2543Smrg
2222706f2543Smrg      /* SGIX_pbuffer / GLX 1.3 */
2223706f2543Smrg      if (screen->has_WGL_ARB_pbuffer)
2224706f2543Smrg        {
2225706f2543Smrg          c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1);
2226706f2543Smrg          c->base.maxPbufferHeight = ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1);
2227706f2543Smrg          c->base.maxPbufferPixels =  ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1);
2228706f2543Smrg        }
2229706f2543Smrg      else
2230706f2543Smrg        {
2231706f2543Smrg          c->base.maxPbufferWidth = -1;
2232706f2543Smrg          c->base.maxPbufferHeight = -1;
2233706f2543Smrg          c->base.maxPbufferPixels =  -1;
2234706f2543Smrg        }
2235706f2543Smrg      c->base.optimalPbufferWidth = 0; // there is no optimal value
2236706f2543Smrg      c->base.optimalPbufferHeight = 0;
2237706f2543Smrg
2238706f2543Smrg      /* SGIX_visual_select_group */
2239706f2543Smrg      // arrange for visuals with the best acceleration to be preferred in selection
2240706f2543Smrg      switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0))
2241706f2543Smrg        {
2242706f2543Smrg        case WGL_FULL_ACCELERATION_ARB:
2243706f2543Smrg          c->base.visualSelectGroup = 2;
2244706f2543Smrg          break;
2245706f2543Smrg
2246706f2543Smrg        case WGL_GENERIC_ACCELERATION_ARB:
2247706f2543Smrg          c->base.visualSelectGroup = 1;
2248706f2543Smrg          break;
2249706f2543Smrg
2250706f2543Smrg        default:
2251706f2543Smrg        case WGL_NO_ACCELERATION_ARB:
2252706f2543Smrg          c->base.visualSelectGroup = 0;
2253706f2543Smrg          break;
2254706f2543Smrg        }
2255706f2543Smrg
2256706f2543Smrg      /* OML_swap_method */
2257706f2543Smrg      switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0))
2258706f2543Smrg        {
2259706f2543Smrg        case WGL_SWAP_EXCHANGE_ARB:
2260706f2543Smrg          c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
2261706f2543Smrg          break;
2262706f2543Smrg
2263706f2543Smrg        case WGL_SWAP_COPY_ARB:
2264706f2543Smrg          c->base.swapMethod = GLX_SWAP_COPY_OML;
2265706f2543Smrg          break;
2266706f2543Smrg
2267706f2543Smrg        default:
2268706f2543Smrg          ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n", ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0));
2269706f2543Smrg
2270706f2543Smrg        case WGL_SWAP_UNDEFINED_ARB:
2271706f2543Smrg          c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
2272706f2543Smrg        }
2273706f2543Smrg
2274706f2543Smrg      /* EXT_import_context */
2275706f2543Smrg      c->base.screen = screen->base.pScreen->myNum;
2276706f2543Smrg
2277706f2543Smrg      /* EXT_texture_from_pixmap */
2278706f2543Smrg      /*
2279706f2543Smrg         Mesa's DRI configs always have bindToTextureRgb/Rgba TRUE (see driCreateConfigs(), so setting
2280706f2543Smrg         bindToTextureRgb/bindToTextureRgba to FALSE means that swrast can't find any fbConfigs to use,
2281706f2543Smrg         so setting these to 0, even if we know bindToTexture isn't available, isn't a good idea...
2282706f2543Smrg       */
2283706f2543Smrg      if (screen->has_WGL_ARB_render_texture)
2284706f2543Smrg        {
2285706f2543Smrg          c->base.bindToTextureRgb = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGB_ARB, -1);
2286706f2543Smrg          c->base.bindToTextureRgba = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGBA_ARB, -1);
2287706f2543Smrg        }
2288706f2543Smrg      else
2289706f2543Smrg        {
2290706f2543Smrg          c->base.bindToTextureRgb = -1;
2291706f2543Smrg          c->base.bindToTextureRgba = -1;
2292706f2543Smrg        }
2293706f2543Smrg      c->base.bindToMipmapTexture = -1;
2294706f2543Smrg      c->base.bindToTextureTargets = GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | GLX_TEXTURE_RECTANGLE_BIT_EXT;
2295706f2543Smrg      c->base.yInverted = -1;
2296706f2543Smrg
2297706f2543Smrg      n++;
2298706f2543Smrg
2299706f2543Smrg      // update previous config to point to this config
2300706f2543Smrg      if (prev)
2301706f2543Smrg        prev->base.next = &(c->base);
2302706f2543Smrg
2303706f2543Smrg      prev = c;
2304706f2543Smrg    }
2305706f2543Smrg
2306706f2543Smrg  screen->base.numFBConfigs = n;
2307706f2543Smrg  screen->base.fbconfigs = &(result->base);
2308706f2543Smrg}
2309