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