1 // 2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Context.cpp: Implements the gl::Context class, managing all GL state and performing 8 // rendering operations. It is the GLES2 specific implementation of EGLContext. 9 10 #include "libGLESv2/Context.h" 11 12 #include <algorithm> 13 14 #include "libEGL/Display.h" 15 16 #include "libGLESv2/main.h" 17 #include "libGLESv2/mathutil.h" 18 #include "libGLESv2/utilities.h" 19 #include "libGLESv2/Blit.h" 20 #include "libGLESv2/ResourceManager.h" 21 #include "libGLESv2/Buffer.h" 22 #include "libGLESv2/Fence.h" 23 #include "libGLESv2/FrameBuffer.h" 24 #include "libGLESv2/Program.h" 25 #include "libGLESv2/RenderBuffer.h" 26 #include "libGLESv2/Shader.h" 27 #include "libGLESv2/Texture.h" 28 #include "libGLESv2/geometry/VertexDataManager.h" 29 #include "libGLESv2/geometry/IndexDataManager.h" 30 31 #undef near 32 #undef far 33 34 namespace gl 35 { 36 Context::Context(const egl::Config *config, const gl::Context *shareContext) 37 : mConfig(config) 38 { 39 setClearColor(0.0f, 0.0f, 0.0f, 0.0f); 40 41 mState.depthClearValue = 1.0f; 42 mState.stencilClearValue = 0; 43 44 mState.cullFace = false; 45 mState.cullMode = GL_BACK; 46 mState.frontFace = GL_CCW; 47 mState.depthTest = false; 48 mState.depthFunc = GL_LESS; 49 mState.blend = false; 50 mState.sourceBlendRGB = GL_ONE; 51 mState.sourceBlendAlpha = GL_ONE; 52 mState.destBlendRGB = GL_ZERO; 53 mState.destBlendAlpha = GL_ZERO; 54 mState.blendEquationRGB = GL_FUNC_ADD; 55 mState.blendEquationAlpha = GL_FUNC_ADD; 56 mState.blendColor.red = 0; 57 mState.blendColor.green = 0; 58 mState.blendColor.blue = 0; 59 mState.blendColor.alpha = 0; 60 mState.stencilTest = false; 61 mState.stencilFunc = GL_ALWAYS; 62 mState.stencilRef = 0; 63 mState.stencilMask = -1; 64 mState.stencilWritemask = -1; 65 mState.stencilBackFunc = GL_ALWAYS; 66 mState.stencilBackRef = 0; 67 mState.stencilBackMask = - 1; 68 mState.stencilBackWritemask = -1; 69 mState.stencilFail = GL_KEEP; 70 mState.stencilPassDepthFail = GL_KEEP; 71 mState.stencilPassDepthPass = GL_KEEP; 72 mState.stencilBackFail = GL_KEEP; 73 mState.stencilBackPassDepthFail = GL_KEEP; 74 mState.stencilBackPassDepthPass = GL_KEEP; 75 mState.polygonOffsetFill = false; 76 mState.polygonOffsetFactor = 0.0f; 77 mState.polygonOffsetUnits = 0.0f; 78 mState.sampleAlphaToCoverage = false; 79 mState.sampleCoverage = false; 80 mState.sampleCoverageValue = 1.0f; 81 mState.sampleCoverageInvert = false; 82 mState.scissorTest = false; 83 mState.dither = true; 84 mState.generateMipmapHint = GL_DONT_CARE; 85 mState.fragmentShaderDerivativeHint = GL_DONT_CARE; 86 87 mState.lineWidth = 1.0f; 88 89 mState.viewportX = 0; 90 mState.viewportY = 0; 91 mState.viewportWidth = config->mDisplayMode.Width; 92 mState.viewportHeight = config->mDisplayMode.Height; 93 mState.zNear = 0.0f; 94 mState.zFar = 1.0f; 95 96 mState.scissorX = 0; 97 mState.scissorY = 0; 98 mState.scissorWidth = config->mDisplayMode.Width; 99 mState.scissorHeight = config->mDisplayMode.Height; 100 101 mState.colorMaskRed = true; 102 mState.colorMaskGreen = true; 103 mState.colorMaskBlue = true; 104 mState.colorMaskAlpha = true; 105 mState.depthMask = true; 106 107 if (shareContext != NULL) 108 { 109 mResourceManager = shareContext->mResourceManager; 110 mResourceManager->addRef(); 111 } 112 else 113 { 114 mResourceManager = new ResourceManager(); 115 } 116 117 // [OpenGL ES 2.0.24] section 3.7 page 83: 118 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional 119 // and cube map texture state vectors respectively associated with them. 120 // In order that access to these initial textures not be lost, they are treated as texture 121 // objects all of whose names are 0. 122 123 mTexture2DZero.set(new Texture2D(0)); 124 mTextureCubeMapZero.set(new TextureCubeMap(0)); 125 126 mState.activeSampler = 0; 127 bindArrayBuffer(0); 128 bindElementArrayBuffer(0); 129 bindTextureCubeMap(0); 130 bindTexture2D(0); 131 bindReadFramebuffer(0); 132 bindDrawFramebuffer(0); 133 bindRenderbuffer(0); 134 135 mState.currentProgram = 0; 136 137 mState.packAlignment = 4; 138 mState.unpackAlignment = 4; 139 140 mVertexDataManager = NULL; 141 mIndexDataManager = NULL; 142 mBlit = NULL; 143 144 mInvalidEnum = false; 145 mInvalidValue = false; 146 mInvalidOperation = false; 147 mOutOfMemory = false; 148 mInvalidFramebufferOperation = false; 149 150 mHasBeenCurrent = false; 151 152 mSupportsCompressedTextures = false; 153 mSupportsEventQueries = false; 154 mMaxSupportedSamples = 0; 155 mMaskedClearSavedState = NULL; 156 markAllStateDirty(); 157 } 158 159 Context::~Context() 160 { 161 if (mState.currentProgram != 0) 162 { 163 Program *programObject = mResourceManager->getProgram(mState.currentProgram); 164 if (programObject) 165 { 166 programObject->release(); 167 } 168 mState.currentProgram = 0; 169 } 170 171 while (!mFramebufferMap.empty()) 172 { 173 deleteFramebuffer(mFramebufferMap.begin()->first); 174 } 175 176 while (!mFenceMap.empty()) 177 { 178 deleteFence(mFenceMap.begin()->first); 179 } 180 181 while (!mMultiSampleSupport.empty()) 182 { 183 delete [] mMultiSampleSupport.begin()->second; 184 mMultiSampleSupport.erase(mMultiSampleSupport.begin()); 185 } 186 187 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++) 188 { 189 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++) 190 { 191 mState.samplerTexture[type][sampler].set(NULL); 192 } 193 } 194 195 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++) 196 { 197 mIncompleteTextures[type].set(NULL); 198 } 199 200 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) 201 { 202 mState.vertexAttribute[i].mBoundBuffer.set(NULL); 203 } 204 205 mState.arrayBuffer.set(NULL); 206 mState.elementArrayBuffer.set(NULL); 207 mState.renderbuffer.set(NULL); 208 209 mTexture2DZero.set(NULL); 210 mTextureCubeMapZero.set(NULL); 211 212 delete mVertexDataManager; 213 delete mIndexDataManager; 214 delete mBlit; 215 216 if (mMaskedClearSavedState) 217 { 218 mMaskedClearSavedState->Release(); 219 } 220 221 mResourceManager->release(); 222 } 223 224 void Context::makeCurrent(egl::Display *display, egl::Surface *surface) 225 { 226 IDirect3DDevice9 *device = display->getDevice(); 227 228 if (!mHasBeenCurrent) 229 { 230 mDeviceCaps = display->getDeviceCaps(); 231 232 mVertexDataManager = new VertexDataManager(this, device); 233 mIndexDataManager = new IndexDataManager(this, device); 234 mBlit = new Blit(this); 235 236 mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0); 237 238 mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight), 239 (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); 240 mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE); 241 mMaxRenderbufferDimension = mMaxTextureDimension; 242 mMaxTextureLevel = log2(mMaxTextureDimension) + 1; 243 TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d", 244 mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel); 245 246 const D3DFORMAT renderBufferFormats[] = 247 { 248 D3DFMT_A8R8G8B8, 249 D3DFMT_X8R8G8B8, 250 D3DFMT_R5G6B5, 251 D3DFMT_D24S8 252 }; 253 254 int max = 0; 255 for (int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i) 256 { 257 bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; 258 display->getMultiSampleSupport(renderBufferFormats[i], multisampleArray); 259 mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray; 260 261 for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) 262 { 263 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) 264 { 265 max = j; 266 } 267 } 268 } 269 270 mMaxSupportedSamples = max; 271 272 mSupportsEventQueries = display->getEventQuerySupport(); 273 mSupportsCompressedTextures = display->getCompressedTextureSupport(); 274 mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures); 275 mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures); 276 mSupportsLuminanceTextures = display->getLuminanceTextureSupport(); 277 mSupportsLuminanceAlphaTextures = display->getLuminanceAlphaTextureSupport(); 278 279 mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16); 280 281 initExtensionString(); 282 283 mState.viewportX = 0; 284 mState.viewportY = 0; 285 mState.viewportWidth = surface->getWidth(); 286 mState.viewportHeight = surface->getHeight(); 287 288 mState.scissorX = 0; 289 mState.scissorY = 0; 290 mState.scissorWidth = surface->getWidth(); 291 mState.scissorHeight = surface->getHeight(); 292 293 mHasBeenCurrent = true; 294 } 295 296 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names 297 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget(); 298 IDirect3DSurface9 *depthStencil = surface->getDepthStencil(); 299 300 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget); 301 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil); 302 Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); 303 304 setFramebufferZero(framebufferZero); 305 306 if (defaultRenderTarget) 307 { 308 defaultRenderTarget->Release(); 309 } 310 311 if (depthStencil) 312 { 313 depthStencil->Release(); 314 } 315 316 markAllStateDirty(); 317 } 318 319 // This function will set all of the state-related dirty flags, so that all state is set during next pre-draw. 320 void Context::markAllStateDirty() 321 { 322 mAppliedRenderTargetSerial = 0; 323 mAppliedDepthbufferSerial = 0; 324 mAppliedStencilbufferSerial = 0; 325 mDepthStencilInitialized = false; 326 mAppliedProgram = 0; 327 328 mClearStateDirty = true; 329 mCullStateDirty = true; 330 mDepthStateDirty = true; 331 mMaskStateDirty = true; 332 mBlendStateDirty = true; 333 mStencilStateDirty = true; 334 mPolygonOffsetStateDirty = true; 335 mScissorStateDirty = true; 336 mSampleStateDirty = true; 337 mDitherStateDirty = true; 338 mFrontFaceDirty = true; 339 } 340 341 void Context::setClearColor(float red, float green, float blue, float alpha) 342 { 343 mState.colorClearValue.red = red; 344 mState.colorClearValue.green = green; 345 mState.colorClearValue.blue = blue; 346 mState.colorClearValue.alpha = alpha; 347 } 348 349 void Context::setClearDepth(float depth) 350 { 351 mState.depthClearValue = depth; 352 } 353 354 void Context::setClearStencil(int stencil) 355 { 356 mState.stencilClearValue = stencil; 357 } 358 359 void Context::setCullFace(bool enabled) 360 { 361 if (mState.cullFace != enabled) 362 { 363 mState.cullFace = enabled; 364 mCullStateDirty = true; 365 } 366 } 367 368 bool Context::isCullFaceEnabled() const 369 { 370 return mState.cullFace; 371 } 372 373 void Context::setCullMode(GLenum mode) 374 { 375 if (mState.cullMode != mode) 376 { 377 mState.cullMode = mode; 378 mCullStateDirty = true; 379 } 380 } 381 382 void Context::setFrontFace(GLenum front) 383 { 384 if (mState.frontFace != front) 385 { 386 mState.frontFace = front; 387 mFrontFaceDirty = true; 388 } 389 } 390 391 void Context::setDepthTest(bool enabled) 392 { 393 if (mState.depthTest != enabled) 394 { 395 mState.depthTest = enabled; 396 mDepthStateDirty = true; 397 } 398 } 399 400 bool Context::isDepthTestEnabled() const 401 { 402 return mState.depthTest; 403 } 404 405 void Context::setDepthFunc(GLenum depthFunc) 406 { 407 if (mState.depthFunc != depthFunc) 408 { 409 mState.depthFunc = depthFunc; 410 mDepthStateDirty = true; 411 } 412 } 413 414 void Context::setDepthRange(float zNear, float zFar) 415 { 416 mState.zNear = zNear; 417 mState.zFar = zFar; 418 } 419 420 void Context::setBlend(bool enabled) 421 { 422 if (mState.blend != enabled) 423 { 424 mState.blend = enabled; 425 mBlendStateDirty = true; 426 } 427 } 428 429 bool Context::isBlendEnabled() const 430 { 431 return mState.blend; 432 } 433 434 void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) 435 { 436 if (mState.sourceBlendRGB != sourceRGB || 437 mState.sourceBlendAlpha != sourceAlpha || 438 mState.destBlendRGB != destRGB || 439 mState.destBlendAlpha != destAlpha) 440 { 441 mState.sourceBlendRGB = sourceRGB; 442 mState.destBlendRGB = destRGB; 443 mState.sourceBlendAlpha = sourceAlpha; 444 mState.destBlendAlpha = destAlpha; 445 mBlendStateDirty = true; 446 } 447 } 448 449 void Context::setBlendColor(float red, float green, float blue, float alpha) 450 { 451 if (mState.blendColor.red != red || 452 mState.blendColor.green != green || 453 mState.blendColor.blue != blue || 454 mState.blendColor.alpha != alpha) 455 { 456 mState.blendColor.red = red; 457 mState.blendColor.green = green; 458 mState.blendColor.blue = blue; 459 mState.blendColor.alpha = alpha; 460 mBlendStateDirty = true; 461 } 462 } 463 464 void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) 465 { 466 if (mState.blendEquationRGB != rgbEquation || 467 mState.blendEquationAlpha != alphaEquation) 468 { 469 mState.blendEquationRGB = rgbEquation; 470 mState.blendEquationAlpha = alphaEquation; 471 mBlendStateDirty = true; 472 } 473 } 474 475 void Context::setStencilTest(bool enabled) 476 { 477 if (mState.stencilTest != enabled) 478 { 479 mState.stencilTest = enabled; 480 mStencilStateDirty = true; 481 } 482 } 483 484 bool Context::isStencilTestEnabled() const 485 { 486 return mState.stencilTest; 487 } 488 489 void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) 490 { 491 if (mState.stencilFunc != stencilFunc || 492 mState.stencilRef != stencilRef || 493 mState.stencilMask != stencilMask) 494 { 495 mState.stencilFunc = stencilFunc; 496 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; 497 mState.stencilMask = stencilMask; 498 mStencilStateDirty = true; 499 } 500 } 501 502 void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) 503 { 504 if (mState.stencilBackFunc != stencilBackFunc || 505 mState.stencilBackRef != stencilBackRef || 506 mState.stencilBackMask != stencilBackMask) 507 { 508 mState.stencilBackFunc = stencilBackFunc; 509 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; 510 mState.stencilBackMask = stencilBackMask; 511 mStencilStateDirty = true; 512 } 513 } 514 515 void Context::setStencilWritemask(GLuint stencilWritemask) 516 { 517 if (mState.stencilWritemask != stencilWritemask) 518 { 519 mState.stencilWritemask = stencilWritemask; 520 mStencilStateDirty = true; 521 } 522 } 523 524 void Context::setStencilBackWritemask(GLuint stencilBackWritemask) 525 { 526 if (mState.stencilBackWritemask != stencilBackWritemask) 527 { 528 mState.stencilBackWritemask = stencilBackWritemask; 529 mStencilStateDirty = true; 530 } 531 } 532 533 void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) 534 { 535 if (mState.stencilFail != stencilFail || 536 mState.stencilPassDepthFail != stencilPassDepthFail || 537 mState.stencilPassDepthPass != stencilPassDepthPass) 538 { 539 mState.stencilFail = stencilFail; 540 mState.stencilPassDepthFail = stencilPassDepthFail; 541 mState.stencilPassDepthPass = stencilPassDepthPass; 542 mStencilStateDirty = true; 543 } 544 } 545 546 void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) 547 { 548 if (mState.stencilBackFail != stencilBackFail || 549 mState.stencilBackPassDepthFail != stencilBackPassDepthFail || 550 mState.stencilBackPassDepthPass != stencilBackPassDepthPass) 551 { 552 mState.stencilBackFail = stencilBackFail; 553 mState.stencilBackPassDepthFail = stencilBackPassDepthFail; 554 mState.stencilBackPassDepthPass = stencilBackPassDepthPass; 555 mStencilStateDirty = true; 556 } 557 } 558 559 void Context::setPolygonOffsetFill(bool enabled) 560 { 561 if (mState.polygonOffsetFill != enabled) 562 { 563 mState.polygonOffsetFill = enabled; 564 mPolygonOffsetStateDirty = true; 565 } 566 } 567 568 bool Context::isPolygonOffsetFillEnabled() const 569 { 570 return mState.polygonOffsetFill; 571 572 } 573 574 void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) 575 { 576 if (mState.polygonOffsetFactor != factor || 577 mState.polygonOffsetUnits != units) 578 { 579 mState.polygonOffsetFactor = factor; 580 mState.polygonOffsetUnits = units; 581 mPolygonOffsetStateDirty = true; 582 } 583 } 584 585 void Context::setSampleAlphaToCoverage(bool enabled) 586 { 587 if (mState.sampleAlphaToCoverage != enabled) 588 { 589 mState.sampleAlphaToCoverage = enabled; 590 mSampleStateDirty = true; 591 } 592 } 593 594 bool Context::isSampleAlphaToCoverageEnabled() const 595 { 596 return mState.sampleAlphaToCoverage; 597 } 598 599 void Context::setSampleCoverage(bool enabled) 600 { 601 if (mState.sampleCoverage != enabled) 602 { 603 mState.sampleCoverage = enabled; 604 mSampleStateDirty = true; 605 } 606 } 607 608 bool Context::isSampleCoverageEnabled() const 609 { 610 return mState.sampleCoverage; 611 } 612 613 void Context::setSampleCoverageParams(GLclampf value, bool invert) 614 { 615 if (mState.sampleCoverageValue != value || 616 mState.sampleCoverageInvert != invert) 617 { 618 mState.sampleCoverageValue = value; 619 mState.sampleCoverageInvert = invert; 620 mSampleStateDirty = true; 621 } 622 } 623 624 void Context::setScissorTest(bool enabled) 625 { 626 if (mState.scissorTest != enabled) 627 { 628 mState.scissorTest = enabled; 629 mScissorStateDirty = true; 630 } 631 } 632 633 bool Context::isScissorTestEnabled() const 634 { 635 return mState.scissorTest; 636 } 637 638 void Context::setDither(bool enabled) 639 { 640 if (mState.dither != enabled) 641 { 642 mState.dither = enabled; 643 mDitherStateDirty = true; 644 } 645 } 646 647 bool Context::isDitherEnabled() const 648 { 649 return mState.dither; 650 } 651 652 void Context::setLineWidth(GLfloat width) 653 { 654 mState.lineWidth = width; 655 } 656 657 void Context::setGenerateMipmapHint(GLenum hint) 658 { 659 mState.generateMipmapHint = hint; 660 } 661 662 void Context::setFragmentShaderDerivativeHint(GLenum hint) 663 { 664 mState.fragmentShaderDerivativeHint = hint; 665 // TODO: Propagate the hint to shader translator so we can write 666 // ddx, ddx_coarse, or ddx_fine depending on the hint. 667 // Ignore for now. It is valid for implementations to ignore hint. 668 } 669 670 void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) 671 { 672 mState.viewportX = x; 673 mState.viewportY = y; 674 mState.viewportWidth = width; 675 mState.viewportHeight = height; 676 } 677 678 void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) 679 { 680 if (mState.scissorX != x || mState.scissorY != y || 681 mState.scissorWidth != width || mState.scissorHeight != height) 682 { 683 mState.scissorX = x; 684 mState.scissorY = y; 685 mState.scissorWidth = width; 686 mState.scissorHeight = height; 687 mScissorStateDirty = true; 688 } 689 } 690 691 void Context::setColorMask(bool red, bool green, bool blue, bool alpha) 692 { 693 if (mState.colorMaskRed != red || mState.colorMaskGreen != green || 694 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha) 695 { 696 mState.colorMaskRed = red; 697 mState.colorMaskGreen = green; 698 mState.colorMaskBlue = blue; 699 mState.colorMaskAlpha = alpha; 700 mMaskStateDirty = true; 701 } 702 } 703 704 void Context::setDepthMask(bool mask) 705 { 706 if (mState.depthMask != mask) 707 { 708 mState.depthMask = mask; 709 mMaskStateDirty = true; 710 } 711 } 712 713 void Context::setActiveSampler(int active) 714 { 715 mState.activeSampler = active; 716 } 717 718 GLuint Context::getReadFramebufferHandle() const 719 { 720 return mState.readFramebuffer; 721 } 722 723 GLuint Context::getDrawFramebufferHandle() const 724 { 725 return mState.drawFramebuffer; 726 } 727 728 GLuint Context::getRenderbufferHandle() const 729 { 730 return mState.renderbuffer.id(); 731 } 732 733 GLuint Context::getArrayBufferHandle() const 734 { 735 return mState.arrayBuffer.id(); 736 } 737 738 void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) 739 { 740 mState.vertexAttribute[attribNum].mArrayEnabled = enabled; 741 } 742 743 const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) 744 { 745 return mState.vertexAttribute[attribNum]; 746 } 747 748 void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, 749 GLsizei stride, const void *pointer) 750 { 751 mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer); 752 mState.vertexAttribute[attribNum].mSize = size; 753 mState.vertexAttribute[attribNum].mType = type; 754 mState.vertexAttribute[attribNum].mNormalized = normalized; 755 mState.vertexAttribute[attribNum].mStride = stride; 756 mState.vertexAttribute[attribNum].mPointer = pointer; 757 } 758 759 const void *Context::getVertexAttribPointer(unsigned int attribNum) const 760 { 761 return mState.vertexAttribute[attribNum].mPointer; 762 } 763 764 const VertexAttributeArray &Context::getVertexAttributes() 765 { 766 return mState.vertexAttribute; 767 } 768 769 void Context::setPackAlignment(GLint alignment) 770 { 771 mState.packAlignment = alignment; 772 } 773 774 GLint Context::getPackAlignment() const 775 { 776 return mState.packAlignment; 777 } 778 779 void Context::setUnpackAlignment(GLint alignment) 780 { 781 mState.unpackAlignment = alignment; 782 } 783 784 GLint Context::getUnpackAlignment() const 785 { 786 return mState.unpackAlignment; 787 } 788 789 GLuint Context::createBuffer() 790 { 791 return mResourceManager->createBuffer(); 792 } 793 794 GLuint Context::createProgram() 795 { 796 return mResourceManager->createProgram(); 797 } 798 799 GLuint Context::createShader(GLenum type) 800 { 801 return mResourceManager->createShader(type); 802 } 803 804 GLuint Context::createTexture() 805 { 806 return mResourceManager->createTexture(); 807 } 808 809 GLuint Context::createRenderbuffer() 810 { 811 return mResourceManager->createRenderbuffer(); 812 } 813 814 // Returns an unused framebuffer name 815 GLuint Context::createFramebuffer() 816 { 817 unsigned int handle = 1; 818 819 while (mFramebufferMap.find(handle) != mFramebufferMap.end()) 820 { 821 handle++; 822 } 823 824 mFramebufferMap[handle] = NULL; 825 826 return handle; 827 } 828 829 GLuint Context::createFence() 830 { 831 unsigned int handle = 0; 832 833 while (mFenceMap.find(handle) != mFenceMap.end()) 834 { 835 handle++; 836 } 837 838 mFenceMap[handle] = new Fence; 839 840 return handle; 841 } 842 843 void Context::deleteBuffer(GLuint buffer) 844 { 845 if (mResourceManager->getBuffer(buffer)) 846 { 847 detachBuffer(buffer); 848 } 849 850 mResourceManager->deleteBuffer(buffer); 851 } 852 853 void Context::deleteShader(GLuint shader) 854 { 855 mResourceManager->deleteShader(shader); 856 } 857 858 void Context::deleteProgram(GLuint program) 859 { 860 mResourceManager->deleteProgram(program); 861 } 862 863 void Context::deleteTexture(GLuint texture) 864 { 865 if (mResourceManager->getTexture(texture)) 866 { 867 detachTexture(texture); 868 } 869 870 mResourceManager->deleteTexture(texture); 871 } 872 873 void Context::deleteRenderbuffer(GLuint renderbuffer) 874 { 875 if (mResourceManager->getRenderbuffer(renderbuffer)) 876 { 877 detachRenderbuffer(renderbuffer); 878 } 879 880 mResourceManager->deleteRenderbuffer(renderbuffer); 881 } 882 883 void Context::deleteFramebuffer(GLuint framebuffer) 884 { 885 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer); 886 887 if (framebufferObject != mFramebufferMap.end()) 888 { 889 detachFramebuffer(framebuffer); 890 891 delete framebufferObject->second; 892 mFramebufferMap.erase(framebufferObject); 893 } 894 } 895 896 void Context::deleteFence(GLuint fence) 897 { 898 FenceMap::iterator fenceObject = mFenceMap.find(fence); 899 900 if (fenceObject != mFenceMap.end()) 901 { 902 delete fenceObject->second; 903 mFenceMap.erase(fenceObject); 904 } 905 } 906 907 Buffer *Context::getBuffer(GLuint handle) 908 { 909 return mResourceManager->getBuffer(handle); 910 } 911 912 Shader *Context::getShader(GLuint handle) 913 { 914 return mResourceManager->getShader(handle); 915 } 916 917 Program *Context::getProgram(GLuint handle) 918 { 919 return mResourceManager->getProgram(handle); 920 } 921 922 Texture *Context::getTexture(GLuint handle) 923 { 924 return mResourceManager->getTexture(handle); 925 } 926 927 Renderbuffer *Context::getRenderbuffer(GLuint handle) 928 { 929 return mResourceManager->getRenderbuffer(handle); 930 } 931 932 Framebuffer *Context::getReadFramebuffer() 933 { 934 return getFramebuffer(mState.readFramebuffer); 935 } 936 937 Framebuffer *Context::getDrawFramebuffer() 938 { 939 return getFramebuffer(mState.drawFramebuffer); 940 } 941 942 void Context::bindArrayBuffer(unsigned int buffer) 943 { 944 mResourceManager->checkBufferAllocation(buffer); 945 946 mState.arrayBuffer.set(getBuffer(buffer)); 947 } 948 949 void Context::bindElementArrayBuffer(unsigned int buffer) 950 { 951 mResourceManager->checkBufferAllocation(buffer); 952 953 mState.elementArrayBuffer.set(getBuffer(buffer)); 954 } 955 956 void Context::bindTexture2D(GLuint texture) 957 { 958 mResourceManager->checkTextureAllocation(texture, SAMPLER_2D); 959 960 mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(getTexture(texture)); 961 } 962 963 void Context::bindTextureCubeMap(GLuint texture) 964 { 965 mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE); 966 967 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(getTexture(texture)); 968 } 969 970 void Context::bindReadFramebuffer(GLuint framebuffer) 971 { 972 if (!getFramebuffer(framebuffer)) 973 { 974 mFramebufferMap[framebuffer] = new Framebuffer(); 975 } 976 977 mState.readFramebuffer = framebuffer; 978 } 979 980 void Context::bindDrawFramebuffer(GLuint framebuffer) 981 { 982 if (!getFramebuffer(framebuffer)) 983 { 984 mFramebufferMap[framebuffer] = new Framebuffer(); 985 } 986 987 mState.drawFramebuffer = framebuffer; 988 } 989 990 void Context::bindRenderbuffer(GLuint renderbuffer) 991 { 992 mResourceManager->checkRenderbufferAllocation(renderbuffer); 993 994 mState.renderbuffer.set(getRenderbuffer(renderbuffer)); 995 } 996 997 void Context::useProgram(GLuint program) 998 { 999 GLuint priorProgram = mState.currentProgram; 1000 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged. 1001 1002 if (priorProgram != program) 1003 { 1004 Program *newProgram = mResourceManager->getProgram(program); 1005 Program *oldProgram = mResourceManager->getProgram(priorProgram); 1006 1007 if (newProgram) 1008 { 1009 newProgram->addRef(); 1010 } 1011 1012 if (oldProgram) 1013 { 1014 oldProgram->release(); 1015 } 1016 } 1017 } 1018 1019 void Context::setFramebufferZero(Framebuffer *buffer) 1020 { 1021 delete mFramebufferMap[0]; 1022 mFramebufferMap[0] = buffer; 1023 } 1024 1025 void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer) 1026 { 1027 Renderbuffer *renderbufferObject = mState.renderbuffer.get(); 1028 renderbufferObject->setStorage(renderbuffer); 1029 } 1030 1031 Framebuffer *Context::getFramebuffer(unsigned int handle) 1032 { 1033 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle); 1034 1035 if (framebuffer == mFramebufferMap.end()) 1036 { 1037 return NULL; 1038 } 1039 else 1040 { 1041 return framebuffer->second; 1042 } 1043 } 1044 1045 Fence *Context::getFence(unsigned int handle) 1046 { 1047 FenceMap::iterator fence = mFenceMap.find(handle); 1048 1049 if (fence == mFenceMap.end()) 1050 { 1051 return NULL; 1052 } 1053 else 1054 { 1055 return fence->second; 1056 } 1057 } 1058 1059 Buffer *Context::getArrayBuffer() 1060 { 1061 return mState.arrayBuffer.get(); 1062 } 1063 1064 Buffer *Context::getElementArrayBuffer() 1065 { 1066 return mState.elementArrayBuffer.get(); 1067 } 1068 1069 Program *Context::getCurrentProgram() 1070 { 1071 return mResourceManager->getProgram(mState.currentProgram); 1072 } 1073 1074 Texture2D *Context::getTexture2D() 1075 { 1076 return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, SAMPLER_2D)); 1077 } 1078 1079 TextureCubeMap *Context::getTextureCubeMap() 1080 { 1081 return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, SAMPLER_CUBE)); 1082 } 1083 1084 Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type) 1085 { 1086 GLuint texid = mState.samplerTexture[type][sampler].id(); 1087 1088 if (texid == 0) // Special case: 0 refers to different initial textures based on the target 1089 { 1090 switch (type) 1091 { 1092 default: UNREACHABLE(); 1093 case SAMPLER_2D: return mTexture2DZero.get(); 1094 case SAMPLER_CUBE: return mTextureCubeMapZero.get(); 1095 } 1096 } 1097 1098 return mState.samplerTexture[type][sampler].get(); 1099 } 1100 1101 bool Context::getBooleanv(GLenum pname, GLboolean *params) 1102 { 1103 switch (pname) 1104 { 1105 case GL_SHADER_COMPILER: *params = GL_TRUE; break; 1106 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; 1107 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break; 1108 case GL_COLOR_WRITEMASK: 1109 params[0] = mState.colorMaskRed; 1110 params[1] = mState.colorMaskGreen; 1111 params[2] = mState.colorMaskBlue; 1112 params[3] = mState.colorMaskAlpha; 1113 break; 1114 case GL_CULL_FACE: *params = mState.cullFace; break; 1115 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break; 1116 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break; 1117 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; 1118 case GL_SCISSOR_TEST: *params = mState.scissorTest; break; 1119 case GL_STENCIL_TEST: *params = mState.stencilTest; break; 1120 case GL_DEPTH_TEST: *params = mState.depthTest; break; 1121 case GL_BLEND: *params = mState.blend; break; 1122 case GL_DITHER: *params = mState.dither; break; 1123 default: 1124 return false; 1125 } 1126 1127 return true; 1128 } 1129 1130 bool Context::getFloatv(GLenum pname, GLfloat *params) 1131 { 1132 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation 1133 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names 1134 // GetIntegerv as its native query function. As it would require conversion in any 1135 // case, this should make no difference to the calling application. 1136 switch (pname) 1137 { 1138 case GL_LINE_WIDTH: *params = mState.lineWidth; break; 1139 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; 1140 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; 1141 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break; 1142 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break; 1143 case GL_ALIASED_LINE_WIDTH_RANGE: 1144 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN; 1145 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX; 1146 break; 1147 case GL_ALIASED_POINT_SIZE_RANGE: 1148 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN; 1149 params[1] = supportsShaderModel3() ? gl::ALIASED_POINT_SIZE_RANGE_MAX_SM3 : gl::ALIASED_POINT_SIZE_RANGE_MAX_SM2; 1150 break; 1151 case GL_DEPTH_RANGE: 1152 params[0] = mState.zNear; 1153 params[1] = mState.zFar; 1154 break; 1155 case GL_COLOR_CLEAR_VALUE: 1156 params[0] = mState.colorClearValue.red; 1157 params[1] = mState.colorClearValue.green; 1158 params[2] = mState.colorClearValue.blue; 1159 params[3] = mState.colorClearValue.alpha; 1160 break; 1161 case GL_BLEND_COLOR: 1162 params[0] = mState.blendColor.red; 1163 params[1] = mState.blendColor.green; 1164 params[2] = mState.blendColor.blue; 1165 params[3] = mState.blendColor.alpha; 1166 break; 1167 default: 1168 return false; 1169 } 1170 1171 return true; 1172 } 1173 1174 bool Context::getIntegerv(GLenum pname, GLint *params) 1175 { 1176 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation 1177 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names 1178 // GetIntegerv as its native query function. As it would require conversion in any 1179 // case, this should make no difference to the calling application. You may find it in 1180 // Context::getFloatv. 1181 switch (pname) 1182 { 1183 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; 1184 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break; 1185 case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break; 1186 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break; 1187 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break; 1188 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; 1189 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break; 1190 case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break; 1191 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break; 1192 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break; 1193 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break; 1194 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break; 1195 //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 1196 case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break; 1197 case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break; 1198 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break; 1199 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break; 1200 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break; 1201 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break; 1202 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break; 1203 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break; 1204 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break; 1205 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break; 1206 case GL_STENCIL_REF: *params = mState.stencilRef; break; 1207 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break; 1208 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break; 1209 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break; 1210 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break; 1211 case GL_STENCIL_FAIL: *params = mState.stencilFail; break; 1212 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break; 1213 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break; 1214 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break; 1215 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break; 1216 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break; 1217 case GL_DEPTH_FUNC: *params = mState.depthFunc; break; 1218 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break; 1219 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break; 1220 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break; 1221 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break; 1222 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break; 1223 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break; 1224 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break; 1225 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break; 1226 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; 1227 case GL_SUBPIXEL_BITS: *params = 4; break; 1228 case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break; 1229 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break; 1230 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: 1231 { 1232 if (supportsCompressedTextures()) 1233 { 1234 // at current, only GL_COMPRESSED_RGB_S3TC_DXT1_EXT and 1235 // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT are supported 1236 *params = 2; 1237 } 1238 else 1239 { 1240 *params = 0; 1241 } 1242 } 1243 break; 1244 case GL_MAX_SAMPLES_ANGLE: 1245 { 1246 GLsizei maxSamples = getMaxSupportedSamples(); 1247 if (maxSamples != 0) 1248 { 1249 *params = maxSamples; 1250 } 1251 else 1252 { 1253 return false; 1254 } 1255 1256 break; 1257 } 1258 case GL_SAMPLE_BUFFERS: 1259 case GL_SAMPLES: 1260 { 1261 gl::Framebuffer *framebuffer = getDrawFramebuffer(); 1262 if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) 1263 { 1264 switch (pname) 1265 { 1266 case GL_SAMPLE_BUFFERS: 1267 if (framebuffer->getSamples() != 0) 1268 { 1269 *params = 1; 1270 } 1271 else 1272 { 1273 *params = 0; 1274 } 1275 break; 1276 case GL_SAMPLES: 1277 *params = framebuffer->getSamples(); 1278 break; 1279 } 1280 } 1281 else 1282 { 1283 *params = 0; 1284 } 1285 } 1286 break; 1287 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break; 1288 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break; 1289 case GL_MAX_VIEWPORT_DIMS: 1290 { 1291 int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension()); 1292 params[0] = maxDimension; 1293 params[1] = maxDimension; 1294 } 1295 break; 1296 case GL_COMPRESSED_TEXTURE_FORMATS: 1297 { 1298 if (supportsCompressedTextures()) 1299 { 1300 params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; 1301 params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; 1302 } 1303 } 1304 break; 1305 case GL_VIEWPORT: 1306 params[0] = mState.viewportX; 1307 params[1] = mState.viewportY; 1308 params[2] = mState.viewportWidth; 1309 params[3] = mState.viewportHeight; 1310 break; 1311 case GL_SCISSOR_BOX: 1312 params[0] = mState.scissorX; 1313 params[1] = mState.scissorY; 1314 params[2] = mState.scissorWidth; 1315 params[3] = mState.scissorHeight; 1316 break; 1317 case GL_CULL_FACE_MODE: *params = mState.cullMode; break; 1318 case GL_FRONT_FACE: *params = mState.frontFace; break; 1319 case GL_RED_BITS: 1320 case GL_GREEN_BITS: 1321 case GL_BLUE_BITS: 1322 case GL_ALPHA_BITS: 1323 { 1324 gl::Framebuffer *framebuffer = getDrawFramebuffer(); 1325 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer(); 1326 1327 if (colorbuffer) 1328 { 1329 switch (pname) 1330 { 1331 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; 1332 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; 1333 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; 1334 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; 1335 } 1336 } 1337 else 1338 { 1339 *params = 0; 1340 } 1341 } 1342 break; 1343 case GL_DEPTH_BITS: 1344 { 1345 gl::Framebuffer *framebuffer = getDrawFramebuffer(); 1346 gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer(); 1347 1348 if (depthbuffer) 1349 { 1350 *params = depthbuffer->getDepthSize(); 1351 } 1352 else 1353 { 1354 *params = 0; 1355 } 1356 } 1357 break; 1358 case GL_STENCIL_BITS: 1359 { 1360 gl::Framebuffer *framebuffer = getDrawFramebuffer(); 1361 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer(); 1362 1363 if (stencilbuffer) 1364 { 1365 *params = stencilbuffer->getStencilSize(); 1366 } 1367 else 1368 { 1369 *params = 0; 1370 } 1371 } 1372 break; 1373 case GL_TEXTURE_BINDING_2D: 1374 { 1375 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1) 1376 { 1377 error(GL_INVALID_OPERATION); 1378 return false; 1379 } 1380 1381 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler].id(); 1382 } 1383 break; 1384 case GL_TEXTURE_BINDING_CUBE_MAP: 1385 { 1386 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1) 1387 { 1388 error(GL_INVALID_OPERATION); 1389 return false; 1390 } 1391 1392 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].id(); 1393 } 1394 break; 1395 default: 1396 return false; 1397 } 1398 1399 return true; 1400 } 1401 1402 bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) 1403 { 1404 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation 1405 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due 1406 // to the fact that it is stored internally as a float, and so would require conversion 1407 // if returned from Context::getIntegerv. Since this conversion is already implemented 1408 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we 1409 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling 1410 // application. 1411 switch (pname) 1412 { 1413 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ 1414 case GL_SHADER_BINARY_FORMATS: 1415 { 1416 *type = GL_INT; 1417 *numParams = 0; 1418 } 1419 break; 1420 case GL_MAX_VERTEX_ATTRIBS: 1421 case GL_MAX_VERTEX_UNIFORM_VECTORS: 1422 case GL_MAX_VARYING_VECTORS: 1423 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: 1424 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: 1425 case GL_MAX_TEXTURE_IMAGE_UNITS: 1426 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: 1427 case GL_MAX_RENDERBUFFER_SIZE: 1428 case GL_NUM_SHADER_BINARY_FORMATS: 1429 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: 1430 case GL_ARRAY_BUFFER_BINDING: 1431 case GL_FRAMEBUFFER_BINDING: 1432 case GL_RENDERBUFFER_BINDING: 1433 case GL_CURRENT_PROGRAM: 1434 case GL_PACK_ALIGNMENT: 1435 case GL_UNPACK_ALIGNMENT: 1436 case GL_GENERATE_MIPMAP_HINT: 1437 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: 1438 case GL_RED_BITS: 1439 case GL_GREEN_BITS: 1440 case GL_BLUE_BITS: 1441 case GL_ALPHA_BITS: 1442 case GL_DEPTH_BITS: 1443 case GL_STENCIL_BITS: 1444 case GL_ELEMENT_ARRAY_BUFFER_BINDING: 1445 case GL_CULL_FACE_MODE: 1446 case GL_FRONT_FACE: 1447 case GL_ACTIVE_TEXTURE: 1448 case GL_STENCIL_FUNC: 1449 case GL_STENCIL_VALUE_MASK: 1450 case GL_STENCIL_REF: 1451 case GL_STENCIL_FAIL: 1452 case GL_STENCIL_PASS_DEPTH_FAIL: 1453 case GL_STENCIL_PASS_DEPTH_PASS: 1454 case GL_STENCIL_BACK_FUNC: 1455 case GL_STENCIL_BACK_VALUE_MASK: 1456 case GL_STENCIL_BACK_REF: 1457 case GL_STENCIL_BACK_FAIL: 1458 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: 1459 case GL_STENCIL_BACK_PASS_DEPTH_PASS: 1460 case GL_DEPTH_FUNC: 1461 case GL_BLEND_SRC_RGB: 1462 case GL_BLEND_SRC_ALPHA: 1463 case GL_BLEND_DST_RGB: 1464 case GL_BLEND_DST_ALPHA: 1465 case GL_BLEND_EQUATION_RGB: 1466 case GL_BLEND_EQUATION_ALPHA: 1467 case GL_STENCIL_WRITEMASK: 1468 case GL_STENCIL_BACK_WRITEMASK: 1469 case GL_STENCIL_CLEAR_VALUE: 1470 case GL_SUBPIXEL_BITS: 1471 case GL_MAX_TEXTURE_SIZE: 1472 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: 1473 case GL_SAMPLE_BUFFERS: 1474 case GL_SAMPLES: 1475 case GL_IMPLEMENTATION_COLOR_READ_TYPE: 1476 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: 1477 case GL_TEXTURE_BINDING_2D: 1478 case GL_TEXTURE_BINDING_CUBE_MAP: 1479 { 1480 *type = GL_INT; 1481 *numParams = 1; 1482 } 1483 break; 1484 case GL_MAX_SAMPLES_ANGLE: 1485 { 1486 if (getMaxSupportedSamples() != 0) 1487 { 1488 *type = GL_INT; 1489 *numParams = 1; 1490 } 1491 else 1492 { 1493 return false; 1494 } 1495 } 1496 break; 1497 case GL_MAX_VIEWPORT_DIMS: 1498 { 1499 *type = GL_INT; 1500 *numParams = 2; 1501 } 1502 break; 1503 case GL_VIEWPORT: 1504 case GL_SCISSOR_BOX: 1505 { 1506 *type = GL_INT; 1507 *numParams = 4; 1508 } 1509 break; 1510 case GL_SHADER_COMPILER: 1511 case GL_SAMPLE_COVERAGE_INVERT: 1512 case GL_DEPTH_WRITEMASK: 1513 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled, 1514 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries. 1515 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural 1516 case GL_SAMPLE_COVERAGE: 1517 case GL_SCISSOR_TEST: 1518 case GL_STENCIL_TEST: 1519 case GL_DEPTH_TEST: 1520 case GL_BLEND: 1521 case GL_DITHER: 1522 { 1523 *type = GL_BOOL; 1524 *numParams = 1; 1525 } 1526 break; 1527 case GL_COLOR_WRITEMASK: 1528 { 1529 *type = GL_BOOL; 1530 *numParams = 4; 1531 } 1532 break; 1533 case GL_POLYGON_OFFSET_FACTOR: 1534 case GL_POLYGON_OFFSET_UNITS: 1535 case GL_SAMPLE_COVERAGE_VALUE: 1536 case GL_DEPTH_CLEAR_VALUE: 1537 case GL_LINE_WIDTH: 1538 { 1539 *type = GL_FLOAT; 1540 *numParams = 1; 1541 } 1542 break; 1543 case GL_ALIASED_LINE_WIDTH_RANGE: 1544 case GL_ALIASED_POINT_SIZE_RANGE: 1545 case GL_DEPTH_RANGE: 1546 { 1547 *type = GL_FLOAT; 1548 *numParams = 2; 1549 } 1550 break; 1551 case GL_COLOR_CLEAR_VALUE: 1552 case GL_BLEND_COLOR: 1553 { 1554 *type = GL_FLOAT; 1555 *numParams = 4; 1556 } 1557 break; 1558 default: 1559 return false; 1560 } 1561 1562 return true; 1563 } 1564 1565 // Applies the render target surface, depth stencil surface, viewport rectangle and 1566 // scissor rectangle to the Direct3D 9 device 1567 bool Context::applyRenderTarget(bool ignoreViewport) 1568 { 1569 IDirect3DDevice9 *device = getDevice(); 1570 1571 Framebuffer *framebufferObject = getDrawFramebuffer(); 1572 1573 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) 1574 { 1575 error(GL_INVALID_FRAMEBUFFER_OPERATION); 1576 1577 return false; 1578 } 1579 1580 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); 1581 1582 if (!renderTarget) 1583 { 1584 return false; // Context must be lost 1585 } 1586 1587 IDirect3DSurface9 *depthStencil = NULL; 1588 1589 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial(); 1590 if (renderTargetSerial != mAppliedRenderTargetSerial) 1591 { 1592 device->SetRenderTarget(0, renderTarget); 1593 mAppliedRenderTargetSerial = renderTargetSerial; 1594 mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets. 1595 } 1596 1597 unsigned int depthbufferSerial = 0; 1598 unsigned int stencilbufferSerial = 0; 1599 if (framebufferObject->getDepthbufferType() != GL_NONE) 1600 { 1601 depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil(); 1602 if (!depthStencil) 1603 { 1604 ERR("Depth stencil pointer unexpectedly null."); 1605 return false; 1606 } 1607 1608 depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial(); 1609 } 1610 else if (framebufferObject->getStencilbufferType() != GL_NONE) 1611 { 1612 depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); 1613 if (!depthStencil) 1614 { 1615 ERR("Depth stencil pointer unexpectedly null."); 1616 return false; 1617 } 1618 1619 stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial(); 1620 } 1621 1622 if (depthbufferSerial != mAppliedDepthbufferSerial || 1623 stencilbufferSerial != mAppliedStencilbufferSerial || 1624 !mDepthStencilInitialized) 1625 { 1626 device->SetDepthStencilSurface(depthStencil); 1627 mAppliedDepthbufferSerial = depthbufferSerial; 1628 mAppliedStencilbufferSerial = stencilbufferSerial; 1629 mDepthStencilInitialized = true; 1630 } 1631 1632 D3DVIEWPORT9 viewport; 1633 D3DSURFACE_DESC desc; 1634 renderTarget->GetDesc(&desc); 1635 1636 float zNear = clamp01(mState.zNear); 1637 float zFar = clamp01(mState.zFar); 1638 1639 if (ignoreViewport) 1640 { 1641 viewport.X = 0; 1642 viewport.Y = 0; 1643 viewport.Width = desc.Width; 1644 viewport.Height = desc.Height; 1645 viewport.MinZ = 0.0f; 1646 viewport.MaxZ = 1.0f; 1647 } 1648 else 1649 { 1650 viewport.X = std::max(mState.viewportX, 0); 1651 viewport.Y = std::max(mState.viewportY, 0); 1652 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X); 1653 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y); 1654 viewport.MinZ = zNear; 1655 viewport.MaxZ = zFar; 1656 } 1657 1658 if (viewport.Width <= 0 || viewport.Height <= 0) 1659 { 1660 return false; // Nothing to render 1661 } 1662 1663 device->SetViewport(&viewport); 1664 1665 if (mScissorStateDirty) 1666 { 1667 if (mState.scissorTest) 1668 { 1669 RECT rect = {mState.scissorX, 1670 mState.scissorY, 1671 mState.scissorX + mState.scissorWidth, 1672 mState.scissorY + mState.scissorHeight}; 1673 rect.right = std::min(static_cast<UINT>(rect.right), desc.Width); 1674 rect.bottom = std::min(static_cast<UINT>(rect.bottom), desc.Height); 1675 device->SetScissorRect(&rect); 1676 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 1677 } 1678 else 1679 { 1680 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); 1681 } 1682 1683 mScissorStateDirty = false; 1684 } 1685 1686 if (mState.currentProgram) 1687 { 1688 Program *programObject = getCurrentProgram(); 1689 1690 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation(); 1691 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height}; 1692 programObject->setUniform2fv(halfPixelSize, 1, xy); 1693 1694 GLint viewport = programObject->getDxViewportLocation(); 1695 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f, 1696 (float)mState.viewportX + mState.viewportWidth / 2.0f, 1697 (float)mState.viewportY + mState.viewportHeight / 2.0f}; 1698 programObject->setUniform4fv(viewport, 1, whxy); 1699 1700 GLint depth = programObject->getDxDepthLocation(); 1701 GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f}; 1702 programObject->setUniform2fv(depth, 1, dz); 1703 1704 GLint depthRange = programObject->getDxDepthRangeLocation(); 1705 GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear}; 1706 programObject->setUniform3fv(depthRange, 1, nearFarDiff); 1707 } 1708 1709 return true; 1710 } 1711 1712 // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device 1713 void Context::applyState(GLenum drawMode) 1714 { 1715 IDirect3DDevice9 *device = getDevice(); 1716 Program *programObject = getCurrentProgram(); 1717 1718 GLint frontCCW = programObject->getDxFrontCCWLocation(); 1719 GLint ccw = (mState.frontFace == GL_CCW); 1720 programObject->setUniform1iv(frontCCW, 1, &ccw); 1721 1722 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation(); 1723 GLint alwaysFront = !isTriangleMode(drawMode); 1724 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront); 1725 1726 Framebuffer *framebufferObject = getDrawFramebuffer(); 1727 1728 if (mCullStateDirty || mFrontFaceDirty) 1729 { 1730 if (mState.cullFace) 1731 { 1732 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace)); 1733 } 1734 else 1735 { 1736 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 1737 } 1738 1739 mCullStateDirty = false; 1740 } 1741 1742 if (mDepthStateDirty) 1743 { 1744 if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE) 1745 { 1746 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); 1747 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc)); 1748 } 1749 else 1750 { 1751 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 1752 } 1753 1754 mDepthStateDirty = false; 1755 } 1756 1757 if (mBlendStateDirty) 1758 { 1759 if (mState.blend) 1760 { 1761 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 1762 1763 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && 1764 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) 1765 { 1766 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor)); 1767 } 1768 else 1769 { 1770 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha), 1771 unorm<8>(mState.blendColor.alpha), 1772 unorm<8>(mState.blendColor.alpha), 1773 unorm<8>(mState.blendColor.alpha))); 1774 } 1775 1776 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB)); 1777 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB)); 1778 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB)); 1779 1780 if (mState.sourceBlendRGB != mState.sourceBlendAlpha || 1781 mState.destBlendRGB != mState.destBlendAlpha || 1782 mState.blendEquationRGB != mState.blendEquationAlpha) 1783 { 1784 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 1785 1786 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha)); 1787 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha)); 1788 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha)); 1789 1790 } 1791 else 1792 { 1793 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); 1794 } 1795 } 1796 else 1797 { 1798 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 1799 } 1800 1801 mBlendStateDirty = false; 1802 } 1803 1804 if (mStencilStateDirty || mFrontFaceDirty) 1805 { 1806 if (mState.stencilTest && framebufferObject->hasStencil()) 1807 { 1808 device->SetRenderState(D3DRS_STENCILENABLE, TRUE); 1809 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); 1810 1811 // FIXME: Unsupported by D3D9 1812 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; 1813 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; 1814 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; 1815 if (mState.stencilWritemask != mState.stencilBackWritemask || 1816 mState.stencilRef != mState.stencilBackRef || 1817 mState.stencilMask != mState.stencilBackMask) 1818 { 1819 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); 1820 return error(GL_INVALID_OPERATION); 1821 } 1822 1823 // get the maximum size of the stencil ref 1824 gl::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer(); 1825 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1; 1826 1827 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask); 1828 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 1829 es2dx::ConvertComparison(mState.stencilFunc)); 1830 1831 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); 1832 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask); 1833 1834 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 1835 es2dx::ConvertStencilOp(mState.stencilFail)); 1836 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 1837 es2dx::ConvertStencilOp(mState.stencilPassDepthFail)); 1838 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 1839 es2dx::ConvertStencilOp(mState.stencilPassDepthPass)); 1840 1841 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask); 1842 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 1843 es2dx::ConvertComparison(mState.stencilBackFunc)); 1844 1845 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil); 1846 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask); 1847 1848 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 1849 es2dx::ConvertStencilOp(mState.stencilBackFail)); 1850 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 1851 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail)); 1852 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 1853 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass)); 1854 } 1855 else 1856 { 1857 device->SetRenderState(D3DRS_STENCILENABLE, FALSE); 1858 } 1859 1860 mStencilStateDirty = false; 1861 } 1862 1863 if (mMaskStateDirty) 1864 { 1865 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, 1866 mState.colorMaskBlue, mState.colorMaskAlpha)); 1867 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE); 1868 1869 mMaskStateDirty = false; 1870 } 1871 1872 if (mPolygonOffsetStateDirty) 1873 { 1874 if (mState.polygonOffsetFill) 1875 { 1876 gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer(); 1877 if (depthbuffer) 1878 { 1879 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor)); 1880 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize())); 1881 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias)); 1882 } 1883 } 1884 else 1885 { 1886 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); 1887 device->SetRenderState(D3DRS_DEPTHBIAS, 0); 1888 } 1889 1890 mPolygonOffsetStateDirty = false; 1891 } 1892 1893 if (mSampleStateDirty) 1894 { 1895 if (framebufferObject->isMultisample()) 1896 { 1897 if (mState.sampleAlphaToCoverage) 1898 { 1899 FIXME("Sample alpha to coverage is unimplemented."); 1900 } 1901 1902 device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); 1903 if (mState.sampleCoverage) 1904 { 1905 unsigned int mask = 0; 1906 if (mState.sampleCoverageValue != 0) 1907 { 1908 float threshold = 0.5f; 1909 1910 for (int i = 0; i < framebufferObject->getSamples(); ++i) 1911 { 1912 mask <<= 1; 1913 1914 if ((i + 1) * mState.sampleCoverageValue >= threshold) 1915 { 1916 threshold += 1.0f; 1917 mask |= 1; 1918 } 1919 } 1920 } 1921 1922 if (mState.sampleCoverageInvert) 1923 { 1924 mask = ~mask; 1925 } 1926 1927 device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask); 1928 } 1929 else 1930 { 1931 device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); 1932 } 1933 } 1934 else 1935 { 1936 device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE); 1937 } 1938 1939 mSampleStateDirty = false; 1940 } 1941 1942 if (mDitherStateDirty) 1943 { 1944 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE); 1945 1946 mDitherStateDirty = false; 1947 } 1948 1949 mFrontFaceDirty = false; 1950 } 1951 1952 // Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program. 1953 void Context::lookupAttributeMapping(TranslatedAttribute *attributes) 1954 { 1955 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) 1956 { 1957 if (attributes[i].active) 1958 { 1959 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i); 1960 } 1961 } 1962 } 1963 1964 GLenum Context::applyVertexBuffer(GLint first, GLsizei count) 1965 { 1966 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS]; 1967 1968 GLenum err = mVertexDataManager->prepareVertexData(first, count, translated); 1969 if (err != GL_NO_ERROR) 1970 { 1971 return err; 1972 } 1973 1974 lookupAttributeMapping(translated); 1975 1976 mVertexDataManager->setupAttributes(translated); 1977 1978 return GL_NO_ERROR; 1979 } 1980 1981 // Applies the indices and element array bindings to the Direct3D 9 device 1982 GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) 1983 { 1984 IDirect3DDevice9 *device = getDevice(); 1985 GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo); 1986 1987 if (err == GL_NO_ERROR) 1988 { 1989 device->SetIndices(indexInfo->indexBuffer); 1990 } 1991 1992 return err; 1993 } 1994 1995 // Applies the shaders and shader constants to the Direct3D 9 device 1996 void Context::applyShaders() 1997 { 1998 IDirect3DDevice9 *device = getDevice(); 1999 Program *programObject = getCurrentProgram(); 2000 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader(); 2001 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader(); 2002 2003 device->SetVertexShader(vertexShader); 2004 device->SetPixelShader(pixelShader); 2005 2006 if (programObject->getSerial() != mAppliedProgram) 2007 { 2008 programObject->dirtyAllUniforms(); 2009 programObject->dirtyAllSamplers(); 2010 mAppliedProgram = programObject->getSerial(); 2011 } 2012 2013 programObject->applyUniforms(); 2014 } 2015 2016 // Applies the textures and sampler states to the Direct3D 9 device 2017 void Context::applyTextures() 2018 { 2019 IDirect3DDevice9 *device = getDevice(); 2020 Program *programObject = getCurrentProgram(); 2021 2022 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++) 2023 { 2024 int textureUnit = programObject->getSamplerMapping(sampler); 2025 if (textureUnit != -1) 2026 { 2027 SamplerType textureType = programObject->getSamplerType(sampler); 2028 2029 Texture *texture = getSamplerTexture(textureUnit, textureType); 2030 2031 if (programObject->isSamplerDirty(sampler) || texture->isDirty()) 2032 { 2033 if (texture->isComplete()) 2034 { 2035 GLenum wrapS = texture->getWrapS(); 2036 GLenum wrapT = texture->getWrapT(); 2037 GLenum minFilter = texture->getMinFilter(); 2038 GLenum magFilter = texture->getMagFilter(); 2039 2040 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS)); 2041 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT)); 2042 2043 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter)); 2044 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; 2045 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter); 2046 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter); 2047 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter); 2048 2049 device->SetTexture(sampler, texture->getTexture()); 2050 } 2051 else 2052 { 2053 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture()); 2054 } 2055 } 2056 2057 programObject->setSamplerDirty(sampler, false); 2058 } 2059 else 2060 { 2061 if (programObject->isSamplerDirty(sampler)) 2062 { 2063 device->SetTexture(sampler, NULL); 2064 programObject->setSamplerDirty(sampler, false); 2065 } 2066 } 2067 } 2068 } 2069 2070 void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) 2071 { 2072 Framebuffer *framebuffer = getReadFramebuffer(); 2073 2074 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) 2075 { 2076 return error(GL_INVALID_FRAMEBUFFER_OPERATION); 2077 } 2078 2079 if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) 2080 { 2081 return error(GL_INVALID_OPERATION); 2082 } 2083 2084 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget(); 2085 2086 if (!renderTarget) 2087 { 2088 return; // Context must be lost, return silently 2089 } 2090 2091 IDirect3DDevice9 *device = getDevice(); 2092 2093 D3DSURFACE_DESC desc; 2094 renderTarget->GetDesc(&desc); 2095 2096 IDirect3DSurface9 *systemSurface; 2097 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL); 2098 2099 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) 2100 { 2101 return error(GL_OUT_OF_MEMORY); 2102 } 2103 2104 ASSERT(SUCCEEDED(result)); 2105 2106 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) 2107 { 2108 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target 2109 } 2110 2111 result = device->GetRenderTargetData(renderTarget, systemSurface); 2112 2113 if (FAILED(result)) 2114 { 2115 systemSurface->Release(); 2116 2117 switch (result) 2118 { 2119 case D3DERR_DRIVERINTERNALERROR: 2120 case D3DERR_DEVICELOST: 2121 return error(GL_OUT_OF_MEMORY); 2122 default: 2123 UNREACHABLE(); 2124 return; // No sensible error to generate 2125 } 2126 } 2127 2128 D3DLOCKED_RECT lock; 2129 RECT rect = {std::max(x, 0), 2130 std::max(y, 0), 2131 std::min(x + width, (int)desc.Width), 2132 std::min(y + height, (int)desc.Height)}; 2133 2134 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); 2135 2136 if (FAILED(result)) 2137 { 2138 UNREACHABLE(); 2139 systemSurface->Release(); 2140 2141 return; // No sensible error to generate 2142 } 2143 2144 unsigned char *source = (unsigned char*)lock.pBits; 2145 unsigned char *dest = (unsigned char*)pixels; 2146 unsigned short *dest16 = (unsigned short*)pixels; 2147 2148 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment); 2149 2150 for (int j = 0; j < rect.bottom - rect.top; j++) 2151 { 2152 if (desc.Format == D3DFMT_A8R8G8B8 && 2153 format == GL_BGRA_EXT && 2154 type == GL_UNSIGNED_BYTE) 2155 { 2156 // Fast path for EXT_read_format_bgra, given 2157 // an RGBA source buffer. Note that buffers with no 2158 // alpha go through the slow path below. 2159 memcpy(dest + j * outputPitch, 2160 source + j * lock.Pitch, 2161 (rect.right - rect.left) * 4); 2162 continue; 2163 } 2164 2165 for (int i = 0; i < rect.right - rect.left; i++) 2166 { 2167 float r; 2168 float g; 2169 float b; 2170 float a; 2171 2172 switch (desc.Format) 2173 { 2174 case D3DFMT_R5G6B5: 2175 { 2176 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch); 2177 2178 a = 1.0f; 2179 b = (rgb & 0x001F) * (1.0f / 0x001F); 2180 g = (rgb & 0x07E0) * (1.0f / 0x07E0); 2181 r = (rgb & 0xF800) * (1.0f / 0xF800); 2182 } 2183 break; 2184 case D3DFMT_A1R5G5B5: 2185 { 2186 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch); 2187 2188 a = (argb & 0x8000) ? 1.0f : 0.0f; 2189 b = (argb & 0x001F) * (1.0f / 0x001F); 2190 g = (argb & 0x03E0) * (1.0f / 0x03E0); 2191 r = (argb & 0x7C00) * (1.0f / 0x7C00); 2192 } 2193 break; 2194 case D3DFMT_A8R8G8B8: 2195 { 2196 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch); 2197 2198 a = (argb & 0xFF000000) * (1.0f / 0xFF000000); 2199 b = (argb & 0x000000FF) * (1.0f / 0x000000FF); 2200 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); 2201 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); 2202 } 2203 break; 2204 case D3DFMT_X8R8G8B8: 2205 { 2206 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch); 2207 2208 a = 1.0f; 2209 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); 2210 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); 2211 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); 2212 } 2213 break; 2214 case D3DFMT_A2R10G10B10: 2215 { 2216 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch); 2217 2218 a = (argb & 0xC0000000) * (1.0f / 0xC0000000); 2219 b = (argb & 0x000003FF) * (1.0f / 0x000003FF); 2220 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); 2221 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); 2222 } 2223 break; 2224 case D3DFMT_A32B32G32R32F: 2225 { 2226 // float formats in D3D are stored rgba, rather than the other way round 2227 r = *((float*)(source + 16 * i + j * lock.Pitch) + 0); 2228 g = *((float*)(source + 16 * i + j * lock.Pitch) + 1); 2229 b = *((float*)(source + 16 * i + j * lock.Pitch) + 2); 2230 a = *((float*)(source + 16 * i + j * lock.Pitch) + 3); 2231 } 2232 break; 2233 case D3DFMT_A16B16G16R16F: 2234 { 2235 // float formats in D3D are stored rgba, rather than the other way round 2236 float abgr[4]; 2237 2238 D3DXFloat16To32Array(abgr, (D3DXFLOAT16*)(source + 8 * i + j * lock.Pitch), 4); 2239 2240 a = abgr[3]; 2241 b = abgr[2]; 2242 g = abgr[1]; 2243 r = abgr[0]; 2244 } 2245 break; 2246 default: 2247 UNIMPLEMENTED(); // FIXME 2248 UNREACHABLE(); 2249 } 2250 2251 switch (format) 2252 { 2253 case GL_RGBA: 2254 switch (type) 2255 { 2256 case GL_UNSIGNED_BYTE: 2257 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); 2258 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); 2259 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); 2260 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); 2261 break; 2262 default: UNREACHABLE(); 2263 } 2264 break; 2265 case GL_BGRA_EXT: 2266 switch (type) 2267 { 2268 case GL_UNSIGNED_BYTE: 2269 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); 2270 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); 2271 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); 2272 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); 2273 break; 2274 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: 2275 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section 2276 // this type is packed as follows: 2277 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 2278 // -------------------------------------------------------------------------------- 2279 // | 4th | 3rd | 2nd | 1st component | 2280 // -------------------------------------------------------------------------------- 2281 // in the case of BGRA_EXT, B is the first component, G the second, and so forth. 2282 dest16[i + j * outputPitch / sizeof(unsigned short)] = 2283 ((unsigned short)(15 * a + 0.5f) << 12)| 2284 ((unsigned short)(15 * r + 0.5f) << 8) | 2285 ((unsigned short)(15 * g + 0.5f) << 4) | 2286 ((unsigned short)(15 * b + 0.5f) << 0); 2287 break; 2288 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: 2289 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section 2290 // this type is packed as follows: 2291 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 2292 // -------------------------------------------------------------------------------- 2293 // | 4th | 3rd | 2nd | 1st component | 2294 // -------------------------------------------------------------------------------- 2295 // in the case of BGRA_EXT, B is the first component, G the second, and so forth. 2296 dest16[i + j * outputPitch / sizeof(unsigned short)] = 2297 ((unsigned short)( a + 0.5f) << 15) | 2298 ((unsigned short)(31 * r + 0.5f) << 10) | 2299 ((unsigned short)(31 * g + 0.5f) << 5) | 2300 ((unsigned short)(31 * b + 0.5f) << 0); 2301 break; 2302 default: UNREACHABLE(); 2303 } 2304 break; 2305 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT 2306 switch (type) 2307 { 2308 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE 2309 dest16[i + j * outputPitch / sizeof(unsigned short)] = 2310 ((unsigned short)(31 * b + 0.5f) << 0) | 2311 ((unsigned short)(63 * g + 0.5f) << 5) | 2312 ((unsigned short)(31 * r + 0.5f) << 11); 2313 break; 2314 default: UNREACHABLE(); 2315 } 2316 break; 2317 default: UNREACHABLE(); 2318 } 2319 } 2320 } 2321 2322 systemSurface->UnlockRect(); 2323 2324 systemSurface->Release(); 2325 } 2326 2327 void Context::clear(GLbitfield mask) 2328 { 2329 Framebuffer *framebufferObject = getDrawFramebuffer(); 2330 2331 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) 2332 { 2333 error(GL_INVALID_FRAMEBUFFER_OPERATION); 2334 2335 return; 2336 } 2337 2338 egl::Display *display = getDisplay(); 2339 IDirect3DDevice9 *device = getDevice(); 2340 DWORD flags = 0; 2341 2342 if (mask & GL_COLOR_BUFFER_BIT) 2343 { 2344 mask &= ~GL_COLOR_BUFFER_BIT; 2345 2346 if (framebufferObject->getColorbufferType() != GL_NONE) 2347 { 2348 flags |= D3DCLEAR_TARGET; 2349 } 2350 } 2351 2352 if (mask & GL_DEPTH_BUFFER_BIT) 2353 { 2354 mask &= ~GL_DEPTH_BUFFER_BIT; 2355 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE) 2356 { 2357 flags |= D3DCLEAR_ZBUFFER; 2358 } 2359 } 2360 2361 GLuint stencilUnmasked = 0x0; 2362 2363 if (mask & GL_STENCIL_BUFFER_BIT) 2364 { 2365 mask &= ~GL_STENCIL_BUFFER_BIT; 2366 if (framebufferObject->getStencilbufferType() != GL_NONE) 2367 { 2368 IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); 2369 if (!depthStencil) 2370 { 2371 ERR("Depth stencil pointer unexpectedly null."); 2372 return; 2373 } 2374 2375 D3DSURFACE_DESC desc; 2376 depthStencil->GetDesc(&desc); 2377 2378 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format); 2379 stencilUnmasked = (0x1 << stencilSize) - 1; 2380 2381 if (stencilUnmasked != 0x0) 2382 { 2383 flags |= D3DCLEAR_STENCIL; 2384 } 2385 } 2386 } 2387 2388 if (mask != 0) 2389 { 2390 return error(GL_INVALID_VALUE); 2391 } 2392 2393 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport 2394 { 2395 return; 2396 } 2397 2398 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha), 2399 unorm<8>(mState.colorClearValue.red), 2400 unorm<8>(mState.colorClearValue.green), 2401 unorm<8>(mState.colorClearValue.blue)); 2402 float depth = clamp01(mState.depthClearValue); 2403 int stencil = mState.stencilClearValue & 0x000000FF; 2404 2405 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); 2406 2407 if (!renderTarget) 2408 { 2409 return; // Context must be lost, return silently 2410 } 2411 2412 D3DSURFACE_DESC desc; 2413 renderTarget->GetDesc(&desc); 2414 2415 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha; 2416 2417 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) && 2418 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked; 2419 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) && 2420 !(mState.colorMaskRed && mState.colorMaskGreen && 2421 mState.colorMaskBlue && alphaUnmasked); 2422 2423 if (needMaskedColorClear || needMaskedStencilClear) 2424 { 2425 // State which is altered in all paths from this point to the clear call is saved. 2426 // State which is altered in only some paths will be flagged dirty in the case that 2427 // that path is taken. 2428 HRESULT hr; 2429 if (mMaskedClearSavedState == NULL) 2430 { 2431 hr = device->BeginStateBlock(); 2432 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); 2433 2434 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); 2435 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); 2436 device->SetRenderState(D3DRS_ZENABLE, FALSE); 2437 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 2438 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); 2439 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 2440 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 2441 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); 2442 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0); 2443 device->SetRenderState(D3DRS_STENCILENABLE, FALSE); 2444 device->SetPixelShader(NULL); 2445 device->SetVertexShader(NULL); 2446 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); 2447 device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); 2448 2449 hr = device->EndStateBlock(&mMaskedClearSavedState); 2450 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); 2451 } 2452 2453 ASSERT(mMaskedClearSavedState != NULL); 2454 2455 if (mMaskedClearSavedState != NULL) 2456 { 2457 hr = mMaskedClearSavedState->Capture(); 2458 ASSERT(SUCCEEDED(hr)); 2459 } 2460 2461 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); 2462 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); 2463 device->SetRenderState(D3DRS_ZENABLE, FALSE); 2464 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 2465 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); 2466 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 2467 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 2468 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); 2469 2470 if (flags & D3DCLEAR_TARGET) 2471 { 2472 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) | 2473 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) | 2474 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) | 2475 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0)); 2476 } 2477 else 2478 { 2479 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0); 2480 } 2481 2482 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL)) 2483 { 2484 device->SetRenderState(D3DRS_STENCILENABLE, TRUE); 2485 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); 2486 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); 2487 device->SetRenderState(D3DRS_STENCILREF, stencil); 2488 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask); 2489 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); 2490 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); 2491 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); 2492 mStencilStateDirty = true; 2493 } 2494 else 2495 { 2496 device->SetRenderState(D3DRS_STENCILENABLE, FALSE); 2497 } 2498 2499 device->SetPixelShader(NULL); 2500 device->SetVertexShader(NULL); 2501 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); 2502 device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); 2503 2504 struct Vertex 2505 { 2506 float x, y, z, w; 2507 D3DCOLOR diffuse; 2508 }; 2509 2510 Vertex quad[4]; 2511 quad[0].x = 0.0f; 2512 quad[0].y = (float)desc.Height; 2513 quad[0].z = 0.0f; 2514 quad[0].w = 1.0f; 2515 quad[0].diffuse = color; 2516 2517 quad[1].x = (float)desc.Width; 2518 quad[1].y = (float)desc.Height; 2519 quad[1].z = 0.0f; 2520 quad[1].w = 1.0f; 2521 quad[1].diffuse = color; 2522 2523 quad[2].x = 0.0f; 2524 quad[2].y = 0.0f; 2525 quad[2].z = 0.0f; 2526 quad[2].w = 1.0f; 2527 quad[2].diffuse = color; 2528 2529 quad[3].x = (float)desc.Width; 2530 quad[3].y = 0.0f; 2531 quad[3].z = 0.0f; 2532 quad[3].w = 1.0f; 2533 quad[3].diffuse = color; 2534 2535 display->startScene(); 2536 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex)); 2537 2538 if (flags & D3DCLEAR_ZBUFFER) 2539 { 2540 device->SetRenderState(D3DRS_ZENABLE, TRUE); 2541 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); 2542 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); 2543 } 2544 2545 if (mMaskedClearSavedState != NULL) 2546 { 2547 mMaskedClearSavedState->Apply(); 2548 } 2549 } 2550 else if (flags) 2551 { 2552 device->Clear(0, NULL, flags, color, depth, stencil); 2553 } 2554 } 2555 2556 void Context::drawArrays(GLenum mode, GLint first, GLsizei count) 2557 { 2558 if (!mState.currentProgram) 2559 { 2560 return error(GL_INVALID_OPERATION); 2561 } 2562 2563 egl::Display *display = getDisplay(); 2564 IDirect3DDevice9 *device = getDevice(); 2565 D3DPRIMITIVETYPE primitiveType; 2566 int primitiveCount; 2567 2568 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount)) 2569 return error(GL_INVALID_ENUM); 2570 2571 if (primitiveCount <= 0) 2572 { 2573 return; 2574 } 2575 2576 if (!applyRenderTarget(false)) 2577 { 2578 return; 2579 } 2580 2581 applyState(mode); 2582 2583 GLenum err = applyVertexBuffer(first, count); 2584 if (err != GL_NO_ERROR) 2585 { 2586 return error(err); 2587 } 2588 2589 applyShaders(); 2590 applyTextures(); 2591 2592 if (!getCurrentProgram()->validateSamplers()) 2593 { 2594 return error(GL_INVALID_OPERATION); 2595 } 2596 2597 if (!cullSkipsDraw(mode)) 2598 { 2599 display->startScene(); 2600 2601 device->DrawPrimitive(primitiveType, 0, primitiveCount); 2602 2603 if (mode == GL_LINE_LOOP) // Draw the last segment separately 2604 { 2605 drawClosingLine(first, first + count - 1); 2606 } 2607 } 2608 } 2609 2610 void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) 2611 { 2612 if (!mState.currentProgram) 2613 { 2614 return error(GL_INVALID_OPERATION); 2615 } 2616 2617 if (!indices && !mState.elementArrayBuffer) 2618 { 2619 return error(GL_INVALID_OPERATION); 2620 } 2621 2622 egl::Display *display = getDisplay(); 2623 IDirect3DDevice9 *device = getDevice(); 2624 D3DPRIMITIVETYPE primitiveType; 2625 int primitiveCount; 2626 2627 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount)) 2628 return error(GL_INVALID_ENUM); 2629 2630 if (primitiveCount <= 0) 2631 { 2632 return; 2633 } 2634 2635 if (!applyRenderTarget(false)) 2636 { 2637 return; 2638 } 2639 2640 applyState(mode); 2641 2642 TranslatedIndexData indexInfo; 2643 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo); 2644 if (err != GL_NO_ERROR) 2645 { 2646 return error(err); 2647 } 2648 2649 GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; 2650 err = applyVertexBuffer(indexInfo.minIndex, vertexCount); 2651 if (err != GL_NO_ERROR) 2652 { 2653 return error(err); 2654 } 2655 2656 applyShaders(); 2657 applyTextures(); 2658 2659 if (!getCurrentProgram()->validateSamplers()) 2660 { 2661 return error(GL_INVALID_OPERATION); 2662 } 2663 2664 if (!cullSkipsDraw(mode)) 2665 { 2666 display->startScene(); 2667 2668 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount); 2669 2670 if (mode == GL_LINE_LOOP) // Draw the last segment separately 2671 { 2672 drawClosingLine(count, type, indices); 2673 } 2674 } 2675 } 2676 2677 void Context::finish() 2678 { 2679 egl::Display *display = getDisplay(); 2680 IDirect3DDevice9 *device = getDevice(); 2681 IDirect3DQuery9 *occlusionQuery = NULL; 2682 2683 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery); 2684 2685 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) 2686 { 2687 return error(GL_OUT_OF_MEMORY); 2688 } 2689 2690 ASSERT(SUCCEEDED(result)); 2691 2692 if (occlusionQuery) 2693 { 2694 IDirect3DStateBlock9 *savedState = NULL; 2695 device->CreateStateBlock(D3DSBT_ALL, &savedState); 2696 2697 HRESULT result = occlusionQuery->Issue(D3DISSUE_BEGIN); 2698 ASSERT(SUCCEEDED(result)); 2699 2700 // Render something outside the render target 2701 device->SetPixelShader(NULL); 2702 device->SetVertexShader(NULL); 2703 device->SetFVF(D3DFVF_XYZRHW); 2704 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f}; 2705 display->startScene(); 2706 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data)); 2707 2708 result = occlusionQuery->Issue(D3DISSUE_END); 2709 ASSERT(SUCCEEDED(result)); 2710 2711 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE) 2712 { 2713 // Keep polling, but allow other threads to do something useful first 2714 Sleep(0); 2715 } 2716 2717 occlusionQuery->Release(); 2718 2719 if (savedState) 2720 { 2721 savedState->Apply(); 2722 savedState->Release(); 2723 } 2724 } 2725 } 2726 2727 void Context::flush() 2728 { 2729 IDirect3DDevice9 *device = getDevice(); 2730 IDirect3DQuery9 *eventQuery = NULL; 2731 2732 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery); 2733 2734 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) 2735 { 2736 return error(GL_OUT_OF_MEMORY); 2737 } 2738 2739 ASSERT(SUCCEEDED(result)); 2740 2741 if (eventQuery) 2742 { 2743 HRESULT result = eventQuery->Issue(D3DISSUE_END); 2744 ASSERT(SUCCEEDED(result)); 2745 2746 result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); 2747 eventQuery->Release(); 2748 2749 if (result == D3DERR_DEVICELOST) 2750 { 2751 error(GL_OUT_OF_MEMORY); 2752 } 2753 } 2754 } 2755 2756 void Context::drawClosingLine(unsigned int first, unsigned int last) 2757 { 2758 IDirect3DDevice9 *device = getDevice(); 2759 IDirect3DIndexBuffer9 *indexBuffer = NULL; 2760 HRESULT result = D3DERR_INVALIDCALL; 2761 2762 if (supports32bitIndices()) 2763 { 2764 result = device->CreateIndexBuffer(8, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &indexBuffer, 0); 2765 2766 if (SUCCEEDED(result)) 2767 { 2768 unsigned int *data; 2769 result = indexBuffer->Lock(0, 0, (void**)&data, 0); 2770 2771 if (SUCCEEDED(result)) 2772 { 2773 data[0] = last; 2774 data[1] = first; 2775 } 2776 } 2777 } 2778 else 2779 { 2780 result = device->CreateIndexBuffer(4, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, 0); 2781 2782 if (SUCCEEDED(result)) 2783 { 2784 unsigned short *data; 2785 result = indexBuffer->Lock(0, 0, (void**)&data, 0); 2786 2787 if (SUCCEEDED(result)) 2788 { 2789 data[0] = last; 2790 data[1] = first; 2791 } 2792 } 2793 } 2794 2795 if (SUCCEEDED(result)) 2796 { 2797 indexBuffer->Unlock(); 2798 device->SetIndices(indexBuffer); 2799 2800 device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 2, 0, 1); 2801 2802 indexBuffer->Release(); 2803 } 2804 else 2805 { 2806 ERR("Could not create an index buffer for closing a line loop."); 2807 error(GL_OUT_OF_MEMORY); 2808 } 2809 } 2810 2811 void Context::drawClosingLine(GLsizei count, GLenum type, const void *indices) 2812 { 2813 unsigned int first = 0; 2814 unsigned int last = 0; 2815 2816 if (mState.elementArrayBuffer.get()) 2817 { 2818 Buffer *indexBuffer = mState.elementArrayBuffer.get(); 2819 intptr_t offset = reinterpret_cast<intptr_t>(indices); 2820 indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset; 2821 } 2822 2823 switch (type) 2824 { 2825 case GL_UNSIGNED_BYTE: 2826 first = static_cast<const GLubyte*>(indices)[0]; 2827 last = static_cast<const GLubyte*>(indices)[count - 1]; 2828 break; 2829 case GL_UNSIGNED_SHORT: 2830 first = static_cast<const GLushort*>(indices)[0]; 2831 last = static_cast<const GLushort*>(indices)[count - 1]; 2832 break; 2833 case GL_UNSIGNED_INT: 2834 first = static_cast<const GLuint*>(indices)[0]; 2835 last = static_cast<const GLuint*>(indices)[count - 1]; 2836 break; 2837 default: UNREACHABLE(); 2838 } 2839 2840 drawClosingLine(first, last); 2841 } 2842 2843 void Context::recordInvalidEnum() 2844 { 2845 mInvalidEnum = true; 2846 } 2847 2848 void Context::recordInvalidValue() 2849 { 2850 mInvalidValue = true; 2851 } 2852 2853 void Context::recordInvalidOperation() 2854 { 2855 mInvalidOperation = true; 2856 } 2857 2858 void Context::recordOutOfMemory() 2859 { 2860 mOutOfMemory = true; 2861 } 2862 2863 void Context::recordInvalidFramebufferOperation() 2864 { 2865 mInvalidFramebufferOperation = true; 2866 } 2867 2868 // Get one of the recorded errors and clear its flag, if any. 2869 // [OpenGL ES 2.0.24] section 2.5 page 13. 2870 GLenum Context::getError() 2871 { 2872 if (mInvalidEnum) 2873 { 2874 mInvalidEnum = false; 2875 2876 return GL_INVALID_ENUM; 2877 } 2878 2879 if (mInvalidValue) 2880 { 2881 mInvalidValue = false; 2882 2883 return GL_INVALID_VALUE; 2884 } 2885 2886 if (mInvalidOperation) 2887 { 2888 mInvalidOperation = false; 2889 2890 return GL_INVALID_OPERATION; 2891 } 2892 2893 if (mOutOfMemory) 2894 { 2895 mOutOfMemory = false; 2896 2897 return GL_OUT_OF_MEMORY; 2898 } 2899 2900 if (mInvalidFramebufferOperation) 2901 { 2902 mInvalidFramebufferOperation = false; 2903 2904 return GL_INVALID_FRAMEBUFFER_OPERATION; 2905 } 2906 2907 return GL_NO_ERROR; 2908 } 2909 2910 bool Context::supportsShaderModel3() const 2911 { 2912 return mSupportsShaderModel3; 2913 } 2914 2915 int Context::getMaximumVaryingVectors() const 2916 { 2917 return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; 2918 } 2919 2920 int Context::getMaximumFragmentUniformVectors() const 2921 { 2922 return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2; 2923 } 2924 2925 int Context::getMaxSupportedSamples() const 2926 { 2927 return mMaxSupportedSamples; 2928 } 2929 2930 int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const 2931 { 2932 if (requested == 0) 2933 { 2934 return requested; 2935 } 2936 2937 std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format); 2938 if (itr == mMultiSampleSupport.end()) 2939 { 2940 return -1; 2941 } 2942 2943 for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) 2944 { 2945 if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) 2946 { 2947 return i; 2948 } 2949 } 2950 2951 return -1; 2952 } 2953 2954 bool Context::supportsEventQueries() const 2955 { 2956 return mSupportsEventQueries; 2957 } 2958 2959 bool Context::supportsCompressedTextures() const 2960 { 2961 return mSupportsCompressedTextures; 2962 } 2963 2964 bool Context::supportsFloatTextures() const 2965 { 2966 return mSupportsFloatTextures; 2967 } 2968 2969 bool Context::supportsFloatLinearFilter() const 2970 { 2971 return mSupportsFloatLinearFilter; 2972 } 2973 2974 bool Context::supportsFloatRenderableTextures() const 2975 { 2976 return mSupportsFloatRenderableTextures; 2977 } 2978 2979 bool Context::supportsHalfFloatTextures() const 2980 { 2981 return mSupportsHalfFloatTextures; 2982 } 2983 2984 bool Context::supportsHalfFloatLinearFilter() const 2985 { 2986 return mSupportsHalfFloatLinearFilter; 2987 } 2988 2989 bool Context::supportsHalfFloatRenderableTextures() const 2990 { 2991 return mSupportsHalfFloatRenderableTextures; 2992 } 2993 2994 int Context::getMaximumRenderbufferDimension() const 2995 { 2996 return mMaxRenderbufferDimension; 2997 } 2998 2999 int Context::getMaximumTextureDimension() const 3000 { 3001 return mMaxTextureDimension; 3002 } 3003 3004 int Context::getMaximumCubeTextureDimension() const 3005 { 3006 return mMaxCubeTextureDimension; 3007 } 3008 3009 int Context::getMaximumTextureLevel() const 3010 { 3011 return mMaxTextureLevel; 3012 } 3013 3014 bool Context::supportsLuminanceTextures() const 3015 { 3016 return mSupportsLuminanceTextures; 3017 } 3018 3019 bool Context::supportsLuminanceAlphaTextures() const 3020 { 3021 return mSupportsLuminanceAlphaTextures; 3022 } 3023 3024 bool Context::supports32bitIndices() const 3025 { 3026 return mSupports32bitIndices; 3027 } 3028 3029 void Context::detachBuffer(GLuint buffer) 3030 { 3031 // [OpenGL ES 2.0.24] section 2.9 page 22: 3032 // If a buffer object is deleted while it is bound, all bindings to that object in the current context 3033 // (i.e. in the thread that called Delete-Buffers) are reset to zero. 3034 3035 if (mState.arrayBuffer.id() == buffer) 3036 { 3037 mState.arrayBuffer.set(NULL); 3038 } 3039 3040 if (mState.elementArrayBuffer.id() == buffer) 3041 { 3042 mState.elementArrayBuffer.set(NULL); 3043 } 3044 3045 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) 3046 { 3047 if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer) 3048 { 3049 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL); 3050 } 3051 } 3052 } 3053 3054 void Context::detachTexture(GLuint texture) 3055 { 3056 // [OpenGL ES 2.0.24] section 3.8 page 84: 3057 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are 3058 // rebound to texture object zero 3059 3060 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++) 3061 { 3062 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++) 3063 { 3064 if (mState.samplerTexture[type][sampler].id() == texture) 3065 { 3066 mState.samplerTexture[type][sampler].set(NULL); 3067 } 3068 } 3069 } 3070 3071 // [OpenGL ES 2.0.24] section 4.4 page 112: 3072 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is 3073 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this 3074 // image was attached in the currently bound framebuffer. 3075 3076 Framebuffer *readFramebuffer = getReadFramebuffer(); 3077 Framebuffer *drawFramebuffer = getDrawFramebuffer(); 3078 3079 if (readFramebuffer) 3080 { 3081 readFramebuffer->detachTexture(texture); 3082 } 3083 3084 if (drawFramebuffer && drawFramebuffer != readFramebuffer) 3085 { 3086 drawFramebuffer->detachTexture(texture); 3087 } 3088 } 3089 3090 void Context::detachFramebuffer(GLuint framebuffer) 3091 { 3092 // [OpenGL ES 2.0.24] section 4.4 page 107: 3093 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though 3094 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. 3095 3096 if (mState.readFramebuffer == framebuffer) 3097 { 3098 bindReadFramebuffer(0); 3099 } 3100 3101 if (mState.drawFramebuffer == framebuffer) 3102 { 3103 bindDrawFramebuffer(0); 3104 } 3105 } 3106 3107 void Context::detachRenderbuffer(GLuint renderbuffer) 3108 { 3109 // [OpenGL ES 2.0.24] section 4.4 page 109: 3110 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer 3111 // had been executed with the target RENDERBUFFER and name of zero. 3112 3113 if (mState.renderbuffer.id() == renderbuffer) 3114 { 3115 bindRenderbuffer(0); 3116 } 3117 3118 // [OpenGL ES 2.0.24] section 4.4 page 111: 3119 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, 3120 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment 3121 // point to which this image was attached in the currently bound framebuffer. 3122 3123 Framebuffer *readFramebuffer = getReadFramebuffer(); 3124 Framebuffer *drawFramebuffer = getDrawFramebuffer(); 3125 3126 if (readFramebuffer) 3127 { 3128 readFramebuffer->detachRenderbuffer(renderbuffer); 3129 } 3130 3131 if (drawFramebuffer && drawFramebuffer != readFramebuffer) 3132 { 3133 drawFramebuffer->detachRenderbuffer(renderbuffer); 3134 } 3135 } 3136 3137 Texture *Context::getIncompleteTexture(SamplerType type) 3138 { 3139 Texture *t = mIncompleteTextures[type].get(); 3140 3141 if (t == NULL) 3142 { 3143 static const GLubyte color[] = { 0, 0, 0, 255 }; 3144 3145 switch (type) 3146 { 3147 default: 3148 UNREACHABLE(); 3149 // default falls through to SAMPLER_2D 3150 3151 case SAMPLER_2D: 3152 { 3153 Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID); 3154 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); 3155 t = incomplete2d; 3156 } 3157 break; 3158 3159 case SAMPLER_CUBE: 3160 { 3161 TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID); 3162 3163 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); 3164 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); 3165 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); 3166 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); 3167 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); 3168 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); 3169 3170 t = incompleteCube; 3171 } 3172 break; 3173 } 3174 3175 mIncompleteTextures[type].set(t); 3176 } 3177 3178 return t; 3179 } 3180 3181 bool Context::cullSkipsDraw(GLenum drawMode) 3182 { 3183 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode); 3184 } 3185 3186 bool Context::isTriangleMode(GLenum drawMode) 3187 { 3188 switch (drawMode) 3189 { 3190 case GL_TRIANGLES: 3191 case GL_TRIANGLE_FAN: 3192 case GL_TRIANGLE_STRIP: 3193 return true; 3194 case GL_POINTS: 3195 case GL_LINES: 3196 case GL_LINE_LOOP: 3197 case GL_LINE_STRIP: 3198 return false; 3199 default: UNREACHABLE(); 3200 } 3201 3202 return false; 3203 } 3204 3205 void Context::setVertexAttrib(GLuint index, const GLfloat *values) 3206 { 3207 ASSERT(index < gl::MAX_VERTEX_ATTRIBS); 3208 3209 mState.vertexAttribute[index].mCurrentValue[0] = values[0]; 3210 mState.vertexAttribute[index].mCurrentValue[1] = values[1]; 3211 mState.vertexAttribute[index].mCurrentValue[2] = values[2]; 3212 mState.vertexAttribute[index].mCurrentValue[3] = values[3]; 3213 3214 mVertexDataManager->dirtyCurrentValue(index); 3215 } 3216 3217 void Context::initExtensionString() 3218 { 3219 mExtensionString += "GL_OES_packed_depth_stencil "; 3220 mExtensionString += "GL_EXT_texture_format_BGRA8888 "; 3221 mExtensionString += "GL_EXT_read_format_bgra "; 3222 mExtensionString += "GL_ANGLE_framebuffer_blit "; 3223 mExtensionString += "GL_OES_rgb8_rgba8 "; 3224 mExtensionString += "GL_OES_standard_derivatives "; 3225 3226 if (supportsEventQueries()) 3227 { 3228 mExtensionString += "GL_NV_fence "; 3229 } 3230 3231 if (supportsCompressedTextures()) 3232 { 3233 mExtensionString += "GL_EXT_texture_compression_dxt1 "; 3234 } 3235 3236 if (supportsFloatTextures()) 3237 { 3238 mExtensionString += "GL_OES_texture_float "; 3239 } 3240 3241 if (supportsHalfFloatTextures()) 3242 { 3243 mExtensionString += "GL_OES_texture_half_float "; 3244 } 3245 3246 if (supportsFloatLinearFilter()) 3247 { 3248 mExtensionString += "GL_OES_texture_float_linear "; 3249 } 3250 3251 if (supportsHalfFloatLinearFilter()) 3252 { 3253 mExtensionString += "GL_OES_texture_half_float_linear "; 3254 } 3255 3256 if (getMaxSupportedSamples() != 0) 3257 { 3258 mExtensionString += "GL_ANGLE_framebuffer_multisample "; 3259 } 3260 3261 if (supports32bitIndices()) 3262 { 3263 mExtensionString += "GL_OES_element_index_uint "; 3264 } 3265 3266 std::string::size_type end = mExtensionString.find_last_not_of(' '); 3267 if (end != std::string::npos) 3268 { 3269 mExtensionString.resize(end+1); 3270 } 3271 } 3272 3273 const char *Context::getExtensionString() const 3274 { 3275 return mExtensionString.c_str(); 3276 } 3277 3278 void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 3279 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 3280 GLbitfield mask) 3281 { 3282 IDirect3DDevice9 *device = getDevice(); 3283 3284 Framebuffer *readFramebuffer = getReadFramebuffer(); 3285 Framebuffer *drawFramebuffer = getDrawFramebuffer(); 3286 3287 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || 3288 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) 3289 { 3290 return error(GL_INVALID_FRAMEBUFFER_OPERATION); 3291 } 3292 3293 if (drawFramebuffer->getSamples() != 0) 3294 { 3295 return error(GL_INVALID_OPERATION); 3296 } 3297 3298 RECT sourceRect; 3299 RECT destRect; 3300 3301 if (srcX0 < srcX1) 3302 { 3303 sourceRect.left = srcX0; 3304 sourceRect.right = srcX1; 3305 destRect.left = dstX0; 3306 destRect.right = dstX1; 3307 } 3308 else 3309 { 3310 sourceRect.left = srcX1; 3311 destRect.left = dstX1; 3312 sourceRect.right = srcX0; 3313 destRect.right = dstX0; 3314 } 3315 3316 // Arguments to StretchRect must be in D3D-style (0-top) coordinates, so we must 3317 // flip our Y-values here 3318 if (srcY0 < srcY1) 3319 { 3320 sourceRect.bottom = srcY1; 3321 destRect.bottom = dstY1; 3322 sourceRect.top = srcY0; 3323 destRect.top = dstY0; 3324 } 3325 else 3326 { 3327 sourceRect.bottom = srcY0; 3328 destRect.bottom = dstY0; 3329 sourceRect.top = srcY1; 3330 destRect.top = dstY1; 3331 } 3332 3333 RECT sourceScissoredRect = sourceRect; 3334 RECT destScissoredRect = destRect; 3335 3336 if (mState.scissorTest) 3337 { 3338 // Only write to parts of the destination framebuffer which pass the scissor test 3339 // Please note: the destRect is now in D3D-style coordinates, so the *top* of the 3340 // rect will be checked against scissorY, rather than the bottom. 3341 if (destRect.left < mState.scissorX) 3342 { 3343 int xDiff = mState.scissorX - destRect.left; 3344 destScissoredRect.left = mState.scissorX; 3345 sourceScissoredRect.left += xDiff; 3346 } 3347 3348 if (destRect.right > mState.scissorX + mState.scissorWidth) 3349 { 3350 int xDiff = destRect.right - (mState.scissorX + mState.scissorWidth); 3351 destScissoredRect.right = mState.scissorX + mState.scissorWidth; 3352 sourceScissoredRect.right -= xDiff; 3353 } 3354 3355 if (destRect.top < mState.scissorY) 3356 { 3357 int yDiff = mState.scissorY - destRect.top; 3358 destScissoredRect.top = mState.scissorY; 3359 sourceScissoredRect.top += yDiff; 3360 } 3361 3362 if (destRect.bottom > mState.scissorY + mState.scissorHeight) 3363 { 3364 int yDiff = destRect.bottom - (mState.scissorY + mState.scissorHeight); 3365 destScissoredRect.bottom = mState.scissorY + mState.scissorHeight; 3366 sourceScissoredRect.bottom -= yDiff; 3367 } 3368 } 3369 3370 bool blitRenderTarget = false; 3371 bool blitDepthStencil = false; 3372 3373 RECT sourceTrimmedRect = sourceScissoredRect; 3374 RECT destTrimmedRect = destScissoredRect; 3375 3376 // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of 3377 // the actual draw and read surfaces. 3378 if (sourceTrimmedRect.left < 0) 3379 { 3380 int xDiff = 0 - sourceTrimmedRect.left; 3381 sourceTrimmedRect.left = 0; 3382 destTrimmedRect.left += xDiff; 3383 } 3384 3385 int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth(); 3386 int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight(); 3387 int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth(); 3388 int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight(); 3389 3390 if (sourceTrimmedRect.right > readBufferWidth) 3391 { 3392 int xDiff = sourceTrimmedRect.right - readBufferWidth; 3393 sourceTrimmedRect.right = readBufferWidth; 3394 destTrimmedRect.right -= xDiff; 3395 } 3396 3397 if (sourceTrimmedRect.top < 0) 3398 { 3399 int yDiff = 0 - sourceTrimmedRect.top; 3400 sourceTrimmedRect.top = 0; 3401 destTrimmedRect.top += yDiff; 3402 } 3403 3404 if (sourceTrimmedRect.bottom > readBufferHeight) 3405 { 3406 int yDiff = sourceTrimmedRect.bottom - readBufferHeight; 3407 sourceTrimmedRect.bottom = readBufferHeight; 3408 destTrimmedRect.bottom -= yDiff; 3409 } 3410 3411 if (destTrimmedRect.left < 0) 3412 { 3413 int xDiff = 0 - destTrimmedRect.left; 3414 destTrimmedRect.left = 0; 3415 sourceTrimmedRect.left += xDiff; 3416 } 3417 3418 if (destTrimmedRect.right > drawBufferWidth) 3419 { 3420 int xDiff = destTrimmedRect.right - drawBufferWidth; 3421 destTrimmedRect.right = drawBufferWidth; 3422 sourceTrimmedRect.right -= xDiff; 3423 } 3424 3425 if (destTrimmedRect.top < 0) 3426 { 3427 int yDiff = 0 - destTrimmedRect.top; 3428 destTrimmedRect.top = 0; 3429 sourceTrimmedRect.top += yDiff; 3430 } 3431 3432 if (destTrimmedRect.bottom > drawBufferHeight) 3433 { 3434 int yDiff = destTrimmedRect.bottom - drawBufferHeight; 3435 destTrimmedRect.bottom = drawBufferHeight; 3436 sourceTrimmedRect.bottom -= yDiff; 3437 } 3438 3439 bool partialBufferCopy = false; 3440 if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight || 3441 sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth || 3442 destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight || 3443 destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth || 3444 sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0) 3445 { 3446 partialBufferCopy = true; 3447 } 3448 3449 if (mask & GL_COLOR_BUFFER_BIT) 3450 { 3451 const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D || 3452 readFramebuffer->getColorbufferType() == GL_RENDERBUFFER; 3453 const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D || 3454 drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER; 3455 if (!validReadType || !validDrawType || 3456 readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat()) 3457 { 3458 ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation"); 3459 return error(GL_INVALID_OPERATION); 3460 } 3461 3462 if (partialBufferCopy && readFramebuffer->getSamples() != 0) 3463 { 3464 return error(GL_INVALID_OPERATION); 3465 } 3466 3467 blitRenderTarget = true; 3468 3469 } 3470 3471 if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) 3472 { 3473 DepthStencilbuffer *readDSBuffer = NULL; 3474 DepthStencilbuffer *drawDSBuffer = NULL; 3475 3476 // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have 3477 // both a depth and stencil buffer, it will be the same buffer. 3478 3479 if (mask & GL_DEPTH_BUFFER_BIT) 3480 { 3481 if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) 3482 { 3483 if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() || 3484 readFramebuffer->getDepthbuffer()->getD3DFormat() != drawFramebuffer->getDepthbuffer()->getD3DFormat()) 3485 { 3486 return error(GL_INVALID_OPERATION); 3487 } 3488 3489 blitDepthStencil = true; 3490 readDSBuffer = readFramebuffer->getDepthbuffer(); 3491 drawDSBuffer = drawFramebuffer->getDepthbuffer(); 3492 } 3493 } 3494 3495 if (mask & GL_STENCIL_BUFFER_BIT) 3496 { 3497 if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) 3498 { 3499 if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() || 3500 readFramebuffer->getStencilbuffer()->getD3DFormat() != drawFramebuffer->getStencilbuffer()->getD3DFormat()) 3501 { 3502 return error(GL_INVALID_OPERATION); 3503 } 3504 3505 blitDepthStencil = true; 3506 readDSBuffer = readFramebuffer->getStencilbuffer(); 3507 drawDSBuffer = drawFramebuffer->getStencilbuffer(); 3508 } 3509 } 3510 3511 if (partialBufferCopy) 3512 { 3513 ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); 3514 return error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted 3515 } 3516 3517 if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) || 3518 (readDSBuffer && readDSBuffer->getSamples() != 0)) 3519 { 3520 return error(GL_INVALID_OPERATION); 3521 } 3522 } 3523 3524 if (blitRenderTarget || blitDepthStencil) 3525 { 3526 egl::Display *display = getDisplay(); 3527 display->endScene(); 3528 3529 if (blitRenderTarget) 3530 { 3531 HRESULT result = device->StretchRect(readFramebuffer->getRenderTarget(), &sourceTrimmedRect, 3532 drawFramebuffer->getRenderTarget(), &destTrimmedRect, D3DTEXF_NONE); 3533 3534 if (FAILED(result)) 3535 { 3536 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); 3537 return; 3538 } 3539 } 3540 3541 if (blitDepthStencil) 3542 { 3543 HRESULT result = device->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE); 3544 3545 if (FAILED(result)) 3546 { 3547 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); 3548 return; 3549 } 3550 } 3551 } 3552 } 3553 3554 } 3555 3556 extern "C" 3557 { 3558 gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext) 3559 { 3560 return new gl::Context(config, shareContext); 3561 } 3562 3563 void glDestroyContext(gl::Context *context) 3564 { 3565 delete context; 3566 3567 if (context == gl::getContext()) 3568 { 3569 gl::makeCurrent(NULL, NULL, NULL); 3570 } 3571 } 3572 3573 void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface) 3574 { 3575 gl::makeCurrent(context, display, surface); 3576 } 3577 3578 gl::Context *glGetCurrentContext() 3579 { 3580 return gl::getContext(); 3581 } 3582 } 3583