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