//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// StateManager9.cpp: Defines a class for caching D3D9 state
#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"

#include "common/bitset_utils.h"
#include "common/utilities.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"

namespace rx
{

StateManager9::StateManager9(Renderer9 *renderer9)
    : mUsingZeroColorMaskWorkaround(false),
      mCurBlendState(),
      mCurBlendColor(0, 0, 0, 0),
      mCurSampleMask(0),
      mCurRasterState(),
      mCurDepthSize(0),
      mCurDepthStencilState(),
      mCurStencilRef(0),
      mCurStencilBackRef(0),
      mCurFrontFaceCCW(0),
      mCurStencilSize(0),
      mCurScissorRect(),
      mCurScissorEnabled(false),
      mCurViewport(),
      mCurNear(0.0f),
      mCurFar(0.0f),
      mCurDepthFront(0.0f),
      mCurIgnoreViewport(false),
      mRenderer9(renderer9),
      mDirtyBits()
{
    mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
    mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
    mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
    mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE);
    mBlendStateDirtyBits.set(DIRTY_BIT_COLOR_MASK);
    mBlendStateDirtyBits.set(DIRTY_BIT_DITHER);
    mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_MASK);

    mRasterizerStateDirtyBits.set(DIRTY_BIT_CULL_MODE);
    mRasterizerStateDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);

    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK);
    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
    mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);

    mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED);
    mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
}

StateManager9::~StateManager9()
{
}

void StateManager9::initialize()
{
    mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId());
}

void StateManager9::forceSetBlendState()
{
    mDirtyBits |= mBlendStateDirtyBits;
}

void StateManager9::forceSetRasterState()
{
    mDirtyBits |= mRasterizerStateDirtyBits;
}

void StateManager9::forceSetDepthStencilState()
{
    mDirtyBits |= mDepthStencilStateDirtyBits;
}

void StateManager9::forceSetScissorState()
{
    mDirtyBits |= mScissorStateDirtyBits;
}

void StateManager9::forceSetViewportState()
{
    mForceSetViewport = true;
}

void StateManager9::forceSetDXUniformsState()
{
    mDxUniformsDirty = true;
}

void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized,
                                               unsigned int stencilSize)
{
    if (!depthStencilInitialized || stencilSize != mCurStencilSize)
    {
        mCurStencilSize = stencilSize;
        forceSetDepthStencilState();
    }
}

