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