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