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