//
// Copyright 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.
//

// StateManagerGL.h: Defines a class for caching applied OpenGL state

#include "libANGLE/renderer/gl/StateManagerGL.h"

#include <string.h>
#include <algorithm>
#include <limits>

#include "anglebase/numerics/safe_conversions.h"
#include "common/bitset_utils.h"
#include "common/mathutil.h"
#include "common/matrix_utils.h"
#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/Query.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/ProgramGL.h"
#include "libANGLE/renderer/gl/QueryGL.h"
#include "libANGLE/renderer/gl/SamplerGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
#include "libANGLE/renderer/gl/VertexArrayGL.h"

namespace rx
{

namespace
{

static void ValidateStateHelper(const FunctionsGL *functions,
                                const GLuint localValue,
                                const GLenum pname,
                                const char *localName,
                                const char *driverName)
{
    GLint queryValue;
    functions->getIntegerv(pname, &queryValue);
    if (localValue != static_cast<GLuint>(queryValue))
    {
        WARN() << localName << " (" << localValue << ") != " << driverName << " (" << queryValue
               << ")";
        // Re-add ASSERT: http://anglebug.com/3900
        // ASSERT(false);
    }
}

}  // anonymous namespace

VertexArrayStateGL::VertexArrayStateGL(size_t maxAttribs, size_t maxBindings)
    : attributes(std::min<size_t>(maxAttribs, gl::MAX_VERTEX_ATTRIBS)),
      bindings(std::min<size_t>(maxBindings, gl::MAX_VERTEX_ATTRIBS))
{
    // Set the cached vertex attribute array and vertex attribute binding array size
    for (GLuint i = 0; i < attributes.size(); i++)
    {
        attributes[i].bindingIndex = i;
    }
}

StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0) {}

StateManagerGL::StateManagerGL(const FunctionsGL *functions,
                               const gl::Caps &rendererCaps,
                               const gl::Extensions &extensions,
                               const angle::FeaturesGL &features)
    : mFunctions(functions),
      mFeatures(features),
      mProgram(0),
      mVAO(0),
      mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
      mDefaultVAOState(rendererCaps.maxVertexAttributes, rendererCaps.maxVertexAttribBindings),
      mVAOState(&mDefaultVAOState),
      mBuffers(),
      mIndexedBuffers(),
      mTextureUnitIndex(0),
      mTextures{},
      mSamplers{},
      mImages(rendererCaps.maxImageUnits, ImageUnitBinding()),
      mTransformFeedback(0),
      mCurrentTransformFeedback(nullptr),
      mQueries(),
      mPrevDrawContext({0}),
      mUnpackAlignment(4),
      mUnpackRowLength(0),
      mUnpackSkipRows(0),
      mUnpackSkipPixels(0),
      mUnpackImageHeight(0),
      mUnpackSkipImages(0),
      mPackAlignment(4),
      mPackRowLength(0),
      mPackSkipRows(0),
      mPackSkipPixels(0),
      mFramebuffers(angle::FramebufferBindingSingletonMax, 0),
      mRenderbuffer(0),
      mScissorTestEnabled(false),
      mScissor(0, 0, 0, 0),
      mViewport(0, 0, 0, 0),
      mNear(0.0f),
      mFar(1.0f),
      mBlendColor(0, 0, 0, 0),
      mBlendStateExt(rendererCaps.maxDrawBuffers),
      mIndependentBlendStates(extensions.drawBuffersIndexedAny()),
      mSampleAlphaToCoverageEnabled(false),
      mSampleCoverageEnabled(false),
      mSampleCoverageValue(1.0f),
      mSampleCoverageInvert(false),
      mSampleMaskEnabled(false),
      mDepthTestEnabled(false),
      mDepthFunc(GL_LESS),
      mDepthMask(true),
      mStencilTestEnabled(false),
      mStencilFrontFunc(GL_ALWAYS),
      mStencilFrontRef(0),
      mStencilFrontValueMask(static_cast<GLuint>(-1)),
      mStencilFrontStencilFailOp(GL_KEEP),
      mStencilFrontStencilPassDepthFailOp(GL_KEEP),
      mStencilFrontStencilPassDepthPassOp(GL_KEEP),
      mStencilFrontWritemask(static_cast<GLuint>(-1)),
      mStencilBackFunc(GL_ALWAYS),
      mStencilBackRef(0),
      mStencilBackValueMask(static_cast<GLuint>(-1)),
      mStencilBackStencilFailOp(GL_KEEP),
      mStencilBackStencilPassDepthFailOp(GL_KEEP),
      mStencilBackStencilPassDepthPassOp(GL_KEEP),
      mStencilBackWritemask(static_cast<GLuint>(-1)),
      mCullFaceEnabled(false),
      mCullFace(gl::CullFaceMode::Back),
      mFrontFace(GL_CCW),
      mPolygonOffsetFillEnabled(false),
      mPolygonOffsetFactor(0.0f),
      mPolygonOffsetUnits(0.0f),
      mRasterizerDiscardEnabled(false),
      mLineWidth(1.0f),
      mPrimitiveRestartEnabled(false),
      mPrimitiveRestartIndex(0),
      mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
      mClearDepth(1.0f),
      mClearStencil(0),
      mFramebufferSRGBAvailable(extensions.sRGBWriteControlEXT),
      mFramebufferSRGBEnabled(false),
      mHasSeparateFramebufferBindings(mFunctions->isAtLeastGL(gl::Version(3, 0)) ||
                                      mFunctions->isAtLeastGLES(gl::Version(3, 0))),
      mDitherEnabled(true),
      mTextureCubemapSeamlessEnabled(false),
      mMultisamplingEnabled(true),
      mSampleAlphaToOneEnabled(false),
      mCoverageModulation(GL_NONE),
      mIsMultiviewEnabled(extensions.multiviewOVR || extensions.multiview2OVR),
      mProvokingVertex(GL_LAST_VERTEX_CONVENTION),
      mMaxClipDistances(rendererCaps.maxClipDistances),
      mLocalDirtyBits()
{
    ASSERT(mFunctions);
    ASSERT(rendererCaps.maxViews >= 1u);

    mIndexedBuffers[gl::BufferBinding::Uniform].resize(rendererCaps.maxUniformBufferBindings);
    mIndexedBuffers[gl::BufferBinding::AtomicCounter].resize(
        rendererCaps.maxAtomicCounterBufferBindings);
    mIndexedBuffers[gl::BufferBinding::ShaderStorage].resize(
        rendererCaps.maxShaderStorageBufferBindings);

    mSampleMaskValues.fill(~GLbitfield(0));

    mQueries.fill(nullptr);
    mTemporaryPausedQueries.fill(nullptr);

    // Initialize point sprite state for desktop GL
    if (mFunctions->standard == STANDARD_GL_DESKTOP)
    {
        mFunctions->enable(GL_PROGRAM_POINT_SIZE);

        // GL_POINT_SPRITE was deprecated in the core profile. Point rasterization is always
        // performed
        // as though POINT_SPRITE were enabled.
        if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0)
        {
            mFunctions->enable(GL_POINT_SPRITE);
        }
    }

    if (features.emulatePrimitiveRestartFixedIndex.enabled)
    {
        // There is no consistent default value for primitive restart index. Set it to UINT -1.
        constexpr GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndexFromType<GLuint>();
        mFunctions->primitiveRestartIndex(primitiveRestartIndex);
        mPrimitiveRestartIndex = primitiveRestartIndex;
    }

    // It's possible we've enabled the emulated VAO feature for testing but we're on a core profile.
    // Use a generated VAO as the default VAO so we can still test.
    if (features.syncVertexArraysToDefault.enabled &&
        !nativegl::CanUseDefaultVertexArrayObject(mFunctions))
    {
        ASSERT(nativegl::SupportsVertexArrayObjects(mFunctions));
        mFunctions->genVertexArrays(1, &mDefaultVAO);
        mFunctions->bindVertexArray(mDefaultVAO);
        mVAO = mDefaultVAO;
    }
}

StateManagerGL::~StateManagerGL()
{
    if (mDefaultVAO != 0)
    {
        mFunctions->deleteVertexArrays(1, &mDefaultVAO);
    }
}

void StateManagerGL::deleteProgram(GLuint program)
{
    if (program != 0)
    {
        if (mProgram == program)
        {
            useProgram(0);
        }

        mFunctions->deleteProgram(program);
    }
}

void StateManagerGL::deleteVertexArray(GLuint vao)
{
    if (vao != 0)
    {
        if (mVAO == vao)
        {
            bindVertexArray(0, &mDefaultVAOState);
        }
        mFunctions->deleteVertexArrays(1, &vao);
    }
}

void StateManagerGL::deleteTexture(GLuint texture)
{
    if (texture != 0)
    {
        for (gl::TextureType type : angle::AllEnums<gl::TextureType>())
        {
            const auto &textureVector = mTextures[type];
            for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size();
                 textureUnitIndex++)
            {
                if (textureVector[textureUnitIndex] == texture)
                {
                    activeTexture(textureUnitIndex);
                    bindTexture(type, 0);
                }
            }
        }

        for (size_t imageUnitIndex = 0; imageUnitIndex < mImages.size(); imageUnitIndex++)
        {
            if (mImages[imageUnitIndex].texture == texture)
            {
                bindImageTexture(imageUnitIndex, 0, 0, false, 0, GL_READ_ONLY, GL_R32UI);
            }
        }

        mFunctions->deleteTextures(1, &texture);
    }
}

void StateManagerGL::deleteSampler(GLuint sampler)
{
    if (sampler != 0)
    {
        for (size_t unit = 0; unit < mSamplers.size(); unit++)
        {
            if (mSamplers[unit] == sampler)
            {
                bindSampler(unit, 0);
            }
        }

        mFunctions->deleteSamplers(1, &sampler);
    }
}

void StateManagerGL::deleteBuffer(GLuint buffer)
{
    if (buffer == 0)
    {
        return;
    }

    for (auto target : angle::AllEnums<gl::BufferBinding>())
    {
        if (mBuffers[target] == buffer)
        {
            bindBuffer(target, 0);
        }

        auto &indexedTarget = mIndexedBuffers[target];
        for (size_t bindIndex = 0; bindIndex < indexedTarget.size(); ++bindIndex)
        {
            if (indexedTarget[bindIndex].buffer == buffer)
            {
                bindBufferBase(target, bindIndex, 0);
            }
        }
    }

    if (mVAOState)
    {
        if (mVAOState->elementArrayBuffer == buffer)
        {
            mVAOState->elementArrayBuffer = 0;
        }

        for (VertexBindingGL &binding : mVAOState->bindings)
        {
            if (binding.buffer == buffer)
            {
                binding.buffer = 0;
            }
        }
    }

    mFunctions->deleteBuffers(1, &buffer);
}

void StateManagerGL::deleteFramebuffer(GLuint fbo)
{
    if (fbo != 0)
    {
        if (mHasSeparateFramebufferBindings)
        {
            for (size_t binding = 0; binding < mFramebuffers.size(); ++binding)
            {
                if (mFramebuffers[binding] == fbo)
                {
                    GLenum enumValue = angle::FramebufferBindingToEnum(
                        static_cast<angle::FramebufferBinding>(binding));
                    bindFramebuffer(enumValue, 0);
                }
            }
        }
        else
        {
            ASSERT(mFramebuffers[angle::FramebufferBindingRead] ==
                   mFramebuffers[angle::FramebufferBindingDraw]);
            if (mFramebuffers[angle::FramebufferBindingRead] == fbo)
            {
                bindFramebuffer(GL_FRAMEBUFFER, 0);
            }
        }
        mFunctions->deleteFramebuffers(1, &fbo);
    }
}

void StateManagerGL::deleteRenderbuffer(GLuint rbo)
{
    if (rbo != 0)
    {
        if (mRenderbuffer == rbo)
        {
            bindRenderbuffer(GL_RENDERBUFFER, 0);
        }

        mFunctions->deleteRenderbuffers(1, &rbo);
    }
}

void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
{
    if (transformFeedback != 0)
    {
        if (mTransformFeedback == transformFeedback)
        {
            bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
        }

        if (mCurrentTransformFeedback != nullptr &&
            mCurrentTransformFeedback->getTransformFeedbackID() == transformFeedback)
        {
            mCurrentTransformFeedback = nullptr;
        }

        mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
    }
}

