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