void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
{
    if (!dirtyBits.any())
    {
        return;
    }

    for (auto dirtyBit : dirtyBits)
    {
        switch (dirtyBit)
        {
            case gl::State::DIRTY_BIT_BLEND_ENABLED:
                if (state.getBlendState().blend != mCurBlendState.blend)
                {
                    mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
                    // BlendColor and funcs and equations has to be set if blend is enabled
                    mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
                    mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);

                    // The color mask may have to be updated if the blend state changes
                    if (mUsingZeroColorMaskWorkaround)
                    {
                        mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
                    }
                }
                break;
            case gl::State::DIRTY_BIT_BLEND_FUNCS:
            {
                const gl::BlendState &blendState = state.getBlendState();
                if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
                    blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
                    blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
                    blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
                {
                    mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
                    // BlendColor depends on the values of blend funcs
                    mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);

                    // The color mask may have to be updated if the blend funcs change
                    if (mUsingZeroColorMaskWorkaround)
                    {
                        mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
                    }
                }
                break;
            }
            case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
            {
                const gl::BlendState &blendState = state.getBlendState();
                if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
                    blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
                {
                    mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);

                    // The color mask may have to be updated if the blend funcs change
                    if (mUsingZeroColorMaskWorkaround)
                    {
                        mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
                    }
                }
                break;
            }
            case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
                if (state.getBlendState().sampleAlphaToCoverage !=
                    mCurBlendState.sampleAlphaToCoverage)
                {
                    mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE);
                }
                break;
            case gl::State::DIRTY_BIT_COLOR_MASK:
            {
                const gl::BlendState &blendState = state.getBlendState();
                if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
                    blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
                    blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
                    blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
                {
                    mDirtyBits.set(DIRTY_BIT_COLOR_MASK);

                    // The color mask can cause the blend state to get out of sync when using the
                    // zero color mask workaround
                    if (mUsingZeroColorMaskWorkaround)
                    {
                        mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
                        mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
                    }
                }
                break;
            }
            case gl::State::DIRTY_BIT_DITHER_ENABLED:
                if (state.getBlendState().dither != mCurBlendState.dither)
                {
                    mDirtyBits.set(DIRTY_BIT_DITHER);
                }
                break;
            case gl::State::DIRTY_BIT_BLEND_COLOR:
                if (state.getBlendColor() != mCurBlendColor)
                {
                    mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
                }
                break;
            case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
                if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
                {
                    mDirtyBits.set(DIRTY_BIT_CULL_MODE);
                }
                break;
            case gl::State::DIRTY_BIT_CULL_FACE:
                if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
                {
                    mDirtyBits.set(DIRTY_BIT_CULL_MODE);
                }
                break;
            case gl::State::DIRTY_BIT_FRONT_FACE:
                if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
                {
                    mDirtyBits.set(DIRTY_BIT_CULL_MODE);

                    // Viewport state depends on rasterizer.frontface
                    mDirtyBits.set(DIRTY_BIT_VIEWPORT);
                }
                break;
            case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
                if (state.getRasterizerState().polygonOffsetFill !=
                    mCurRasterState.polygonOffsetFill)
                {
                    mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
                }
                break;
            case gl::State::DIRTY_BIT_POLYGON_OFFSET:
            {
                const gl::RasterizerState &rasterizerState = state.getRasterizerState();
                if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
                    rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
                {
                    mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
                }
            }
            case gl::State::DIRTY_BIT_DEPTH_MASK:
                if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK);
                }
                break;
            case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
                if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
                }
                break;
            case gl::State::DIRTY_BIT_DEPTH_FUNC:
                if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
                }
                break;
            case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
                if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
                    // If we enable the stencil test, all of these must be set
                    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
                    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
                    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
                    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
                    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
                    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
                }
                break;
            case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
            {
                const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
                if (depthStencilState.stencilFunc != mCurDepthStencilState.stencilFunc ||
                    depthStencilState.stencilMask != mCurDepthStencilState.stencilMask ||
                    state.getStencilRef() != mCurStencilRef)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
                }
                break;
            }
            case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
            {
                const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
                if (depthStencilState.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
                    depthStencilState.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
                    state.getStencilBackRef() != mCurStencilBackRef)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
                }
                break;
            }
            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
                if (state.getDepthStencilState().stencilWritemask !=
                    mCurDepthStencilState.stencilWritemask)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
                }
                break;
            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
                if (state.getDepthStencilState().stencilBackWritemask !=
                    mCurDepthStencilState.stencilBackWritemask)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
                }
                break;
            case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
            {
                const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
                if (depthStencilState.stencilFail != mCurDepthStencilState.stencilFail ||
                    depthStencilState.stencilPassDepthFail !=
                        mCurDepthStencilState.stencilPassDepthFail ||
                    depthStencilState.stencilPassDepthPass !=
                        mCurDepthStencilState.stencilPassDepthPass)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
                }
                break;
            }
            case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
            {
                const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
                if (depthStencilState.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
                    depthStencilState.stencilBackPassDepthFail !=
                        mCurDepthStencilState.stencilBackPassDepthFail ||
                    depthStencilState.stencilBackPassDepthPass !=
                        mCurDepthStencilState.stencilBackPassDepthPass)
                {
                    mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
                }
                break;
            }
            case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
                if (state.isScissorTestEnabled() != mCurScissorEnabled)
                {
                    mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED);
                    // If scissor is enabled, we have to set the scissor rect
                    mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
                }
                break;
            case gl::State::DIRTY_BIT_SCISSOR:
                if (state.getScissor() != mCurScissorRect)
                {
                    mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
                }
                break;
            case gl::State::DIRTY_BIT_DEPTH_RANGE:
                if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
                {
                    mDirtyBits.set(DIRTY_BIT_VIEWPORT);
                }
                break;
            case gl::State::DIRTY_BIT_VIEWPORT:
                if (state.getViewport() != mCurViewport)
                {
                    mDirtyBits.set(DIRTY_BIT_VIEWPORT);
                }
                break;
            default:
                break;
        }
    }
}

gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState,
                                                   unsigned int sampleMask)
{
    const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();

    const gl::BlendState &blendState       = glState.getBlendState();
    const gl::ColorF &blendColor           = glState.getBlendColor();
    const gl::RasterizerState &rasterState = glState.getRasterizerState();

    const auto &depthStencilState = glState.getDepthStencilState();
    bool frontFaceCCW             = (glState.getRasterizerState().frontFace == GL_CCW);
    unsigned int maxStencil       = (1 << mCurStencilSize) - 1;

    // All the depth stencil states depends on the front face ccw variable
    if (frontFaceCCW != mCurFrontFaceCCW)
    {
        forceSetDepthStencilState();
        mCurFrontFaceCCW = frontFaceCCW;
    }

    for (auto dirtyBit : mDirtyBits)
    {
        switch (dirtyBit)
        {
            case DIRTY_BIT_BLEND_ENABLED:
                setBlendEnabled(blendState.blend);
                break;
            case DIRTY_BIT_BLEND_COLOR:
                setBlendColor(blendState, blendColor);
                break;
            case DIRTY_BIT_BLEND_FUNCS_EQUATIONS:
                setBlendFuncsEquations(blendState);
                break;
            case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE:
                setSampleAlphaToCoverage(blendState.sampleAlphaToCoverage);
                break;
            case DIRTY_BIT_COLOR_MASK:
                setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue,
                             blendState.colorMaskGreen, blendState.colorMaskAlpha);
                break;
            case DIRTY_BIT_DITHER:
                setDither(blendState.dither);
                break;
            case DIRTY_BIT_CULL_MODE:
                setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace);
                break;
            case DIRTY_BIT_DEPTH_BIAS:
                setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor,
                             rasterState.polygonOffsetUnits);
                break;
            case DIRTY_BIT_STENCIL_DEPTH_MASK:
                setDepthMask(depthStencilState.depthMask);
                break;
            case DIRTY_BIT_STENCIL_DEPTH_FUNC:
                setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc);
                break;
            case DIRTY_BIT_STENCIL_TEST_ENABLED:
                setStencilTestEnabled(depthStencilState.stencilTest);
                break;
            case DIRTY_BIT_STENCIL_FUNCS_FRONT:
                setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask,
                                     glState.getStencilRef(), frontFaceCCW, maxStencil);
                break;
            case DIRTY_BIT_STENCIL_FUNCS_BACK:
                setStencilFuncsBack(depthStencilState.stencilBackFunc,
                                    depthStencilState.stencilBackMask, glState.getStencilBackRef(),
                                    frontFaceCCW, maxStencil);
                break;
            case DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
                setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW);
                break;
            case DIRTY_BIT_STENCIL_WRITEMASK_BACK:
                setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW);
                break;
            case DIRTY_BIT_STENCIL_OPS_FRONT:
                setStencilOpsFront(depthStencilState.stencilFail,
                                   depthStencilState.stencilPassDepthFail,
                                   depthStencilState.stencilPassDepthPass, frontFaceCCW);
                break;
            case DIRTY_BIT_STENCIL_OPS_BACK:
                setStencilOpsBack(depthStencilState.stencilBackFail,
                                  depthStencilState.stencilBackPassDepthFail,
                                  depthStencilState.stencilBackPassDepthPass, frontFaceCCW);
                break;
            default:
                break;
        }
    }

    if (sampleMask != mCurSampleMask)
    {
        setSampleMask(sampleMask);
    }

    return gl::NoError();
}

