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