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