void StateManager9::setViewportState(const gl::Rectangle &viewport,
                                     float zNear,
                                     float zFar,
                                     GLenum drawMode,
                                     GLenum frontFace,
                                     bool ignoreViewport)
{
    if (!mDirtyBits.test(DIRTY_BIT_VIEWPORT) && mCurIgnoreViewport == ignoreViewport)
        return;

    gl::Rectangle actualViewport = viewport;
    float actualZNear            = gl::clamp01(zNear);
    float actualZFar             = gl::clamp01(zFar);

    if (ignoreViewport)
    {
        actualViewport.x      = 0;
        actualViewport.y      = 0;
        actualViewport.width  = static_cast<int>(mRenderTargetBounds.width);
        actualViewport.height = static_cast<int>(mRenderTargetBounds.height);
        actualZNear           = 0.0f;
        actualZFar            = 1.0f;
    }

    D3DVIEWPORT9 dxViewport;
    dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetBounds.width));
    dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetBounds.height));
    dxViewport.Width =
        gl::clamp(actualViewport.width, 0,
                  static_cast<int>(mRenderTargetBounds.width) - static_cast<int>(dxViewport.X));
    dxViewport.Height =
        gl::clamp(actualViewport.height, 0,
                  static_cast<int>(mRenderTargetBounds.height) - static_cast<int>(dxViewport.Y));
    dxViewport.MinZ = actualZNear;
    dxViewport.MaxZ = actualZFar;

    float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);

    mRenderer9->getDevice()->SetViewport(&dxViewport);

    mCurViewport       = actualViewport;
    mCurNear           = actualZNear;
    mCurFar            = actualZFar;
    mCurDepthFront     = depthFront;
    mCurIgnoreViewport = ignoreViewport;

    // Setting shader constants
    dx_VertexConstants9 vc = {};
    dx_PixelConstants9 pc  = {};

    vc.viewAdjust[0] =
        static_cast<float>((actualViewport.width - static_cast<int>(dxViewport.Width)) +
                           2 * (actualViewport.x - static_cast<int>(dxViewport.X)) - 1) /
        dxViewport.Width;
    vc.viewAdjust[1] =
        static_cast<float>((actualViewport.height - static_cast<int>(dxViewport.Height)) +
                           2 * (actualViewport.y - static_cast<int>(dxViewport.Y)) - 1) /
        dxViewport.Height;
    vc.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width;
    vc.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height;

    pc.viewCoords[0] = actualViewport.width * 0.5f;
    pc.viewCoords[1] = actualViewport.height * 0.5f;
    pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
    pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);

    pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
    pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
    pc.depthFront[2] = depthFront;

    vc.depthRange[0] = actualZNear;
    vc.depthRange[1] = actualZFar;
    vc.depthRange[2] = actualZFar - actualZNear;

    pc.depthRange[0] = actualZNear;
    pc.depthRange[1] = actualZFar;
    pc.depthRange[2] = actualZFar - actualZNear;

    if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants9)) != 0)
    {
        mVertexConstants = vc;
        mDxUniformsDirty = true;
    }

    if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants9)) != 0)
    {
        mPixelConstants  = pc;
        mDxUniformsDirty = true;
    }

    mForceSetViewport = false;
}

void StateManager9::setShaderConstants()
{
    if (!mDxUniformsDirty)
        return;

    IDirect3DDevice9 *device = mRenderer9->getDevice();
    device->SetVertexShaderConstantF(0, reinterpret_cast<float *>(&mVertexConstants),
                                     sizeof(dx_VertexConstants9) / sizeof(float[4]));
    device->SetPixelShaderConstantF(0, reinterpret_cast<float *>(&mPixelConstants),
                                    sizeof(dx_PixelConstants9) / sizeof(float[4]));
    mDxUniformsDirty = false;
}