void StateManagerGL::useProgram(GLuint program)
{
    if (mProgram != program)
    {
        forceUseProgram(program);
    }
}

void StateManagerGL::forceUseProgram(GLuint program)
{
    mProgram = program;
    mFunctions->useProgram(mProgram);
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROGRAM_BINDING);
}

void StateManagerGL::bindVertexArray(GLuint vao, VertexArrayStateGL *vaoState)
{
    ASSERT(vaoState);
    if (mVAO != vao)
    {
        ASSERT(!mFeatures.syncVertexArraysToDefault.enabled);

        mVAO                                      = vao;
        mVAOState                                 = vaoState;
        mBuffers[gl::BufferBinding::ElementArray] = vaoState ? vaoState->elementArrayBuffer : 0;

        mFunctions->bindVertexArray(vao);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
    }
}

void StateManagerGL::bindBuffer(gl::BufferBinding target, GLuint buffer)
{
    // GL drivers differ in whether the transform feedback bind point is modified when
    // glBindTransformFeedback is called. To avoid these behavior differences we shouldn't try to
    // use it.
    ASSERT(target != gl::BufferBinding::TransformFeedback);
    if (mBuffers[target] != buffer)
    {
        mBuffers[target] = buffer;
        mFunctions->bindBuffer(gl::ToGLenum(target), buffer);
    }
}

void StateManagerGL::bindBufferBase(gl::BufferBinding target, size_t index, GLuint buffer)
{
    // Transform feedback buffer bindings are tracked in TransformFeedbackGL
    ASSERT(target != gl::BufferBinding::TransformFeedback);

    ASSERT(index < mIndexedBuffers[target].size());
    auto &binding = mIndexedBuffers[target][index];
    if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) ||
        binding.size != static_cast<size_t>(-1))
    {
        binding.buffer   = buffer;
        binding.offset   = static_cast<size_t>(-1);
        binding.size     = static_cast<size_t>(-1);
        mBuffers[target] = buffer;
        mFunctions->bindBufferBase(gl::ToGLenum(target), static_cast<GLuint>(index), buffer);
    }
}

void StateManagerGL::bindBufferRange(gl::BufferBinding target,
                                     size_t index,
                                     GLuint buffer,
                                     size_t offset,
                                     size_t size)
{
    // Transform feedback buffer bindings are tracked in TransformFeedbackGL
    ASSERT(target != gl::BufferBinding::TransformFeedback);

    auto &binding = mIndexedBuffers[target][index];
    if (binding.buffer != buffer || binding.offset != offset || binding.size != size)
    {
        binding.buffer   = buffer;
        binding.offset   = offset;
        binding.size     = size;
        mBuffers[target] = buffer;
        mFunctions->bindBufferRange(gl::ToGLenum(target), static_cast<GLuint>(index), buffer,
                                    offset, size);
    }
}

void StateManagerGL::activeTexture(size_t unit)
{
    if (mTextureUnitIndex != unit)
    {
        mTextureUnitIndex = unit;
        mFunctions->activeTexture(GL_TEXTURE0 + static_cast<GLenum>(mTextureUnitIndex));
    }
}

void StateManagerGL::bindTexture(gl::TextureType type, GLuint texture)
{
    gl::TextureType nativeType = nativegl::GetNativeTextureType(type);
    if (mTextures[nativeType][mTextureUnitIndex] != texture)
    {
        mTextures[nativeType][mTextureUnitIndex] = texture;
        mFunctions->bindTexture(nativegl::GetTextureBindingTarget(type), texture);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
    }
}

void StateManagerGL::invalidateTexture(gl::TextureType type)
{
    // Assume the tracked texture binding is incorrect, query the real bound texture from GL.
    GLint boundTexture = 0;
    mFunctions->getIntegerv(nativegl::GetTextureBindingQuery(type), &boundTexture);
    mTextures[type][mTextureUnitIndex] = static_cast<GLuint>(boundTexture);
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
}

void StateManagerGL::bindSampler(size_t unit, GLuint sampler)
{
    if (mSamplers[unit] != sampler)
    {
        mSamplers[unit] = sampler;
        mFunctions->bindSampler(static_cast<GLuint>(unit), sampler);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLER_BINDINGS);
    }
}

void StateManagerGL::bindImageTexture(size_t unit,
                                      GLuint texture,
                                      GLint level,
                                      GLboolean layered,
                                      GLint layer,
                                      GLenum access,
                                      GLenum format)
{
    auto &binding = mImages[unit];
    if (binding.texture != texture || binding.level != level || binding.layered != layered ||
        binding.layer != layer || binding.access != access || binding.format != format)
    {
        binding.texture = texture;
        binding.level   = level;
        binding.layered = layered;
        binding.layer   = layer;
        binding.access  = access;
        binding.format  = format;
        mFunctions->bindImageTexture(angle::base::checked_cast<GLuint>(unit), texture, level,
                                     layered, layer, access, format);
    }
}

angle::Result StateManagerGL::setPixelUnpackState(const gl::Context *context,
                                                  const gl::PixelUnpackState &unpack)
{
    if (mUnpackAlignment != unpack.alignment)
    {
        mUnpackAlignment = unpack.alignment;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, mUnpackAlignment));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
    }

    if (mUnpackRowLength != unpack.rowLength)
    {
        mUnpackRowLength = unpack.rowLength;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_ROW_LENGTH, mUnpackRowLength));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
    }

    if (mUnpackSkipRows != unpack.skipRows)
    {
        mUnpackSkipRows = unpack.skipRows;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_SKIP_ROWS, mUnpackSkipRows));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
    }

    if (mUnpackSkipPixels != unpack.skipPixels)
    {
        mUnpackSkipPixels = unpack.skipPixels;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
    }

    if (mUnpackImageHeight != unpack.imageHeight)
    {
        mUnpackImageHeight = unpack.imageHeight;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, mUnpackImageHeight));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
    }

    if (mUnpackSkipImages != unpack.skipImages)
    {
        mUnpackSkipImages = unpack.skipImages;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
    }

    return angle::Result::Continue;
}

angle::Result StateManagerGL::setPixelUnpackBuffer(const gl::Context *context,
                                                   const gl::Buffer *pixelBuffer)
{
    GLuint bufferID = 0;
    if (pixelBuffer != nullptr)
    {
        bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
    }
    bindBuffer(gl::BufferBinding::PixelUnpack, bufferID);

    return angle::Result::Continue;
}

angle::Result StateManagerGL::setPixelPackState(const gl::Context *context,
                                                const gl::PixelPackState &pack)
{
    if (mPackAlignment != pack.alignment)
    {
        mPackAlignment = pack.alignment;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_ALIGNMENT, mPackAlignment));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
    }

    if (mPackRowLength != pack.rowLength)
    {
        mPackRowLength = pack.rowLength;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_ROW_LENGTH, mPackRowLength));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
    }

    if (mPackSkipRows != pack.skipRows)
    {
        mPackSkipRows = pack.skipRows;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_SKIP_ROWS, mPackSkipRows));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
    }

    if (mPackSkipPixels != pack.skipPixels)
    {
        mPackSkipPixels = pack.skipPixels;
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_SKIP_PIXELS, mPackSkipPixels));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
    }

    return angle::Result::Continue;
}

angle::Result StateManagerGL::setPixelPackBuffer(const gl::Context *context,
                                                 const gl::Buffer *pixelBuffer)
{
    GLuint bufferID = 0;
    if (pixelBuffer != nullptr)
    {
        bufferID = GetImplAs<BufferGL>(pixelBuffer)->getBufferID();
    }
    bindBuffer(gl::BufferBinding::PixelPack, bufferID);

    return angle::Result::Continue;
}

void StateManagerGL::bindFramebuffer(GLenum type, GLuint framebuffer)
{
    bool framebufferChanged = false;
    switch (type)
    {
        case GL_FRAMEBUFFER:
            if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer ||
                mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
            {
                mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
                mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
                mFunctions->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);

                mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
                mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);

                framebufferChanged = true;
            }
            break;

        case GL_READ_FRAMEBUFFER:
            ASSERT(mHasSeparateFramebufferBindings);
            if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer)
            {
                mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
                mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);

                mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);

                framebufferChanged = true;
            }
            break;

        case GL_DRAW_FRAMEBUFFER:
            ASSERT(mHasSeparateFramebufferBindings);
            if (mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
            {
                mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
                mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);

                mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);

                framebufferChanged = true;
            }
            break;

        default:
            UNREACHABLE();
            break;
    }

    if (framebufferChanged && mFeatures.flushOnFramebufferChange.enabled)
    {
        mFunctions->flush();
    }
}

void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
{
    ASSERT(type == GL_RENDERBUFFER);
    if (mRenderbuffer != renderbuffer)
    {
        mRenderbuffer = renderbuffer;
        mFunctions->bindRenderbuffer(type, mRenderbuffer);
    }
}

void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
{
    ASSERT(type == GL_TRANSFORM_FEEDBACK);
    if (mTransformFeedback != transformFeedback)
    {
        // Pause the current transform feedback if one is active.
        // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
        // feedback at any time, even if there is one active.
        if (mCurrentTransformFeedback != nullptr &&
            mCurrentTransformFeedback->getTransformFeedbackID() != transformFeedback)
        {
            mCurrentTransformFeedback->syncPausedState(true);
            mCurrentTransformFeedback = nullptr;
        }

        mTransformFeedback = transformFeedback;
        mFunctions->bindTransformFeedback(type, mTransformFeedback);
        onTransformFeedbackStateChange();
    }
}

void StateManagerGL::onTransformFeedbackStateChange()
{
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
}

void StateManagerGL::beginQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId)
{
    // Make sure this is a valid query type and there is no current active query of this type
    ASSERT(mQueries[type] == nullptr);
    ASSERT(queryId != 0);

    mQueries[type] = queryObject;
    mFunctions->beginQuery(ToGLenum(type), queryId);
}

void StateManagerGL::endQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId)
{
    ASSERT(queryObject != nullptr);
    ASSERT(mQueries[type] == queryObject);
    mQueries[type] = nullptr;
    mFunctions->endQuery(ToGLenum(type));
}

void StateManagerGL::updateDrawIndirectBufferBinding(const gl::Context *context)
{
    gl::Buffer *drawIndirectBuffer =
        context->getState().getTargetBuffer(gl::BufferBinding::DrawIndirect);
    if (drawIndirectBuffer != nullptr)
    {
        const BufferGL *bufferGL = GetImplAs<BufferGL>(drawIndirectBuffer);
        bindBuffer(gl::BufferBinding::DrawIndirect, bufferGL->getBufferID());
    }
}

void StateManagerGL::updateDispatchIndirectBufferBinding(const gl::Context *context)
{
    gl::Buffer *dispatchIndirectBuffer =
        context->getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
    if (dispatchIndirectBuffer != nullptr)
    {
        const BufferGL *bufferGL = GetImplAs<BufferGL>(dispatchIndirectBuffer);
        bindBuffer(gl::BufferBinding::DispatchIndirect, bufferGL->getBufferID());
    }
}

void StateManagerGL::pauseTransformFeedback()
{
    if (mCurrentTransformFeedback != nullptr)
    {
        mCurrentTransformFeedback->syncPausedState(true);
        onTransformFeedbackStateChange();
    }
}

angle::Result StateManagerGL::pauseAllQueries(const gl::Context *context)
{
    for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
    {
        QueryGL *previousQuery = mQueries[type];

        if (previousQuery != nullptr)
        {
            ANGLE_TRY(previousQuery->pause(context));
            mTemporaryPausedQueries[type] = previousQuery;
            mQueries[type]                = nullptr;
        }
    }

    return angle::Result::Continue;
}

angle::Result StateManagerGL::pauseQuery(const gl::Context *context, gl::QueryType type)
{
    QueryGL *previousQuery = mQueries[type];

    if (previousQuery)
    {
        ANGLE_TRY(previousQuery->pause(context));
        mTemporaryPausedQueries[type] = previousQuery;
        mQueries[type]                = nullptr;
    }

    return angle::Result::Continue;
}

