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