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 if (GetObjectType( hdc ) != OBJ_DC && GetObjectType( hdc ) != OBJ_MEMDC) 746 { 747 ERR( "Error: hdc is not a DC handle!\n"); 748 SetLastError( ERROR_INVALID_HANDLE ); 749 return FALSE; 750 } 751 } 752 753 return TRUE; 754 } 755 756 BOOL WINAPI wglRealizeLayerPalette(HDC hdc, 757 int iLayerPlane, 758 BOOL bRealize) 759 { 760 struct wgl_dc_data* dc_data = get_dc_data(hdc); 761 762 if(!dc_data) 763 { 764 SetLastError(ERROR_INVALID_HANDLE); 765 return FALSE; 766 } 767 768 if(!dc_data->pixelformat) 769 { 770 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 771 return FALSE; 772 } 773 774 if(dc_data->icd_data) 775 return dc_data->icd_data->DrvRealizeLayerPalette(hdc, iLayerPlane, bRealize); 776 777 /* SW implementation doesn't support this */ 778 return FALSE; 779 } 780 781 int WINAPI wglSetLayerPaletteEntries(HDC hdc, 782 int iLayerPlane, 783 int iStart, 784 int cEntries, 785 const COLORREF *pcr) 786 { 787 struct wgl_dc_data* dc_data = get_dc_data(hdc); 788 789 if(!dc_data) 790 { 791 SetLastError(ERROR_INVALID_HANDLE); 792 return 0; 793 } 794 795 if(!dc_data->pixelformat) 796 { 797 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 798 return 0; 799 } 800 801 if(dc_data->icd_data) 802 return dc_data->icd_data->DrvSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); 803 804 /* SW implementation doesn't support this */ 805 return 0; 806 } 807 808 BOOL WINAPI wglSetPixelFormat(HDC hdc, INT format, const PIXELFORMATDESCRIPTOR *descr) 809 { 810 struct wgl_dc_data* dc_data = get_dc_data(hdc); 811 INT sw_format; 812 BOOL ret; 813 814 TRACE("HDC %p, format %i.\n", hdc, format); 815 816 if(!dc_data) 817 { 818 WARN("Not a valid DC!.\n"); 819 SetLastError(ERROR_INVALID_HANDLE); 820 return FALSE; 821 } 822 823 if(!format) 824 { 825 WARN("format == 0!\n"); 826 SetLastError(ERROR_INVALID_PARAMETER); 827 return FALSE; 828 } 829 830 if(dc_data->pixelformat) 831 { 832 TRACE("DC format already set, %i.\n", dc_data->pixelformat); 833 return (format == dc_data->pixelformat); 834 } 835 836 if(format <= dc_data->nb_icd_formats) 837 { 838 TRACE("Calling ICD.\n"); 839 ret = dc_data->icd_data->DrvSetPixelFormat(hdc, format); 840 if(ret) 841 { 842 TRACE("Success!\n"); 843 dc_data->pixelformat = format; 844 } 845 return ret; 846 } 847 848 sw_format = format - dc_data->nb_icd_formats; 849 if(sw_format <= dc_data->nb_sw_formats) 850 { 851 TRACE("Calling SW implementation.\n"); 852 ret = sw_SetPixelFormat(hdc, dc_data, sw_format); 853 if(ret) 854 { 855 TRACE("Success!\n"); 856 /* This is now officially a software-only HDC */ 857 dc_data->icd_data = NULL; 858 dc_data->pixelformat = format; 859 } 860 return ret; 861 } 862 863 TRACE("Invalid pixel format!\n"); 864 SetLastError(ERROR_INVALID_PARAMETER); 865 return FALSE; 866 } 867 868 BOOL WINAPI wglShareLists(HGLRC hglrcSrc, HGLRC hglrcDst) 869 { 870 struct wgl_context* ctx_src = get_context(hglrcSrc); 871 struct wgl_context* ctx_dst = get_context(hglrcDst); 872 873 if(!ctx_src || !ctx_dst) 874 { 875 SetLastError(ERROR_INVALID_HANDLE); 876 return FALSE; 877 } 878 879 /* Check this is the same pixel format */ 880 if((ctx_dst->icd_data != ctx_src->icd_data) || 881 (ctx_dst->pixelformat != ctx_src->pixelformat)) 882 { 883 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 884 return FALSE; 885 } 886 887 if(ctx_src->icd_data) 888 return ctx_src->icd_data->DrvShareLists(ctx_src->dhglrc, ctx_dst->dhglrc); 889 890 return sw_ShareLists(ctx_src->dhglrc, ctx_dst->dhglrc); 891 } 892 893 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers(HDC hdc) 894 { 895 struct wgl_dc_data* dc_data = get_dc_data(hdc); 896 897 if(!dc_data) 898 { 899 SetLastError(ERROR_INVALID_HANDLE); 900 return FALSE; 901 } 902 903 if(!dc_data->pixelformat) 904 { 905 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 906 return FALSE; 907 } 908 909 if(dc_data->icd_data) 910 return dc_data->icd_data->DrvSwapBuffers(hdc); 911 912 return sw_SwapBuffers(hdc, dc_data); 913 } 914 915 BOOL WINAPI wglSwapLayerBuffers(HDC hdc, UINT fuPlanes) 916 { 917 return FALSE; 918 } 919 920 DWORD WINAPI wglSwapMultipleBuffers(UINT count, CONST WGLSWAP * toSwap) 921 { 922 return 0; 923 } 924 925 /* Clean up on DLL unload */ 926 void 927 IntDeleteAllContexts(void) 928 { 929 struct wgl_context* context; 930 LIST_ENTRY* Entry = ContextListHead.Flink; 931 932 while (Entry != &ContextListHead) 933 { 934 context = CONTAINING_RECORD(Entry, struct wgl_context, ListEntry); 935 wglDeleteContext((HGLRC)context); 936 Entry = Entry->Flink; 937 } 938 } 939