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