1 /************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include <windows.h> 29 30 #define WGL_WGLEXT_PROTOTYPES 31 32 #include <GL/gl.h> 33 #include <GL/wglext.h> 34 35 #include "pipe/p_compiler.h" 36 #include "pipe/p_context.h" 37 #include "pipe/p_state.h" 38 #include "util/u_memory.h" 39 #include "util/u_atomic.h" 40 #include "state_tracker/st_api.h" 41 42 #include "stw_icd.h" 43 #include "stw_device.h" 44 #include "stw_winsys.h" 45 #include "stw_framebuffer.h" 46 #include "stw_pixelformat.h" 47 #include "stw_context.h" 48 #include "stw_tls.h" 49 50 51 static INLINE struct stw_context * 52 stw_current_context(void) 53 { 54 struct st_context_iface *st; 55 56 st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL; 57 58 return (struct stw_context *) ((st) ? st->st_manager_private : NULL); 59 } 60 61 BOOL APIENTRY 62 DrvCopyContext( 63 DHGLRC dhrcSource, 64 DHGLRC dhrcDest, 65 UINT fuMask ) 66 { 67 struct stw_context *src; 68 struct stw_context *dst; 69 BOOL ret = FALSE; 70 71 if (!stw_dev) 72 return FALSE; 73 74 pipe_mutex_lock( stw_dev->ctx_mutex ); 75 76 src = stw_lookup_context_locked( dhrcSource ); 77 dst = stw_lookup_context_locked( dhrcDest ); 78 79 if (src && dst) { 80 /* FIXME */ 81 assert(0); 82 (void) src; 83 (void) dst; 84 (void) fuMask; 85 } 86 87 pipe_mutex_unlock( stw_dev->ctx_mutex ); 88 89 return ret; 90 } 91 92 BOOL APIENTRY 93 DrvShareLists( 94 DHGLRC dhglrc1, 95 DHGLRC dhglrc2 ) 96 { 97 struct stw_context *ctx1; 98 struct stw_context *ctx2; 99 BOOL ret = FALSE; 100 101 if (!stw_dev) 102 return FALSE; 103 104 pipe_mutex_lock( stw_dev->ctx_mutex ); 105 106 ctx1 = stw_lookup_context_locked( dhglrc1 ); 107 ctx2 = stw_lookup_context_locked( dhglrc2 ); 108 109 if (ctx1 && ctx2 && ctx2->st->share) 110 ret = ctx2->st->share(ctx2->st, ctx1->st); 111 112 pipe_mutex_unlock( stw_dev->ctx_mutex ); 113 114 return ret; 115 } 116 117 DHGLRC APIENTRY 118 DrvCreateContext( 119 HDC hdc ) 120 { 121 return DrvCreateLayerContext( hdc, 0 ); 122 } 123 124 DHGLRC APIENTRY 125 DrvCreateLayerContext( 126 HDC hdc, 127 INT iLayerPlane ) 128 { 129 return stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0, 130 WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); 131 } 132 133 DHGLRC 134 stw_create_context_attribs( 135 HDC hdc, 136 INT iLayerPlane, 137 DHGLRC hShareContext, 138 int majorVersion, int minorVersion, 139 int contextFlags, int profileMask) 140 { 141 int iPixelFormat; 142 struct stw_framebuffer *fb; 143 const struct stw_pixelformat_info *pfi; 144 struct st_context_attribs attribs; 145 struct stw_context *ctx = NULL; 146 struct stw_context *shareCtx = NULL; 147 enum st_context_error ctx_err = 0; 148 149 if (!stw_dev) 150 return 0; 151 152 if (iLayerPlane != 0) 153 return 0; 154 155 iPixelFormat = GetPixelFormat(hdc); 156 if(!iPixelFormat) 157 return 0; 158 159 /* 160 * GDI only knows about displayable pixel formats, so determine the pixel 161 * format from the framebuffer. 162 * 163 * TODO: Remove the GetPixelFormat() above, and stop relying on GDI. 164 */ 165 fb = stw_framebuffer_from_hdc( hdc ); 166 if (fb) { 167 assert(iPixelFormat == fb->iDisplayablePixelFormat); 168 iPixelFormat = fb->iPixelFormat; 169 stw_framebuffer_release(fb); 170 } 171 172 pfi = stw_pixelformat_get_info( iPixelFormat ); 173 174 if (hShareContext != 0) { 175 pipe_mutex_lock( stw_dev->ctx_mutex ); 176 shareCtx = stw_lookup_context_locked( hShareContext ); 177 pipe_mutex_unlock( stw_dev->ctx_mutex ); 178 } 179 180 ctx = CALLOC_STRUCT( stw_context ); 181 if (ctx == NULL) 182 goto no_ctx; 183 184 ctx->hdc = hdc; 185 ctx->iPixelFormat = iPixelFormat; 186 187 memset(&attribs, 0, sizeof(attribs)); 188 attribs.visual = pfi->stvis; 189 attribs.major = majorVersion; 190 attribs.minor = minorVersion; 191 if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) 192 attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; 193 if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB) 194 attribs.flags |= ST_CONTEXT_FLAG_DEBUG; 195 196 /* There are no profiles before OpenGL 3.2. The 197 * WGL_ARB_create_context_profile spec says: 198 * 199 * "If the requested OpenGL version is less than 3.2, 200 * WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality of the 201 * context is determined solely by the requested version." 202 * 203 * The spec also says: 204 * 205 * "The default value for WGL_CONTEXT_PROFILE_MASK_ARB is 206 * WGL_CONTEXT_CORE_PROFILE_BIT_ARB." 207 */ 208 attribs.profile = ST_PROFILE_DEFAULT; 209 if ((majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2)) 210 && ((profileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) == 0)) 211 attribs.profile = ST_PROFILE_OPENGL_CORE; 212 213 ctx->st = stw_dev->stapi->create_context(stw_dev->stapi, 214 stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL); 215 if (ctx->st == NULL) 216 goto no_st_ctx; 217 218 ctx->st->st_manager_private = (void *) ctx; 219 220 pipe_mutex_lock( stw_dev->ctx_mutex ); 221 ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx); 222 pipe_mutex_unlock( stw_dev->ctx_mutex ); 223 if (!ctx->dhglrc) 224 goto no_hglrc; 225 226 return ctx->dhglrc; 227 228 no_hglrc: 229 ctx->st->destroy(ctx->st); 230 no_st_ctx: 231 FREE(ctx); 232 no_ctx: 233 return 0; 234 } 235 236 BOOL APIENTRY 237 DrvDeleteContext( 238 DHGLRC dhglrc ) 239 { 240 struct stw_context *ctx ; 241 BOOL ret = FALSE; 242 243 if (!stw_dev) 244 return FALSE; 245 246 pipe_mutex_lock( stw_dev->ctx_mutex ); 247 ctx = stw_lookup_context_locked(dhglrc); 248 handle_table_remove(stw_dev->ctx_table, dhglrc); 249 pipe_mutex_unlock( stw_dev->ctx_mutex ); 250 251 if (ctx) { 252 struct stw_context *curctx = stw_current_context(); 253 254 /* Unbind current if deleting current context. */ 255 if (curctx == ctx) 256 stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); 257 258 ctx->st->destroy(ctx->st); 259 FREE(ctx); 260 261 ret = TRUE; 262 } 263 264 return ret; 265 } 266 267 BOOL APIENTRY 268 DrvReleaseContext( 269 DHGLRC dhglrc ) 270 { 271 struct stw_context *ctx; 272 273 if (!stw_dev) 274 return FALSE; 275 276 pipe_mutex_lock( stw_dev->ctx_mutex ); 277 ctx = stw_lookup_context_locked( dhglrc ); 278 pipe_mutex_unlock( stw_dev->ctx_mutex ); 279 280 if (!ctx) 281 return FALSE; 282 283 /* The expectation is that ctx is the same context which is 284 * current for this thread. We should check that and return False 285 * if not the case. 286 */ 287 if (ctx != stw_current_context()) 288 return FALSE; 289 290 if (stw_make_current( NULL, 0 ) == FALSE) 291 return FALSE; 292 293 return TRUE; 294 } 295 296 297 DHGLRC 298 stw_get_current_context( void ) 299 { 300 struct stw_context *ctx; 301 302 ctx = stw_current_context(); 303 if(!ctx) 304 return 0; 305 306 return ctx->dhglrc; 307 } 308 309 HDC 310 stw_get_current_dc( void ) 311 { 312 struct stw_context *ctx; 313 314 ctx = stw_current_context(); 315 if(!ctx) 316 return NULL; 317 318 return ctx->hdc; 319 } 320 321 BOOL 322 stw_make_current( 323 HDC hdc, 324 DHGLRC dhglrc ) 325 { 326 struct stw_context *curctx = NULL; 327 struct stw_context *ctx = NULL; 328 struct stw_framebuffer *fb = NULL; 329 BOOL ret = FALSE; 330 331 if (!stw_dev) 332 return FALSE; 333 334 curctx = stw_current_context(); 335 if (curctx != NULL) { 336 if (curctx->dhglrc == dhglrc) { 337 if (curctx->hdc == hdc) { 338 /* Return if already current. */ 339 return TRUE; 340 } 341 } else { 342 curctx->st->flush(curctx->st, ST_FLUSH_FRONT, NULL); 343 } 344 } 345 346 if (dhglrc) { 347 pipe_mutex_lock( stw_dev->ctx_mutex ); 348 ctx = stw_lookup_context_locked( dhglrc ); 349 pipe_mutex_unlock( stw_dev->ctx_mutex ); 350 if (!ctx) { 351 goto fail; 352 } 353 354 fb = stw_framebuffer_from_hdc( hdc ); 355 if (fb) { 356 stw_framebuffer_update(fb); 357 } 358 else { 359 /* Applications should call SetPixelFormat before creating a context, 360 * but not all do, and the opengl32 runtime seems to use a default pixel 361 * format in some cases, so we must create a framebuffer for those here 362 */ 363 int iPixelFormat = GetPixelFormat(hdc); 364 if (iPixelFormat) 365 fb = stw_framebuffer_create( hdc, iPixelFormat ); 366 if (!fb) 367 goto fail; 368 } 369 370 if (fb->iPixelFormat != ctx->iPixelFormat) { 371 SetLastError(ERROR_INVALID_PIXEL_FORMAT); 372 goto fail; 373 } 374 375 /* Bind the new framebuffer */ 376 ctx->hdc = hdc; 377 378 ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, 379 fb->stfb, fb->stfb); 380 stw_framebuffer_reference(&ctx->current_framebuffer, fb); 381 } else { 382 ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); 383 } 384 385 fail: 386 387 if (fb) { 388 stw_framebuffer_release(fb); 389 } 390 391 /* On failure, make the thread's current rendering context not current 392 * before returning */ 393 if (!ret) { 394 stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); 395 ctx = NULL; 396 } 397 398 /* Unreference the previous framebuffer if any. It must be done after 399 * make_current, as it can be referenced inside. 400 */ 401 if (curctx && curctx != ctx) { 402 stw_framebuffer_reference(&curctx->current_framebuffer, NULL); 403 } 404 405 return ret; 406 } 407 408 /** 409 * Flush the current context if it is bound to the framebuffer. 410 */ 411 void 412 stw_flush_current_locked( struct stw_framebuffer *fb ) 413 { 414 struct stw_context *ctx = stw_current_context(); 415 416 if (ctx && ctx->current_framebuffer == fb) { 417 ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); 418 } 419 } 420 421 /** 422 * Notify the current context that the framebuffer has become invalid. 423 */ 424 void 425 stw_notify_current_locked( struct stw_framebuffer *fb ) 426 { 427 p_atomic_inc(&fb->stfb->stamp); 428 } 429 430 /** 431 * Although WGL allows different dispatch entrypoints per context 432 */ 433 static const GLCLTPROCTABLE cpt = 434 { 435 OPENGL_VERSION_110_ENTRIES, 436 { 437 &glNewList, 438 &glEndList, 439 &glCallList, 440 &glCallLists, 441 &glDeleteLists, 442 &glGenLists, 443 &glListBase, 444 &glBegin, 445 &glBitmap, 446 &glColor3b, 447 &glColor3bv, 448 &glColor3d, 449 &glColor3dv, 450 &glColor3f, 451 &glColor3fv, 452 &glColor3i, 453 &glColor3iv, 454 &glColor3s, 455 &glColor3sv, 456 &glColor3ub, 457 &glColor3ubv, 458 &glColor3ui, 459 &glColor3uiv, 460 &glColor3us, 461 &glColor3usv, 462 &glColor4b, 463 &glColor4bv, 464 &glColor4d, 465 &glColor4dv, 466 &glColor4f, 467 &glColor4fv, 468 &glColor4i, 469 &glColor4iv, 470 &glColor4s, 471 &glColor4sv, 472 &glColor4ub, 473 &glColor4ubv, 474 &glColor4ui, 475 &glColor4uiv, 476 &glColor4us, 477 &glColor4usv, 478 &glEdgeFlag, 479 &glEdgeFlagv, 480 &glEnd, 481 &glIndexd, 482 &glIndexdv, 483 &glIndexf, 484 &glIndexfv, 485 &glIndexi, 486 &glIndexiv, 487 &glIndexs, 488 &glIndexsv, 489 &glNormal3b, 490 &glNormal3bv, 491 &glNormal3d, 492 &glNormal3dv, 493 &glNormal3f, 494 &glNormal3fv, 495 &glNormal3i, 496 &glNormal3iv, 497 &glNormal3s, 498 &glNormal3sv, 499 &glRasterPos2d, 500 &glRasterPos2dv, 501 &glRasterPos2f, 502 &glRasterPos2fv, 503 &glRasterPos2i, 504 &glRasterPos2iv, 505 &glRasterPos2s, 506 &glRasterPos2sv, 507 &glRasterPos3d, 508 &glRasterPos3dv, 509 &glRasterPos3f, 510 &glRasterPos3fv, 511 &glRasterPos3i, 512 &glRasterPos3iv, 513 &glRasterPos3s, 514 &glRasterPos3sv, 515 &glRasterPos4d, 516 &glRasterPos4dv, 517 &glRasterPos4f, 518 &glRasterPos4fv, 519 &glRasterPos4i, 520 &glRasterPos4iv, 521 &glRasterPos4s, 522 &glRasterPos4sv, 523 &glRectd, 524 &glRectdv, 525 &glRectf, 526 &glRectfv, 527 &glRecti, 528 &glRectiv, 529 &glRects, 530 &glRectsv, 531 &glTexCoord1d, 532 &glTexCoord1dv, 533 &glTexCoord1f, 534 &glTexCoord1fv, 535 &glTexCoord1i, 536 &glTexCoord1iv, 537 &glTexCoord1s, 538 &glTexCoord1sv, 539 &glTexCoord2d, 540 &glTexCoord2dv, 541 &glTexCoord2f, 542 &glTexCoord2fv, 543 &glTexCoord2i, 544 &glTexCoord2iv, 545 &glTexCoord2s, 546 &glTexCoord2sv, 547 &glTexCoord3d, 548 &glTexCoord3dv, 549 &glTexCoord3f, 550 &glTexCoord3fv, 551 &glTexCoord3i, 552 &glTexCoord3iv, 553 &glTexCoord3s, 554 &glTexCoord3sv, 555 &glTexCoord4d, 556 &glTexCoord4dv, 557 &glTexCoord4f, 558 &glTexCoord4fv, 559 &glTexCoord4i, 560 &glTexCoord4iv, 561 &glTexCoord4s, 562 &glTexCoord4sv, 563 &glVertex2d, 564 &glVertex2dv, 565 &glVertex2f, 566 &glVertex2fv, 567 &glVertex2i, 568 &glVertex2iv, 569 &glVertex2s, 570 &glVertex2sv, 571 &glVertex3d, 572 &glVertex3dv, 573 &glVertex3f, 574 &glVertex3fv, 575 &glVertex3i, 576 &glVertex3iv, 577 &glVertex3s, 578 &glVertex3sv, 579 &glVertex4d, 580 &glVertex4dv, 581 &glVertex4f, 582 &glVertex4fv, 583 &glVertex4i, 584 &glVertex4iv, 585 &glVertex4s, 586 &glVertex4sv, 587 &glClipPlane, 588 &glColorMaterial, 589 &glCullFace, 590 &glFogf, 591 &glFogfv, 592 &glFogi, 593 &glFogiv, 594 &glFrontFace, 595 &glHint, 596 &glLightf, 597 &glLightfv, 598 &glLighti, 599 &glLightiv, 600 &glLightModelf, 601 &glLightModelfv, 602 &glLightModeli, 603 &glLightModeliv, 604 &glLineStipple, 605 &glLineWidth, 606 &glMaterialf, 607 &glMaterialfv, 608 &glMateriali, 609 &glMaterialiv, 610 &glPointSize, 611 &glPolygonMode, 612 &glPolygonStipple, 613 &glScissor, 614 &glShadeModel, 615 &glTexParameterf, 616 &glTexParameterfv, 617 &glTexParameteri, 618 &glTexParameteriv, 619 &glTexImage1D, 620 &glTexImage2D, 621 &glTexEnvf, 622 &glTexEnvfv, 623 &glTexEnvi, 624 &glTexEnviv, 625 &glTexGend, 626 &glTexGendv, 627 &glTexGenf, 628 &glTexGenfv, 629 &glTexGeni, 630 &glTexGeniv, 631 &glFeedbackBuffer, 632 &glSelectBuffer, 633 &glRenderMode, 634 &glInitNames, 635 &glLoadName, 636 &glPassThrough, 637 &glPopName, 638 &glPushName, 639 &glDrawBuffer, 640 &glClear, 641 &glClearAccum, 642 &glClearIndex, 643 &glClearColor, 644 &glClearStencil, 645 &glClearDepth, 646 &glStencilMask, 647 &glColorMask, 648 &glDepthMask, 649 &glIndexMask, 650 &glAccum, 651 &glDisable, 652 &glEnable, 653 &glFinish, 654 &glFlush, 655 &glPopAttrib, 656 &glPushAttrib, 657 &glMap1d, 658 &glMap1f, 659 &glMap2d, 660 &glMap2f, 661 &glMapGrid1d, 662 &glMapGrid1f, 663 &glMapGrid2d, 664 &glMapGrid2f, 665 &glEvalCoord1d, 666 &glEvalCoord1dv, 667 &glEvalCoord1f, 668 &glEvalCoord1fv, 669 &glEvalCoord2d, 670 &glEvalCoord2dv, 671 &glEvalCoord2f, 672 &glEvalCoord2fv, 673 &glEvalMesh1, 674 &glEvalPoint1, 675 &glEvalMesh2, 676 &glEvalPoint2, 677 &glAlphaFunc, 678 &glBlendFunc, 679 &glLogicOp, 680 &glStencilFunc, 681 &glStencilOp, 682 &glDepthFunc, 683 &glPixelZoom, 684 &glPixelTransferf, 685 &glPixelTransferi, 686 &glPixelStoref, 687 &glPixelStorei, 688 &glPixelMapfv, 689 &glPixelMapuiv, 690 &glPixelMapusv, 691 &glReadBuffer, 692 &glCopyPixels, 693 &glReadPixels, 694 &glDrawPixels, 695 &glGetBooleanv, 696 &glGetClipPlane, 697 &glGetDoublev, 698 &glGetError, 699 &glGetFloatv, 700 &glGetIntegerv, 701 &glGetLightfv, 702 &glGetLightiv, 703 &glGetMapdv, 704 &glGetMapfv, 705 &glGetMapiv, 706 &glGetMaterialfv, 707 &glGetMaterialiv, 708 &glGetPixelMapfv, 709 &glGetPixelMapuiv, 710 &glGetPixelMapusv, 711 &glGetPolygonStipple, 712 &glGetString, 713 &glGetTexEnvfv, 714 &glGetTexEnviv, 715 &glGetTexGendv, 716 &glGetTexGenfv, 717 &glGetTexGeniv, 718 &glGetTexImage, 719 &glGetTexParameterfv, 720 &glGetTexParameteriv, 721 &glGetTexLevelParameterfv, 722 &glGetTexLevelParameteriv, 723 &glIsEnabled, 724 &glIsList, 725 &glDepthRange, 726 &glFrustum, 727 &glLoadIdentity, 728 &glLoadMatrixf, 729 &glLoadMatrixd, 730 &glMatrixMode, 731 &glMultMatrixf, 732 &glMultMatrixd, 733 &glOrtho, 734 &glPopMatrix, 735 &glPushMatrix, 736 &glRotated, 737 &glRotatef, 738 &glScaled, 739 &glScalef, 740 &glTranslated, 741 &glTranslatef, 742 &glViewport, 743 &glArrayElement, 744 &glBindTexture, 745 &glColorPointer, 746 &glDisableClientState, 747 &glDrawArrays, 748 &glDrawElements, 749 &glEdgeFlagPointer, 750 &glEnableClientState, 751 &glIndexPointer, 752 &glIndexub, 753 &glIndexubv, 754 &glInterleavedArrays, 755 &glNormalPointer, 756 &glPolygonOffset, 757 &glTexCoordPointer, 758 &glVertexPointer, 759 &glAreTexturesResident, 760 &glCopyTexImage1D, 761 &glCopyTexImage2D, 762 &glCopyTexSubImage1D, 763 &glCopyTexSubImage2D, 764 &glDeleteTextures, 765 &glGenTextures, 766 &glGetPointerv, 767 &glIsTexture, 768 &glPrioritizeTextures, 769 &glTexSubImage1D, 770 &glTexSubImage2D, 771 &glPopClientAttrib, 772 &glPushClientAttrib 773 } 774 }; 775 776 PGLCLTPROCTABLE APIENTRY 777 DrvSetContext( 778 HDC hdc, 779 DHGLRC dhglrc, 780 PFN_SETPROCTABLE pfnSetProcTable ) 781 { 782 PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt; 783 784 if (!stw_make_current( hdc, dhglrc )) 785 r = NULL; 786 787 return r; 788 } 789