angle::Result StateManagerGL::resumeAllQueries(const gl::Context *context)
{
    for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
    {
        QueryGL *pausedQuery = mTemporaryPausedQueries[type];

        if (pausedQuery != nullptr)
        {
            ASSERT(mQueries[type] == nullptr);
            ANGLE_TRY(pausedQuery->resume(context));
            mTemporaryPausedQueries[type] = nullptr;
        }
    }

    return angle::Result::Continue;
}

angle::Result StateManagerGL::resumeQuery(const gl::Context *context, gl::QueryType type)
{
    QueryGL *pausedQuery = mTemporaryPausedQueries[type];

    if (pausedQuery != nullptr)
    {
        ANGLE_TRY(pausedQuery->resume(context));
        mTemporaryPausedQueries[type] = nullptr;
    }

    return angle::Result::Continue;
}

angle::Result StateManagerGL::onMakeCurrent(const gl::Context *context)
{
    const gl::State &glState = context->getState();

#if defined(ANGLE_ENABLE_ASSERTS)
    // Temporarily pausing queries during context switch is not supported
    for (QueryGL *pausedQuery : mTemporaryPausedQueries)
    {
        ASSERT(pausedQuery == nullptr);
    }
#endif

    // If the context has changed, pause the previous context's queries
    auto contextID = context->getState().getContextID();
    if (contextID != mPrevDrawContext)
    {
        for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
        {
            QueryGL *currentQuery = mQueries[type];
            // Pause any old query object
            if (currentQuery != nullptr)
            {
                ANGLE_TRY(currentQuery->pause(context));
                mQueries[type] = nullptr;
            }

            // Check if this new context needs to resume a query
            gl::Query *newQuery = glState.getActiveQuery(type);
            if (newQuery != nullptr)
            {
                QueryGL *queryGL = GetImplAs<QueryGL>(newQuery);
                ANGLE_TRY(queryGL->resume(context));
            }
        }
    }
    onTransformFeedbackStateChange();
    mPrevDrawContext = contextID;

    // Seamless cubemaps are required for ES3 and higher contexts. It should be the cheapest to set
    // this state here since MakeCurrent is expected to be called less frequently than draw calls.
    setTextureCubemapSeamlessEnabled(context->getClientMajorVersion() >= 3);

    return angle::Result::Continue;
}

void StateManagerGL::updateProgramTextureBindings(const gl::Context *context)
{
    const gl::State &glState                = context->getState();
    const gl::ProgramExecutable *executable = glState.getProgramExecutable();

    // It is possible there is no active program during a path operation.
    if (!executable)
        return;

    const gl::ActiveTexturesCache &textures        = glState.getActiveTexturesCache();
    const gl::ActiveTextureMask &activeTextures    = executable->getActiveSamplersMask();
    const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();

    for (size_t textureUnitIndex : activeTextures)
    {
        gl::TextureType textureType = textureTypes[textureUnitIndex];
        gl::Texture *texture        = textures[textureUnitIndex];

        // A nullptr texture indicates incomplete.
        if (texture != nullptr)
        {
            const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
            // The DIRTY_BIT_BOUND_AS_ATTACHMENT may get inserted when texture is attached to
            // FBO and if texture is already bound, Texture::syncState will not get called and dirty
            // bit not gets cleared. But this bit is not used by GL backend at all, so it is
            // harmless even though we expect texture is clean when reaching here. The bit will
            // still get cleared next time syncState been called.
            ASSERT(!texture->hasAnyDirtyBitExcludingBoundAsAttachmentBit());
            ASSERT(!textureGL->hasAnyDirtyBit());

            activeTexture(textureUnitIndex);
            bindTexture(textureType, textureGL->getTextureID());
        }
        else
        {
            activeTexture(textureUnitIndex);
            bindTexture(textureType, 0);
        }
    }
}

void StateManagerGL::updateProgramStorageBufferBindings(const gl::Context *context)
{
    const gl::State &glState   = context->getState();
    const gl::Program *program = glState.getProgram();

    for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
         blockIndex++)
    {
        GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
        const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);

        if (shaderStorageBuffer.get() != nullptr)
        {
            BufferGL *bufferGL = GetImplAs<BufferGL>(shaderStorageBuffer.get());

            if (shaderStorageBuffer.getSize() == 0)
            {
                bindBufferBase(gl::BufferBinding::ShaderStorage, binding, bufferGL->getBufferID());
            }
            else
            {
                bindBufferRange(gl::BufferBinding::ShaderStorage, binding, bufferGL->getBufferID(),
                                shaderStorageBuffer.getOffset(), shaderStorageBuffer.getSize());
            }
        }
    }
}

void StateManagerGL::updateProgramUniformBufferBindings(const gl::Context *context)
{
    // Sync the current program state
    const gl::State &glState   = context->getState();
    const gl::Program *program = glState.getProgram();

    for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
         uniformBlockIndex++)
    {
        GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
        const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);

        if (uniformBuffer.get() != nullptr)
        {
            BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());

            if (uniformBuffer.getSize() == 0)
            {
                bindBufferBase(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID());
            }
            else
            {
                bindBufferRange(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID(),
                                uniformBuffer.getOffset(), uniformBuffer.getSize());
            }
        }
    }
}

void StateManagerGL::updateProgramAtomicCounterBufferBindings(const gl::Context *context)
{
    const gl::State &glState   = context->getState();
    const gl::Program *program = glState.getProgram();

    for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
    {
        GLuint binding     = atomicCounterBuffer.binding;
        const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);

        if (buffer.get() != nullptr)
        {
            BufferGL *bufferGL = GetImplAs<BufferGL>(buffer.get());

            if (buffer.getSize() == 0)
            {
                bindBufferBase(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID());
            }
            else
            {
                bindBufferRange(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID(),
                                buffer.getOffset(), buffer.getSize());
            }
        }
    }
}

void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
{
    const gl::State &glState                = context->getState();
    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
    const gl::Program *program              = glState.getProgram();

    // It is possible there is no active program during a path operation.
    if (!executable || !program)
        return;

    ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().empty());
    for (size_t imageUnitIndex : executable->getActiveImagesMask())
    {
        const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
        const TextureGL *textureGL     = SafeGetImplAs<TextureGL>(imageUnit.texture.get());
        if (textureGL)
        {
            bindImageTexture(imageUnitIndex, textureGL->getTextureID(), imageUnit.level,
                             imageUnit.layered, imageUnit.layer, imageUnit.access,
                             imageUnit.format);
        }
        else
        {
            bindImageTexture(imageUnitIndex, 0, imageUnit.level, imageUnit.layered, imageUnit.layer,
                             imageUnit.access, imageUnit.format);
        }
    }
}

void StateManagerGL::setAttributeCurrentData(size_t index,
                                             const gl::VertexAttribCurrentValueData &data)
{
    if (mVertexAttribCurrentValues[index] != data)
    {
        mVertexAttribCurrentValues[index] = data;
        switch (mVertexAttribCurrentValues[index].Type)
        {
            case gl::VertexAttribType::Float:
                mFunctions->vertexAttrib4fv(static_cast<GLuint>(index),
                                            mVertexAttribCurrentValues[index].Values.FloatValues);
                break;
            case gl::VertexAttribType::Int:
                mFunctions->vertexAttribI4iv(static_cast<GLuint>(index),
                                             mVertexAttribCurrentValues[index].Values.IntValues);
                break;
            case gl::VertexAttribType::UnsignedInt:
                mFunctions->vertexAttribI4uiv(
                    static_cast<GLuint>(index),
                    mVertexAttribCurrentValues[index].Values.UnsignedIntValues);
                break;
            default:
                UNREACHABLE();
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CURRENT_VALUES);
        mLocalDirtyCurrentValues.set(index);
    }
}

void StateManagerGL::setScissorTestEnabled(bool enabled)
{
    if (mScissorTestEnabled != enabled)
    {
        mScissorTestEnabled = enabled;
        if (mScissorTestEnabled)
        {
            mFunctions->enable(GL_SCISSOR_TEST);
        }
        else
        {
            mFunctions->disable(GL_SCISSOR_TEST);
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
    }
}

void StateManagerGL::setScissor(const gl::Rectangle &scissor)
{
    if (scissor != mScissor)
    {
        mScissor = scissor;
        mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
    }
}

void StateManagerGL::setViewport(const gl::Rectangle &viewport)
{
    if (viewport != mViewport)
    {
        mViewport = viewport;
        mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
    }
}

void StateManagerGL::setDepthRange(float near, float far)
{
    mNear = near;
    mFar  = far;

    // The glDepthRangef function isn't available until OpenGL 4.1.  Prefer it when it is
    // available because OpenGL ES only works in floats.
    if (mFunctions->depthRangef)
    {
        mFunctions->depthRangef(mNear, mFar);
    }
    else
    {
        ASSERT(mFunctions->depthRange);
        mFunctions->depthRange(mNear, mFar);
    }

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
}

void StateManagerGL::setBlendEnabled(bool enabled)
{
    const gl::DrawBufferMask mask =
        enabled ? mBlendStateExt.getAllEnabledMask() : gl::DrawBufferMask::Zero();
    if (mBlendStateExt.getEnabledMask() == mask)
    {
        return;
    }

    if (enabled)
    {
        mFunctions->enable(GL_BLEND);
    }
    else
    {
        mFunctions->disable(GL_BLEND);
    }

    mBlendStateExt.setEnabled(enabled);
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
}

void StateManagerGL::setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)
{
    if (mBlendStateExt.getEnabledMask() == enabledMask)
    {
        return;
    }

    // Get DrawBufferMask of buffers with different blend enable state
    gl::DrawBufferMask diffMask = mBlendStateExt.getEnabledMask() ^ enabledMask;
    const size_t diffCount      = diffMask.count();

    // Check if enabling or disabling blending for all buffers reduces the number of subsequent
    // indexed commands. Implicitly handles the case when the new blend enable state is the same for
    // all buffers.
    if (diffCount > 1)
    {
        // The number of indexed blend enable commands in case a mass disable is used.
        const size_t enabledCount = enabledMask.count();

        // The mask and the number of indexed blend disable commands in case a mass enable is used.
        const gl::DrawBufferMask disabledMask = enabledMask ^ mBlendStateExt.getAllEnabledMask();
        const size_t disabledCount            = disabledMask.count();

        if (enabledCount < diffCount && enabledCount <= disabledCount)
        {
            diffMask = enabledMask;
            mFunctions->disable(GL_BLEND);
        }
        else if (disabledCount < diffCount && disabledCount <= enabledCount)
        {
            diffMask = disabledMask;
            mFunctions->enable(GL_BLEND);
        }
    }

    for (size_t drawBufferIndex : diffMask)
    {
        if (enabledMask.test(drawBufferIndex))
        {
            mFunctions->enablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
        }
        else
        {
            mFunctions->disablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
        }
    }

    mBlendStateExt.setEnabledMask(enabledMask);
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
}

void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
{
    if (mBlendColor != blendColor)
    {
        mBlendColor = blendColor;
        mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue,
                               mBlendColor.alpha);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
    }
}

