1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS 4 * FILE: dll/opengl/opengl32/wgl.c 5 * PURPOSE: OpenGL32 DLL, WGL functions 6 */ 7 8 #include "opengl32.h" 9 10 #include <pseh/pseh2.h> 11 12 WINE_DEFAULT_DEBUG_CHANNEL(wgl); 13 14 static CRITICAL_SECTION dc_data_cs = {NULL, -1, 0, 0, 0, 0}; 15 static struct wgl_dc_data* dc_data_list = NULL; 16 17 LIST_ENTRY ContextListHead; 18 19 /* FIXME: suboptimal */ 20 static 21 struct wgl_dc_data* 22 get_dc_data(HDC hdc) 23 { 24 HWND hwnd = NULL; 25 struct wgl_dc_data* data; 26 DWORD objType = GetObjectType(hdc); 27 ULONG flags = 0; 28 union 29 { 30 HWND hwnd; 31 HDC hdc; 32 HANDLE u; 33 } id; 34 35 /* Look for the right data identifier */ 36 if(objType == OBJ_DC) 37 { 38 hwnd = WindowFromDC(hdc); 39 if(!hwnd) 40 return NULL; 41 id.hwnd = hwnd; 42 flags = WGL_DC_OBJ_DC; 43 } 44 else if(objType == OBJ_MEMDC) 45 { 46 id.hdc = hdc; 47 } 48 else 49 { 50 return NULL; 51 } 52 53 EnterCriticalSection(&dc_data_cs); 54 data = dc_data_list; 55 while(data) 56 { 57 if(data->owner.u == id.u) 58 { 59 LeaveCriticalSection(&dc_data_cs); 60 return data; 61 } 62 data = data->next; 63 } 64 data= HeapAlloc(GetProcessHeap(), 0, sizeof(*data)); 65 if(!data) 66 { 67 LeaveCriticalSection(&dc_data_cs); 68 return NULL; 69 } 70 /* initialize the structure */ 71 data->owner.u = id.u; 72 data->flags = flags; 73 data->pixelformat = 0; 74 data->sw_data = NULL; 75 /* Load the driver */ 76 data->icd_data = IntGetIcdData(hdc); 77 /* Get the number of available formats for this DC once and for all */ 78 if(data->icd_data) 79 data->nb_icd_formats = data->icd_data->DrvDescribePixelFormat(hdc, 0, 0, NULL); 80 else 81 data->nb_icd_formats = 0; 82 TRACE("ICD %S has %u formats for HDC %x.\n", data->icd_data ? data->icd_data->DriverName : NULL, data->nb_icd_formats, hdc); 83 data->nb_sw_formats = sw_DescribePixelFormat(hdc, 0, 0, NULL); 84 data->next = dc_data_list; 85 dc_data_list = data; 86 LeaveCriticalSection(&dc_data_cs); 87 return data; 88 } 89 90 void release_dc_data(struct wgl_dc_data* dc_data) 91 { 92 (void)dc_data; 93 } 94 95 struct wgl_context* get_context(HGLRC hglrc) 96 { 97 struct wgl_context* context = (struct wgl_context*)hglrc; 98 99 if(!hglrc) 100 return NULL; 101 102 _SEH2_TRY 103 { 104 if(context->magic != 'GLRC') 105 context = NULL; 106 } 107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 108 { 109 context = NULL; 110 } 111 _SEH2_END; 112 113 return context; 114 } 115 116 INT WINAPI wglDescribePixelFormat(HDC hdc, INT format, UINT size, PIXELFORMATDESCRIPTOR *descr ) 117 { 118 struct wgl_dc_data* dc_data = get_dc_data(hdc); 119 INT ret; 120 121 if(!dc_data) 122 { 123 SetLastError(ERROR_INVALID_HANDLE); 124 return 0; 125 } 126 127 ret = dc_data->nb_icd_formats + dc_data->nb_sw_formats; 128 129 if(!descr) 130 { 131 release_dc_data(dc_data); 132 return ret; 133 } 134 if((format == 0) || (format > ret) || (size != sizeof(*descr))) 135 { 136 release_dc_data(dc_data); 137 SetLastError(ERROR_INVALID_PARAMETER); 138 return 0; 139 } 140 141 /* Query ICD if needed */ 142 if(format <= dc_data->nb_icd_formats) 143 { 144 struct ICD_Data* icd_data = dc_data->icd_data; 145 /* SetPixelFormat may have NULLified this */ 146 if (!icd_data) 147 icd_data = IntGetIcdData(hdc); 148 if(!icd_data->DrvDescribePixelFormat(hdc, format, size, descr)) 149 { 150 ret = 0; 151 } 152 } 153 else 154 { 155 /* This is a software format */ 156 format -= dc_data->nb_icd_formats; 157 if(!sw_DescribePixelFormat(hdc, format, size, descr)) 158 { 159 ret = 0; 160 } 161 } 162 163 release_dc_data(dc_data); 164 return ret; 165 } 166 167 INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd) 168 { 169 PIXELFORMATDESCRIPTOR format, best; 170 int i, count, best_format; 171 int bestDBuffer = -1, bestStereo = -1; 172 173 TRACE_(wgl)( "%p %p: size %u version %u flags %u type %u color %u %u,%u,%u,%u " 174 "accum %u depth %u stencil %u aux %u\n", 175 hdc, ppfd, ppfd->nSize, ppfd->nVersion, ppfd->dwFlags, ppfd->iPixelType, 176 ppfd->cColorBits, ppfd->cRedBits, ppfd->cGreenBits, ppfd->cBlueBits, ppfd->cAlphaBits, 177 ppfd->cAccumBits, ppfd->cDepthBits, ppfd->cStencilBits, ppfd->cAuxBuffers ); 178 179 count = wglDescribePixelFormat( hdc, 0, 0, NULL ); 180 if (!count) return 0; 181 182 best_format = 0; 183 best.dwFlags = PFD_GENERIC_FORMAT; 184 best.cAlphaBits = -1; 185 best.cColorBits = -1; 186 best.cDepthBits = -1; 187 best.cStencilBits = -1; 188 best.cAuxBuffers = -1; 189 190 for (i = 1; i <= count; i++) 191 { 192 if (!wglDescribePixelFormat( hdc, i, sizeof(format), &format )) continue; 193 194 if (ppfd->iPixelType != format.iPixelType) 195 { 196 TRACE( "pixel type mismatch for iPixelFormat=%d\n", i ); 197 continue; 198 } 199 200 /* only use bitmap capable formats for bitmap rendering */ 201 if ((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) != (format.dwFlags & PFD_DRAW_TO_BITMAP)) 202 { 203 TRACE( "PFD_DRAW_TO_BITMAP mismatch for iPixelFormat=%d\n", i ); 204 continue; 205 } 206 207 /* only use window capable formats for window rendering */ 208 if ((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) != (format.dwFlags & PFD_DRAW_TO_WINDOW)) 209 { 210 TRACE( "PFD_DRAW_TO_WINDOW mismatch for iPixelFormat=%d\n", i ); 211 continue; 212 } 213 214 /* only use opengl capable formats for opengl rendering */ 215 if ((ppfd->dwFlags & PFD_SUPPORT_OPENGL) != (format.dwFlags & PFD_SUPPORT_OPENGL)) 216 { 217 TRACE( "PFD_SUPPORT_OPENGL mismatch for iPixelFormat=%d\n", i ); 218 continue; 219 } 220 221 /* only use GDI capable formats for GDI rendering */ 222 if ((ppfd->dwFlags & PFD_SUPPORT_GDI) != (format.dwFlags & PFD_SUPPORT_GDI)) 223 { 224 TRACE( "PFD_SUPPORT_GDI mismatch for iPixelFormat=%d\n", i ); 225 continue; 226 } 227 228 /* The behavior of PDF_STEREO/PFD_STEREO_DONTCARE and PFD_DOUBLEBUFFER / PFD_DOUBLEBUFFER_DONTCARE 229 * is not very clear on MSDN. They specify that ChoosePixelFormat tries to match pixel formats 230 * with the flag (PFD_STEREO / PFD_DOUBLEBUFFERING) set. Otherwise it says that it tries to match 231 * formats without the given flag set. 232 * A test on Windows using a Radeon 9500pro on WinXP (the driver doesn't support Stereo) 233 * has indicated that a format without stereo is returned when stereo is unavailable. 234 * So in case PFD_STEREO is set, formats that support it should have priority above formats 235 * without. In case PFD_STEREO_DONTCARE is set, stereo is ignored. 236 * 237 * To summarize the following is most likely the correct behavior: 238 * stereo not set -> prefer non-stereo formats, but also accept stereo formats 239 * stereo set -> prefer stereo formats, but also accept non-stereo formats 240 * stereo don't care -> it doesn't matter whether we get stereo or not 241 * 242 * In Wine we will treat non-stereo the same way as don't care because it makes 243 * format selection even more complicated and second drivers with Stereo advertise 244 * each format twice anyway. 245 */ 246 247 /* Doublebuffer, see the comments above */ 248 if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) 249 { 250 if (((ppfd->dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) && 251 ((format.dwFlags & PFD_DOUBLEBUFFER) == (ppfd->dwFlags & PFD_DOUBLEBUFFER))) 252 goto found; 253 254 if (bestDBuffer != -1 && (format.dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) continue; 255 } 256 257 /* Stereo, see the comments above. */ 258 if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE)) 259 { 260 if (((ppfd->dwFlags & PFD_STEREO) != bestStereo) && 261 ((format.dwFlags & PFD_STEREO) == (ppfd->dwFlags & PFD_STEREO))) 262 goto found; 263 264 if (bestStereo != -1 && (format.dwFlags & PFD_STEREO) != bestStereo) continue; 265 } 266 267 /* Below we will do a number of checks to select the 'best' pixelformat. 268 * We assume the precedence cColorBits > cAlphaBits > cDepthBits > cStencilBits -> cAuxBuffers. 269 * The code works by trying to match the most important options as close as possible. 270 * When a reasonable format is found, we will try to match more options. 271 * It appears (see the opengl32 test) that Windows opengl drivers ignore options 272 * like cColorBits, cAlphaBits and friends if they are set to 0, so they are considered 273 * as DONTCARE. At least Serious Sam TSE relies on this behavior. */ 274 275 if (ppfd->cColorBits) 276 { 277 if (((ppfd->cColorBits > best.cColorBits) && (format.cColorBits > best.cColorBits)) || 278 ((format.cColorBits >= ppfd->cColorBits) && (format.cColorBits < best.cColorBits))) 279 goto found; 280 281 if (best.cColorBits != format.cColorBits) /* Do further checks if the format is compatible */ 282 { 283 TRACE( "color mismatch for iPixelFormat=%d\n", i ); 284 continue; 285 } 286 } 287 if (ppfd->cAlphaBits) 288 { 289 if (((ppfd->cAlphaBits > best.cAlphaBits) && (format.cAlphaBits > best.cAlphaBits)) || 290 ((format.cAlphaBits >= ppfd->cAlphaBits) && (format.cAlphaBits < best.cAlphaBits))) 291 goto found; 292 293 if (best.cAlphaBits != format.cAlphaBits) 294 { 295 TRACE( "alpha mismatch for iPixelFormat=%d\n", i ); 296 continue; 297 } 298 } 299 if (ppfd->cDepthBits) 300 { 301 if (((ppfd->cDepthBits > best.cDepthBits) && (format.cDepthBits > best.cDepthBits)) || 302 ((format.cDepthBits >= ppfd->cDepthBits) && (format.cDepthBits < best.cDepthBits))) 303 goto found; 304 305 if (best.cDepthBits != format.cDepthBits) 306 { 307 TRACE( "depth mismatch for iPixelFormat=%d\n", i ); 308 continue; 309 } 310 } 311 if (ppfd->cStencilBits) 312 { 313 if (((ppfd->cStencilBits > best.cStencilBits) && (format.cStencilBits > best.cStencilBits)) || 314 ((format.cStencilBits >= ppfd->cStencilBits) && (format.cStencilBits < best.cStencilBits))) 315 goto found; 316 317 if (best.cStencilBits != format.cStencilBits) 318 { 319 TRACE( "stencil mismatch for iPixelFormat=%d\n", i ); 320 continue; 321 } 322 } 323 if (ppfd->cAuxBuffers) 324 { 325 if (((ppfd->cAuxBuffers > best.cAuxBuffers) && (format.cAuxBuffers > best.cAuxBuffers)) || 326 ((format.cAuxBuffers >= ppfd->cAuxBuffers) && (format.cAuxBuffers < best.cAuxBuffers))) 327 goto found; 328 329 if (best.cAuxBuffers != format.cAuxBuffers) 330 { 331 TRACE( "aux mismatch for iPixelFormat=%d\n", i ); 332 continue; 333 } 334 } 335 continue; 336 337 found: 338 /* Prefer HW accelerated formats */ 339 if ((format.dwFlags & PFD_GENERIC_FORMAT) && !(best.dwFlags & PFD_GENERIC_FORMAT)) 340 continue; 341 best_format = i; 342 best = format; 343 bestDBuffer = format.dwFlags & PFD_DOUBLEBUFFER; 344 bestStereo = format.dwFlags & PFD_STEREO; 345 } 346 347 TRACE( "returning %u\n", best_format ); 348 return best_format; 349 } 350 351 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) 352 { 353 struct wgl_context* ctx_src = get_context(hglrcSrc); 354 struct wgl_context* ctx_dst = get_context(hglrcDst); 355 356 if(!ctx_src || !ctx_dst) 357 { 358 SetLastError(ERROR_INVALID_HANDLE); 359 return FALSE; 360 } 361 362 /* Check this is the same pixel format */ 363 if((ctx_dst->icd_data != ctx_src->icd_data) || 364 (ctx_dst->pixelformat != ctx_src->pixelformat)) 365 { 366 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 367 return FALSE; 368 } 369 370 if(ctx_src->icd_data) 371 return ctx_src->icd_data->DrvCopyContext(ctx_src->dhglrc, ctx_dst->dhglrc, mask); 372 373 return sw_CopyContext(ctx_src->dhglrc, ctx_dst->dhglrc, mask); 374 } 375 376 HGLRC WINAPI wglCreateContext(HDC hdc) 377 { 378 struct wgl_dc_data* dc_data = get_dc_data(hdc); 379 struct wgl_context* context; 380 DHGLRC dhglrc; 381 382 TRACE("Creating context for %p, format %i\n", hdc); 383 384 if(!dc_data) 385 { 386 WARN("Not a DC handle!\n"); 387 SetLastError(ERROR_INVALID_HANDLE); 388 return NULL; 389 } 390 391 if(!dc_data->pixelformat) 392 { 393 WARN("Pixel format not set!\n"); 394 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 395 return NULL; 396 } 397 398 if(!dc_data->icd_data) 399 { 400 TRACE("Calling SW implementation.\n"); 401 dhglrc = sw_CreateContext(dc_data); 402 TRACE("done\n"); 403 } 404 else 405 { 406 TRACE("Calling ICD.\n"); 407 dhglrc = dc_data->icd_data->DrvCreateContext(hdc); 408 } 409 410 if(!dhglrc) 411 { 412 WARN("Failed!\n"); 413 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 414 return NULL; 415 } 416 417 context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context)); 418 if(!context) 419 { 420 WARN("Failed to allocate a context!\n"); 421 if(!dc_data->icd_data) 422 sw_DeleteContext(dhglrc); 423 else 424 dc_data->icd_data->DrvDeleteContext(dhglrc); 425 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 426 return NULL; 427 } 428 /* Copy info from the DC data */ 429 context->dhglrc = dhglrc; 430 context->icd_data = dc_data->icd_data; 431 context->pixelformat = dc_data->pixelformat; 432 context->thread_id = 0; 433 434 /* Insert into the list */ 435 InsertTailList(&ContextListHead, &context->ListEntry); 436 437 context->magic = 'GLRC'; 438 TRACE("Success!\n"); 439 return (HGLRC)context; 440 } 441 442 HGLRC WINAPI wglCreateLayerContext(HDC hdc, int iLayerPlane) 443 { 444 struct wgl_dc_data* dc_data = get_dc_data(hdc); 445 struct wgl_context* context; 446 DHGLRC dhglrc; 447 448 if(!dc_data) 449 { 450 SetLastError(ERROR_INVALID_HANDLE); 451 return NULL; 452 } 453 454 if(!dc_data->pixelformat) 455 { 456 release_dc_data(dc_data); 457 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 458 return NULL; 459 } 460 461 if(!dc_data->icd_data) 462 { 463 if(iLayerPlane != 0) 464 { 465 /* Not supported in SW implementation */ 466 release_dc_data(dc_data); 467 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 468 return NULL; 469 } 470 dhglrc = sw_CreateContext(dc_data); 471 } 472 else 473 { 474 dhglrc = dc_data->icd_data->DrvCreateLayerContext(hdc, iLayerPlane); 475 } 476 477 if(!dhglrc) 478 { 479 release_dc_data(dc_data); 480 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 481 return NULL; 482 } 483 484 context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context)); 485 if(!context) 486 { 487 if(!dc_data->icd_data) 488 sw_DeleteContext(dhglrc); 489 else 490 dc_data->icd_data->DrvDeleteContext(dhglrc); 491 release_dc_data(dc_data); 492 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 493 return NULL; 494 } 495 /* Copy info from the DC data */ 496 context->dhglrc = dhglrc; 497 context->icd_data = dc_data->icd_data; 498 context->pixelformat = dc_data->pixelformat; 499 context->thread_id = 0; 500 501 context->magic = 'GLRC'; 502 503 release_dc_data(dc_data); 504 return (HGLRC)context; 505 } 506 507 BOOL WINAPI wglDeleteContext(HGLRC hglrc) 508 { 509 struct wgl_context* context = get_context(hglrc); 510 LONG thread_id = GetCurrentThreadId(); 511 512 if(!context) 513 { 514 SetLastError(ERROR_INVALID_HANDLE); 515 return FALSE; 516 } 517 518 /* Own this context before touching it */ 519 if(InterlockedCompareExchange(&context->thread_id, thread_id, 0) != 0) 520 { 521 /* We can't delete a context current to another thread */ 522 if(context->thread_id != thread_id) 523 { 524 SetLastError(ERROR_BUSY); 525 return FALSE; 526 } 527 528 /* This is in our thread. Release and try again */ 529 if(!wglMakeCurrent(NULL, NULL)) 530 return FALSE; 531 return wglDeleteContext(hglrc); 532 } 533 534 if(context->icd_data) 535 context->icd_data->DrvDeleteContext(context->dhglrc); 536 else 537 sw_DeleteContext(context->dhglrc); 538 539 context->magic = 0; 540 RemoveEntryList(&context->ListEntry); 541 HeapFree(GetProcessHeap(), 0, context); 542 543 return TRUE; 544 } 545 546 BOOL WINAPI wglDescribeLayerPlane(HDC hdc, 547 int iPixelFormat, 548 int iLayerPlane, 549 UINT nBytes, 550 LPLAYERPLANEDESCRIPTOR plpd) 551 { 552 struct wgl_dc_data* dc_data = get_dc_data(hdc); 553 554 if(!dc_data) 555 { 556 SetLastError(ERROR_INVALID_HANDLE); 557 return FALSE; 558 } 559 560 if(iPixelFormat <= dc_data->nb_icd_formats) 561 return dc_data->icd_data->DrvDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd); 562 563 /* SW implementation doesn't support this */ 564 return FALSE; 565 } 566 567 HGLRC WINAPI wglGetCurrentContext(void) 568 { 569 return IntGetCurrentRC(); 570 } 571 572 HDC WINAPI wglGetCurrentDC(void) 573 { 574 return IntGetCurrentDC(); 575 } 576 577 PROC WINAPI wglGetDefaultProcAddress(LPCSTR lpszProc) 578 { 579 /* undocumented... */ 580 return NULL; 581 } 582 583 int WINAPI wglGetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, COLORREF* pcr ) 584 { 585 struct wgl_dc_data* dc_data = get_dc_data(hdc); 586 587 if(!dc_data) 588 { 589 SetLastError(ERROR_INVALID_HANDLE); 590 return 0; 591 } 592 593 if(!dc_data->pixelformat) 594 { 595 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 596 return 0; 597 } 598 599 if(dc_data->icd_data) 600 return dc_data->icd_data->DrvGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); 601 602 /* SW implementation doesn't support this */ 603 return 0; 604 } 605 606 INT WINAPI wglGetPixelFormat(HDC hdc) 607 { 608 INT ret; 609 struct wgl_dc_data* dc_data = get_dc_data(hdc); 610 611 if(!dc_data) 612 { 613 SetLastError(ERROR_INVALID_HANDLE); 614 return 0; 615 } 616 617 ret = dc_data->pixelformat; 618 release_dc_data(dc_data); 619 return ret; 620 } 621 622 PROC WINAPI wglGetProcAddress(LPCSTR name) 623 { 624 struct wgl_context* context = get_context(IntGetCurrentRC()); 625 if(!context) 626 return NULL; 627 628 /* This shall fail for opengl 1.1 functions */ 629 #define USE_GL_FUNC(func, w, x, y, z) if(!strcmp(name, "gl" #func)) return NULL; 630 #include "glfuncs.h" 631 632 /* Forward */ 633 if(context->icd_data) 634 return context->icd_data->DrvGetProcAddress(name); 635 return sw_GetProcAddress(name); 636 } 637 638 void APIENTRY set_api_table(const GLCLTPROCTABLE* table) 639 { 640 IntSetCurrentDispatchTable(&table->glDispatchTable); 641 } 642 643 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc) 644 { 645 struct wgl_context* ctx = get_context(hglrc); 646 struct wgl_context* old_ctx = get_context(IntGetCurrentRC()); 647 const GLCLTPROCTABLE* apiTable; 648 LONG thread_id = (LONG)GetCurrentThreadId(); 649 650 if(ctx) 651 { 652 struct wgl_dc_data* dc_data = get_dc_data(hdc); 653 if(!dc_data) 654 { 655 ERR("wglMakeCurrent was passed an invalid DC handle.\n"); 656 SetLastError(ERROR_INVALID_HANDLE); 657 return FALSE; 658 } 659 660 /* Check compatibility */ 661 if((ctx->icd_data != dc_data->icd_data) || (ctx->pixelformat != dc_data->pixelformat)) 662 { 663 /* That's bad, man */ 664 ERR("HGLRC %p and HDC %p are not compatible.\n", hglrc, hdc); 665 release_dc_data(dc_data); 666 SetLastError(ERROR_INVALID_HANDLE); 667 return FALSE; 668 } 669 670 /* Set the thread ID */ 671 if(InterlockedCompareExchange(&ctx->thread_id, thread_id, 0) != 0) 672 { 673 /* Already current for a thread. Maybe it's us ? */ 674 release_dc_data(dc_data); 675 if(ctx->thread_id != thread_id) 676 SetLastError(ERROR_BUSY); 677 return (ctx->thread_id == thread_id); 678 } 679 680 if(old_ctx) 681 { 682 /* Unset it */ 683 if(old_ctx->icd_data) 684 old_ctx->icd_data->DrvReleaseContext(old_ctx->dhglrc); 685 else 686 sw_ReleaseContext(old_ctx->dhglrc); 687 InterlockedExchange(&old_ctx->thread_id, 0); 688 } 689 690 /* Call the ICD or SW implementation */ 691 if(ctx->icd_data) 692 { 693 apiTable = ctx->icd_data->DrvSetContext(hdc, ctx->dhglrc, set_api_table); 694 if(!apiTable) 695 { 696 ERR("DrvSetContext failed!\n"); 697 /* revert */ 698 InterlockedExchange(&ctx->thread_id, 0); 699 IntSetCurrentDispatchTable(&StubTable.glDispatchTable); 700 SetLastError(ERROR_INVALID_PARAMETER); 701 return FALSE; 702 } 703 set_api_table(apiTable); 704 /* Make it current */ 705 IntMakeCurrent(hglrc, hdc, dc_data); 706 } 707 else 708 { 709 /* We must set current before, SW implementation relies on it */ 710 IntMakeCurrent(hglrc, hdc, dc_data); 711 if(!sw_SetContext(dc_data, ctx->dhglrc)) 712 { 713 ERR("sw_SetContext failed!\n"); 714 /* revert */ 715 IntMakeCurrent(NULL, NULL, NULL); 716 InterlockedExchange(&ctx->thread_id, 0); 717 SetLastError(ERROR_INVALID_PARAMETER); 718 return FALSE; 719 } 720 } 721 } 722 else if(old_ctx) 723 { 724 if(old_ctx->icd_data) 725 old_ctx->icd_data->DrvReleaseContext(old_ctx->dhglrc); 726 else 727 sw_ReleaseContext(old_ctx->dhglrc); 728 InterlockedExchange(&old_ctx->thread_id, 0); 729 /* Unset it */ 730 IntMakeCurrent(NULL, NULL, NULL); 731 /* Reset the no-op table */ 732 set_api_table(&StubTable); 733 /* Test conformance (extreme cases) */ 734 return hglrc == NULL; 735 } 736 else 737 { 738 /* Winetest conformance */ 739 if (GetObjectType( hdc ) != OBJ_DC && GetObjectType( hdc ) != OBJ_MEMDC) 740 { 741 ERR( "Error: hdc is not a DC handle!\n"); 742 SetLastError( ERROR_INVALID_HANDLE ); 743 return FALSE; 744 } 745 } 746 747 return TRUE; 748 } 749 750 BOOL WINAPI wglRealizeLayerPalette(HDC hdc, 751 int iLayerPlane, 752 BOOL bRealize) 753 { 754 struct wgl_dc_data* dc_data = get_dc_data(hdc); 755 756 if(!dc_data) 757 { 758 SetLastError(ERROR_INVALID_HANDLE); 759 return FALSE; 760 } 761 762 if(!dc_data->pixelformat) 763 { 764 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 765 return FALSE; 766 } 767 768 if(dc_data->icd_data) 769 return dc_data->icd_data->DrvRealizeLayerPalette(hdc, iLayerPlane, bRealize); 770 771 /* SW implementation doesn't support this */ 772 return FALSE; 773 } 774 775 int WINAPI wglSetLayerPaletteEntries(HDC hdc, 776 int iLayerPlane, 777 int iStart, 778 int cEntries, 779 const COLORREF *pcr) 780 { 781 struct wgl_dc_data* dc_data = get_dc_data(hdc); 782 783 if(!dc_data) 784 { 785 SetLastError(ERROR_INVALID_HANDLE); 786 return 0; 787 } 788 789 if(!dc_data->pixelformat) 790 { 791 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 792 return 0; 793 } 794 795 if(dc_data->icd_data) 796 return dc_data->icd_data->DrvSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); 797 798 /* SW implementation doesn't support this */ 799 return 0; 800 } 801 802 BOOL WINAPI wglSetPixelFormat(HDC hdc, INT format, const PIXELFORMATDESCRIPTOR *descr) 803 { 804 struct wgl_dc_data* dc_data = get_dc_data(hdc); 805 INT sw_format; 806 BOOL ret; 807 808 TRACE("HDC %p, format %i.\n", hdc, format); 809 810 if(!dc_data) 811 { 812 WARN("Not a valid DC!.\n"); 813 SetLastError(ERROR_INVALID_HANDLE); 814 return FALSE; 815 } 816 817 if(!format) 818 { 819 WARN("format == 0!\n"); 820 SetLastError(ERROR_INVALID_PARAMETER); 821 return FALSE; 822 } 823 824 if(dc_data->pixelformat) 825 { 826 TRACE("DC format already set, %i.\n", dc_data->pixelformat); 827 return (format == dc_data->pixelformat); 828 } 829 830 if(format <= dc_data->nb_icd_formats) 831 { 832 TRACE("Calling ICD.\n"); 833 ret = dc_data->icd_data->DrvSetPixelFormat(hdc, format); 834 if(ret) 835 { 836 TRACE("Success!\n"); 837 dc_data->pixelformat = format; 838 } 839 return ret; 840 } 841 842 sw_format = format - dc_data->nb_icd_formats; 843 if(sw_format <= dc_data->nb_sw_formats) 844 { 845 TRACE("Calling SW implementation.\n"); 846 ret = sw_SetPixelFormat(hdc, dc_data, sw_format); 847 if(ret) 848 { 849 TRACE("Success!\n"); 850 /* This is now officially a software-only HDC */ 851 dc_data->icd_data = NULL; 852 dc_data->pixelformat = format; 853 } 854 return ret; 855 } 856 857 TRACE("Invalid pixel format!\n"); 858 SetLastError(ERROR_INVALID_PARAMETER); 859 return FALSE; 860 } 861 862 BOOL WINAPI wglShareLists(HGLRC hglrcSrc, HGLRC hglrcDst) 863 { 864 struct wgl_context* ctx_src = get_context(hglrcSrc); 865 struct wgl_context* ctx_dst = get_context(hglrcDst); 866 867 if(!ctx_src || !ctx_dst) 868 { 869 SetLastError(ERROR_INVALID_HANDLE); 870 return FALSE; 871 } 872 873 /* Check this is the same pixel format */ 874 if((ctx_dst->icd_data != ctx_src->icd_data) || 875 (ctx_dst->pixelformat != ctx_src->pixelformat)) 876 { 877 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 878 return FALSE; 879 } 880 881 if(ctx_src->icd_data) 882 return ctx_src->icd_data->DrvShareLists(ctx_src->dhglrc, ctx_dst->dhglrc); 883 884 return sw_ShareLists(ctx_src->dhglrc, ctx_dst->dhglrc); 885 } 886 887 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers(HDC hdc) 888 { 889 struct wgl_dc_data* dc_data = get_dc_data(hdc); 890 891 if(!dc_data) 892 { 893 SetLastError(ERROR_INVALID_HANDLE); 894 return FALSE; 895 } 896 897 if(!dc_data->pixelformat) 898 { 899 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 900 return FALSE; 901 } 902 903 if(dc_data->icd_data) 904 return dc_data->icd_data->DrvSwapBuffers(hdc); 905 906 return sw_SwapBuffers(hdc, dc_data); 907 } 908 909 BOOL WINAPI wglSwapLayerBuffers(HDC hdc, UINT fuPlanes) 910 { 911 return FALSE; 912 } 913 914 DWORD WINAPI wglSwapMultipleBuffers(UINT count, CONST WGLSWAP * toSwap) 915 { 916 return 0; 917 } 918 919 /* Clean up on DLL unload */ 920 void 921 IntDeleteAllContexts(void) 922 { 923 struct wgl_context* context; 924 LIST_ENTRY* Entry = ContextListHead.Flink; 925 926 while (Entry != &ContextListHead) 927 { 928 context = CONTAINING_RECORD(Entry, struct wgl_context, ListEntry); 929 wglDeleteContext((HGLRC)context); 930 Entry = Entry->Flink; 931 } 932 } 933