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