void StateManagerGL::setBlendFuncs(const gl::BlendStateExt &blendStateExt)
{
    if (mBlendStateExt.getSrcColorBits() == blendStateExt.getSrcColorBits() &&
        mBlendStateExt.getDstColorBits() == blendStateExt.getDstColorBits() &&
        mBlendStateExt.getSrcAlphaBits() == blendStateExt.getSrcAlphaBits() &&
        mBlendStateExt.getDstAlphaBits() == blendStateExt.getDstAlphaBits())
    {
        return;
    }

    if (!mIndependentBlendStates)
    {
        mFunctions->blendFuncSeparate(
            blendStateExt.getSrcColorIndexed(0), blendStateExt.getDstColorIndexed(0),
            blendStateExt.getSrcAlphaIndexed(0), blendStateExt.getDstAlphaIndexed(0));
    }
    else
    {
        // Get DrawBufferMask of buffers with different blend factors
        gl::DrawBufferMask diffMask = mBlendStateExt.compareFactors(blendStateExt);
        size_t diffCount            = diffMask.count();

        // Check if setting all buffers to the same value reduces the number of subsequent indexed
        // commands. Implicitly handles the case when the new blend function state is the same for
        // all buffers.
        if (diffCount > 1)
        {
            bool found                                            = false;
            gl::BlendStateExt::FactorStorage::Type commonSrcColor = 0;
            gl::BlendStateExt::FactorStorage::Type commonDstColor = 0;
            gl::BlendStateExt::FactorStorage::Type commonSrcAlpha = 0;
            gl::BlendStateExt::FactorStorage::Type commonDstAlpha = 0;
            for (size_t i = 0; i < mBlendStateExt.getDrawBufferCount() - 1; i++)
            {
                const gl::BlendStateExt::FactorStorage::Type tempCommonSrcColor =
                    blendStateExt.expandSrcColorIndexed(i);
                const gl::BlendStateExt::FactorStorage::Type tempCommonDstColor =
                    blendStateExt.expandDstColorIndexed(i);
                const gl::BlendStateExt::FactorStorage::Type tempCommonSrcAlpha =
                    blendStateExt.expandSrcAlphaIndexed(i);
                const gl::BlendStateExt::FactorStorage::Type tempCommonDstAlpha =
                    blendStateExt.expandDstAlphaIndexed(i);

                const gl::DrawBufferMask tempDiffMask = blendStateExt.compareFactors(
                    tempCommonSrcColor, tempCommonDstColor, tempCommonSrcAlpha, tempCommonDstAlpha);

                const size_t tempDiffCount = tempDiffMask.count();
                if (tempDiffCount < diffCount)
                {
                    found          = true;
                    diffMask       = tempDiffMask;
                    diffCount      = tempDiffCount;
                    commonSrcColor = tempCommonSrcColor;
                    commonDstColor = tempCommonDstColor;
                    commonSrcAlpha = tempCommonSrcAlpha;
                    commonDstAlpha = tempCommonDstAlpha;
                    if (tempDiffCount == 0)
                    {
                        break;  // the blend factors are the same for all buffers
                    }
                }
            }
            if (found)
            {
                mFunctions->blendFuncSeparate(
                    ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcColor)),
                    ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstColor)),
                    ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcAlpha)),
                    ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstAlpha)));
            }
        }

        for (size_t drawBufferIndex : diffMask)
        {
            mFunctions->blendFuncSeparatei(static_cast<GLuint>(drawBufferIndex),
                                           blendStateExt.getSrcColorIndexed(drawBufferIndex),
                                           blendStateExt.getDstColorIndexed(drawBufferIndex),
                                           blendStateExt.getSrcAlphaIndexed(drawBufferIndex),
                                           blendStateExt.getDstAlphaIndexed(drawBufferIndex));
        }
    }
    mBlendStateExt.setSrcColorBits(blendStateExt.getSrcColorBits());
    mBlendStateExt.setDstColorBits(blendStateExt.getDstColorBits());
    mBlendStateExt.setSrcAlphaBits(blendStateExt.getSrcAlphaBits());
    mBlendStateExt.setDstAlphaBits(blendStateExt.getDstAlphaBits());
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
}

void StateManagerGL::setBlendEquations(const gl::BlendStateExt &blendStateExt)
{
    if (mBlendStateExt.getEquationColorBits() == blendStateExt.getEquationColorBits() &&
        mBlendStateExt.getEquationAlphaBits() == blendStateExt.getEquationAlphaBits())
    {
        return;
    }

    if (!mIndependentBlendStates)
    {
        mFunctions->blendEquationSeparate(blendStateExt.getEquationColorIndexed(0),
                                          blendStateExt.getEquationAlphaIndexed(0));
    }
    else
    {
        // Get DrawBufferMask of buffers with different blend equations
        gl::DrawBufferMask diffMask = mBlendStateExt.compareEquations(blendStateExt);
        size_t diffCount            = diffMask.count();

        // Check if setting all buffers to the same value reduces the number of subsequent indexed
        // commands. Implicitly handles the case when the new blend equation state is the same for
        // all buffers.
        if (diffCount > 1)
        {
            bool found                                                   = false;
            gl::BlendStateExt::EquationStorage::Type commonEquationColor = 0;
            gl::BlendStateExt::EquationStorage::Type commonEquationAlpha = 0;
            for (size_t i = 0; i < mBlendStateExt.getDrawBufferCount() - 1; i++)
            {
                const gl::BlendStateExt::EquationStorage::Type tempCommonEquationColor =
                    blendStateExt.expandEquationColorIndexed(i);
                const gl::BlendStateExt::EquationStorage::Type tempCommonEquationAlpha =
                    blendStateExt.expandEquationAlphaIndexed(i);

                const gl::DrawBufferMask tempDiffMask = blendStateExt.compareEquations(
                    tempCommonEquationColor, tempCommonEquationAlpha);

                const size_t tempDiffCount = tempDiffMask.count();
                if (tempDiffCount < diffCount)
                {
                    found               = true;
                    diffMask            = tempDiffMask;
                    diffCount           = tempDiffCount;
                    commonEquationColor = tempCommonEquationColor;
                    commonEquationAlpha = tempCommonEquationAlpha;
                    if (tempDiffCount == 0)
                    {
                        break;  // the new blend equations are the same for all buffers
                    }
                }
            }
            if (found)
            {
                mFunctions->blendEquationSeparate(
                    ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
                        0, commonEquationColor)),
                    ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
                        0, commonEquationAlpha)));
            }
        }

        for (size_t drawBufferIndex : diffMask)
        {
            mFunctions->blendEquationSeparatei(
                static_cast<GLuint>(drawBufferIndex),
                blendStateExt.getEquationColorIndexed(drawBufferIndex),
                blendStateExt.getEquationAlphaIndexed(drawBufferIndex));
        }
    }
    mBlendStateExt.setEquationColorBits(blendStateExt.getEquationColorBits());
    mBlendStateExt.setEquationAlphaBits(blendStateExt.getEquationAlphaBits());
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
}

void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
{
    const gl::BlendStateExt::ColorMaskStorage::Type mask =
        mBlendStateExt.expandColorMaskValue(red, green, blue, alpha);
    if (mBlendStateExt.getColorMaskBits() != mask)
    {
        mFunctions->colorMask(red, green, blue, alpha);
        mBlendStateExt.setColorMaskBits(mask);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
    }
}

void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
{
    if (mSampleAlphaToCoverageEnabled != enabled)
    {
        mSampleAlphaToCoverageEnabled = enabled;
        if (mSampleAlphaToCoverageEnabled)
        {
            mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
        }
        else
        {
            mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
    }
}

void StateManagerGL::setSampleCoverageEnabled(bool enabled)
{
    if (mSampleCoverageEnabled != enabled)
    {
        mSampleCoverageEnabled = enabled;
        if (mSampleCoverageEnabled)
        {
            mFunctions->enable(GL_SAMPLE_COVERAGE);
        }
        else
        {
            mFunctions->disable(GL_SAMPLE_COVERAGE);
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
    }
}

void StateManagerGL::setSampleCoverage(float value, bool invert)
{
    if (mSampleCoverageValue != value || mSampleCoverageInvert != invert)
    {
        mSampleCoverageValue  = value;
        mSampleCoverageInvert = invert;
        mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
    }
}

void StateManagerGL::setSampleMaskEnabled(bool enabled)
{
    if (mSampleMaskEnabled != enabled)
    {
        mSampleMaskEnabled = enabled;
        if (mSampleMaskEnabled)
        {
            mFunctions->enable(GL_SAMPLE_MASK);
        }
        else
        {
            mFunctions->disable(GL_SAMPLE_MASK);
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED);
    }
}

void StateManagerGL::setSampleMaski(GLuint maskNumber, GLbitfield mask)
{
    ASSERT(maskNumber < mSampleMaskValues.size());
    if (mSampleMaskValues[maskNumber] != mask)
    {
        mSampleMaskValues[maskNumber] = mask;
        mFunctions->sampleMaski(maskNumber, mask);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_MASK);
    }
}

// Depth and stencil redundant state changes are guarded in the
// frontend so for related cases here just set the dirty bit
// and update backend states.
void StateManagerGL::setDepthTestEnabled(bool enabled)
{
    mDepthTestEnabled = enabled;
    if (mDepthTestEnabled)
    {
        mFunctions->enable(GL_DEPTH_TEST);
    }
    else
    {
        mFunctions->disable(GL_DEPTH_TEST);
    }

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
}

void StateManagerGL::setDepthFunc(GLenum depthFunc)
{
    mDepthFunc = depthFunc;
    mFunctions->depthFunc(mDepthFunc);

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
}

void StateManagerGL::setDepthMask(bool mask)
{
    mDepthMask = mask;
    mFunctions->depthMask(mDepthMask);

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
}

void StateManagerGL::setStencilTestEnabled(bool enabled)
{
    mStencilTestEnabled = enabled;
    if (mStencilTestEnabled)
    {
        mFunctions->enable(GL_STENCIL_TEST);
    }
    else
    {
        mFunctions->disable(GL_STENCIL_TEST);
    }

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
}

void StateManagerGL::setStencilFrontWritemask(GLuint mask)
{
    mStencilFrontWritemask = mask;
    mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask);

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
}

void StateManagerGL::setStencilBackWritemask(GLuint mask)
{
    mStencilBackWritemask = mask;
    mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask);

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
}

void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
{
    mStencilFrontFunc      = func;
    mStencilFrontRef       = ref;
    mStencilFrontValueMask = mask;
    mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef,
                                    mStencilFrontValueMask);

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
}

void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
{
    mStencilBackFunc      = func;
    mStencilBackRef       = ref;
    mStencilBackValueMask = mask;
    mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef,
                                    mStencilBackValueMask);

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
}

void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
{
    mStencilFrontStencilFailOp          = sfail;
    mStencilFrontStencilPassDepthFailOp = dpfail;
    mStencilFrontStencilPassDepthPassOp = dppass;
    mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp,
                                  mStencilFrontStencilPassDepthFailOp,
                                  mStencilFrontStencilPassDepthPassOp);

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
}

void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
{
    mStencilBackStencilFailOp          = sfail;
    mStencilBackStencilPassDepthFailOp = dpfail;
    mStencilBackStencilPassDepthPassOp = dppass;
    mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp,
                                  mStencilBackStencilPassDepthFailOp,
                                  mStencilBackStencilPassDepthPassOp);

    mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
}

