StateManager9.cpp (35774B)
1 // 2 // Copyright 2015 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 // StateManager9.cpp: Defines a class for caching D3D9 state 8 #include "libANGLE/renderer/d3d/d3d9/StateManager9.h" 9 10 #include "common/bitset_utils.h" 11 #include "common/utilities.h" 12 #include "libANGLE/formatutils.h" 13 #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" 14 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" 15 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" 16 17 namespace rx 18 { 19 20 StateManager9::StateManager9(Renderer9 *renderer9) 21 : mUsingZeroColorMaskWorkaround(false), 22 mCurSampleAlphaToCoverage(false), 23 mCurBlendState(), 24 mCurBlendColor(0, 0, 0, 0), 25 mCurSampleMask(0), 26 mCurRasterState(), 27 mCurDepthSize(0), 28 mCurDepthStencilState(), 29 mCurStencilRef(0), 30 mCurStencilBackRef(0), 31 mCurFrontFaceCCW(0), 32 mCurStencilSize(0), 33 mCurScissorRect(), 34 mCurScissorEnabled(false), 35 mCurViewport(), 36 mCurNear(0.0f), 37 mCurFar(0.0f), 38 mCurDepthFront(0.0f), 39 mCurIgnoreViewport(false), 40 mRenderer9(renderer9), 41 mDirtyBits() 42 { 43 mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); 44 mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_COLOR); 45 mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); 46 mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); 47 mBlendStateDirtyBits.set(DIRTY_BIT_COLOR_MASK); 48 mBlendStateDirtyBits.set(DIRTY_BIT_DITHER); 49 mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_MASK); 50 51 mRasterizerStateDirtyBits.set(DIRTY_BIT_CULL_MODE); 52 mRasterizerStateDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); 53 54 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); 55 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); 56 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); 57 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); 58 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); 59 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); 60 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); 61 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); 62 mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); 63 64 mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); 65 mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); 66 } 67 68 StateManager9::~StateManager9() {} 69 70 void StateManager9::initialize() 71 { 72 mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId()); 73 } 74 75 void StateManager9::forceSetBlendState() 76 { 77 mDirtyBits |= mBlendStateDirtyBits; 78 } 79 80 void StateManager9::forceSetRasterState() 81 { 82 mDirtyBits |= mRasterizerStateDirtyBits; 83 } 84 85 void StateManager9::forceSetDepthStencilState() 86 { 87 mDirtyBits |= mDepthStencilStateDirtyBits; 88 } 89 90 void StateManager9::forceSetScissorState() 91 { 92 mDirtyBits |= mScissorStateDirtyBits; 93 } 94 95 void StateManager9::forceSetViewportState() 96 { 97 mForceSetViewport = true; 98 } 99 100 void StateManager9::forceSetDXUniformsState() 101 { 102 mDxUniformsDirty = true; 103 } 104 105 void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized, 106 unsigned int stencilSize) 107 { 108 if (!depthStencilInitialized || stencilSize != mCurStencilSize) 109 { 110 mCurStencilSize = stencilSize; 111 forceSetDepthStencilState(); 112 } 113 } 114 115 void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) 116 { 117 if (!dirtyBits.any()) 118 { 119 return; 120 } 121 122 for (auto dirtyBit : dirtyBits) 123 { 124 switch (dirtyBit) 125 { 126 case gl::State::DIRTY_BIT_BLEND_ENABLED: 127 if (state.getBlendState().blend != mCurBlendState.blend) 128 { 129 mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); 130 // BlendColor and funcs and equations has to be set if blend is enabled 131 mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); 132 mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); 133 134 // The color mask may have to be updated if the blend state changes 135 if (mUsingZeroColorMaskWorkaround) 136 { 137 mDirtyBits.set(DIRTY_BIT_COLOR_MASK); 138 } 139 } 140 break; 141 case gl::State::DIRTY_BIT_BLEND_FUNCS: 142 { 143 const gl::BlendState &blendState = state.getBlendState(); 144 if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB || 145 blendState.destBlendRGB != mCurBlendState.destBlendRGB || 146 blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || 147 blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) 148 { 149 mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); 150 // BlendColor depends on the values of blend funcs 151 mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); 152 153 // The color mask may have to be updated if the blend funcs change 154 if (mUsingZeroColorMaskWorkaround) 155 { 156 mDirtyBits.set(DIRTY_BIT_COLOR_MASK); 157 } 158 } 159 break; 160 } 161 case gl::State::DIRTY_BIT_BLEND_EQUATIONS: 162 { 163 const gl::BlendState &blendState = state.getBlendState(); 164 if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || 165 blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) 166 { 167 mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); 168 169 // The color mask may have to be updated if the blend funcs change 170 if (mUsingZeroColorMaskWorkaround) 171 { 172 mDirtyBits.set(DIRTY_BIT_COLOR_MASK); 173 } 174 } 175 break; 176 } 177 case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: 178 if (state.isSampleAlphaToCoverageEnabled() != mCurSampleAlphaToCoverage) 179 { 180 mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); 181 } 182 break; 183 case gl::State::DIRTY_BIT_COLOR_MASK: 184 { 185 const gl::BlendState &blendState = state.getBlendState(); 186 if (blendState.colorMaskRed != mCurBlendState.colorMaskRed || 187 blendState.colorMaskGreen != mCurBlendState.colorMaskGreen || 188 blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || 189 blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) 190 { 191 mDirtyBits.set(DIRTY_BIT_COLOR_MASK); 192 193 // The color mask can cause the blend state to get out of sync when using the 194 // zero color mask workaround 195 if (mUsingZeroColorMaskWorkaround) 196 { 197 mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); 198 mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); 199 } 200 } 201 break; 202 } 203 case gl::State::DIRTY_BIT_DITHER_ENABLED: 204 if (state.getRasterizerState().dither != mCurRasterState.dither) 205 { 206 mDirtyBits.set(DIRTY_BIT_DITHER); 207 } 208 break; 209 case gl::State::DIRTY_BIT_BLEND_COLOR: 210 if (state.getBlendColor() != mCurBlendColor) 211 { 212 mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); 213 } 214 break; 215 case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: 216 if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) 217 { 218 mDirtyBits.set(DIRTY_BIT_CULL_MODE); 219 } 220 break; 221 case gl::State::DIRTY_BIT_CULL_FACE: 222 if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) 223 { 224 mDirtyBits.set(DIRTY_BIT_CULL_MODE); 225 } 226 break; 227 case gl::State::DIRTY_BIT_FRONT_FACE: 228 if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) 229 { 230 mDirtyBits.set(DIRTY_BIT_CULL_MODE); 231 232 // Viewport state depends on rasterizer.frontface 233 mDirtyBits.set(DIRTY_BIT_VIEWPORT); 234 } 235 break; 236 case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: 237 if (state.getRasterizerState().polygonOffsetFill != 238 mCurRasterState.polygonOffsetFill) 239 { 240 mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); 241 } 242 break; 243 case gl::State::DIRTY_BIT_POLYGON_OFFSET: 244 { 245 const gl::RasterizerState &rasterizerState = state.getRasterizerState(); 246 if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || 247 rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) 248 { 249 mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); 250 } 251 break; 252 } 253 // Depth and stencil redundant state changes are guarded in the 254 // frontend so for related cases here just set the dirty bit. 255 case gl::State::DIRTY_BIT_DEPTH_MASK: 256 if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) 257 { 258 mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); 259 } 260 break; 261 case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: 262 mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); 263 break; 264 case gl::State::DIRTY_BIT_DEPTH_FUNC: 265 mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); 266 break; 267 case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: 268 mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); 269 // If we enable the stencil test, all of these must be set 270 mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); 271 mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); 272 mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); 273 mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); 274 mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); 275 mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); 276 break; 277 case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: 278 mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); 279 break; 280 case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: 281 mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); 282 break; 283 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: 284 mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); 285 break; 286 case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: 287 mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); 288 break; 289 case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: 290 mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); 291 break; 292 case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: 293 mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); 294 break; 295 case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: 296 if (state.isScissorTestEnabled() != mCurScissorEnabled) 297 { 298 mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); 299 // If scissor is enabled, we have to set the scissor rect 300 mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); 301 } 302 break; 303 case gl::State::DIRTY_BIT_SCISSOR: 304 if (state.getScissor() != mCurScissorRect) 305 { 306 mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); 307 } 308 break; 309 case gl::State::DIRTY_BIT_DEPTH_RANGE: 310 mDirtyBits.set(DIRTY_BIT_VIEWPORT); 311 break; 312 case gl::State::DIRTY_BIT_VIEWPORT: 313 if (state.getViewport() != mCurViewport) 314 { 315 mDirtyBits.set(DIRTY_BIT_VIEWPORT); 316 } 317 break; 318 default: 319 break; 320 } 321 } 322 } 323 324 void StateManager9::setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask) 325 { 326 const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); 327 328 const gl::BlendState &blendState = glState.getBlendState(); 329 const gl::ColorF &blendColor = glState.getBlendColor(); 330 const gl::RasterizerState &rasterState = glState.getRasterizerState(); 331 332 const auto &depthStencilState = glState.getDepthStencilState(); 333 bool frontFaceCCW = (glState.getRasterizerState().frontFace == GL_CCW); 334 unsigned int maxStencil = (1 << mCurStencilSize) - 1; 335 336 // All the depth stencil states depends on the front face ccw variable 337 if (frontFaceCCW != mCurFrontFaceCCW) 338 { 339 forceSetDepthStencilState(); 340 mCurFrontFaceCCW = frontFaceCCW; 341 } 342 343 for (auto dirtyBit : mDirtyBits) 344 { 345 switch (dirtyBit) 346 { 347 case DIRTY_BIT_BLEND_ENABLED: 348 setBlendEnabled(blendState.blend); 349 break; 350 case DIRTY_BIT_BLEND_COLOR: 351 setBlendColor(blendState, blendColor); 352 break; 353 case DIRTY_BIT_BLEND_FUNCS_EQUATIONS: 354 setBlendFuncsEquations(blendState); 355 break; 356 case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE: 357 setSampleAlphaToCoverage(glState.isSampleAlphaToCoverageEnabled()); 358 break; 359 case DIRTY_BIT_COLOR_MASK: 360 setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue, 361 blendState.colorMaskGreen, blendState.colorMaskAlpha); 362 break; 363 case DIRTY_BIT_DITHER: 364 setDither(rasterState.dither); 365 break; 366 case DIRTY_BIT_CULL_MODE: 367 setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace); 368 break; 369 case DIRTY_BIT_DEPTH_BIAS: 370 setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor, 371 rasterState.polygonOffsetUnits); 372 break; 373 case DIRTY_BIT_STENCIL_DEPTH_MASK: 374 setDepthMask(depthStencilState.depthMask); 375 break; 376 case DIRTY_BIT_STENCIL_DEPTH_FUNC: 377 setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc); 378 break; 379 case DIRTY_BIT_STENCIL_TEST_ENABLED: 380 setStencilTestEnabled(depthStencilState.stencilTest); 381 break; 382 case DIRTY_BIT_STENCIL_FUNCS_FRONT: 383 setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask, 384 glState.getStencilRef(), frontFaceCCW, maxStencil); 385 break; 386 case DIRTY_BIT_STENCIL_FUNCS_BACK: 387 setStencilFuncsBack(depthStencilState.stencilBackFunc, 388 depthStencilState.stencilBackMask, glState.getStencilBackRef(), 389 frontFaceCCW, maxStencil); 390 break; 391 case DIRTY_BIT_STENCIL_WRITEMASK_FRONT: 392 setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW); 393 break; 394 case DIRTY_BIT_STENCIL_WRITEMASK_BACK: 395 setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW); 396 break; 397 case DIRTY_BIT_STENCIL_OPS_FRONT: 398 setStencilOpsFront(depthStencilState.stencilFail, 399 depthStencilState.stencilPassDepthFail, 400 depthStencilState.stencilPassDepthPass, frontFaceCCW); 401 break; 402 case DIRTY_BIT_STENCIL_OPS_BACK: 403 setStencilOpsBack(depthStencilState.stencilBackFail, 404 depthStencilState.stencilBackPassDepthFail, 405 depthStencilState.stencilBackPassDepthPass, frontFaceCCW); 406 break; 407 default: 408 break; 409 } 410 } 411 412 if (sampleMask != mCurSampleMask) 413 { 414 setSampleMask(sampleMask); 415 } 416 } 417 418 void StateManager9::setViewportState(const gl::Rectangle &viewport, 419 float zNear, 420 float zFar, 421 gl::PrimitiveMode drawMode, 422 GLenum frontFace, 423 bool ignoreViewport) 424 { 425 if (!mDirtyBits.test(DIRTY_BIT_VIEWPORT) && mCurIgnoreViewport == ignoreViewport) 426 return; 427 428 gl::Rectangle actualViewport = viewport; 429 float actualZNear = gl::clamp01(zNear); 430 float actualZFar = gl::clamp01(zFar); 431 432 if (ignoreViewport) 433 { 434 actualViewport.x = 0; 435 actualViewport.y = 0; 436 actualViewport.width = static_cast<int>(mRenderTargetBounds.width); 437 actualViewport.height = static_cast<int>(mRenderTargetBounds.height); 438 actualZNear = 0.0f; 439 actualZFar = 1.0f; 440 } 441 442 D3DVIEWPORT9 dxViewport; 443 dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetBounds.width)); 444 dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetBounds.height)); 445 dxViewport.Width = 446 gl::clamp(actualViewport.width, 0, 447 static_cast<int>(mRenderTargetBounds.width) - static_cast<int>(dxViewport.X)); 448 dxViewport.Height = 449 gl::clamp(actualViewport.height, 0, 450 static_cast<int>(mRenderTargetBounds.height) - static_cast<int>(dxViewport.Y)); 451 dxViewport.MinZ = actualZNear; 452 dxViewport.MaxZ = actualZFar; 453 454 float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); 455 456 mRenderer9->getDevice()->SetViewport(&dxViewport); 457 458 mCurViewport = actualViewport; 459 mCurNear = actualZNear; 460 mCurFar = actualZFar; 461 mCurDepthFront = depthFront; 462 mCurIgnoreViewport = ignoreViewport; 463 464 // Setting shader constants 465 dx_VertexConstants9 vc = {}; 466 dx_PixelConstants9 pc = {}; 467 468 vc.viewAdjust[0] = 469 static_cast<float>((actualViewport.width - static_cast<int>(dxViewport.Width)) + 470 2 * (actualViewport.x - static_cast<int>(dxViewport.X)) - 1) / 471 dxViewport.Width; 472 vc.viewAdjust[1] = 473 static_cast<float>((actualViewport.height - static_cast<int>(dxViewport.Height)) + 474 2 * (actualViewport.y - static_cast<int>(dxViewport.Y)) - 1) / 475 dxViewport.Height; 476 vc.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width; 477 vc.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height; 478 479 pc.viewCoords[0] = actualViewport.width * 0.5f; 480 pc.viewCoords[1] = actualViewport.height * 0.5f; 481 pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); 482 pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); 483 484 pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; 485 pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; 486 pc.depthFront[2] = depthFront; 487 488 vc.depthRange[0] = actualZNear; 489 vc.depthRange[1] = actualZFar; 490 vc.depthRange[2] = actualZFar - actualZNear; 491 492 pc.depthRange[0] = actualZNear; 493 pc.depthRange[1] = actualZFar; 494 pc.depthRange[2] = actualZFar - actualZNear; 495 496 if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants9)) != 0) 497 { 498 mVertexConstants = vc; 499 mDxUniformsDirty = true; 500 } 501 502 if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants9)) != 0) 503 { 504 mPixelConstants = pc; 505 mDxUniformsDirty = true; 506 } 507 508 mForceSetViewport = false; 509 } 510 511 void StateManager9::setShaderConstants() 512 { 513 if (!mDxUniformsDirty) 514 return; 515 516 IDirect3DDevice9 *device = mRenderer9->getDevice(); 517 device->SetVertexShaderConstantF(0, reinterpret_cast<float *>(&mVertexConstants), 518 sizeof(dx_VertexConstants9) / sizeof(float[4])); 519 device->SetPixelShaderConstantF(0, reinterpret_cast<float *>(&mPixelConstants), 520 sizeof(dx_PixelConstants9) / sizeof(float[4])); 521 mDxUniformsDirty = false; 522 } 523 524 // This is separate from the main state loop because other functions 525 // outside call only setScissorState to update scissor state 526 void StateManager9::setScissorState(const gl::Rectangle &scissor, bool enabled) 527 { 528 if (mDirtyBits.test(DIRTY_BIT_SCISSOR_ENABLED)) 529 setScissorEnabled(enabled); 530 531 if (mDirtyBits.test(DIRTY_BIT_SCISSOR_RECT)) 532 setScissorRect(scissor, enabled); 533 } 534 535 void StateManager9::setRenderTargetBounds(size_t width, size_t height) 536 { 537 mRenderTargetBounds.width = (int)width; 538 mRenderTargetBounds.height = (int)height; 539 forceSetViewportState(); 540 } 541 542 void StateManager9::setScissorEnabled(bool scissorEnabled) 543 { 544 mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE); 545 mCurScissorEnabled = scissorEnabled; 546 } 547 548 void StateManager9::setScissorRect(const gl::Rectangle &scissor, bool enabled) 549 { 550 if (!enabled) 551 return; 552 553 RECT rect; 554 rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetBounds.width)); 555 rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetBounds.height)); 556 rect.right = 557 gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetBounds.width)); 558 rect.bottom = 559 gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetBounds.height)); 560 mRenderer9->getDevice()->SetScissorRect(&rect); 561 } 562 563 void StateManager9::setDepthFunc(bool depthTest, GLenum depthFunc) 564 { 565 if (depthTest) 566 { 567 IDirect3DDevice9 *device = mRenderer9->getDevice(); 568 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); 569 device->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthFunc)); 570 } 571 else 572 { 573 mRenderer9->getDevice()->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 574 } 575 576 mCurDepthStencilState.depthTest = depthTest; 577 mCurDepthStencilState.depthFunc = depthFunc; 578 } 579 580 void StateManager9::setStencilOpsFront(GLenum stencilFail, 581 GLenum stencilPassDepthFail, 582 GLenum stencilPassDepthPass, 583 bool frontFaceCCW) 584 { 585 // TODO(dianx) It may be slightly more efficient todo these and other similar areas 586 // with separate dirty bits. 587 IDirect3DDevice9 *device = mRenderer9->getDevice(); 588 device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 589 gl_d3d9::ConvertStencilOp(stencilFail)); 590 device->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 591 gl_d3d9::ConvertStencilOp(stencilPassDepthFail)); 592 device->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 593 gl_d3d9::ConvertStencilOp(stencilPassDepthPass)); 594 595 mCurDepthStencilState.stencilFail = stencilFail; 596 mCurDepthStencilState.stencilPassDepthFail = stencilPassDepthFail; 597 mCurDepthStencilState.stencilPassDepthPass = stencilPassDepthPass; 598 } 599 600 void StateManager9::setStencilOpsBack(GLenum stencilBackFail, 601 GLenum stencilBackPassDepthFail, 602 GLenum stencilBackPassDepthPass, 603 bool frontFaceCCW) 604 { 605 IDirect3DDevice9 *device = mRenderer9->getDevice(); 606 device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 607 gl_d3d9::ConvertStencilOp(stencilBackFail)); 608 device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 609 gl_d3d9::ConvertStencilOp(stencilBackPassDepthFail)); 610 device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 611 gl_d3d9::ConvertStencilOp(stencilBackPassDepthPass)); 612 613 mCurDepthStencilState.stencilBackFail = stencilBackFail; 614 mCurDepthStencilState.stencilBackPassDepthFail = stencilBackPassDepthFail; 615 mCurDepthStencilState.stencilBackPassDepthPass = stencilBackPassDepthPass; 616 } 617 618 void StateManager9::setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW) 619 { 620 mRenderer9->getDevice()->SetRenderState( 621 !frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWriteMask); 622 623 mCurDepthStencilState.stencilBackWritemask = stencilBackWriteMask; 624 } 625 626 void StateManager9::setStencilFuncsBack(GLenum stencilBackFunc, 627 GLuint stencilBackMask, 628 GLint stencilBackRef, 629 bool frontFaceCCW, 630 unsigned int maxStencil) 631 { 632 IDirect3DDevice9 *device = mRenderer9->getDevice(); 633 device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 634 gl_d3d9::ConvertComparison(stencilBackFunc)); 635 device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, 636 (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); 637 device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, 638 stencilBackMask); 639 640 mCurDepthStencilState.stencilBackFunc = stencilBackFunc; 641 mCurStencilBackRef = stencilBackRef; 642 mCurDepthStencilState.stencilBackMask = stencilBackMask; 643 } 644 645 void StateManager9::setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW) 646 { 647 mRenderer9->getDevice()->SetRenderState( 648 frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWriteMask); 649 mCurDepthStencilState.stencilWritemask = stencilWriteMask; 650 } 651 652 void StateManager9::setStencilFuncsFront(GLenum stencilFunc, 653 GLuint stencilMask, 654 GLint stencilRef, 655 bool frontFaceCCW, 656 unsigned int maxStencil) 657 { 658 IDirect3DDevice9 *device = mRenderer9->getDevice(); 659 device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 660 gl_d3d9::ConvertComparison(stencilFunc)); 661 device->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, 662 (stencilRef < static_cast<int>(maxStencil)) ? stencilRef : maxStencil); 663 device->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask); 664 665 mCurDepthStencilState.stencilFunc = stencilFunc; 666 mCurStencilRef = stencilRef; 667 mCurDepthStencilState.stencilMask = stencilMask; 668 } 669 void StateManager9::setStencilTestEnabled(bool stencilTestEnabled) 670 { 671 if (stencilTestEnabled && mCurStencilSize > 0) 672 { 673 mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE); 674 mRenderer9->getDevice()->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); 675 } 676 else 677 { 678 mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, FALSE); 679 } 680 681 mCurDepthStencilState.stencilTest = stencilTestEnabled; 682 } 683 684 void StateManager9::setDepthMask(bool depthMask) 685 { 686 mRenderer9->getDevice()->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE); 687 mCurDepthStencilState.depthMask = depthMask; 688 } 689 690 // TODO(dianx) one bit for sampleAlphaToCoverage 691 void StateManager9::setSampleAlphaToCoverage(bool enabled) 692 { 693 if (enabled) 694 { 695 // D3D9 support for alpha-to-coverage is vendor-specific. 696 UNIMPLEMENTED(); 697 } 698 } 699 700 void StateManager9::setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor) 701 { 702 if (!blendState.blend) 703 return; 704 705 if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && 706 blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && 707 blendState.destBlendRGB != GL_CONSTANT_ALPHA && 708 blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) 709 { 710 mRenderer9->getDevice()->SetRenderState(D3DRS_BLENDFACTOR, 711 gl_d3d9::ConvertColor(blendColor)); 712 } 713 else 714 { 715 mRenderer9->getDevice()->SetRenderState( 716 D3DRS_BLENDFACTOR, 717 D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha), 718 gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha))); 719 } 720 mCurBlendColor = blendColor; 721 } 722 723 void StateManager9::setBlendFuncsEquations(const gl::BlendState &blendState) 724 { 725 if (!blendState.blend) 726 return; 727 728 IDirect3DDevice9 *device = mRenderer9->getDevice(); 729 730 device->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); 731 device->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); 732 device->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); 733 734 if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || 735 blendState.destBlendRGB != blendState.destBlendAlpha || 736 blendState.blendEquationRGB != blendState.blendEquationAlpha) 737 { 738 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 739 740 device->SetRenderState(D3DRS_SRCBLENDALPHA, 741 gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); 742 device->SetRenderState(D3DRS_DESTBLENDALPHA, 743 gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); 744 device->SetRenderState(D3DRS_BLENDOPALPHA, 745 gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); 746 } 747 else 748 { 749 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); 750 } 751 752 mCurBlendState.sourceBlendRGB = blendState.sourceBlendRGB; 753 mCurBlendState.destBlendRGB = blendState.destBlendRGB; 754 mCurBlendState.blendEquationRGB = blendState.blendEquationRGB; 755 mCurBlendState.blendEquationAlpha = blendState.blendEquationAlpha; 756 } 757 758 void StateManager9::setBlendEnabled(bool enabled) 759 { 760 mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE); 761 mCurBlendState.blend = enabled; 762 } 763 764 void StateManager9::setDither(bool dither) 765 { 766 mRenderer9->getDevice()->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE); 767 mCurRasterState.dither = dither; 768 } 769 770 // TODO(dianx) one bit for color mask 771 void StateManager9::setColorMask(const gl::Framebuffer *framebuffer, 772 bool red, 773 bool blue, 774 bool green, 775 bool alpha) 776 { 777 // Set the color mask 778 779 const auto *attachment = framebuffer->getFirstColorAttachment(); 780 const auto &format = attachment ? attachment->getFormat() : gl::Format::Invalid(); 781 782 DWORD colorMask = gl_d3d9::ConvertColorMask( 783 format.info->redBits > 0 && red, format.info->greenBits > 0 && green, 784 format.info->blueBits > 0 && blue, format.info->alphaBits > 0 && alpha); 785 786 // Apparently some ATI cards have a bug where a draw with a zero color write mask can cause 787 // later draws to have incorrect results. Instead, set a nonzero color write mask but modify the 788 // blend state so that no drawing is done. 789 // http://anglebug.com/169 790 if (colorMask == 0 && mUsingZeroColorMaskWorkaround) 791 { 792 IDirect3DDevice9 *device = mRenderer9->getDevice(); 793 // Enable green channel, but set blending so nothing will be drawn. 794 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); 795 796 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 797 798 device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); 799 device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); 800 device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); 801 802 mCurBlendState.colorMaskRed = false; 803 mCurBlendState.colorMaskGreen = true; 804 mCurBlendState.colorMaskBlue = false; 805 mCurBlendState.colorMaskAlpha = false; 806 807 mCurBlendState.blend = true; 808 mCurBlendState.sourceBlendRGB = GL_ZERO; 809 mCurBlendState.sourceBlendAlpha = GL_ZERO; 810 mCurBlendState.destBlendRGB = GL_ONE; 811 mCurBlendState.destBlendAlpha = GL_ONE; 812 mCurBlendState.blendEquationRGB = GL_FUNC_ADD; 813 mCurBlendState.blendEquationAlpha = GL_FUNC_ADD; 814 } 815 else 816 { 817 mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); 818 819 mCurBlendState.colorMaskRed = red; 820 mCurBlendState.colorMaskGreen = green; 821 mCurBlendState.colorMaskBlue = blue; 822 mCurBlendState.colorMaskAlpha = alpha; 823 } 824 } 825 826 void StateManager9::setSampleMask(unsigned int sampleMask) 827 { 828 IDirect3DDevice9 *device = mRenderer9->getDevice(); 829 // Set the multisample mask 830 device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); 831 device->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask)); 832 833 mCurSampleMask = sampleMask; 834 } 835 836 void StateManager9::setCullMode(bool cullFace, gl::CullFaceMode cullMode, GLenum frontFace) 837 { 838 if (cullFace) 839 { 840 mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, 841 gl_d3d9::ConvertCullMode(cullMode, frontFace)); 842 } 843 else 844 { 845 mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 846 } 847 848 mCurRasterState.cullFace = cullFace; 849 mCurRasterState.cullMode = cullMode; 850 mCurRasterState.frontFace = frontFace; 851 } 852 853 void StateManager9::setDepthBias(bool polygonOffsetFill, 854 GLfloat polygonOffsetFactor, 855 GLfloat polygonOffsetUnits) 856 { 857 if (polygonOffsetFill) 858 { 859 if (mCurDepthSize > 0) 860 { 861 IDirect3DDevice9 *device = mRenderer9->getDevice(); 862 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD *)&polygonOffsetFactor); 863 864 float depthBias = ldexp(polygonOffsetUnits, -static_cast<int>(mCurDepthSize)); 865 device->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD *)&depthBias); 866 } 867 } 868 else 869 { 870 IDirect3DDevice9 *device = mRenderer9->getDevice(); 871 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); 872 device->SetRenderState(D3DRS_DEPTHBIAS, 0); 873 } 874 875 mCurRasterState.polygonOffsetFill = polygonOffsetFill; 876 mCurRasterState.polygonOffsetFactor = polygonOffsetFactor; 877 mCurRasterState.polygonOffsetUnits = polygonOffsetUnits; 878 } 879 880 void StateManager9::updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize) 881 { 882 if (!depthStencilInitialized || depthSize != mCurDepthSize) 883 { 884 mCurDepthSize = depthSize; 885 forceSetRasterState(); 886 } 887 } 888 } // namespace rx