• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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