void StateManagerGL::setCullFaceEnabled(bool enabled)
{
    if (mCullFaceEnabled != enabled)
    {
        mCullFaceEnabled = enabled;
        if (mCullFaceEnabled)
        {
            mFunctions->enable(GL_CULL_FACE);
        }
        else
        {
            mFunctions->disable(GL_CULL_FACE);
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
    }
}

void StateManagerGL::setCullFace(gl::CullFaceMode cullFace)
{
    if (mCullFace != cullFace)
    {
        mCullFace = cullFace;
        mFunctions->cullFace(ToGLenum(mCullFace));

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
    }
}

void StateManagerGL::setFrontFace(GLenum frontFace)
{
    if (mFrontFace != frontFace)
    {
        mFrontFace = frontFace;
        mFunctions->frontFace(mFrontFace);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
    }
}

void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
{
    if (mPolygonOffsetFillEnabled != enabled)
    {
        mPolygonOffsetFillEnabled = enabled;
        if (mPolygonOffsetFillEnabled)
        {
            mFunctions->enable(GL_POLYGON_OFFSET_FILL);
        }
        else
        {
            mFunctions->disable(GL_POLYGON_OFFSET_FILL);
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
    }
}

void StateManagerGL::setPolygonOffset(float factor, float units)
{
    if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units)
    {
        mPolygonOffsetFactor = factor;
        mPolygonOffsetUnits  = units;
        mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
    }
}

void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
{
    if (mRasterizerDiscardEnabled != enabled)
    {
        mRasterizerDiscardEnabled = enabled;
        if (mRasterizerDiscardEnabled)
        {
            mFunctions->enable(GL_RASTERIZER_DISCARD);
        }
        else
        {
            mFunctions->disable(GL_RASTERIZER_DISCARD);
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
    }
}

void StateManagerGL::setLineWidth(float width)
{
    if (mLineWidth != width)
    {
        mLineWidth = width;
        mFunctions->lineWidth(mLineWidth);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
    }
}

angle::Result StateManagerGL::setPrimitiveRestartEnabled(const gl::Context *context, bool enabled)
{
    if (mPrimitiveRestartEnabled != enabled)
    {
        GLenum cap = mFeatures.emulatePrimitiveRestartFixedIndex.enabled
                         ? GL_PRIMITIVE_RESTART
                         : GL_PRIMITIVE_RESTART_FIXED_INDEX;

        if (enabled)
        {
            ANGLE_GL_TRY(context, mFunctions->enable(cap));
        }
        else
        {
            ANGLE_GL_TRY(context, mFunctions->disable(cap));
        }
        mPrimitiveRestartEnabled = enabled;

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
    }

    return angle::Result::Continue;
}

angle::Result StateManagerGL::setPrimitiveRestartIndex(const gl::Context *context, GLuint index)
{
    if (mPrimitiveRestartIndex != index)
    {
        ANGLE_GL_TRY(context, mFunctions->primitiveRestartIndex(index));
        mPrimitiveRestartIndex = index;

        // No dirty bit for this state, it is not exposed to the frontend.
    }

    return angle::Result::Continue;
}

void StateManagerGL::setClearDepth(float clearDepth)
{
    if (mClearDepth != clearDepth)
    {
        mClearDepth = clearDepth;

        // The glClearDepthf function isn't available until OpenGL 4.1.  Prefer it when it is
        // available because OpenGL ES only works in floats.
        if (mFunctions->clearDepthf)
        {
            mFunctions->clearDepthf(mClearDepth);
        }
        else
        {
            ASSERT(mFunctions->clearDepth);
            mFunctions->clearDepth(mClearDepth);
        }

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
    }
}

void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
{
    gl::ColorF modifiedClearColor = clearColor;
    if (mFeatures.clearToZeroOrOneBroken.enabled &&
        (clearColor.red == 1.0f || clearColor.red == 0.0f) &&
        (clearColor.green == 1.0f || clearColor.green == 0.0f) &&
        (clearColor.blue == 1.0f || clearColor.blue == 0.0f) &&
        (clearColor.alpha == 1.0f || clearColor.alpha == 0.0f))
    {
        if (clearColor.alpha == 1.0f)
        {
            modifiedClearColor.alpha = 2.0f;
        }
        else
        {
            modifiedClearColor.alpha = -1.0f;
        }
    }

    if (mClearColor != modifiedClearColor)
    {
        mClearColor = modifiedClearColor;
        mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue,
                               mClearColor.alpha);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
    }
}

void StateManagerGL::setClearStencil(GLint clearStencil)
{
    if (mClearStencil != clearStencil)
    {
        mClearStencil = clearStencil;
        mFunctions->clearStencil(mClearStencil);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
    }
}

angle::Result StateManagerGL::syncState(const gl::Context *context,
                                        const gl::State::DirtyBits &glDirtyBits,
                                        const gl::State::DirtyBits &bitMask)
{
    const gl::State &state = context->getState();

    const gl::State::DirtyBits glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask;
    if (!glAndLocalDirtyBits.any())
    {
        return angle::Result::Continue;
    }

    // TODO(jmadill): Investigate only syncing vertex state for active attributes
    for (auto iter = glAndLocalDirtyBits.begin(), endIter = glAndLocalDirtyBits.end();
         iter != endIter; ++iter)
    {
        switch (*iter)
        {
            case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
                setScissorTestEnabled(state.isScissorTestEnabled());
                break;
            case gl::State::DIRTY_BIT_SCISSOR:
            {
                const gl::Rectangle &scissor = state.getScissor();
                setScissor(scissor);
            }
            break;
            case gl::State::DIRTY_BIT_VIEWPORT:
            {
                const gl::Rectangle &viewport = state.getViewport();
                setViewport(viewport);
            }
            break;
            case gl::State::DIRTY_BIT_DEPTH_RANGE:
                setDepthRange(state.getNearPlane(), state.getFarPlane());
                break;
            case gl::State::DIRTY_BIT_BLEND_ENABLED:
                if (mIndependentBlendStates)
                {
                    setBlendEnabledIndexed(state.getBlendEnabledDrawBufferMask());
                }
                else
                {
                    setBlendEnabled(state.isBlendEnabled());
                }
                break;
            case gl::State::DIRTY_BIT_BLEND_COLOR:
                setBlendColor(state.getBlendColor());
                break;
            case gl::State::DIRTY_BIT_BLEND_FUNCS:
            {
                setBlendFuncs(state.getBlendStateExt());
                break;
            }
            case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
            {
                setBlendEquations(state.getBlendStateExt());
                break;
            }
            case gl::State::DIRTY_BIT_COLOR_MASK:
            {
                const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
                const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
                const bool disableAlphaWrite =
                    framebufferGL->hasEmulatedAlphaChannelTextureAttachment();

                setColorMaskForFramebuffer(state.getBlendStateExt(), disableAlphaWrite);
                break;
            }
            case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
                setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled());
                break;
            case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
                setSampleCoverageEnabled(state.isSampleCoverageEnabled());
                break;
            case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
                setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert());
                break;
            case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
                setDepthTestEnabled(state.isDepthTestEnabled());
                break;
            case gl::State::DIRTY_BIT_DEPTH_FUNC:
                setDepthFunc(state.getDepthStencilState().depthFunc);
                break;
            case gl::State::DIRTY_BIT_DEPTH_MASK:
                setDepthMask(state.getDepthStencilState().depthMask);
                break;
            case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
                setStencilTestEnabled(state.isStencilTestEnabled());
                break;
            case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
            {
                const auto &depthStencilState = state.getDepthStencilState();
                setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(),
                                     depthStencilState.stencilMask);
                break;
            }
            case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
            {
                const auto &depthStencilState = state.getDepthStencilState();
                setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(),
                                    depthStencilState.stencilBackMask);
                break;
            }
            case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
            {
                const auto &depthStencilState = state.getDepthStencilState();
                setStencilFrontOps(depthStencilState.stencilFail,
                                   depthStencilState.stencilPassDepthFail,
                                   depthStencilState.stencilPassDepthPass);
                break;
            }
            case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
            {
                const auto &depthStencilState = state.getDepthStencilState();
                setStencilBackOps(depthStencilState.stencilBackFail,
                                  depthStencilState.stencilBackPassDepthFail,
                                  depthStencilState.stencilBackPassDepthPass);
                break;
            }
            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
                setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask);
                break;
            case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
                setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask);
                break;
            case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
                setCullFaceEnabled(state.isCullFaceEnabled());
                break;
            case gl::State::DIRTY_BIT_CULL_FACE:
                setCullFace(state.getRasterizerState().cullMode);
                break;
            case gl::State::DIRTY_BIT_FRONT_FACE:
                setFrontFace(state.getRasterizerState().frontFace);
                break;
            case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
                setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled());
                break;
            case gl::State::DIRTY_BIT_POLYGON_OFFSET:
            {
                const auto &rasterizerState = state.getRasterizerState();
                setPolygonOffset(rasterizerState.polygonOffsetFactor,
                                 rasterizerState.polygonOffsetUnits);
                break;
            }
            case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
                setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled());
                break;
            case gl::State::DIRTY_BIT_LINE_WIDTH:
                setLineWidth(state.getLineWidth());
                break;
            case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
                ANGLE_TRY(setPrimitiveRestartEnabled(context, state.isPrimitiveRestartEnabled()));
                break;
            case gl::State::DIRTY_BIT_CLEAR_COLOR:
                setClearColor(state.getColorClearValue());
                break;
            case gl::State::DIRTY_BIT_CLEAR_DEPTH:
                setClearDepth(state.getDepthClearValue());
                break;
            case gl::State::DIRTY_BIT_CLEAR_STENCIL:
                setClearStencil(state.getStencilClearValue());
                break;
            case gl::State::DIRTY_BIT_UNPACK_STATE:
                ANGLE_TRY(setPixelUnpackState(context, state.getUnpackState()));
                break;
            case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
                ANGLE_TRY(setPixelUnpackBuffer(
                    context, state.getTargetBuffer(gl::BufferBinding::PixelUnpack)));
                break;
            case gl::State::DIRTY_BIT_PACK_STATE:
                ANGLE_TRY(setPixelPackState(context, state.getPackState()));
                break;
            case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
                ANGLE_TRY(setPixelPackBuffer(context,
                                             state.getTargetBuffer(gl::BufferBinding::PixelPack)));
                break;
            case gl::State::DIRTY_BIT_DITHER_ENABLED:
                setDitherEnabled(state.isDitherEnabled());
                break;
            case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
            {
                gl::Framebuffer *framebuffer = state.getReadFramebuffer();

                // Necessary for an Intel TexImage workaround.
                if (!framebuffer)
                    continue;

                FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
                bindFramebuffer(
                    mHasSeparateFramebufferBindings ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER,
                    framebufferGL->getFramebufferID());
                break;
            }
            case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
            {
                gl::Framebuffer *framebuffer = state.getDrawFramebuffer();

                // Necessary for an Intel TexImage workaround.
                if (!framebuffer)
                    continue;

                FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
                bindFramebuffer(
                    mHasSeparateFramebufferBindings ? GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER,
                    framebufferGL->getFramebufferID());

                const gl::Program *program = state.getProgram();
                if (program)
                {
                    updateMultiviewBaseViewLayerIndexUniform(program, framebufferGL->getState());
                }

                // Changing the draw framebuffer binding sometimes requires resetting srgb blending.
                iter.setLaterBit(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);

                // If the framebuffer is emulating RGB on top of RGBA, the color mask has to be
                // updated
                iter.setLaterBit(gl::State::DIRTY_BIT_COLOR_MASK);
                break;
            }
            case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
                // TODO(jmadill): implement this
                break;
            case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
            {
                VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
                bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getNativeState());

                ANGLE_TRY(propagateProgramToVAO(context, state.getProgram(),
                                                GetImplAs<VertexArrayGL>(state.getVertexArray())));

                if (mFeatures.syncVertexArraysToDefault.enabled)
                {
                    // Re-sync the vertex array because all frontend VAOs share the same backend
                    // state. Only sync bits that can be set in ES2.0 or 3.0
                    gl::VertexArray::DirtyBits dirtyBits;
                    gl::VertexArray::DirtyAttribBitsArray dirtyAttribBits;
                    gl::VertexArray::DirtyBindingBitsArray dirtBindingBits;

                    dirtyBits.set(gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
                    for (size_t attrib = 0; attrib < mDefaultVAOState.attributes.size(); attrib++)
                    {
                        dirtyBits.set(gl::VertexArray::DIRTY_BIT_ATTRIB_0 + attrib);
                        dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_ENABLED);
                        dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_POINTER);
                        dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_POINTER_BUFFER);
                    }
                    for (size_t binding = 0; binding < mDefaultVAOState.bindings.size(); binding++)
                    {
                        dirtyBits.set(gl::VertexArray::DIRTY_BIT_BINDING_0 + binding);
                        dirtBindingBits[binding].set(gl::VertexArray::DIRTY_BINDING_DIVISOR);
                    }

                    ANGLE_TRY(
                        vaoGL->syncState(context, dirtyBits, &dirtyAttribBits, &dirtBindingBits));
                }
                break;
            }
            case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
                updateDrawIndirectBufferBinding(context);
                break;
            case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
                updateDispatchIndirectBufferBinding(context);
                break;
            case gl::State::DIRTY_BIT_PROGRAM_BINDING:
            {
                gl::Program *program = state.getProgram();
                if (program != nullptr)
                {
                    useProgram(GetImplAs<ProgramGL>(program)->getProgramID());
                }
                break;
            }
            case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
            {
                const gl::Program *program              = state.getProgram();
                const gl::ProgramExecutable *executable = state.getProgramExecutable();

                if (program && executable)
                {
                    iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);

                    if (executable->getActiveImagesMask().any())
                    {
                        iter.setLaterBit(gl::State::DIRTY_BIT_IMAGE_BINDINGS);
                    }

                    if (program->getActiveShaderStorageBlockCount() > 0)
                    {
                        iter.setLaterBit(gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
                    }

                    if (program->getActiveUniformBlockCount() > 0)
                    {
                        iter.setLaterBit(gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
                    }

                    if (program->getActiveAtomicCounterBufferCount() > 0)
                    {
                        iter.setLaterBit(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
                    }

                    if (mIsMultiviewEnabled && program->usesMultiview())
                    {
                        updateMultiviewBaseViewLayerIndexUniform(
                            program, state.getDrawFramebuffer()->getImplementation()->getState());
                    }
                }

                if (!program ||
                    !program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Compute))
                {
                    ANGLE_TRY(propagateProgramToVAO(
                        context, program, GetImplAs<VertexArrayGL>(state.getVertexArray())));
                }
                break;
            }
            case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
                updateProgramTextureBindings(context);
                break;
            case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
                syncSamplersState(context);
                break;
            case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
                updateProgramImageBindings(context);
                break;
            case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
                syncTransformFeedbackState(context);
                break;
            case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
                updateProgramStorageBufferBindings(context);
                break;
            case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
                updateProgramUniformBufferBindings(context);
                break;
            case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
                updateProgramAtomicCounterBufferBindings(context);
                break;
            case gl::State::DIRTY_BIT_MULTISAMPLING:
                setMultisamplingStateEnabled(state.isMultisamplingEnabled());
                break;
            case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
                setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
                break;
            case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
                setCoverageModulation(state.getCoverageModulation());
                break;
            case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
                setFramebufferSRGBEnabledForFramebuffer(
                    context, state.getFramebufferSRGB(),
                    GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
                break;
            case gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED:
                setSampleMaskEnabled(state.isSampleMaskEnabled());
                break;
            case gl::State::DIRTY_BIT_SAMPLE_MASK:
            {
                for (GLuint maskNumber = 0; maskNumber < state.getMaxSampleMaskWords();
                     ++maskNumber)
                {
                    setSampleMaski(maskNumber, state.getSampleMaskWord(maskNumber));
                }
                break;
            }
            case gl::State::DIRTY_BIT_CURRENT_VALUES:
            {
                gl::AttributesMask combinedMask =
                    (state.getAndResetDirtyCurrentValues() | mLocalDirtyCurrentValues);
                mLocalDirtyCurrentValues.reset();

                for (auto attribIndex : combinedMask)
                {
                    setAttributeCurrentData(attribIndex,
                                            state.getVertexAttribCurrentValue(attribIndex));
                }
                break;
            }
            case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
                setProvokingVertex(ToGLenum(state.getProvokingVertex()));
                break;
            case gl::State::DIRTY_BIT_EXTENDED:
                // Handling clip distance enabled flags:
                setClipDistancesEnable(state.getEnabledClipDistances());
                // TODO(jmadill): handle mipmap generation hint
                // TODO(jmadill): handle shader derivative hint
                // Nothing to do until EXT_clip_contorl is implemented.
                break;
            case gl::State::DIRTY_BIT_SAMPLE_SHADING:
                // Nothing to do until OES_sample_shading is implemented.
                break;
            case gl::State::DIRTY_BIT_PATCH_VERTICES:
                // Nothing to do until EXT_tessellation_shader is implemented.
                break;
            default:
                UNREACHABLE();
                break;
        }
    }

    mLocalDirtyBits &= ~(bitMask);

    return angle::Result::Continue;
}