// This is separate from the main state loop because other functions
// outside call only setScissorState to update scissor state
void StateManager9::setScissorState(const gl::Rectangle &scissor, bool enabled)
{
    if (mDirtyBits.test(DIRTY_BIT_SCISSOR_ENABLED))
        setScissorEnabled(enabled);

    if (mDirtyBits.test(DIRTY_BIT_SCISSOR_RECT))
        setScissorRect(scissor, enabled);
}

void StateManager9::setRenderTargetBounds(size_t width, size_t height)
{
    mRenderTargetBounds.width  = (int)width;
    mRenderTargetBounds.height = (int)height;
    forceSetViewportState();
}

void StateManager9::setScissorEnabled(bool scissorEnabled)
{
    mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE);
    mCurScissorEnabled = scissorEnabled;
}

void StateManager9::setScissorRect(const gl::Rectangle &scissor, bool enabled)
{
    if (!enabled)
        return;

    RECT rect;
    rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetBounds.width));
    rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetBounds.height));
    rect.right =
        gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetBounds.width));
    rect.bottom =
        gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetBounds.height));
    mRenderer9->getDevice()->SetScissorRect(&rect);
}

void StateManager9::setDepthFunc(bool depthTest, GLenum depthFunc)
{
    if (depthTest)
    {
        IDirect3DDevice9 *device = mRenderer9->getDevice();
        device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
        device->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthFunc));
    }
    else
    {
        mRenderer9->getDevice()->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
    }

    mCurDepthStencilState.depthTest = depthTest;
    mCurDepthStencilState.depthFunc = depthFunc;
}

void StateManager9::setStencilOpsFront(GLenum stencilFail,
                                       GLenum stencilPassDepthFail,
                                       GLenum stencilPassDepthPass,
                                       bool frontFaceCCW)
{
    // TODO(dianx) It may be slightly more efficient todo these and other similar areas
    // with separate dirty bits.
    IDirect3DDevice9 *device = mRenderer9->getDevice();
    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
                           gl_d3d9::ConvertStencilOp(stencilFail));
    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
                           gl_d3d9::ConvertStencilOp(stencilPassDepthFail));
    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
                           gl_d3d9::ConvertStencilOp(stencilPassDepthPass));

    mCurDepthStencilState.stencilFail          = stencilFail;
    mCurDepthStencilState.stencilPassDepthFail = stencilPassDepthFail;
    mCurDepthStencilState.stencilPassDepthPass = stencilPassDepthPass;
}

void StateManager9::setStencilOpsBack(GLenum stencilBackFail,
                                      GLenum stencilBackPassDepthFail,
                                      GLenum stencilBackPassDepthPass,
                                      bool frontFaceCCW)
{
    IDirect3DDevice9 *device = mRenderer9->getDevice();
    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
                           gl_d3d9::ConvertStencilOp(stencilBackFail));
    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
                           gl_d3d9::ConvertStencilOp(stencilBackPassDepthFail));
    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
                           gl_d3d9::ConvertStencilOp(stencilBackPassDepthPass));

    mCurDepthStencilState.stencilBackFail          = stencilBackFail;
    mCurDepthStencilState.stencilBackPassDepthFail = stencilBackPassDepthFail;
    mCurDepthStencilState.stencilBackPassDepthPass = stencilBackPassDepthPass;
}

void StateManager9::setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW)
{
    mRenderer9->getDevice()->SetRenderState(
        !frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWriteMask);

    mCurDepthStencilState.stencilBackWritemask = stencilBackWriteMask;
}

