3 * Purpose: A GLX implementation that uses Windows OpenGL library
5 * Authors: Alexander Gottwald
8 * Copyright (c) Jon TURNEY 2009
9 * Copyright (c) Alexander Gottwald 2004
11 * Portions of this file are copied from GL/apple/indirect.c,
12 * which contains the following copyright:
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.
18 * Portions of this file are copied from Mesa's xf86glx.c,
19 * which contains the following copyright:
21 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
22 * All Rights Reserved.
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:
32 * The above copyright notice and this permission notice shall be included in
33 * all copies or substantial portions of the Software.
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.
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
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
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
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
72 wglMakeCurrent ignores the hdc if hglrc is NULL, so wglMakeCurrent(NULL, NULL)
73 is used to make no context current
77 #ifdef HAVE_XWIN_CONFIG_H
78 #include <xwin-config.h>
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>
88 #include <wgl_ext_api.h>
89 #include <winglobals.h>
91 #define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1]))
93 /* Not yet in w32api */
94 #ifndef PFD_SUPPORT_DIRECTDRAW
95 #define PFD_SUPPORT_DIRECTDRAW 0x00002000
97 #ifndef PFD_DIRECT3D_ACCELERATED
98 #define PFD_DIRECT3D_ACCELERATED 0x00004000
100 #ifndef PFD_SUPPORT_COMPOSITION
101 #define PFD_SUPPORT_COMPOSITION 0x00008000
104 /* ---------------------------------------------------------------------- */
106 * structure definitions
109 typedef struct __GLXWinContext __GLXWinContext
;
110 typedef struct __GLXWinDrawable __GLXWinDrawable
;
111 typedef struct __GLXWinScreen glxWinScreen
;
112 typedef struct __GLXWinConfig GLXWinConfig
;
114 struct __GLXWinContext
{
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 */
121 struct __GLXWinDrawable
{
123 __GLXWinContext
*drawContext
;
124 __GLXWinContext
*readContext
;
126 /* If this drawable is GLX_DRAWABLE_PBUFFER */
127 HPBUFFERARB hPbuffer
;
129 /* If this drawable is GLX_DRAWABLE_PIXMAP */
132 HBITMAP hOldDIB
; /* original DIB for DC */
133 void *pOldBits
; /* original pBits for this drawable's pixmap */
136 struct __GLXWinScreen
{
139 /* Supported GLX extensions */
140 unsigned char glx_enable_bits
[__GLX_EXT_BYTES
];
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
;
147 /* wrapped screen functions */
148 RealizeWindowProcPtr RealizeWindow
;
149 UnrealizeWindowProcPtr UnrealizeWindow
;
150 CopyWindowProcPtr CopyWindow
;
153 struct __GLXWinConfig
{
155 int pixelFormatIndex
;
158 /* ---------------------------------------------------------------------- */
160 * Various debug helpers
163 #define GLWIN_DEBUG_HWND(hwnd) \
164 if (glxWinDebugSettings.dumpHWND) { \
166 if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; \
167 GLWIN_DEBUG_MSG("Got HWND %p for window '%s'", hwnd, buffer); \
170 glxWinDebugSettingsRec glxWinDebugSettings
= { 0, 0, 0, 0, 0, 0 };
173 glxWinInitDebugSettings(void)
177 envptr
= getenv("GLWIN_ENABLE_DEBUG");
179 glxWinDebugSettings
.enableDebug
= (atoi(envptr
) == 1);
181 envptr
= getenv("GLWIN_ENABLE_TRACE");
183 glxWinDebugSettings
.enableTrace
= (atoi(envptr
) == 1);
185 envptr
= getenv("GLWIN_DUMP_PFD");
187 glxWinDebugSettings
.dumpPFD
= (atoi(envptr
) == 1);
189 envptr
= getenv("GLWIN_DUMP_HWND");
191 glxWinDebugSettings
.dumpHWND
= (atoi(envptr
) == 1);
193 envptr
= getenv("GLWIN_DUMP_DC");
195 glxWinDebugSettings
.dumpDC
= (atoi(envptr
) == 1);
197 envptr
= getenv("GLWIN_ENABLE_GLCALL_TRACE");
199 glxWinDebugSettings
.enableGLcallTrace
= (atoi(envptr
) == 1);
201 envptr
= getenv("GLWIN_ENABLE_WGLCALL_TRACE");
203 glxWinDebugSettings
.enableWGLcallTrace
= (atoi(envptr
) == 1);
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;
219 glxWinErrorMessage(void)
221 static char errorbuffer
[1024];
222 unsigned int last_error
= GetLastError();
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");
231 if ((errorbuffer
[strlen(errorbuffer
) - 1] == '\n') ||
232 (errorbuffer
[strlen(errorbuffer
) - 1] == '\r'))
233 errorbuffer
[strlen(errorbuffer
) - 1] = 0;
235 sprintf(errorbuffer
+ strlen(errorbuffer
), " (%08x)", last_error
);
240 static void pfdOut(const PIXELFORMATDESCRIPTOR
* pfd
);
242 #define DUMP_PFD_FLAG(flag) \
243 if (pfd->dwFlags & flag) { \
244 ErrorF("%s%s", pipesym, #flag); \
249 pfdOut(const PIXELFORMATDESCRIPTOR
* pfd
)
251 const char *pipesym
= ""; /* will be set after first flag dump */
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
);
278 ErrorF("iPixelType = %hu = %s\n", 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
);
307 visual_class_name(int cls
)
310 case GLX_STATIC_COLOR
:
311 return "StaticColor";
312 case GLX_PSEUDO_COLOR
:
313 return "PseudoColor";
314 case GLX_STATIC_GRAY
:
320 case GLX_DIRECT_COLOR
:
321 return "DirectColor";
328 swap_method_name(int mthd
)
331 case GLX_SWAP_EXCHANGE_OML
:
333 case GLX_SWAP_COPY_OML
:
335 case GLX_SWAP_UNDEFINED_OML
:
343 fbConfigsDump(unsigned int n
, __GLXconfig
* c
)
345 LogMessage(X_INFO
, "%d fbConfigs\n", n
);
347 if (g_iLogVerbose
< 3)
349 ErrorF("%d fbConfigs\n", n
);
351 ("pxf vis fb render Ste aux accum MS drawable Group/\n");
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");
355 ("-----------------------------------------------------------------------------------------------------------------------------\n");
358 unsigned int i
= ((GLXWinConfig
*) c
)->pixelFormatIndex
;
360 ErrorF("%3d %3x %3x "
362 " %3d %3d %s %s %s %s %s "
373 i
, c
->visualID
, c
->fbconfigID
,
374 visual_class_name(c
->visualType
),
375 c
->rgbBits
? c
->rgbBits
: c
->indexBits
,
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
,
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
) ? "*" : " ");
400 /* ---------------------------------------------------------------------- */
402 * Forward declarations
405 static __GLXscreen
*glxWinScreenProbe(ScreenPtr pScreen
);
406 static __GLXcontext
*glxWinCreateContext(__GLXscreen
* screen
,
408 __GLXcontext
* baseShareContext
,
409 unsigned num_attribs
,
410 const uint32_t * attribs
, int *error
);
411 static __GLXdrawable
*glxWinCreateDrawable(ClientPtr client
,
412 __GLXscreen
* screen
,
416 XID glxDrawId
, __GLXconfig
* conf
);
418 static Bool
glxWinRealizeWindow(WindowPtr pWin
);
419 static Bool
glxWinUnrealizeWindow(WindowPtr pWin
);
420 static void glxWinCopyWindow(WindowPtr pWindow
, DDXPointRec ptOldOrg
,
423 static HDC
glxWinMakeDC(__GLXWinContext
* gc
, __GLXWinDrawable
* draw
,
424 HDC
* hdc
, HWND
* hwnd
);
425 static void glxWinReleaseDC(HWND hwnd
, HDC hdc
, __GLXWinDrawable
* draw
);
427 static void glxWinCreateConfigs(HDC dc
, glxWinScreen
* screen
);
428 static void glxWinCreateConfigsExt(HDC hdc
, glxWinScreen
* screen
);
429 static int fbConfigToPixelFormat(__GLXconfig
* mode
,
430 PIXELFORMATDESCRIPTOR
* pfdret
,
431 int drawableTypeOverride
);
432 static int fbConfigToPixelFormatIndex(HDC hdc
, __GLXconfig
* mode
,
433 int drawableTypeOverride
,
434 glxWinScreen
* winScreen
);
436 /* ---------------------------------------------------------------------- */
441 __GLXprovider __glXWGLProvider
= {
448 glxWinPushNativeProvider(void)
450 GlxPushProvider(&__glXWGLProvider
);
453 /* ---------------------------------------------------------------------- */
459 glxWinScreenDestroy(__GLXscreen
* screen
)
461 GLWIN_DEBUG_MSG("glxWinScreenDestroy(%p)", screen
);
462 __glXScreenDestroy(screen
);
467 glxWinScreenSwapInterval(__GLXdrawable
* drawable
, int interval
)
469 BOOL ret
= wglSwapIntervalEXTWrapper(interval
);
472 ErrorF("wglSwapIntervalEXT interval %d failed:%s\n", interval
,
473 glxWinErrorMessage());
479 Report the extensions split and formatted to avoid overflowing a line
482 glxLogExtensions(const char *prefix
, const char *extensions
)
486 char *str
= strdup(extensions
);
489 ErrorF("glxLogExtensions: xalloc error\n");
493 strl
= strtok(str
, " ");
496 ErrorF("%s%s", prefix
, strl
);
497 length
= strlen(prefix
) + strlen(strl
);
500 strl
= strtok(NULL
, " ");
504 if (length
+ strlen(strl
) + 1 > 120) {
506 ErrorF("%s", prefix
);
507 length
= strlen(prefix
);
515 length
= length
+ strlen(strl
);
523 /* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */
525 glxWinScreenProbe(ScreenPtr pScreen
)
527 glxWinScreen
*screen
;
528 const char *gl_extensions
;
529 const char *gl_renderer
;
530 const char *wgl_extensions
;
535 GLWIN_DEBUG_MSG("glxWinScreenProbe");
537 glxWinInitDebugSettings();
542 if (!winCheckScreenAiglxIsSupported(pScreen
)) {
544 "AIGLX: No native OpenGL in modes with a root window\n");
548 screen
= calloc(1, sizeof(glxWinScreen
));
553 // Select the native GL implementation (WGL)
554 if (glWinSelectImplementation(1))
557 // create window class
558 #define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest"
560 static wATOM glTestWndClass
= 0;
562 if (glTestWndClass
== 0) {
565 wc
.cbSize
= sizeof(WNDCLASSEX
);
566 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
567 wc
.lpfnWndProc
= DefWindowProc
;
570 wc
.hInstance
= GetModuleHandle(NULL
);
573 wc
.hbrBackground
= (HBRUSH
) GetStockObject(WHITE_BRUSH
);
574 wc
.lpszMenuName
= NULL
;
575 wc
.lpszClassName
= WIN_GL_TEST_WINDOW_CLASS
;
577 RegisterClassEx(&wc
);
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
),
589 "AIGLX: Couldn't create a window for render capabilities testing\n");
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
);
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();
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
);
612 if (g_iLogVerbose
>= 3) {
613 glxLogExtensions("GL_EXTENSIONS: ", gl_extensions
);
614 glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions
);
617 if (strcasecmp(gl_renderer
, "GDI Generic") == 0) {
620 "AIGLX: Won't use generic native renderer as it is not accelerated\n");
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...
630 // testing facility to not use any WGL extensions
631 char *envptr
= getenv("GLWIN_NO_WGL_EXTENSIONS");
633 if ((envptr
!= NULL
) && (atoi(envptr
) != 0)) {
634 ErrorF("GLWIN_NO_WGL_EXTENSIONS is set, ignoring WGL_EXTENSIONS\n");
640 Bool glx_sgi_make_current_read
= FALSE
;
643 // Based on the WGL extensions available, enable various GLX extensions
644 // XXX: make this table-driven ?
646 memset(screen
->glx_enable_bits
, 0, __GLX_EXT_BYTES
);
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");
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
;
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");
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");
673 "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
676 /* // Hmm? screen->texOffset */
677 /* if (strstr(wgl_extensions, "WGL_ARB_render_texture")) */
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; */
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
;
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");
696 "AIGLX: enabled GLX_ARB_multisample and GLX_SGIS_multisample\n");
697 screen
->has_WGL_ARB_multisample
= TRUE
;
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
;
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
);
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()
715 if (screen
->base
.numFBConfigs
> 0) {
716 screen
->has_WGL_ARB_pixel_format
= TRUE
;
720 if (screen
->base
.numFBConfigs
<= 0) {
721 glxWinCreateConfigs(hdc
, screen
);
722 screen
->has_WGL_ARB_pixel_format
= FALSE
;
726 If we still didn't get any fbConfigs, we can't provide GLX for this screen
728 if (screen
->base
.numFBConfigs
<= 0) {
731 "AIGLX: No fbConfigs could be made from native OpenGL pixel formats\n");
735 /* These will be set by __glXScreenInit */
736 screen
->base
.visuals
= NULL
;
737 screen
->base
.numVisuals
= 0;
739 __glXScreenInit(&screen
->base
, pScreen
);
741 // Override the GL extensions string set by __glXScreenInit()
742 screen
->base
.GLextensions
= strdup(gl_extensions
);
744 // Generate the GLX extensions string (overrides that set by __glXScreenInit())
746 unsigned int buffer_size
=
747 __glXGetExtensionString(screen
->glx_enable_bits
, NULL
);
748 if (buffer_size
> 0) {
749 free(screen
->base
.GLXextensions
);
751 screen
->base
.GLXextensions
= xnfalloc(buffer_size
);
752 __glXGetExtensionString(screen
->glx_enable_bits
,
753 screen
->base
.GLXextensions
);
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
761 // SGIX_fbconfig && SGIX_pbuffer && SGI_make_current_read -> 1.3
762 // ARB_multisample -> 1.4
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;
770 screen
->base
.GLXmajor
= 1;
771 screen
->base
.GLXminor
= 3;
775 LogMessage(X_INFO
, "AIGLX: Set GLX version to %d.%d\n",
776 screen
->base
.GLXmajor
, screen
->base
.GLXminor
);
778 wglMakeCurrent(NULL
, NULL
);
779 wglDeleteContext(hglrc
);
780 ReleaseDC(hwnd
, hdc
);
783 // dump out fbConfigs now fbConfigIds and visualIDs have been assigned
784 fbConfigsDump(screen
->base
.numFBConfigs
, screen
->base
.fbconfigs
);
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
;
794 return &screen
->base
;
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);
804 /* ---------------------------------------------------------------------- */
810 glxWinRealizeWindow(WindowPtr pWin
)
813 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
814 glxWinScreen
*screenPriv
= (glxWinScreen
*) glxGetScreen(pScreen
);
816 GLWIN_DEBUG_MSG("glxWinRealizeWindow");
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
;
827 glxWinCopyWindow(WindowPtr pWindow
, DDXPointRec ptOldOrg
, RegionPtr prgnSrc
)
829 __GLXWinDrawable
*pGlxDraw
;
830 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
831 glxWinScreen
*screenPriv
= (glxWinScreen
*) glxGetScreen(pScreen
);
833 GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow
);
835 dixLookupResourceByType((pointer
) &pGlxDraw
, pWindow
->drawable
.id
,
836 __glXDrawableRes
, NullClient
, DixUnknownAccess
);
839 Discard any CopyWindow requests if a GL drawing context is pointing at the window
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....
845 if (pGlxDraw
&& pGlxDraw
->drawContext
) {
846 GLWIN_DEBUG_MSG("glxWinCopyWindow: discarding");
850 GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer");
852 pScreen
->CopyWindow
= screenPriv
->CopyWindow
;
853 pScreen
->CopyWindow(pWindow
, ptOldOrg
, prgnSrc
);
854 pScreen
->CopyWindow
= glxWinCopyWindow
;
858 glxWinUnrealizeWindow(WindowPtr pWin
)
861 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
862 glxWinScreen
*screenPriv
= (glxWinScreen
*) glxGetScreen(pScreen
);
864 GLWIN_DEBUG_MSG("glxWinUnrealizeWindow");
866 pScreen
->UnrealizeWindow
= screenPriv
->UnrealizeWindow
;
867 result
= pScreen
->UnrealizeWindow(pWin
);
868 pScreen
->UnrealizeWindow
= glxWinUnrealizeWindow
;
873 /* ---------------------------------------------------------------------- */
879 glxWinDrawableSwapBuffers(ClientPtr client
, __GLXdrawable
* base
)
884 __GLXWinDrawable
*draw
= (__GLXWinDrawable
*) base
;
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");
893 ("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)",
894 base
, draw
->drawContext
, draw
->drawContext
->ctx
);
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....
900 assert((draw
->drawContext
->base
.drawPriv
== NULL
) ||
901 (draw
->drawContext
->base
.drawPriv
== base
));
903 dc
= glxWinMakeDC(draw
->drawContext
, draw
, &dc
, &hwnd
);
907 ret
= wglSwapLayerBuffers(dc
, WGL_SWAP_MAIN_PLANE
);
909 glxWinReleaseDC(hwnd
, dc
, draw
);
912 ErrorF("wglSwapBuffers failed: %s\n", glxWinErrorMessage());
920 glxWinDrawableCopySubBuffer(__GLXdrawable
* drawable
,
921 int x
, int y
, int w
, int h
)
923 glAddSwapHintRectWINWrapper(x
, y
, w
, h
);
924 glxWinDrawableSwapBuffers(NULL
, drawable
);
928 glxWinDrawableDestroy(__GLXdrawable
* base
)
930 __GLXWinDrawable
*glxPriv
= (__GLXWinDrawable
*) base
;
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
;
943 if (glxPriv
->hPbuffer
)
944 if (!wglDestroyPbufferARBWrapper(glxPriv
->hPbuffer
)) {
945 ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage());
948 if (glxPriv
->dibDC
) {
949 // restore the default DIB
950 SelectObject(glxPriv
->dibDC
, glxPriv
->hOldDIB
);
952 if (!DeleteDC(glxPriv
->dibDC
)) {
953 ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage());
958 if (!DeleteObject(glxPriv
->hDIB
)) {
959 ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
962 ((PixmapPtr
) glxPriv
->base
.pDraw
)->devPrivate
.ptr
= glxPriv
->pOldBits
;
965 GLWIN_DEBUG_MSG("glxWinDestroyDrawable");
969 static __GLXdrawable
*
970 glxWinCreateDrawable(ClientPtr client
,
971 __GLXscreen
* screen
,
973 XID drawId
, int type
, XID glxDrawId
, __GLXconfig
* conf
)
975 __GLXWinDrawable
*glxPriv
;
977 glxPriv
= malloc(sizeof *glxPriv
);
982 memset(glxPriv
, 0, sizeof *glxPriv
);
984 if (!__glXDrawableInit
985 (&glxPriv
->base
, screen
, pDraw
, type
, glxDrawId
, conf
)) {
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
996 GLWIN_DEBUG_MSG("glxWinCreateDrawable %p", glxPriv
);
998 return &glxPriv
->base
;
1001 /* ---------------------------------------------------------------------- */
1008 glxWinBindTexImage(__GLXcontext
* baseContext
,
1009 int buffer
, __GLXdrawable
* pixmap
)
1011 ErrorF("glxWinBindTexImage: not implemented\n");
1017 glxWinReleaseTexImage(__GLXcontext
* baseContext
,
1018 int buffer
, __GLXdrawable
* pixmap
)
1020 ErrorF(" glxWinReleaseTexImage: not implemented\n");
1024 /* ---------------------------------------------------------------------- */
1026 * Lazy update context implementation
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,
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
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...
1044 glxWinSetPixelFormat(__GLXWinContext
* gc
, HDC hdc
, int bppOverride
,
1045 int drawableTypeOverride
)
1047 __GLXscreen
*screen
= gc
->base
.pGlxScreen
;
1048 glxWinScreen
*winScreen
= (glxWinScreen
*) screen
;
1050 __GLXconfig
*config
= gc
->base
.config
;
1051 GLXWinConfig
*winConfig
= (GLXWinConfig
*) config
;
1053 GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d",
1054 winConfig
->pixelFormatIndex
);
1057 Normally, we can just use the the pixelFormatIndex corresponding
1058 to the fbconfig which has been specified by the client
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());
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:
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
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)
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...
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
);
1096 if (!winScreen
->has_WGL_ARB_pixel_format
) {
1097 PIXELFORMATDESCRIPTOR pfd
;
1100 /* convert fbConfig to PFD */
1101 if (fbConfigToPixelFormat(gc
->base
.config
, &pfd
, drawableTypeOverride
)) {
1102 ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n");
1106 if (glxWinDebugSettings
.dumpPFD
)
1110 GLWIN_DEBUG_MSG("glxWinSetPixelFormat: Forcing bpp from %d to %d\n",
1111 pfd
.cColorBits
, bppOverride
);
1112 pfd
.cColorBits
= bppOverride
;
1115 pixelFormat
= ChoosePixelFormat(hdc
, &pfd
);
1116 if (pixelFormat
== 0) {
1117 ErrorF("ChoosePixelFormat error: %s\n", glxWinErrorMessage());
1121 GLWIN_DEBUG_MSG("ChoosePixelFormat: chose pixelFormatIndex %d",
1124 ("ChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n",
1125 pixelFormat
, winConfig
->pixelFormatIndex
);
1127 if (!SetPixelFormat(hdc
, pixelFormat
, &pfd
)) {
1128 ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
1134 fbConfigToPixelFormatIndex(hdc
, gc
->base
.config
,
1135 drawableTypeOverride
, winScreen
);
1136 if (pixelFormat
== 0) {
1137 ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
1141 GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d",
1144 ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n",
1145 pixelFormat
, winConfig
->pixelFormatIndex
);
1147 if (!SetPixelFormat(hdc
, pixelFormat
, NULL
)) {
1148 ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
1157 glxWinMakeDC(__GLXWinContext
* gc
, __GLXWinDrawable
* draw
, HDC
* hdc
,
1164 GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc
,
1169 switch (draw
->base
.type
) {
1170 case GLX_DRAWABLE_WINDOW
:
1174 pWin
= (WindowPtr
) draw
->base
.pDraw
;
1176 GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin
);
1180 *hwnd
= winGetWindowInfo(pWin
);
1182 if (*hwnd
== NULL
) {
1183 ErrorF("No HWND error: %s\n", glxWinErrorMessage());
1187 *hdc
= GetDC(*hwnd
);
1190 ErrorF("GetDC error: %s\n", glxWinErrorMessage());
1192 /* Check if the hwnd has changed... */
1193 if (*hwnd
!= gc
->hwnd
) {
1194 if (glxWinDebugSettings
.enableTrace
)
1195 GLWIN_DEBUG_HWND(*hwnd
);
1198 ("for context %p (native ctx %p), hWnd changed from %p to %p",
1199 gc
, gc
->ctx
, gc
->hwnd
, *hwnd
);
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
);
1214 case GLX_DRAWABLE_PBUFFER
:
1216 *hdc
= wglGetPbufferDCARBWrapper(draw
->hPbuffer
);
1219 ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage());
1223 case GLX_DRAWABLE_PIXMAP
:
1231 ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n",
1236 if (glxWinDebugSettings
.dumpDC
)
1237 GLWIN_DEBUG_MSG("Got HDC %p", *hdc
);
1243 glxWinReleaseDC(HWND hwnd
, HDC hdc
, __GLXWinDrawable
* draw
)
1245 switch (draw
->base
.type
) {
1246 case GLX_DRAWABLE_WINDOW
:
1248 ReleaseDC(hwnd
, hdc
);
1252 case GLX_DRAWABLE_PBUFFER
:
1254 if (!wglReleasePbufferDCARBWrapper(draw
->hPbuffer
, hdc
)) {
1255 ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage());
1260 case GLX_DRAWABLE_PIXMAP
:
1262 // don't release DC, the memory DC lives as long as the bitmap
1264 // We must ensure that all GDI drawing into the bitmap has completed
1265 // in case we subsequently access the bits from it
1273 ("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n",
1280 glxWinDeferredCreateContext(__GLXWinContext
* gc
, __GLXWinDrawable
* draw
)
1286 ("glxWinDeferredCreateContext: attach context %p to drawable %p", gc
,
1289 switch (draw
->base
.type
) {
1290 case GLX_DRAWABLE_WINDOW
:
1292 WindowPtr pWin
= (WindowPtr
) draw
->base
.pDraw
;
1294 if (!(gc
->base
.config
->drawableType
& GLX_WINDOW_BIT
)) {
1296 ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable\n");
1300 GLWIN_DEBUG_MSG("Deferring until X window is created");
1304 GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pWin %p", pWin
);
1306 if (winGetWindowInfo(pWin
) == NULL
) {
1307 GLWIN_DEBUG_MSG("Deferring until native window is created");
1313 case GLX_DRAWABLE_PBUFFER
:
1315 if (draw
->hPbuffer
== NULL
) {
1316 __GLXscreen
*screen
;
1317 glxWinScreen
*winScreen
;
1320 // XXX: which DC are supposed to use???
1321 HDC screenDC
= GetDC(NULL
);
1323 if (!(gc
->base
.config
->drawableType
& GLX_PBUFFER_BIT
)) {
1325 ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable\n");
1328 screen
= gc
->base
.pGlxScreen
;
1329 winScreen
= (glxWinScreen
*) screen
;
1332 fbConfigToPixelFormatIndex(screenDC
, gc
->base
.config
,
1333 GLX_DRAWABLE_PBUFFER
, winScreen
);
1334 if (pixelFormat
== 0) {
1335 ErrorF("wglChoosePixelFormat error: %s\n",
1336 glxWinErrorMessage());
1341 wglCreatePbufferARBWrapper(screenDC
, pixelFormat
,
1342 draw
->base
.pDraw
->width
,
1343 draw
->base
.pDraw
->height
, NULL
);
1344 ReleaseDC(NULL
, screenDC
);
1346 if (draw
->hPbuffer
== NULL
) {
1347 ErrorF("wglCreatePbufferARBWrapper error: %s\n",
1348 glxWinErrorMessage());
1353 ("glxWinDeferredCreateContext: pBuffer %p created for drawable %p",
1354 draw
->hPbuffer
, draw
);
1359 case GLX_DRAWABLE_PIXMAP
:
1361 if (draw
->dibDC
== NULL
) {
1362 BITMAPINFOHEADER bmpHeader
;
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
;
1373 if (!(gc
->base
.config
->drawableType
& GLX_PIXMAP_BIT
)) {
1375 ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n");
1378 draw
->dibDC
= CreateCompatibleDC(NULL
);
1379 if (draw
->dibDC
== NULL
) {
1380 ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
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());
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
;
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());
1405 // Set the pixel format of the bitmap
1406 glxWinSetPixelFormat(gc
, draw
->dibDC
,
1407 draw
->base
.pDraw
->bitsPerPixel
,
1411 ("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p",
1420 ("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n",
1426 dc
= glxWinMakeDC(gc
, draw
, &dc
, &hwnd
);
1427 gc
->ctx
= wglCreateContext(dc
);
1428 glxWinReleaseDC(hwnd
, dc
, draw
);
1430 if (gc
->ctx
== NULL
) {
1431 ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage());
1436 ("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p",
1439 // if the native context was created successfully, shareLists if needed
1440 if (gc
->ctx
&& gc
->shareContext
) {
1442 ("glxWinCreateContextReal shareLists with context %p (native ctx %p)",
1443 gc
->shareContext
, gc
->shareContext
->ctx
);
1445 if (!wglShareLists(gc
->shareContext
->ctx
, gc
->ctx
)) {
1446 ErrorF("wglShareLists error: %s\n", glxWinErrorMessage());
1451 /* ---------------------------------------------------------------------- */
1456 /* Context manipulation routines should return TRUE on success, FALSE on failure */
1458 glxWinContextMakeCurrent(__GLXcontext
* base
)
1460 __GLXWinContext
*gc
= (__GLXWinContext
*) base
;
1464 __GLXdrawable
*drawPriv
;
1465 __GLXdrawable
*readPriv
= NULL
;
1469 GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc
,
1472 /* Keep a note of the last active context in the drawable */
1473 drawPriv
= gc
->base
.drawPriv
;
1474 ((__GLXWinDrawable
*) drawPriv
)->drawContext
= gc
;
1476 if (gc
->ctx
== NULL
) {
1477 glxWinDeferredCreateContext(gc
, (__GLXWinDrawable
*) drawPriv
);
1480 if (gc
->ctx
== NULL
) {
1481 ErrorF("glxWinContextMakeCurrent: Native context is NULL\n");
1486 glxWinMakeDC(gc
, (__GLXWinDrawable
*) drawPriv
, &drawDC
, &hDrawWnd
);
1487 if (drawDC
== NULL
) {
1488 ErrorF("glxWinMakeDC failed for drawDC\n");
1492 if ((gc
->base
.readPriv
!= NULL
) && (gc
->base
.readPriv
!= gc
->base
.drawPriv
)) {
1493 // XXX: should only occur with WGL_ARB_make_current_read
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
1499 readPriv
= gc
->base
.readPriv
;
1501 glxWinMakeDC(gc
, (__GLXWinDrawable
*) readPriv
, &readDC
, &hReadWnd
);
1502 if (readDC
== NULL
) {
1503 ErrorF("glxWinMakeDC failed for readDC\n");
1504 glxWinReleaseDC(hDrawWnd
, drawDC
, (__GLXWinDrawable
*) drawPriv
);
1508 ret
= wglMakeContextCurrentARBWrapper(drawDC
, readDC
, gc
->ctx
);
1510 ErrorF("wglMakeContextCurrentARBWrapper error: %s\n",
1511 glxWinErrorMessage());
1515 /* Otherwise, just use wglMakeCurrent */
1516 ret
= wglMakeCurrent(drawDC
, gc
->ctx
);
1518 ErrorF("wglMakeCurrent error: %s\n", glxWinErrorMessage());
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...
1525 glxWinReleaseDC(hDrawWnd
, drawDC
, (__GLXWinDrawable
*) drawPriv
);
1527 glxWinReleaseDC(hReadWnd
, readDC
, (__GLXWinDrawable
*) readPriv
);
1533 glxWinContextLoseCurrent(__GLXcontext
* base
)
1536 __GLXWinContext
*gc
= (__GLXWinContext
*) base
;
1538 GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc
,
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...
1545 if (__glXLastContext
!= NULL
) {
1546 ret
= wglMakeCurrent(NULL
, NULL
); /* We don't need a DC when setting no current context */
1548 ErrorF("glxWinContextLoseCurrent error: %s\n",
1549 glxWinErrorMessage());
1556 glxWinContextCopy(__GLXcontext
* dst_base
, __GLXcontext
* src_base
,
1559 __GLXWinContext
*dst
= (__GLXWinContext
*) dst_base
;
1560 __GLXWinContext
*src
= (__GLXWinContext
*) src_base
;
1563 GLWIN_DEBUG_MSG("glxWinContextCopy");
1565 ret
= wglCopyContext(src
->ctx
, dst
->ctx
, mask
);
1567 ErrorF("wglCopyContext error: %s\n", glxWinErrorMessage());
1574 glxWinContextDestroy(__GLXcontext
* base
)
1576 __GLXWinContext
*gc
= (__GLXWinContext
*) base
;
1579 GLWIN_DEBUG_MSG("GLXcontext %p destroyed (native ctx %p)", base
,
1583 /* It's bad style to delete the context while it's still current */
1584 if (wglGetCurrentContext() == gc
->ctx
) {
1585 wglMakeCurrent(NULL
, NULL
);
1589 BOOL ret
= wglDeleteContext(gc
->ctx
);
1592 ErrorF("wglDeleteContext error: %s\n",
1593 glxWinErrorMessage());
1603 static __GLXcontext
*
1604 glxWinCreateContext(__GLXscreen
* screen
,
1605 __GLXconfig
* modes
, __GLXcontext
* baseShareContext
,
1606 unsigned num_attribs
, const uint32_t * attribs
, int *error
)
1608 __GLXWinContext
*context
;
1609 __GLXWinContext
*shareContext
= (__GLXWinContext
*) baseShareContext
;
1611 static __GLXtextureFromPixmap glxWinTextureFromPixmap
= {
1613 glxWinReleaseTexImage
1616 context
= (__GLXWinContext
*) calloc(1, sizeof(__GLXWinContext
));
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
;
1630 // actual native GL context creation is deferred until attach()
1631 context
->ctx
= NULL
;
1632 context
->shareContext
= shareContext
;
1634 GLWIN_DEBUG_MSG("GLXcontext %p created", context
);
1636 return &(context
->base
);
1639 /* ---------------------------------------------------------------------- */
1649 while ((mask
&1) == 0) {
1657 fbConfigToPixelFormat(__GLXconfig
* mode
, PIXELFORMATDESCRIPTOR
* pfdret
,
1658 int drawableTypeOverride
)
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 */
1676 0, 0, 0 /* layer masks ignored */
1679 if ((mode
->drawableType
| drawableTypeOverride
) & GLX_WINDOW_BIT
)
1680 pfd
.dwFlags
|= PFD_DRAW_TO_WINDOW
; /* support window */
1682 if ((mode
->drawableType
| drawableTypeOverride
) & GLX_PIXMAP_BIT
)
1683 pfd
.dwFlags
|= (PFD_DRAW_TO_BITMAP
| PFD_SUPPORT_GDI
); /* supports software rendering to bitmap */
1685 if (mode
->stereoMode
) {
1686 pfd
.dwFlags
|= PFD_STEREO
;
1688 if (mode
->doubleBufferMode
) {
1689 pfd
.dwFlags
|= PFD_DOUBLEBUFFER
;
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
);
1702 if (mode
->visualType
== GLX_TRUE_COLOR
) {
1703 pfd
.iPixelType
= PFD_TYPE_RGBA
;
1705 (pfd
.cRedBits
<< pfd
.cRedShift
) | (pfd
.cGreenBits
<< pfd
.cGreenShift
) |
1706 (pfd
.cBlueBits
<< pfd
.cBlueShift
) | (pfd
.cAlphaBits
<< pfd
.cAlphaShift
);
1709 pfd
.iPixelType
= PFD_TYPE_COLORINDEX
;
1710 pfd
.dwVisibleMask
= mode
->transparentIndex
;
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
;
1721 pfd
.cDepthBits
= mode
->depthBits
;
1722 pfd
.cStencilBits
= mode
->stencilBits
;
1723 pfd
.cAuxBuffers
= mode
->numAuxBuffers
;
1732 #define SET_ATTR_VALUE(attr, value) { attribList[i++] = attr; attribList[i++] = value; assert(i < NUM_ELEMENTS(attribList)); }
1735 fbConfigToPixelFormatIndex(HDC hdc
, __GLXconfig
* mode
,
1736 int drawableTypeOverride
, glxWinScreen
* winScreen
)
1741 /* convert fbConfig to attr-value list */
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
);
1764 if (mode
->doubleBufferMode
)
1765 SET_ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB
, TRUE
);
1767 if (mode
->stereoMode
)
1768 SET_ATTR_VALUE(WGL_STEREO_ARB
, TRUE
);
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
);
1774 if (mode
->swapMethod
== GLX_SWAP_COPY_OML
)
1775 SET_ATTR_VALUE(WGL_SWAP_COPY_ARB
, TRUE
);
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
);
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
);
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
);
1791 if (mode
->drawableType
& GLX_PBUFFER_BIT
)
1792 if (winScreen
->has_WGL_ARB_pbuffer
)
1793 SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB
, TRUE
);
1796 if (drawableTypeOverride
& GLX_PIXMAP_BIT
)
1797 SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB
, TRUE
);
1799 if (drawableTypeOverride
& GLX_PBUFFER_BIT
)
1800 if (winScreen
->has_WGL_ARB_pbuffer
)
1801 SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB
, TRUE
);
1804 SET_ATTR_VALUE(0, 0); // terminator
1806 /* choose the first match */
1808 int pixelFormatIndex
;
1810 if (!wglChoosePixelFormatARBWrapper
1811 (hdc
, attribList
, NULL
, 1, &pixelFormatIndex
, &numFormats
)) {
1812 ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
1815 if (numFormats
> 0) {
1817 ("wglChoosePixelFormat: chose pixelFormatIndex %d)",
1819 return pixelFormatIndex
;
1822 ErrorF("wglChoosePixelFormat couldn't decide\n");
1829 /* ---------------------------------------------------------------------- */
1831 #define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask))
1834 // Create the GLXconfigs using DescribePixelFormat()
1837 glxWinCreateConfigs(HDC hdc
, glxWinScreen
* screen
)
1839 GLXWinConfig
*c
, *result
, *prev
= NULL
;
1843 PIXELFORMATDESCRIPTOR pfd
;
1845 GLWIN_DEBUG_MSG("glxWinCreateConfigs");
1847 screen
->base
.numFBConfigs
= 0;
1848 screen
->base
.fbconfigs
= NULL
;
1850 // get the number of pixelformats
1852 DescribePixelFormat(hdc
, 1, sizeof(PIXELFORMATDESCRIPTOR
), NULL
);
1853 LogMessage(X_INFO
, "%d pixel formats reported by DescribePixelFormat\n",
1857 result
= malloc(sizeof(GLXWinConfig
) * numConfigs
);
1859 if (NULL
== result
) {
1863 memset(result
, 0, sizeof(GLXWinConfig
) * numConfigs
);
1866 /* fill in configs */
1867 for (i
= 0; i
< numConfigs
; i
++) {
1871 c
->base
.next
= NULL
;
1872 c
->pixelFormatIndex
= i
+ 1;
1874 rc
= DescribePixelFormat(hdc
, i
+ 1, sizeof(PIXELFORMATDESCRIPTOR
),
1878 ErrorF("DescribePixelFormat failed for index %d, error %s\n", i
+ 1,
1879 glxWinErrorMessage());
1883 if (glxWinDebugSettings
.dumpPFD
)
1886 if (!(pfd
.dwFlags
& (PFD_DRAW_TO_WINDOW
| PFD_DRAW_TO_BITMAP
)) ||
1887 !(pfd
.dwFlags
& PFD_SUPPORT_OPENGL
)) {
1889 ("pixelFormat %d has unsuitable flags 0x%08lx, skipping", i
+ 1,
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
;
1898 c
->base
.redBits
= pfd
.cRedBits
;
1899 c
->base
.greenBits
= pfd
.cGreenBits
;
1900 c
->base
.blueBits
= pfd
.cBlueBits
;
1901 c
->base
.alphaBits
= pfd
.cAlphaBits
;
1903 c
->base
.redMask
= BITS_AND_SHIFT_TO_MASK(pfd
.cRedBits
, pfd
.cRedShift
);
1905 BITS_AND_SHIFT_TO_MASK(pfd
.cGreenBits
, pfd
.cGreenShift
);
1907 BITS_AND_SHIFT_TO_MASK(pfd
.cBlueBits
, pfd
.cBlueShift
);
1909 BITS_AND_SHIFT_TO_MASK(pfd
.cAlphaBits
, pfd
.cAlphaShift
);
1911 c
->base
.rgbBits
= pfd
.cColorBits
;
1913 if (pfd
.iPixelType
== PFD_TYPE_COLORINDEX
) {
1914 c
->base
.indexBits
= pfd
.cColorBits
;
1917 c
->base
.indexBits
= 0;
1920 c
->base
.accumRedBits
= pfd
.cAccumRedBits
;
1921 c
->base
.accumGreenBits
= pfd
.cAccumGreenBits
;
1922 c
->base
.accumBlueBits
= pfd
.cAccumBlueBits
;
1923 c
->base
.accumAlphaBits
= pfd
.cAccumAlphaBits
;
1926 c
->base
.depthBits
= pfd
.cDepthBits
;
1927 c
->base
.stencilBits
= pfd
.cStencilBits
;
1928 c
->base
.numAuxBuffers
= pfd
.cAuxBuffers
;
1930 // pfd.iLayerType; // ignored
1932 // pfd.dwLayerMask; // ignored
1933 // pfd.dwDamageMask; // ignored
1935 c
->base
.visualID
= -1; // will be set by __glXScreenInit()
1937 /* EXT_visual_rating / GLX 1.2 */
1938 if (pfd
.dwFlags
& PFD_GENERIC_FORMAT
) {
1939 c
->base
.visualRating
= GLX_SLOW_VISUAL_EXT
;
1942 // PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated...
1943 c
->base
.visualRating
= GLX_NONE_EXT
;
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
;
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
;
1970 /* ARB_multisample / SGIS_multisample */
1971 c
->base
.sampleBuffers
= 0;
1972 c
->base
.samples
= 0;
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));
1979 if (pfd
.iPixelType
== PFD_TYPE_COLORINDEX
) {
1980 c
->base
.renderType
= GLX_RGBA_BIT
| GLX_COLOR_INDEX_BIT
;
1983 c
->base
.renderType
= GLX_RGBA_BIT
;
1986 c
->base
.xRenderable
= GL_TRUE
;
1987 c
->base
.fbconfigID
= -1; // will be set by __glXScreenInit()
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;
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
)) {
2001 c
->base
.visualSelectGroup
= 2;
2004 case PFD_GENERIC_ACCELERATED
:
2005 c
->base
.visualSelectGroup
= 1;
2008 case PFD_GENERIC_FORMAT
:
2009 c
->base
.visualSelectGroup
= 0;
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
;
2023 c
->base
.swapMethod
= GLX_SWAP_UNDEFINED_OML
;
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;
2035 // update previous config to point to this config
2037 prev
->base
.next
= &(c
->base
);
2043 ("found %d pixelFormats suitable for conversion to fbConfigs", n
);
2045 screen
->base
.numFBConfigs
= n
;
2046 screen
->base
.fbconfigs
= &(result
->base
);
2049 // helper function to access an attribute value from an attribute value array by attribute
2052 getAttrValue(const int attrs
[], int values
[], unsigned int num
, int attr
,
2057 for (i
= 0; i
< num
; i
++) {
2058 if (attrs
[i
] == attr
) {
2059 GLWIN_TRACE_MSG("getAttrValue attr 0x%x, value %d", attr
,
2065 ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n",
2071 // Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
2074 glxWinCreateConfigsExt(HDC hdc
, glxWinScreen
* screen
)
2076 GLXWinConfig
*c
, *result
, *prev
= NULL
;
2080 const int attr
= WGL_NUMBER_PIXEL_FORMATS_ARB
;
2084 unsigned int num_attrs
= 0;
2086 GLWIN_DEBUG_MSG("glxWinCreateConfigsExt");
2088 screen
->base
.numFBConfigs
= 0;
2089 screen
->base
.fbconfigs
= NULL
;
2091 if (!wglGetPixelFormatAttribivARBWrapper(hdc
, 0, 0, 1, &attr
, &numConfigs
)) {
2093 ("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n",
2094 glxWinErrorMessage());
2099 "%d pixel formats reported by wglGetPixelFormatAttribivARB\n",
2103 result
= malloc(sizeof(GLXWinConfig
) * numConfigs
);
2105 if (NULL
== result
) {
2109 memset(result
, 0, sizeof(GLXWinConfig
) * numConfigs
);
2112 #define ADD_ATTR(a) { attrs[num_attrs++] = a; assert(num_attrs < NUM_ELEMENTS(attrs)); }
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
);
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
);
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
);
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
);
2167 /* fill in configs */
2168 for (i
= 0; i
< numConfigs
; i
++) {
2169 int values
[num_attrs
];
2172 c
->base
.next
= NULL
;
2173 c
->pixelFormatIndex
= i
+ 1;
2175 if (!wglGetPixelFormatAttribivARBWrapper
2176 (hdc
, i
+ 1, 0, num_attrs
, attrs
, values
)) {
2178 ("wglGetPixelFormatAttribivARB failed for index %d, error %s\n",
2179 i
+ 1, glxWinErrorMessage());
2183 #define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
2185 if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB
, 0)) {
2187 ("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping",
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
;
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);
2202 BITS_AND_SHIFT_TO_MASK(c
->base
.redBits
,
2203 ATTR_VALUE(WGL_RED_SHIFT_ARB
, 0));
2205 BITS_AND_SHIFT_TO_MASK(c
->base
.greenBits
,
2206 ATTR_VALUE(WGL_GREEN_SHIFT_ARB
, 0));
2208 BITS_AND_SHIFT_TO_MASK(c
->base
.blueBits
,
2209 ATTR_VALUE(WGL_BLUE_SHIFT_ARB
, 0));
2211 BITS_AND_SHIFT_TO_MASK(c
->base
.alphaBits
,
2212 ATTR_VALUE(WGL_ALPHA_SHIFT_ARB
, 0));
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
;
2221 case WGL_TYPE_RGBA_FLOAT_ARB
:
2223 ("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i
+ 1);
2226 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
:
2228 ("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping",
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
;
2240 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n",
2241 ATTR_VALUE(WGL_PIXEL_TYPE_ARB
, 0));
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);
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);
2256 ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB
,
2257 0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB
, 0);
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?
2269 c
->base
.visualID
= -1; // will be set by __glXScreenInit()
2271 /* EXT_visual_rating / GLX 1.2 */
2272 switch (ATTR_VALUE(WGL_ACCELERATION_ARB
, 0)) {
2275 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_ACCELERATION_ARB\n",
2276 ATTR_VALUE(WGL_ACCELERATION_ARB
, 0));
2278 case WGL_NO_ACCELERATION_ARB
:
2279 c
->base
.visualRating
= GLX_SLOW_VISUAL_EXT
;
2282 case WGL_GENERIC_ACCELERATION_ARB
:
2283 case WGL_FULL_ACCELERATION_ARB
:
2284 c
->base
.visualRating
= GLX_NONE_EXT
;
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);
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
;
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);
2321 c
->base
.sampleBuffers
= 0;
2322 c
->base
.samples
= 0;
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));
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
2337 Color index rendering is only supported on single-channel visuals
2339 if (c
->base
.visualType
== GLX_STATIC_COLOR
) {
2340 c
->base
.renderType
= GLX_RGBA_BIT
| GLX_COLOR_INDEX_BIT
;
2343 c
->base
.renderType
= GLX_RGBA_BIT
;
2346 c
->base
.xRenderable
= GL_TRUE
;
2347 c
->base
.fbconfigID
= -1; // will be set by __glXScreenInit()
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);
2358 c
->base
.maxPbufferWidth
= -1;
2359 c
->base
.maxPbufferHeight
= -1;
2360 c
->base
.maxPbufferPixels
= -1;
2362 c
->base
.optimalPbufferWidth
= 0; // there is no optimal value
2363 c
->base
.optimalPbufferHeight
= 0;
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;
2372 case WGL_GENERIC_ACCELERATION_ARB
:
2373 c
->base
.visualSelectGroup
= 1;
2377 case WGL_NO_ACCELERATION_ARB
:
2378 c
->base
.visualSelectGroup
= 0;
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
;
2388 case WGL_SWAP_COPY_ARB
:
2389 c
->base
.swapMethod
= GLX_SWAP_COPY_OML
;
2394 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n",
2395 ATTR_VALUE(WGL_SWAP_METHOD_ARB
, 0));
2397 case WGL_SWAP_UNDEFINED_ARB
:
2398 c
->base
.swapMethod
= GLX_SWAP_UNDEFINED_OML
;
2401 /* EXT_texture_from_pixmap */
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...
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);
2414 c
->base
.bindToTextureRgb
= -1;
2415 c
->base
.bindToTextureRgba
= -1;
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;
2426 // update previous config to point to this config
2428 prev
->base
.next
= &(c
->base
);
2433 screen
->base
.numFBConfigs
= n
;
2434 screen
->base
.fbconfigs
= &(result
->base
);