void StateManagerGL::setFramebufferSRGBEnabled(const gl::Context *context, bool enabled)
{
    if (!mFramebufferSRGBAvailable)
    {
        return;
    }

    if (mFramebufferSRGBEnabled != enabled)
    {
        mFramebufferSRGBEnabled = enabled;
        if (mFramebufferSRGBEnabled)
        {
            mFunctions->enable(GL_FRAMEBUFFER_SRGB);
        }
        else
        {
            mFunctions->disable(GL_FRAMEBUFFER_SRGB);
        }
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
    }
}

void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
                                                             bool enabled,
                                                             const FramebufferGL *framebuffer)
{
    if (framebuffer->isDefault())
    {
        // Obey the framebuffer sRGB state for blending on all framebuffers except the default
        // framebuffer.
        // When SRGB blending is enabled, only SRGB capable formats will use it but the default
        // framebuffer will always use it if it is enabled.
        // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
        setFramebufferSRGBEnabled(context, false);
    }
    else
    {
        setFramebufferSRGBEnabled(context, enabled);
    }
}

void StateManagerGL::setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt,
                                                const bool disableAlpha)
{
    bool r, g, b, a;

    // Given that disableAlpha can be true only on macOS backbuffers and color mask is re-synced on
    // bound draw framebuffer change, switch all draw buffers color masks to avoid special case
    // later.
    if (!mIndependentBlendStates || disableAlpha)
    {
        blendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
        setColorMask(r, g, b, disableAlpha ? false : a);
        return;
    }

    // Check if the current mask already matches the new state
    if (mBlendStateExt.getColorMaskBits() == blendStateExt.getColorMaskBits())
    {
        return;
    }

    // Get DrawBufferMask of buffers with different color masks
    gl::DrawBufferMask diffMask = mBlendStateExt.compareColorMask(blendStateExt.getColorMaskBits());
    size_t diffCount            = diffMask.count();

    // Check if setting all buffers to the same value reduces the number of subsequent indexed
    // commands. Implicitly handles the case when the new mask is the same for all buffers.
    // For instance, let's say that previously synced mask is ccccff00 and the new state is
    // ffeeeeee. Instead of calling colorMaski 8 times, ANGLE can set all buffers to `e` and then
    // use colorMaski only twice. On the other hand, if the new state is cceeee00, a non-indexed
    // call will increase the total number of GL commands.
    if (diffCount > 1)
    {
        bool found                                                = false;
        gl::BlendStateExt::ColorMaskStorage::Type commonColorMask = 0;
        for (size_t i = 0; i < mBlendStateExt.getDrawBufferCount() - 1; i++)
        {
            const gl::BlendStateExt::ColorMaskStorage::Type tempCommonColorMask =
                blendStateExt.expandColorMaskIndexed(i);
            const gl::DrawBufferMask tempDiffMask =
                blendStateExt.compareColorMask(tempCommonColorMask);
            const size_t tempDiffCount = tempDiffMask.count();
            if (tempDiffCount < diffCount)
            {
                found           = true;
                diffMask        = tempDiffMask;
                diffCount       = tempDiffCount;
                commonColorMask = tempCommonColorMask;
                if (tempDiffCount == 0)
                {
                    break;  // the new mask is the same for all buffers
                }
            }
        }
        if (found)
        {
            gl::BlendStateExt::UnpackColorMask(commonColorMask, &r, &g, &b, &a);
            mFunctions->colorMask(r, g, b, a);
        }
    }

    for (size_t drawBufferIndex : diffMask)
    {
        blendStateExt.getColorMaskIndexed(drawBufferIndex, &r, &g, &b, &a);
        mFunctions->colorMaski(static_cast<GLuint>(drawBufferIndex), r, g, b, a);
    }

    mBlendStateExt.setColorMaskBits(blendStateExt.getColorMaskBits());
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
}

void StateManagerGL::setDitherEnabled(bool enabled)
{
    if (mDitherEnabled != enabled)
    {
        mDitherEnabled = enabled;
        if (mDitherEnabled)
        {
            mFunctions->enable(GL_DITHER);
        }
        else
        {
            mFunctions->disable(GL_DITHER);
        }
    }
}

void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
{
    if (mMultisamplingEnabled != enabled)
    {
        mMultisamplingEnabled = enabled;
        if (mMultisamplingEnabled)
        {
            mFunctions->enable(GL_MULTISAMPLE_EXT);
        }
        else
        {
            mFunctions->disable(GL_MULTISAMPLE_EXT);
        }
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
    }
}

void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
{
    if (mSampleAlphaToOneEnabled != enabled)
    {
        mSampleAlphaToOneEnabled = enabled;
        if (mSampleAlphaToOneEnabled)
        {
            mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE);
        }
        else
        {
            mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE);
        }
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
    }
}

void StateManagerGL::setCoverageModulation(GLenum components)
{
    if (mCoverageModulation != components)
    {
        mCoverageModulation = components;
        mFunctions->coverageModulationNV(components);

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION);
    }
}

void StateManagerGL::setProvokingVertex(GLenum mode)
{
    if (mode != mProvokingVertex)
    {
        mFunctions->provokingVertex(mode);
        mProvokingVertex = mode;

        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROVOKING_VERTEX);
    }
}

void StateManagerGL::setClipDistancesEnable(const gl::State::ClipDistanceEnableBits &enables)
{
    if (enables == mEnabledClipDistances)
    {
        return;
    }
    ASSERT(mMaxClipDistances <= gl::IMPLEMENTATION_MAX_CLIP_DISTANCES);

    gl::State::ClipDistanceEnableBits diff = enables ^ mEnabledClipDistances;
    for (size_t i : diff)
    {
        if (enables.test(i))
        {
            mFunctions->enable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
        }
        else
        {
            mFunctions->disable(GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i));
        }
    }

    mEnabledClipDistances = enables;
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_EXTENDED);
}

void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
{
    // TODO(jmadill): Also check for seamless extension.
    if (!mFunctions->isAtLeastGL(gl::Version(3, 2)))
    {
        return;
    }

    if (mTextureCubemapSeamlessEnabled != enabled)
    {
        mTextureCubemapSeamlessEnabled = enabled;
        if (mTextureCubemapSeamlessEnabled)
        {
            mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
        }
        else
        {
            mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
        }
    }
}

angle::Result StateManagerGL::propagateProgramToVAO(const gl::Context *context,
                                                    const gl::Program *program,
                                                    VertexArrayGL *vao)
{
    if (vao == nullptr)
    {
        return angle::Result::Continue;
    }

    // Number of views:
    if (mIsMultiviewEnabled)
    {
        int programNumViews = 1;
        if (program && program->usesMultiview())
        {
            programNumViews = program->getNumViews();
        }
        ANGLE_TRY(vao->applyNumViewsToDivisor(context, programNumViews));
    }

    // Attribute enabled mask:
    if (program)
    {
        ANGLE_TRY(vao->applyActiveAttribLocationsMask(
            context, program->getExecutable().getActiveAttribLocationsMask()));
    }

    return angle::Result::Continue;
}

void StateManagerGL::updateMultiviewBaseViewLayerIndexUniformImpl(
    const gl::Program *program,
    const gl::FramebufferState &drawFramebufferState) const
{
    ASSERT(mIsMultiviewEnabled && program && program->usesMultiview());
    const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
    if (drawFramebufferState.isMultiview())
    {
        programGL->enableLayeredRenderingPath(drawFramebufferState.getBaseViewIndex());
    }
}

void StateManagerGL::syncSamplersState(const gl::Context *context)
{
    const gl::SamplerBindingVector &samplers = context->getState().getSamplers();

    // This could be optimized by using a separate binding dirty bit per sampler.
    for (size_t samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex)
    {
        const gl::Sampler *sampler = samplers[samplerIndex].get();
        if (sampler != nullptr)
        {
            SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
            bindSampler(samplerIndex, samplerGL->getSamplerID());
        }
        else
        {
            bindSampler(samplerIndex, 0);
        }
    }
}

void StateManagerGL::syncTransformFeedbackState(const gl::Context *context)
{
    // Set the current transform feedback state
    gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
    if (transformFeedback)
    {
        TransformFeedbackGL *transformFeedbackGL =
            GetImplAs<TransformFeedbackGL>(transformFeedback);
        bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
        transformFeedbackGL->syncActiveState(context, transformFeedback->isActive(),
                                             transformFeedback->getPrimitiveMode());
        transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
        mCurrentTransformFeedback = transformFeedbackGL;
    }
    else
    {
        bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
        mCurrentTransformFeedback = nullptr;
    }
}

GLuint StateManagerGL::getDefaultVAO() const
{
    return mDefaultVAO;
}

VertexArrayStateGL *StateManagerGL::getDefaultVAOState()
{
    return &mDefaultVAOState;
}

void StateManagerGL::validateState() const
{
    // Current program
    ValidateStateHelper(mFunctions, mProgram, GL_CURRENT_PROGRAM, "mProgram", "GL_CURRENT_PROGRAM");

    // Buffers
    for (gl::BufferBinding bindingType : angle::AllEnums<gl::BufferBinding>())
    {
        // These binding types need compute support to be queried
        if (bindingType == gl::BufferBinding::AtomicCounter ||
            bindingType == gl::BufferBinding::DispatchIndirect ||
            bindingType == gl::BufferBinding::ShaderStorage)
        {
            if (!nativegl::SupportsCompute(mFunctions))
            {
                continue;
            }
        }

        // Transform feedback buffer bindings are tracked in TransformFeedbackGL
        if (bindingType == gl::BufferBinding::TransformFeedback)
        {
            continue;
        }

        GLenum bindingTypeGL  = nativegl::GetBufferBindingQuery(bindingType);
        std::string localName = "mBuffers[" + ToString(bindingType) + "]";
        ValidateStateHelper(mFunctions, mBuffers[bindingType], bindingTypeGL, localName.c_str(),
                            nativegl::GetBufferBindingString(bindingType).c_str());
    }

    // Vertex array object
    ValidateStateHelper(mFunctions, mVAO, GL_VERTEX_ARRAY_BINDING, "mVAO",
                        "GL_VERTEX_ARRAY_BINDING");
}

