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
StateManager9(Renderer9 * renderer9)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
~StateManager9()68 StateManager9::~StateManager9() {}
69
initialize()70 void StateManager9::initialize()
71 {
72 mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId());
73 }
74
forceSetBlendState()75 void StateManager9::forceSetBlendState()
76 {
77 mDirtyBits |= mBlendStateDirtyBits;
78 }
79
forceSetRasterState()80 void StateManager9::forceSetRasterState()
81 {
82 mDirtyBits |= mRasterizerStateDirtyBits;
83 }
84
forceSetDepthStencilState()85 void StateManager9::forceSetDepthStencilState()
86 {
87 mDirtyBits |= mDepthStencilStateDirtyBits;
88 }
89
forceSetScissorState()90 void StateManager9::forceSetScissorState()
91 {
92 mDirtyBits |= mScissorStateDirtyBits;
93 }
94
forceSetViewportState()95 void StateManager9::forceSetViewportState()
96 {
97 mForceSetViewport = true;
98 }
99
forceSetDXUniformsState()100 void StateManager9::forceSetDXUniformsState()
101 {
102 mDxUniformsDirty = true;
103 }
104
updateStencilSizeIfChanged(bool depthStencilInitialized,unsigned int stencilSize)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
syncState(const gl::State & state,const gl::State::DirtyBits & dirtyBits)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
setBlendDepthRasterStates(const gl::State & glState,unsigned int sampleMask)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
setViewportState(const gl::Rectangle & viewport,float zNear,float zFar,gl::PrimitiveMode drawMode,GLenum frontFace,bool ignoreViewport)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
setShaderConstants()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
setScissorState(const gl::Rectangle & scissor,bool enabled)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
setRenderTargetBounds(size_t width,size_t height)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
setScissorEnabled(bool scissorEnabled)542 void StateManager9::setScissorEnabled(bool scissorEnabled)
543 {
544 mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE);
545 mCurScissorEnabled = scissorEnabled;
546 }
547
setScissorRect(const gl::Rectangle & scissor,bool enabled)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
setDepthFunc(bool depthTest,GLenum depthFunc)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
setStencilOpsFront(GLenum stencilFail,GLenum stencilPassDepthFail,GLenum stencilPassDepthPass,bool frontFaceCCW)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
setStencilOpsBack(GLenum stencilBackFail,GLenum stencilBackPassDepthFail,GLenum stencilBackPassDepthPass,bool frontFaceCCW)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
setStencilBackWriteMask(GLuint stencilBackWriteMask,bool frontFaceCCW)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
setStencilFuncsBack(GLenum stencilBackFunc,GLuint stencilBackMask,GLint stencilBackRef,bool frontFaceCCW,unsigned int maxStencil)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
setStencilWriteMask(GLuint stencilWriteMask,bool frontFaceCCW)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
setStencilFuncsFront(GLenum stencilFunc,GLuint stencilMask,GLint stencilRef,bool frontFaceCCW,unsigned int maxStencil)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 }
setStencilTestEnabled(bool stencilTestEnabled)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
setDepthMask(bool depthMask)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
setSampleAlphaToCoverage(bool enabled)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
setBlendColor(const gl::BlendState & blendState,const gl::ColorF & blendColor)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
setBlendFuncsEquations(const gl::BlendState & blendState)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
setBlendEnabled(bool enabled)758 void StateManager9::setBlendEnabled(bool enabled)
759 {
760 mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE);
761 mCurBlendState.blend = enabled;
762 }
763
setDither(bool dither)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
setColorMask(const gl::Framebuffer * framebuffer,bool red,bool blue,bool green,bool alpha)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
setSampleMask(unsigned int sampleMask)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
setCullMode(bool cullFace,gl::CullFaceMode cullMode,GLenum frontFace)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
setDepthBias(bool polygonOffsetFill,GLfloat polygonOffsetFactor,GLfloat polygonOffsetUnits)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
updateDepthSizeIfChanged(bool depthStencilInitialized,unsigned int depthSize)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
889