void StateManager9::setStencilFuncsBack(GLenum stencilBackFunc,
                                        GLuint stencilBackMask,
                                        GLint stencilBackRef,
                                        bool frontFaceCCW,
                                        unsigned int maxStencil)
{
    IDirect3DDevice9 *device = mRenderer9->getDevice();
    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
                           gl_d3d9::ConvertComparison(stencilBackFunc));
    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
                           (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
    device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
                           stencilBackMask);

    mCurDepthStencilState.stencilBackFunc = stencilBackFunc;
    mCurStencilBackRef                    = stencilBackRef;
    mCurDepthStencilState.stencilBackMask = stencilBackMask;
}

void StateManager9::setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW)
{
    mRenderer9->getDevice()->SetRenderState(
        frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWriteMask);
    mCurDepthStencilState.stencilWritemask = stencilWriteMask;
}

void StateManager9::setStencilFuncsFront(GLenum stencilFunc,
                                         GLuint stencilMask,
                                         GLint stencilRef,
                                         bool frontFaceCCW,
                                         unsigned int maxStencil)
{
    IDirect3DDevice9 *device = mRenderer9->getDevice();
    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
                           gl_d3d9::ConvertComparison(stencilFunc));
    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
                           (stencilRef < static_cast<int>(maxStencil)) ? stencilRef : maxStencil);
    device->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);

    mCurDepthStencilState.stencilFunc = stencilFunc;
    mCurStencilRef                    = stencilRef;
    mCurDepthStencilState.stencilMask = stencilMask;
}
void StateManager9::setStencilTestEnabled(bool stencilTestEnabled)
{
    if (stencilTestEnabled && mCurStencilSize > 0)
    {
        mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE);
        mRenderer9->getDevice()->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
    }
    else
    {
        mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, FALSE);
    }

    mCurDepthStencilState.stencilTest = stencilTestEnabled;
}

void StateManager9::setDepthMask(bool depthMask)
{
    mRenderer9->getDevice()->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
    mCurDepthStencilState.depthMask = depthMask;
}

// TODO(dianx) one bit for sampleAlphaToCoverage
void StateManager9::setSampleAlphaToCoverage(bool enabled)
{
    if (enabled)
    {
        UNREACHABLE();
    }
}

void StateManager9::setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor)
{
    if (!blendState.blend)
        return;

    if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
        blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
        blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
        blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
    {
        mRenderer9->getDevice()->SetRenderState(D3DRS_BLENDFACTOR,
                                                gl_d3d9::ConvertColor(blendColor));
    }
    else
    {
        mRenderer9->getDevice()->SetRenderState(
            D3DRS_BLENDFACTOR,
            D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha),
                          gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha)));
    }
    mCurBlendColor = blendColor;
}

void StateManager9::setBlendFuncsEquations(const gl::BlendState &blendState)
{
    if (!blendState.blend)
        return;

    IDirect3DDevice9 *device = mRenderer9->getDevice();

    device->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
    device->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
    device->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));

    if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
        blendState.destBlendRGB != blendState.destBlendAlpha ||
        blendState.blendEquationRGB != blendState.blendEquationAlpha)
    {
        device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);

        device->SetRenderState(D3DRS_SRCBLENDALPHA,
                               gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
        device->SetRenderState(D3DRS_DESTBLENDALPHA,
                               gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
        device->SetRenderState(D3DRS_BLENDOPALPHA,
                               gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
    }
    else
    {
        device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
    }

    mCurBlendState.sourceBlendRGB     = blendState.sourceBlendRGB;
    mCurBlendState.destBlendRGB       = blendState.destBlendRGB;
    mCurBlendState.blendEquationRGB   = blendState.blendEquationRGB;
    mCurBlendState.blendEquationAlpha = blendState.blendEquationAlpha;
}

void StateManager9::setBlendEnabled(bool enabled)
{
    mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE);
    mCurBlendState.blend = enabled;
}

void StateManager9::setDither(bool dither)
{
    mRenderer9->getDevice()->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
    mCurBlendState.dither = dither;
}