template <>
void StateManagerGL::get(GLenum name, GLboolean *value)
{
    mFunctions->getBooleanv(name, value);
}

template <>
void StateManagerGL::get(GLenum name, bool *value)
{
    GLboolean v;
    get(name, &v);
    *value = (v == GL_TRUE);
}

template <>
void StateManagerGL::get(GLenum name, std::array<bool, 4> *values)
{
    GLboolean v[4];
    get(name, v);
    for (size_t i = 0; i < 4; i++)
    {
        (*values)[i] = (v[i] == GL_TRUE);
    }
}

template <>
void StateManagerGL::get(GLenum name, GLint *value)
{
    mFunctions->getIntegerv(name, value);
}

template <>
void StateManagerGL::get(GLenum name, GLenum *value)
{
    GLint v;
    get(name, &v);
    *value = static_cast<GLenum>(v);
}

template <>
void StateManagerGL::get(GLenum name, gl::Rectangle *rect)
{
    GLint v[4];
    get(name, v);
    *rect = gl::Rectangle(v[0], v[1], v[2], v[3]);
}

template <>
void StateManagerGL::get(GLenum name, GLfloat *value)
{
    mFunctions->getFloatv(name, value);
}

template <>
void StateManagerGL::get(GLenum name, gl::ColorF *color)
{
    GLfloat v[4];
    get(name, v);
    *color = gl::ColorF(v[0], v[1], v[2], v[3]);
}

void StateManagerGL::syncFromNativeContext(const gl::Extensions &extensions,
                                           ExternalContextState *state)
{
    ASSERT(mFunctions->getError() == GL_NO_ERROR);

    get(GL_VIEWPORT, &state->viewport);
    if (mViewport != state->viewport)
    {
        mViewport = state->viewport;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
    }

    get(GL_SCISSOR_TEST, &state->scissorTest);
    if (mScissorTestEnabled != static_cast<bool>(state->scissorTest))
    {
        mScissorTestEnabled = state->scissorTest;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
    }

    get(GL_SCISSOR_BOX, &state->scissorBox);
    if (mScissor != state->scissorBox)
    {
        mScissor = state->scissorBox;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
    }

    get(GL_DEPTH_TEST, &state->depthTest);
    if (mDepthTestEnabled != state->depthTest)
    {
        mDepthTestEnabled = state->depthTest;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
    }

    get(GL_CULL_FACE, &state->cullFace);
    if (mCullFaceEnabled != state->cullFace)
    {
        mCullFaceEnabled = state->cullFace;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
    }

    get(GL_CULL_FACE_MODE, &state->cullFaceMode);
    if (mCullFace != gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode))
    {
        mCullFace = gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
    }

    get(GL_COLOR_WRITEMASK, &state->colorMask);
    auto colorMask = mBlendStateExt.expandColorMaskValue(state->colorMask[0], state->colorMask[1],
                                                         state->colorMask[2], state->colorMask[3]);
    if (mBlendStateExt.getColorMaskBits() != colorMask)
    {
        mBlendStateExt.setColorMaskBits(colorMask);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
    }

    get(GL_CURRENT_PROGRAM, &state->currentProgram);
    if (mProgram != static_cast<GLuint>(state->currentProgram))
    {
        mProgram = state->currentProgram;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROGRAM_BINDING);
    }

    get(GL_COLOR_CLEAR_VALUE, &state->colorClear);
    if (mClearColor != state->colorClear)
    {
        mClearColor = state->colorClear;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
    }

    get(GL_DEPTH_CLEAR_VALUE, &state->depthClear);
    if (mClearDepth != state->depthClear)
    {
        mClearDepth = state->depthClear;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
    }

    get(GL_DEPTH_FUNC, &state->depthFunc);
    if (mDepthFunc != static_cast<GLenum>(state->depthFunc))
    {
        mDepthFunc = state->depthFunc;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
    }

    get(GL_DEPTH_WRITEMASK, &state->depthMask);
    if (mDepthMask != state->depthMask)
    {
        mDepthMask = state->depthMask;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
    }

    get(GL_DEPTH_RANGE, state->depthRage);
    if (mNear != state->depthRage[0] || mFar != state->depthRage[1])
    {
        mNear = state->depthRage[0];
        mFar  = state->depthRage[1];
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
    }

    get(GL_FRONT_FACE, &state->frontFace);
    if (mFrontFace != static_cast<GLenum>(state->frontFace))
    {
        mFrontFace = state->frontFace;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
    }

    get(GL_LINE_WIDTH, &state->lineWidth);
    if (mLineWidth != state->lineWidth)
    {
        mLineWidth = state->lineWidth;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
    }

    get(GL_POLYGON_OFFSET_FACTOR, &state->polygonOffsetFactor);
    get(GL_POLYGON_OFFSET_UNITS, &state->polygonOffsetUnits);
    if (mPolygonOffsetFactor != state->polygonOffsetFactor ||
        mPolygonOffsetUnits != state->polygonOffsetUnits)
    {
        mPolygonOffsetFactor = state->polygonOffsetFactor;
        mPolygonOffsetUnits  = state->polygonOffsetUnits;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
    }

    get(GL_SAMPLE_COVERAGE_VALUE, &state->sampleCoverageValue);
    get(GL_SAMPLE_COVERAGE_INVERT, &state->sampleCoverageInvert);
    if (mSampleCoverageValue != state->sampleCoverageValue ||
        mSampleCoverageInvert != state->sampleCoverageInvert)
    {
        mSampleCoverageValue  = state->sampleCoverageValue;
        mSampleCoverageInvert = state->sampleCoverageInvert;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
    }

    get(GL_DITHER, &state->enableDither);
    if (mDitherEnabled != state->enableDither)
    {
        mDitherEnabled = state->enableDither;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DITHER_ENABLED);
    }

    get(GL_POLYGON_OFFSET_FILL, &state->enablePolygonOffsetFill);
    if (mPolygonOffsetFillEnabled != state->enablePolygonOffsetFill)
    {
        mPolygonOffsetFillEnabled = state->enablePolygonOffsetFill;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
    }

    get(GL_SAMPLE_ALPHA_TO_COVERAGE, &state->enableSampleAlphaToCoverage);
    if (mSampleAlphaToOneEnabled != state->enableSampleAlphaToCoverage)
    {
        mSampleAlphaToOneEnabled = state->enableSampleAlphaToCoverage;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
    }

    get(GL_SAMPLE_COVERAGE, &state->enableSampleCoverage);
    if (mSampleCoverageEnabled != state->enableSampleCoverage)
    {
        mSampleCoverageEnabled = state->enableSampleCoverage;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
    }

    if (extensions.multisampleCompatibilityEXT)
    {
        get(GL_MULTISAMPLE, &state->multisampleEnabled);
        if (mMultisamplingEnabled != state->multisampleEnabled)
        {
            mMultisamplingEnabled = state->multisampleEnabled;
            mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
        }
    }

    syncBlendFromNativeContext(extensions, state);
    syncFramebufferFromNativeContext(extensions, state);
    syncPixelPackUnpackFromNativeContext(extensions, state);
    syncStencilFromNativeContext(extensions, state);
    syncVertexArraysFromNativeContext(extensions, state);
    syncBufferBindingsFromNativeContext(extensions, state);
    syncTextureUnitsFromNativeContext(extensions, state);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void StateManagerGL::restoreNativeContext(const gl::Extensions &extensions,
                                          const ExternalContextState *state)
{
    ASSERT(mFunctions->getError() == GL_NO_ERROR);

    setViewport(state->viewport);

    setScissorTestEnabled(state->scissorTest);
    setScissor(state->scissorBox);

    setDepthTestEnabled(state->depthTest);

    setCullFaceEnabled(state->cullFace);
    setCullFace(gl::FromGLenum<gl::CullFaceMode>(state->cullFaceMode));

    setColorMask(state->colorMask[0], state->colorMask[1], state->colorMask[2],
                 state->colorMask[3]);

    forceUseProgram(state->currentProgram);

    setClearColor(state->colorClear);

    setClearDepth(state->depthClear);
    setDepthFunc(state->depthFunc);
    setDepthMask(state->depthMask);
    setDepthRange(state->depthRage[0], state->depthRage[1]);

    setFrontFace(state->frontFace);

    setLineWidth(state->lineWidth);

    setPolygonOffset(state->polygonOffsetFactor, state->polygonOffsetUnits);

    setSampleCoverage(state->sampleCoverageValue, state->sampleCoverageInvert);

    setDitherEnabled(state->enableDither);

    setPolygonOffsetFillEnabled(state->enablePolygonOffsetFill);

    setSampleAlphaToOneStateEnabled(state->enableSampleAlphaToCoverage);

    setSampleCoverageEnabled(state->enableSampleCoverage);

    if (extensions.multisampleCompatibilityEXT)
        setMultisamplingStateEnabled(state->multisampleEnabled);

    restoreBlendNativeContext(extensions, state);
    restoreFramebufferNativeContext(extensions, state);
    restorePixelPackUnpackNativeContext(extensions, state);
    restoreStencilNativeContext(extensions, state);
    restoreVertexArraysNativeContext(extensions, state);
    restoreBufferBindingsNativeContext(extensions, state);
    restoreTextureUnitsNativeContext(extensions, state);

    // if (mFunctions->coverageModulationNV) ?
    setCoverageModulation(GL_NONE);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void StateManagerGL::syncBlendFromNativeContext(const gl::Extensions &extensions,
                                                ExternalContextState *state)
{
    get(GL_BLEND, &state->blendEnabled);
    if (mBlendStateExt.getEnabledMask() !=
        (state->blendEnabled ? mBlendStateExt.getAllEnabledMask() : gl::DrawBufferMask::Zero()))
    {
        mBlendStateExt.setEnabled(state->blendEnabled);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
    }

    get(GL_BLEND_SRC_RGB, &state->blendSrcRgb);
    get(GL_BLEND_DST_RGB, &state->blendDestRgb);
    get(GL_BLEND_SRC_ALPHA, &state->blendSrcAlpha);
    get(GL_BLEND_DST_ALPHA, &state->blendDestAlpha);
    if (mBlendStateExt.getSrcColorBits() != mBlendStateExt.expandFactorValue(state->blendSrcRgb) ||
        mBlendStateExt.getDstColorBits() != mBlendStateExt.expandFactorValue(state->blendDestRgb) ||
        mBlendStateExt.getSrcAlphaBits() !=
            mBlendStateExt.expandFactorValue(state->blendSrcAlpha) ||
        mBlendStateExt.getDstAlphaBits() != mBlendStateExt.expandFactorValue(state->blendDestAlpha))
    {
        mBlendStateExt.setFactors(state->blendSrcRgb, state->blendDestRgb, state->blendSrcAlpha,
                                  state->blendDestAlpha);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
    }

    get(GL_BLEND_COLOR, &state->blendColor);
    if (mBlendColor != state->blendColor)
    {
        mBlendColor = state->blendColor;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
    }

    get(GL_BLEND_EQUATION_RGB, &state->blendEquationRgb);
    get(GL_BLEND_EQUATION_ALPHA, &state->blendEquationAlpha);
    if (mBlendStateExt.getEquationColorBits() !=
            mBlendStateExt.expandEquationValue(state->blendEquationRgb) ||
        mBlendStateExt.getEquationAlphaBits() !=
            mBlendStateExt.expandEquationValue(state->blendEquationAlpha))
    {
        mBlendStateExt.setEquations(state->blendEquationRgb, state->blendEquationAlpha);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_EQUATIONS);
    }
}

