tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

StateManager9.cpp (35774B)


      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 
     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 
     68 StateManager9::~StateManager9() {}
     69 
     70 void StateManager9::initialize()
     71 {
     72    mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId());
     73 }
     74 
     75 void StateManager9::forceSetBlendState()
     76 {
     77    mDirtyBits |= mBlendStateDirtyBits;
     78 }
     79 
     80 void StateManager9::forceSetRasterState()
     81 {
     82    mDirtyBits |= mRasterizerStateDirtyBits;
     83 }
     84 
     85 void StateManager9::forceSetDepthStencilState()
     86 {
     87    mDirtyBits |= mDepthStencilStateDirtyBits;
     88 }
     89 
     90 void StateManager9::forceSetScissorState()
     91 {
     92    mDirtyBits |= mScissorStateDirtyBits;
     93 }
     94 
     95 void StateManager9::forceSetViewportState()
     96 {
     97    mForceSetViewport = true;
     98 }
     99 
    100 void StateManager9::forceSetDXUniformsState()
    101 {
    102    mDxUniformsDirty = true;
    103 }
    104 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    542 void StateManager9::setScissorEnabled(bool scissorEnabled)
    543 {
    544    mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE);
    545    mCurScissorEnabled = scissorEnabled;
    546 }
    547 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 }
    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 
    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
    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 
    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 
    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 
    758 void StateManager9::setBlendEnabled(bool enabled)
    759 {
    760    mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE);
    761    mCurBlendState.blend = enabled;
    762 }
    763 
    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
    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 
    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 
    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 
    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 
    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