// TODO(dianx) one bit for color mask
void StateManager9::setColorMask(const gl::Framebuffer *framebuffer,
                                 bool red,
                                 bool blue,
                                 bool green,
                                 bool alpha)
{
    // Set the color mask

    const auto *attachment = framebuffer->getFirstColorbuffer();
    const auto &format     = attachment ? attachment->getFormat() : gl::Format::Invalid();

    DWORD colorMask = gl_d3d9::ConvertColorMask(
        format.info->redBits > 0 && red, format.info->greenBits > 0 && green,
        format.info->blueBits > 0 && blue, format.info->alphaBits > 0 && alpha);

    // Apparently some ATI cards have a bug where a draw with a zero color write mask can cause
    // later draws to have incorrect results. Instead, set a nonzero color write mask but modify the
    // blend state so that no drawing is done.
    // http://anglebug.com/169
    if (colorMask == 0 && mUsingZeroColorMaskWorkaround)
    {
        IDirect3DDevice9 *device = mRenderer9->getDevice();
        // Enable green channel, but set blending so nothing will be drawn.
        device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);

        device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

        device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
        device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
        device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);

        mCurBlendState.colorMaskRed   = false;
        mCurBlendState.colorMaskGreen = true;
        mCurBlendState.colorMaskBlue  = false;
        mCurBlendState.colorMaskAlpha = false;

        mCurBlendState.blend              = true;
        mCurBlendState.sourceBlendRGB     = GL_ZERO;
        mCurBlendState.sourceBlendAlpha   = GL_ZERO;
        mCurBlendState.destBlendRGB       = GL_ONE;
        mCurBlendState.destBlendAlpha     = GL_ONE;
        mCurBlendState.blendEquationRGB   = GL_FUNC_ADD;
        mCurBlendState.blendEquationAlpha = GL_FUNC_ADD;
    }
    else
    {
        mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);

        mCurBlendState.colorMaskRed   = red;
        mCurBlendState.colorMaskGreen = green;
        mCurBlendState.colorMaskBlue  = blue;
        mCurBlendState.colorMaskAlpha = alpha;
    }
}

void StateManager9::setSampleMask(unsigned int sampleMask)
{
    IDirect3DDevice9 *device = mRenderer9->getDevice();
    // Set the multisample mask
    device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
    device->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));

    mCurSampleMask = sampleMask;
}

void StateManager9::setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace)
{
    if (cullFace)
    {
        mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE,
                                                gl_d3d9::ConvertCullMode(cullMode, frontFace));
    }
    else
    {
        mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    }

    mCurRasterState.cullFace  = cullFace;
    mCurRasterState.cullMode  = cullMode;
    mCurRasterState.frontFace = frontFace;
}

void StateManager9::setDepthBias(bool polygonOffsetFill,
                                 GLfloat polygonOffsetFactor,
                                 GLfloat polygonOffsetUnits)
{
    if (polygonOffsetFill)
    {
        if (mCurDepthSize > 0)
        {
            IDirect3DDevice9 *device = mRenderer9->getDevice();
            device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD *)&polygonOffsetFactor);

            float depthBias = ldexp(polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
            device->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD *)&depthBias);
        }
    }
    else
    {
        IDirect3DDevice9 *device = mRenderer9->getDevice();
        device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
        device->SetRenderState(D3DRS_DEPTHBIAS, 0);
    }

    mCurRasterState.polygonOffsetFill   = polygonOffsetFill;
    mCurRasterState.polygonOffsetFactor = polygonOffsetFactor;
    mCurRasterState.polygonOffsetUnits  = polygonOffsetUnits;
}

void StateManager9::updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize)
{
    if (!depthStencilInitialized || depthSize != mCurDepthSize)
    {
        mCurDepthSize = depthSize;
        forceSetRasterState();
    }
}
}  // namespace rx