void StateManagerGL::restoreBlendNativeContext(const gl::Extensions &extensions,
                                               const ExternalContextState *state)
{
    setBlendEnabled(state->blendEnabled);

    mFunctions->blendFuncSeparate(state->blendSrcRgb, state->blendDestRgb, state->blendSrcAlpha,
                                  state->blendDestAlpha);
    mBlendStateExt.setFactors(state->blendSrcRgb, state->blendDestRgb, state->blendSrcAlpha,
                              state->blendDestAlpha);
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);

    setBlendColor(state->blendColor);

    mFunctions->blendEquationSeparate(state->blendEquationRgb, state->blendEquationAlpha);
    mBlendStateExt.setEquations(state->blendEquationRgb, state->blendEquationAlpha);
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_EQUATIONS);
}

void StateManagerGL::syncFramebufferFromNativeContext(const gl::Extensions &extensions,
                                                      ExternalContextState *state)
{
    // TODO: wrap fbo into an EGLSurface
    get(GL_FRAMEBUFFER_BINDING, &state->framebufferBinding);
    if (mFramebuffers[angle::FramebufferBindingDraw] !=
        static_cast<GLenum>(state->framebufferBinding))
    {
        mFramebuffers[angle::FramebufferBindingDraw] =
            static_cast<GLenum>(state->framebufferBinding);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
    }
    if (mFramebuffers[angle::FramebufferBindingRead] !=
        static_cast<GLenum>(state->framebufferBinding))
    {
        mFramebuffers[angle::FramebufferBindingRead] =
            static_cast<GLenum>(state->framebufferBinding);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
    }
}

void StateManagerGL::restoreFramebufferNativeContext(const gl::Extensions &extensions,
                                                     const ExternalContextState *state)
{
    bindFramebuffer(GL_FRAMEBUFFER, state->framebufferBinding);
}

void StateManagerGL::syncPixelPackUnpackFromNativeContext(const gl::Extensions &extensions,
                                                          ExternalContextState *state)
{
    get(GL_PACK_ALIGNMENT, &state->packAlignment);
    if (mPackAlignment != state->packAlignment)
    {
        mPackAlignment = state->packAlignment;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
    }

    get(GL_UNPACK_ALIGNMENT, &state->unpackAlignment);
    if (mUnpackAlignment != state->unpackAlignment)
    {
        mUnpackAlignment = state->unpackAlignment;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
    }
}

void StateManagerGL::restorePixelPackUnpackNativeContext(const gl::Extensions &extensions,
                                                         const ExternalContextState *state)
{
    if (mPackAlignment != state->packAlignment)
    {
        mFunctions->pixelStorei(GL_PACK_ALIGNMENT, state->packAlignment);
        mPackAlignment = state->packAlignment;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_STATE);
    }

    if (mUnpackAlignment != state->unpackAlignment)
    {
        mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, state->unpackAlignment);
        mUnpackAlignment = state->unpackAlignment;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_STATE);
    }
}

void StateManagerGL::syncStencilFromNativeContext(const gl::Extensions &extensions,
                                                  ExternalContextState *state)
{
    get(GL_STENCIL_TEST, &state->stencilState.stencilTestEnabled);
    if (state->stencilState.stencilTestEnabled != mStencilTestEnabled)
    {
        mStencilTestEnabled = state->stencilState.stencilTestEnabled;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
    }

    get(GL_STENCIL_FUNC, &state->stencilState.stencilFrontFunc);
    get(GL_STENCIL_VALUE_MASK, &state->stencilState.stencilFrontMask);
    get(GL_STENCIL_REF, &state->stencilState.stencilFrontRef);
    if (state->stencilState.stencilFrontFunc != mStencilFrontFunc ||
        state->stencilState.stencilFrontMask != mStencilFrontValueMask ||
        state->stencilState.stencilFrontRef != mStencilFrontRef)
    {
        mStencilFrontFunc      = state->stencilState.stencilFrontFunc;
        mStencilFrontValueMask = state->stencilState.stencilFrontMask;
        mStencilFrontRef       = state->stencilState.stencilFrontRef;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
    }

    get(GL_STENCIL_BACK_FUNC, &state->stencilState.stencilBackFunc);
    get(GL_STENCIL_BACK_VALUE_MASK, &state->stencilState.stencilBackMask);
    get(GL_STENCIL_BACK_REF, &state->stencilState.stencilBackRef);
    if (state->stencilState.stencilBackFunc != mStencilBackFunc ||
        state->stencilState.stencilBackMask != mStencilBackValueMask ||
        state->stencilState.stencilBackRef != mStencilBackRef)
    {
        mStencilBackFunc      = state->stencilState.stencilBackFunc;
        mStencilBackValueMask = state->stencilState.stencilBackMask;
        mStencilBackRef       = state->stencilState.stencilBackRef;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
    }

    get(GL_STENCIL_CLEAR_VALUE, &state->stencilState.stencilClear);
    if (mClearStencil != state->stencilState.stencilClear)
    {
        mClearStencil = state->stencilState.stencilClear;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
    }

    get(GL_STENCIL_WRITEMASK, &state->stencilState.stencilFrontWritemask);
    if (mStencilFrontWritemask != static_cast<GLenum>(state->stencilState.stencilFrontWritemask))
    {
        mStencilFrontWritemask = state->stencilState.stencilFrontWritemask;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
    }

    get(GL_STENCIL_BACK_WRITEMASK, &state->stencilState.stencilBackWritemask);
    if (mStencilBackWritemask != static_cast<GLenum>(state->stencilState.stencilBackWritemask))
    {
        mStencilBackWritemask = state->stencilState.stencilBackWritemask;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
    }

    get(GL_STENCIL_FAIL, &state->stencilState.stencilFrontFailOp);
    get(GL_STENCIL_PASS_DEPTH_FAIL, &state->stencilState.stencilFrontZFailOp);
    get(GL_STENCIL_PASS_DEPTH_PASS, &state->stencilState.stencilFrontZPassOp);
    if (mStencilFrontStencilFailOp != static_cast<GLenum>(state->stencilState.stencilFrontFailOp) ||
        mStencilFrontStencilPassDepthFailOp !=
            static_cast<GLenum>(state->stencilState.stencilFrontZFailOp) ||
        mStencilFrontStencilPassDepthPassOp !=
            static_cast<GLenum>(state->stencilState.stencilFrontZPassOp))
    {
        mStencilFrontStencilFailOp = static_cast<GLenum>(state->stencilState.stencilFrontFailOp);
        mStencilFrontStencilPassDepthFailOp =
            static_cast<GLenum>(state->stencilState.stencilFrontZFailOp);
        mStencilFrontStencilPassDepthPassOp =
            static_cast<GLenum>(state->stencilState.stencilFrontZPassOp);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
    }

    get(GL_STENCIL_BACK_FAIL, &state->stencilState.stencilBackFailOp);
    get(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &state->stencilState.stencilBackZFailOp);
    get(GL_STENCIL_BACK_PASS_DEPTH_PASS, &state->stencilState.stencilBackZPassOp);
    if (mStencilBackStencilFailOp != static_cast<GLenum>(state->stencilState.stencilBackFailOp) ||
        mStencilBackStencilPassDepthFailOp !=
            static_cast<GLenum>(state->stencilState.stencilBackZFailOp) ||
        mStencilBackStencilPassDepthPassOp !=
            static_cast<GLenum>(state->stencilState.stencilBackZPassOp))
    {
        mStencilBackStencilFailOp = static_cast<GLenum>(state->stencilState.stencilBackFailOp);
        mStencilBackStencilPassDepthFailOp =
            static_cast<GLenum>(state->stencilState.stencilBackZFailOp);
        mStencilBackStencilPassDepthPassOp =
            static_cast<GLenum>(state->stencilState.stencilBackZPassOp);
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
    }
}

void StateManagerGL::restoreStencilNativeContext(const gl::Extensions &extensions,
                                                 const ExternalContextState *state)
{
    setStencilTestEnabled(state->stencilState.stencilTestEnabled);
    setStencilFrontFuncs(state->stencilState.stencilFrontFunc, state->stencilState.stencilFrontMask,
                         state->stencilState.stencilFrontRef);
    setStencilBackFuncs(state->stencilState.stencilBackFunc, state->stencilState.stencilBackMask,
                        state->stencilState.stencilBackRef);
    setClearStencil(state->stencilState.stencilClear);
    setStencilFrontWritemask(state->stencilState.stencilFrontWritemask);
    setStencilBackWritemask(state->stencilState.stencilBackWritemask);
    setStencilFrontOps(state->stencilState.stencilFrontFailOp,
                       state->stencilState.stencilFrontZFailOp,
                       state->stencilState.stencilFrontZPassOp);
    setStencilBackOps(state->stencilState.stencilBackFailOp, state->stencilState.stencilBackZFailOp,
                      state->stencilState.stencilBackZPassOp);
}

void StateManagerGL::syncBufferBindingsFromNativeContext(const gl::Extensions &extensions,
                                                         ExternalContextState *state)
{
    get(GL_ARRAY_BUFFER_BINDING, &state->vertexArrayBufferBinding);
    mBuffers[gl::BufferBinding::Array] = state->vertexArrayBufferBinding;

    get(GL_ELEMENT_ARRAY_BUFFER_BINDING, &state->elementArrayBufferBinding);
    mBuffers[gl::BufferBinding::ElementArray] = state->elementArrayBufferBinding;
}

void StateManagerGL::restoreBufferBindingsNativeContext(const gl::Extensions &extensions,
                                                        const ExternalContextState *state)
{
    bindBuffer(gl::BufferBinding::Array, state->vertexArrayBufferBinding);
    bindBuffer(gl::BufferBinding::ElementArray, state->elementArrayBufferBinding);
}

void StateManagerGL::syncTextureUnitsFromNativeContext(const gl::Extensions &extensions,
                                                       ExternalContextState *state)
{
    get(GL_ACTIVE_TEXTURE, &state->activeTexture);

    for (size_t i = 0; i < state->textureBindings.size(); ++i)
    {
        auto &bindings = state->textureBindings[i];
        activeTexture(i);
        get(GL_TEXTURE_BINDING_2D, &bindings.texture2d);
        get(GL_TEXTURE_BINDING_CUBE_MAP, &bindings.textureCubeMap);
        get(GL_TEXTURE_BINDING_EXTERNAL_OES, &bindings.textureExternalOES);
        if (mTextures[gl::TextureType::_2D][i] != static_cast<GLuint>(bindings.texture2d) ||
            mTextures[gl::TextureType::CubeMap][i] !=
                static_cast<GLuint>(bindings.textureCubeMap) ||
            mTextures[gl::TextureType::External][i] !=
                static_cast<GLuint>(bindings.textureExternalOES))
        {
            mTextures[gl::TextureType::_2D][i]      = bindings.texture2d;
            mTextures[gl::TextureType::CubeMap][i]  = bindings.textureCubeMap;
            mTextures[gl::TextureType::External][i] = bindings.textureExternalOES;
            mLocalDirtyBits.set(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
        }
    }
}

void StateManagerGL::restoreTextureUnitsNativeContext(const gl::Extensions &extensions,
                                                      const ExternalContextState *state)
{
    for (size_t i = 0; i < state->textureBindings.size(); ++i)
    {
        const auto &bindings = state->textureBindings[i];
        activeTexture(i);
        bindTexture(gl::TextureType::_2D, bindings.texture2d);
        bindTexture(gl::TextureType::CubeMap, bindings.textureCubeMap);
        bindTexture(gl::TextureType::External, bindings.textureExternalOES);
        bindSampler(i, 0);
    }
    activeTexture(state->activeTexture - GL_TEXTURE0);
}

void StateManagerGL::syncVertexArraysFromNativeContext(const gl::Extensions &extensions,
                                                       ExternalContextState *state)
{
    get(GL_VERTEX_ARRAY_BINDING, &state->vertexArrayBinding);
    if (mVAO != static_cast<GLuint>(state->vertexArrayBinding))
    {
        mVAO                                      = state->vertexArrayBinding;
        mBuffers[gl::BufferBinding::ElementArray] = 0;
        mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
    }
}

void StateManagerGL::restoreVertexArraysNativeContext(const gl::Extensions &extensions,
                                                      const ExternalContextState *state)
{
    bindVertexArray(state->vertexArrayBinding, 0);
}

void StateManagerGL::setDefaultVAOStateDirty()
{
    mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
}

}  // namespace rx
