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