//
// 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 "libANGLE/renderer/gl/ContextGL.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 "common/unsafe_buffers.h"
#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/Query.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/histogram_macros.h"
#include "libANGLE/queryconversions.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"
#include "platform/PlatformMethods.h"

namespace rx
{

namespace
{

inline void SetGLBoolState(const FunctionsGL *functions, GLenum name, bool value)
{
    if (value)
    {
        functions->enable(name);
    }
    else
    {
        functions->disable(name);
    }
}

inline void SetGLIndexedBoolState(const FunctionsGL *functions,
                                  GLenum name,
                                  GLuint index,
                                  bool value)
{
    if (value)
    {
        functions->enablei(name, index);
    }
    else
    {
        functions->disablei(name, index);
    }
}

inline void SetVertexAttribArrayEnabled(const FunctionsGL *functions, GLuint index, bool value)
{
    if (value)
    {
        functions->enableVertexAttribArray(index);
    }
    else
    {
        functions->disableVertexAttribArray(index);
    }
}

#if defined(ANGLE_ENABLE_ASSERTS)
#    define ANGLE_GL_CHECK_GET_HELPER(functions, getter, name, value)                              \
        do                                                                                         \
        {                                                                                          \
            ANGLE_GL_CLEAR_ERRORS(functions);                                                      \
            functions->getter(name, value);                                                        \
            GLenum error = functions->getError();                                                  \
            (error == GL_NO_ERROR) ? static_cast<void>(0)                                          \
                                   : ERR() << "Querying " << gl::FmtHex(name) << " using "         \
                                           << #getter << " generated error " << gl::FmtHex(error); \
        } while (0)

#    define ANGLE_GL_CHECK_GET_INDEXED_HELPER(functions, getter, name, index, value)               \
        do                                                                                         \
        {                                                                                          \
            ANGLE_GL_CLEAR_ERRORS(functions);                                                      \
            functions->getter(name, index, value);                                                 \
            GLenum error = functions->getError();                                                  \
            (error == GL_NO_ERROR) ? static_cast<void>(0)                                          \
                                   : ERR() << "Querying " << gl::FmtHex(name) << " at index "      \
                                           << index << " using " << #getter << " generated error " \
                                           << gl::FmtHex(error);                                   \
        } while (0)

#    define ANGLE_GL_CHECK_GET_ENABLED_HELPER(functions, getter, name, value)                      \
        do                                                                                         \
        {                                                                                          \
            ANGLE_GL_CLEAR_ERRORS(functions);                                                      \
            *value       = functions->getter(name);                                                \
            GLenum error = functions->getError();                                                  \
            (error == GL_NO_ERROR) ? static_cast<void>(0)                                          \
                                   : ERR() << "Querying " << gl::FmtHex(name) << " using "         \
                                           << #getter << " generated error " << gl::FmtHex(error); \
        } while (0)

#    define ANGLE_GL_CHECK_GET_INDEXED_ENABLED_HELPER(functions, getter, name, index, value)       \
        do                                                                                         \
        {                                                                                          \
            ANGLE_GL_CLEAR_ERRORS(functions);                                                      \
            *value       = functions->getter(name, index);                                         \
            GLenum error = functions->getError();                                                  \
            (error == GL_NO_ERROR) ? static_cast<void>(0)                                          \
                                   : ERR() << "Querying " << gl::FmtHex(name) << " at index "      \
                                           << index << " using " << #getter << " generated error " \
                                           << gl::FmtHex(error);                                   \
        } while (0)

#    define ANGLE_GL_CHECK_GET_VERTEX_HELPER(functions, getter, index, name, value)                \
        do                                                                                         \
        {                                                                                          \
            ANGLE_GL_CLEAR_ERRORS(functions);                                                      \
            functions->getter(index, name, value);                                                 \
            GLenum error = functions->getError();                                                  \
            (error == GL_NO_ERROR) ? static_cast<void>(0)                                          \
                                   : ERR() << "Querying " << gl::FmtHex(name) << " for attribute " \
                                           << index << " using " << #getter << " generated error " \
                                           << gl::FmtHex(error);                                   \
        } while (0)
#else
#    define ANGLE_GL_CHECK_GET_HELPER(functions, getter, name, value) functions->getter(name, value)
#    define ANGLE_GL_CHECK_GET_INDEXED_HELPER(functions, getter, name, index, value) \
        functions->getter(name, index, value)
#    define ANGLE_GL_CHECK_GET_ENABLED_HELPER(functions, getter, name, value) \
        *value = functions->getter(name)
#    define ANGLE_GL_CHECK_GET_INDEXED_ENABLED_HELPER(functions, getter, name, index, value) \
        *value = functions->getter(name, index)
#    define ANGLE_GL_CHECK_GET_VERTEX_HELPER(functions, getter, index, name, value) \
        functions->getter(index, name, value)
#endif

// Non-indexed GLboolean -> glIsEnabled
void GetEnabledHelper(const FunctionsGL *functions, GLenum name, GLboolean *value)
{
    ANGLE_GL_CHECK_GET_ENABLED_HELPER(functions, isEnabled, name, value);
}

// Indexed GLboolean -> glIsEnabledi
void GetEnabledHelper(const FunctionsGL *functions, GLenum name, GLuint index, GLboolean *value)
{
    ANGLE_GL_CHECK_GET_INDEXED_ENABLED_HELPER(functions, isEnabledi, name, index, value);
}
// Non-indexed bool -> Non-indexed GLboolean (for enabled checks)
void GetEnabledHelper(const FunctionsGL *functions, GLenum name, bool *value)
{
    GLboolean v = gl::ConvertToGLBoolean(*value);
    GetEnabledHelper(functions, name, &v);
    *value = gl::ConvertToBool(v);
}

// Indexed bool -> Indexed GLboolean (for enabled checks)
void GetEnabledHelper(const FunctionsGL *functions, GLenum name, GLuint index, bool *value)
{
    GLboolean v = gl::ConvertToGLBoolean(*value);
    GetEnabledHelper(functions, name, index, &v);
    *value = gl::ConvertToBool(v);
}

// Non-indexed GLint -> glGetIntegerv
void GetHelper(const FunctionsGL *functions, GLenum name, GLint *value)
{
    ANGLE_GL_CHECK_GET_HELPER(functions, getIntegerv, name, value);
}

// Indexed GLint -> glGetIntegeri_v
void GetHelper(const FunctionsGL *functions, GLenum name, GLuint index, GLint *value)
{
    ANGLE_GL_CHECK_GET_INDEXED_HELPER(functions, getIntegeri_v, name, index, value);
}

// Non-indexed GLenum -> Non-indexed GLint
void GetHelper(const FunctionsGL *functions, GLenum name, GLenum *value)
{
    GLint v = *value;
    GetHelper(functions, name, &v);
    *value = static_cast<GLenum>(v);
}

// Indexed GLenum -> Indexed GLint
void GetHelper(const FunctionsGL *functions, GLenum name, GLuint index, GLenum *value)
{
    GLint v = *value;
    GetHelper(functions, name, index, &v);
    *value = static_cast<GLenum>(v);
}

// Non-indexed bool -> Non-indexed GLint
void GetHelper(const FunctionsGL *functions, GLenum name, bool *value)
{
    GLint v = gl::ConvertToGLBoolean(*value);
    GetHelper(functions, name, &v);
    *value = gl::ConvertToBool(v);
}

// Indexed GLboolean -> Indexed GLint
void GetHelper(const FunctionsGL *functions, GLenum name, GLuint index, GLboolean *value)
{
    GLint v = gl::ConvertToGLBoolean(*value);
    GetHelper(functions, name, index, &v);
    *value = gl::ConvertToBool(v);
}

// Non-indexed std::array<bool, N> -> Non-indexed GLboolean
template <size_t N>
void GetHelper(const FunctionsGL *functions, GLenum name, std::array<bool, N> *values)
{
    std::array<GLint, N> v;
    for (size_t i = 0; i < N; i++)
    {
        v[i] = gl::ConvertToGLBoolean(values->at(i));
    }
    GetHelper(functions, name, v.data());
    for (size_t i = 0; i < N; i++)
    {
        (*values)[i] = gl::ConvertToBool(v[i]);
    }
}

// Indexed std::array<bool, N> -> Indexed GLboolean
template <size_t N>
void GetHelper(const FunctionsGL *functions, GLenum name, GLuint index, std::array<bool, N> *values)
{
    std::array<GLint, N> v;
    for (size_t i = 0; i < N; i++)
    {
        v[i] = gl::ConvertToGLBoolean(values->at(i));
    }
    GetHelper(functions, name, index, v.data());
    for (size_t i = 0; i < N; i++)
    {
        (*values)[i] = gl::ConvertToBool(v[i]);
    }
}

// Non-indexed gl::Rectangle -> Non-indexed GLint
void GetHelper(const FunctionsGL *functions, GLenum name, gl::Rectangle *rect)
{
    std::array<GLint, 4> v = {rect->x, rect->y, rect->width, rect->height};
    GetHelper(functions, name, v.data());
    *rect = gl::Rectangle(v[0], v[1], v[2], v[3]);
}

// Non-indexed GLfloat -> glGetFloatv
void GetHelper(const FunctionsGL *functions, GLenum name, GLfloat *value)
{
    ANGLE_GL_CHECK_GET_HELPER(functions, getFloatv, name, value);
}

// Non-indexed gl::ColorF -> Non-indexed GLfloat
void GetHelper(const FunctionsGL *functions, GLenum name, gl::ColorF *color)
{
    std::array<GLfloat, 4> v = {color->red, color->green, color->blue, color->alpha};
    GetHelper(functions, name, v.data());
    *color = gl::ColorF(v[0], v[1], v[2], v[3]);
}

// Non-indexed packed enum -> Non-indexed GLint
template <typename InternalEnumType, InternalEnumType MaxSize = InternalEnumType::EnumCount>
void GetHelper(const FunctionsGL *functions, GLenum name, InternalEnumType *internalEnum)
{
    GLint v = gl::ToGLenum(*internalEnum);
    GetHelper(functions, name, &v);
    *internalEnum = gl::FromGLenum<InternalEnumType>(v);
}

// Indexed packed enum -> Indexed GLint
template <typename InternalEnumType, InternalEnumType MaxSize = InternalEnumType::EnumCount>
void GetHelper(const FunctionsGL *functions,
               GLenum name,
               GLuint index,
               InternalEnumType *internalEnum)
{
    GLint v = gl::ToGLenum(*internalEnum);
    GetHelper(functions, name, index, &v);
    *internalEnum = gl::FromGLenum<InternalEnumType>(v);
}

// Non-indexed std::array<packed enum> -> Non-indexed GLint
template <typename InternalEnumType,
          size_t N,
          InternalEnumType MaxSize = InternalEnumType::EnumCount>
void GetHelper(const FunctionsGL *functions,
               GLenum name,
               std::array<InternalEnumType, N> *internalEnum)
{
    std::array<GLint, N> v;
    for (size_t i = 0; i < N; i++)
    {
        v[i] = gl::ToGLenum(internalEnum->at(i));
    }
    GetHelper(functions, name, v.data());
    for (size_t i = 0; i < N; i++)
    {
        internalEnum->at(i) = gl::FromGLenum<InternalEnumType>(v[i]);
    }
}

// Indexed GLint64 -> glGetInteger64i_v
void GetHelper(const FunctionsGL *functions, GLenum name, GLuint index, GLint64 *value)
{
    ANGLE_GL_CHECK_GET_INDEXED_HELPER(functions, getInteger64i_v, name, index, value);
}

// Indexed GLintptr -> Indexed GLint64. Enabled only if GLintptr is not the same as GLint64.
template <typename T = void>
void GetHelper(const FunctionsGL *functions, GLenum name, GLuint index, GLintptr *value)
    requires(!std::is_same_v<GLintptr, GLint64>)
{
    GLint64 v = *value;
    GetHelper(functions, name, index, &v);
    *value = static_cast<GLintptr>(v);
}

// GLint -> glGetVertexAttribiv
void GetVertexHelper(const FunctionsGL *functions, GLuint index, GLenum name, GLint *value)
{
    ANGLE_GL_CHECK_GET_VERTEX_HELPER(functions, getVertexAttribiv, index, name, value);
}

// GLenum -> GLint
void GetVertexHelper(const FunctionsGL *functions, GLuint index, GLenum name, GLenum *value)
{
    GLint v = static_cast<GLint>(*value);
    GetVertexHelper(functions, index, name, &v);
    *value = static_cast<GLint>(v);
}

// bool -> GLint
void GetVertexHelper(const FunctionsGL *functions, GLuint index, GLenum name, bool *value)
{
    GLint v = gl::ConvertToGLBoolean(*value);
    GetVertexHelper(functions, index, name, &v);
    *value = gl::ConvertToBool(v);
}

// packed enum -> GLint
template <typename InternalEnumType, InternalEnumType MaxSize = InternalEnumType::EnumCount>
void GetVertexHelper(const FunctionsGL *functions,
                     GLuint index,
                     GLenum name,
                     InternalEnumType *internalEnum)
{
    GLint v = gl::ToGLenum(*internalEnum);
    GetVertexHelper(functions, index, name, &v);
    *internalEnum = gl::FromGLenum<InternalEnumType>(v);
}

// const void* -> glGetVertexAttribPointerv
void GetVertexHelper(const FunctionsGL *functions, GLuint index, GLenum name, void **value)
{
    ANGLE_GL_CHECK_GET_VERTEX_HELPER(functions, getVertexAttribPointerv, index, name, value);
}

struct ScopedBindDrawFramebuffer
{
    ScopedBindDrawFramebuffer(const FunctionsGL *functions, GLuint prevFbo, GLuint fbo)
        : functions(functions),
          binding(nativegl::SupportsSeparateFramebufferBindings(functions) ? GL_DRAW_FRAMEBUFFER
                                                                           : GL_FRAMEBUFFER),
          prevFbo(prevFbo)
    {
        functions->bindFramebuffer(binding, fbo);
    }

    ~ScopedBindDrawFramebuffer() { functions->bindFramebuffer(binding, prevFbo); }

    const FunctionsGL *functions = nullptr;
    GLenum binding               = 0;
    GLenum prevFbo               = 0;
};

struct ScopedBindVAO
{
    ScopedBindVAO(const FunctionsGL *functions, GLuint prevVAO, GLuint newVAO)
        : functions(functions), prevVAO(prevVAO), newVAO(newVAO)
    {
        if (newVAO != prevVAO)
        {
            functions->bindVertexArray(newVAO);
        }
    }

    ~ScopedBindVAO()
    {
        if (newVAO != prevVAO)
        {
            functions->bindVertexArray(prevVAO);
        }
    }

    const FunctionsGL *functions = nullptr;
    GLuint prevVAO               = 0;
    GLuint newVAO                = 0;
};

void QueryContextStateGL(const FunctionsGL *functions,
                         GLuint framebufferWithStencilBits,
                         ContextStateGL *state)
{
    GetHelper(functions, GL_CURRENT_PROGRAM, &state->program);

    if (nativegl::SupportsVertexArrayObjects(functions))
    {
        GetHelper(functions, GL_VERTEX_ARRAY_BINDING, &state->vao);
    }

    {
        // Query the default VAO state, temporarily bind VAO 0
        ScopedBindVAO scopedVAO(functions, state->vao, 0);
        QueryVertexArrayStateGL(functions, &state->defaultVAOState);
    }

    GLint maxVertexAttribs = 0;
    GetHelper(functions, GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
    maxVertexAttribs = std::min(maxVertexAttribs, static_cast<GLint>(gl::MAX_VERTEX_ATTRIBS));

    for (GLint i = 0; i < maxVertexAttribs; i++)
    {
        // It is only valid to query the vertex attrib data using the same type used to set the data
        // but there is no query for the data type. Do our best and query using the type that
        // already exists in state.
        switch (state->vertexAttribCurrentValues[i].Type)
        {
            case gl::VertexAttribType::Float:
                functions->getVertexAttribfv(
                    i, GL_CURRENT_VERTEX_ATTRIB,
                    state->vertexAttribCurrentValues[i].Values.FloatValues);
                break;
            case gl::VertexAttribType::Int:
                functions->getVertexAttribIiv(i, GL_CURRENT_VERTEX_ATTRIB,
                                              state->vertexAttribCurrentValues[i].Values.IntValues);
                break;
            case gl::VertexAttribType::UnsignedInt:
                functions->getVertexAttribIuiv(
                    i, GL_CURRENT_VERTEX_ATTRIB,
                    state->vertexAttribCurrentValues[i].Values.UnsignedIntValues);
                break;
            default:
                UNREACHABLE();
        }
    }

    for (gl::BufferBinding bufferBinding : angle::AllEnums<gl::BufferBinding>())
    {
        if (!nativegl::SupportsBufferBinding(functions, bufferBinding))
        {
            continue;
        }

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

        nativegl::BufferBindingQuery queryEnums = nativegl::GetBufferBindingQuery(bufferBinding);
        GetHelper(functions, queryEnums.bindingQuery, &state->buffers[bufferBinding]);

        for (GLuint i = 0; i < state->indexedBuffers[bufferBinding].size(); i++)
        {
            IndexedBufferBindingGL &binding = state->indexedBuffers[bufferBinding][i];

            GetHelper(functions, queryEnums.bindingQuery, i, &binding.buffer);

            ASSERT(queryEnums.startQuery.has_value());
            GetHelper(functions, queryEnums.startQuery.value(), i, &binding.offset);

            ASSERT(queryEnums.sizeQuery.has_value());
            GetHelper(functions, queryEnums.sizeQuery.value(), i, &binding.size);
        }
    }

    GLuint activeTexture = 0;
    GetHelper(functions, GL_ACTIVE_TEXTURE, &activeTexture);
    state->textureUnitIndex = activeTexture - GL_TEXTURE0;

    GLint maxCombinedTextureImageUnits = 0;
    GetHelper(functions, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedTextureImageUnits);
    maxCombinedTextureImageUnits = std::min(
        maxCombinedTextureImageUnits, static_cast<GLint>(gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES));

    for (GLint i = 0; i < maxCombinedTextureImageUnits; i++)
    {
        functions->activeTexture(GL_TEXTURE0 + i);
        for (gl::TextureType textureType : angle::AllEnums<gl::TextureType>())
        {
            if (!nativegl::SupportsTextureType(functions, textureType))
            {
                continue;
            }

            GetHelper(functions, nativegl::GetTextureBindingQuery(textureType),
                      &state->textures[textureType][i]);
        }

        if (nativegl::SupportsSamplerObjects(functions))
        {
            GetHelper(functions, GL_SAMPLER_BINDING, &state->samplers[i]);
        }
    }
    // Reset the active texture
    functions->activeTexture(activeTexture);

    for (GLuint i = 0; i < state->images.size(); i++)
    {
        ImageUnitBindingGL &image = state->images[i];
        GetHelper(functions, GL_IMAGE_BINDING_NAME, i, &image.texture);
        GetHelper(functions, GL_IMAGE_BINDING_LEVEL, i, &image.level);
        GetHelper(functions, GL_IMAGE_BINDING_LAYERED, i, &image.layered);
        GetHelper(functions, GL_IMAGE_BINDING_LAYER, i, &image.layer);
        GetHelper(functions, GL_IMAGE_BINDING_ACCESS, i, &image.access);
        GetHelper(functions, GL_IMAGE_BINDING_FORMAT, i, &image.format);
    }

    if (nativegl::SupportsTransformFeedback(functions))
    {
        GetHelper(functions, GL_TRANSFORM_FEEDBACK_BINDING, &state->transformFeedback);
    }

    GetHelper(functions, GL_UNPACK_ALIGNMENT, &state->unpackState.alignment);

    if (nativegl::SupportsUnpackSubImage(functions))
    {
        GetHelper(functions, GL_UNPACK_ROW_LENGTH, &state->unpackState.rowLength);
        GetHelper(functions, GL_UNPACK_SKIP_ROWS, &state->unpackState.skipRows);
        GetHelper(functions, GL_UNPACK_SKIP_PIXELS, &state->unpackState.skipPixels);
    }

    if (nativegl::Supports3DUnpackParameters(functions))
    {
        GetHelper(functions, GL_UNPACK_IMAGE_HEIGHT, &state->unpackState.imageHeight);
        GetHelper(functions, GL_UNPACK_SKIP_IMAGES, &state->unpackState.skipImages);
    }

    GetHelper(functions, GL_PACK_ALIGNMENT, &state->packState.alignment);

    if (nativegl::SupportsPackSubImage(functions))
    {
        GetHelper(functions, GL_PACK_ROW_LENGTH, &state->packState.rowLength);
        GetHelper(functions, GL_PACK_SKIP_ROWS, &state->packState.skipRows);
        GetHelper(functions, GL_PACK_SKIP_PIXELS, &state->packState.skipPixels);
    }

    if (nativegl::SupportsSeparateFramebufferBindings(functions))
    {
        GetHelper(functions, GL_READ_FRAMEBUFFER_BINDING,
                  &state->framebuffers[angle::FramebufferBindingRead]);
        GetHelper(functions, GL_DRAW_FRAMEBUFFER_BINDING,
                  &state->framebuffers[angle::FramebufferBindingDraw]);
    }
    else
    {
        GetHelper(functions, GL_FRAMEBUFFER_BINDING,
                  &state->framebuffers[angle::FramebufferBindingDraw]);
        state->framebuffers[angle::FramebufferBindingRead] =
            state->framebuffers[angle::FramebufferBindingDraw];
    }

    // Bind a framebuffer with stencil bits for the rest of the queries. Many queries related to
    // stencil will mask with the number of bits in the current stencil buffer.
    ScopedBindDrawFramebuffer scopedFramebufferWithStencil(
        functions, state->framebuffers[angle::FramebufferBindingDraw], framebufferWithStencilBits);

    GetHelper(functions, GL_RENDERBUFFER_BINDING, &state->renderbuffer);

    GetEnabledHelper(functions, GL_SCISSOR_TEST, &state->scissorTestEnabled);
    GetHelper(functions, GL_SCISSOR_BOX, &state->scissor);
    GetHelper(functions, GL_VIEWPORT, &state->viewport);
    {
        float depthRange[2] = {state->near, state->far};
        GetHelper(functions, GL_DEPTH_RANGE, depthRange);
        state->near = depthRange[0];
        state->far  = depthRange[1];
    }

    if (nativegl::SupportsClipControl(functions))
    {
        GetHelper(functions, GL_CLIP_ORIGIN, &state->clipOrigin);
        GetHelper(functions, GL_CLIP_DEPTH_MODE, &state->clipDepthMode);
    }

    GetHelper(functions, GL_BLEND_COLOR, &state->blendColor);
    if (nativegl::SupportsDrawBuffersIndexed(functions))
    {
        GLint maxDrawBuffers = 0;
        GetHelper(functions, GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
        maxDrawBuffers =
            std::min(maxDrawBuffers, static_cast<GLint>(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS));

        for (GLuint i = 0; i < static_cast<GLuint>(maxDrawBuffers); i++)
        {
            bool enabled = state->blendState.getEnabledMask().test(i);
            GetEnabledHelper(functions, GL_BLEND, i, &enabled);
            state->blendState.setEnabledIndexed(i, enabled);

            std::array<bool, 4> colorMask;
            state->blendState.getColorMaskIndexed(i, &colorMask[0], &colorMask[1], &colorMask[2],
                                                  &colorMask[3]);
            GetHelper(functions, GL_COLOR_WRITEMASK, i, &colorMask);
            state->blendState.setColorMaskIndexed(i, colorMask[0], colorMask[1], colorMask[2],
                                                  colorMask[3]);

            gl::BlendFactorType blendSrcRgb = state->blendState.getSrcColorIndexed(i);
            GetHelper(functions, GL_BLEND_SRC_RGB, i, &blendSrcRgb);
            gl::BlendFactorType blendDestRgb = state->blendState.getDstColorIndexed(i);
            GetHelper(functions, GL_BLEND_DST_RGB, i, &blendDestRgb);
            gl::BlendFactorType blendSrcAlpha = state->blendState.getSrcAlphaIndexed(i);
            GetHelper(functions, GL_BLEND_SRC_ALPHA, i, &blendSrcAlpha);
            gl::BlendFactorType blendDestAlpha = state->blendState.getDstAlphaIndexed(i);
            GetHelper(functions, GL_BLEND_DST_ALPHA, i, &blendDestAlpha);
            state->blendState.setFactorsIndexed(i, blendSrcRgb, blendDestRgb, blendSrcAlpha,
                                                blendDestAlpha);

            gl::BlendEquationType blendEquationRgb = state->blendState.getEquationColorIndexed(i);
            GetHelper(functions, GL_BLEND_EQUATION_RGB, i, &blendEquationRgb);
            gl::BlendEquationType blendEquationAlpha = state->blendState.getEquationAlphaIndexed(i);
            GetHelper(functions, GL_BLEND_EQUATION_ALPHA, i, &blendEquationAlpha);
            state->blendState.setEquationsIndexed(i, blendEquationRgb, blendEquationAlpha);
        }
    }
    else
    {
        bool enabled = state->blendState.getEnabledMask().test(0);
        GetEnabledHelper(functions, GL_BLEND, &enabled);
        state->blendState.setEnabled(enabled);

        std::array<bool, 4> colorMask;
        state->blendState.getColorMaskIndexed(0, &colorMask[0], &colorMask[1], &colorMask[2],
                                              &colorMask[3]);
        GetHelper(functions, GL_COLOR_WRITEMASK, &colorMask);
        state->blendState.setColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);

        gl::BlendFactorType blendSrcRgb = state->blendState.getSrcColorIndexed(0);
        GetHelper(functions, GL_BLEND_SRC_RGB, &blendSrcRgb);
        gl::BlendFactorType blendDestRgb = state->blendState.getDstColorIndexed(0);
        GetHelper(functions, GL_BLEND_DST_RGB, &blendDestRgb);
        gl::BlendFactorType blendSrcAlpha = state->blendState.getSrcAlphaIndexed(0);
        GetHelper(functions, GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
        gl::BlendFactorType blendDestAlpha = state->blendState.getDstAlphaIndexed(0);
        GetHelper(functions, GL_BLEND_DST_ALPHA, &blendDestAlpha);
        state->blendState.setFactors(blendSrcRgb, blendDestRgb, blendSrcAlpha, blendDestAlpha);

        gl::BlendEquationType blendEquationRgb = state->blendState.getEquationColorIndexed(0);
        GetHelper(functions, GL_BLEND_EQUATION_RGB, &blendEquationRgb);
        gl::BlendEquationType blendEquationAlpha = state->blendState.getEquationAlphaIndexed(0);
        GetHelper(functions, GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
        state->blendState.setEquations(blendEquationRgb, blendEquationAlpha);
    }
    if (nativegl::SupportsBlendEquationAdvancedCoherent(functions))
    {
        GetEnabledHelper(functions, GL_BLEND_ADVANCED_COHERENT_KHR, &state->blendAdvancedCoherent);
    }

    GetEnabledHelper(functions, GL_SAMPLE_ALPHA_TO_COVERAGE, &state->sampleAlphaToCoverageEnabled);
    GetEnabledHelper(functions, GL_SAMPLE_COVERAGE, &state->sampleCoverageEnabled);
    GetHelper(functions, GL_SAMPLE_COVERAGE_VALUE, &state->sampleCoverageValue);
    GetHelper(functions, GL_SAMPLE_COVERAGE_INVERT, &state->sampleCoverageInvert);
    if (nativegl::SupportsSampleMask(functions))
    {
        GLint maxSampleMaskWords = 0;
        GetHelper(functions, GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
        maxSampleMaskWords = std::min(maxSampleMaskWords,
                                      static_cast<GLint>(gl::IMPLEMENTATION_MAX_SAMPLE_MASK_WORDS));

        GetEnabledHelper(functions, GL_SAMPLE_MASK, &state->sampleMaskEnabled);
        for (GLuint i = 0; i < static_cast<GLuint>(maxSampleMaskWords); i++)
        {
            GetHelper(functions, GL_SAMPLE_MASK_VALUE, i, &state->sampleMaskValues[i]);
        }
    }

    GetEnabledHelper(functions, GL_DEPTH_TEST, &state->depthTestEnabled);
    GetHelper(functions, GL_DEPTH_FUNC, &state->depthFunc);
    GetHelper(functions, GL_DEPTH_WRITEMASK, &state->depthMask);

    GetEnabledHelper(functions, GL_STENCIL_TEST, &state->stencilTestEnabled);

    GetHelper(functions, GL_STENCIL_FUNC, &state->stencilFrontFunc);
    GetHelper(functions, GL_STENCIL_REF, &state->stencilFrontRef);
    GetHelper(functions, GL_STENCIL_VALUE_MASK, &state->stencilFrontValueMask);
    GetHelper(functions, GL_STENCIL_FAIL, &state->stencilFrontStencilFailOp);
    GetHelper(functions, GL_STENCIL_PASS_DEPTH_FAIL, &state->stencilFrontStencilPassDepthFailOp);
    GetHelper(functions, GL_STENCIL_PASS_DEPTH_PASS, &state->stencilFrontStencilPassDepthPassOp);
    GetHelper(functions, GL_STENCIL_WRITEMASK, &state->stencilFrontWritemask);

    GetHelper(functions, GL_STENCIL_BACK_FUNC, &state->stencilBackFunc);
    GetHelper(functions, GL_STENCIL_BACK_REF, &state->stencilBackRef);
    GetHelper(functions, GL_STENCIL_BACK_VALUE_MASK, &state->stencilBackValueMask);
    GetHelper(functions, GL_STENCIL_BACK_FAIL, &state->stencilBackStencilFailOp);
    GetHelper(functions, GL_STENCIL_BACK_PASS_DEPTH_FAIL,
              &state->stencilBackStencilPassDepthFailOp);
    GetHelper(functions, GL_STENCIL_BACK_PASS_DEPTH_PASS,
              &state->stencilBackStencilPassDepthPassOp);
    GetHelper(functions, GL_STENCIL_BACK_WRITEMASK, &state->stencilBackWritemask);

    GetEnabledHelper(functions, GL_CULL_FACE, &state->cullFaceEnabled);
    GetHelper(functions, GL_CULL_FACE_MODE, &state->cullFace);
    GetHelper(functions, GL_FRONT_FACE, &state->frontFace);
    if (nativegl::SupportsPolygonMode(functions))
    {
        // GL Core and ES contexts return one value. GL Compatibility contexts return two values.
        std::array<gl::PolygonMode, 2> polygonMode = {state->polygonMode, state->polygonMode};
        GetHelper(functions, GL_POLYGON_MODE, &polygonMode);
        // Check that either the two values are equal or the second one is unwritten.
        ASSERT(polygonMode[0] == polygonMode[1] || polygonMode[1] == state->polygonMode);
        state->polygonMode = polygonMode[0];

        GetEnabledHelper(functions, GL_POLYGON_OFFSET_POINT, &state->polygonOffsetPointEnabled);
        GetEnabledHelper(functions, GL_POLYGON_OFFSET_LINE, &state->polygonOffsetLineEnabled);
    }
    GetEnabledHelper(functions, GL_POLYGON_OFFSET_FILL, &state->polygonOffsetFillEnabled);
    GetHelper(functions, GL_POLYGON_OFFSET_FACTOR, &state->polygonOffsetFactor);
    GetHelper(functions, GL_POLYGON_OFFSET_UNITS, &state->polygonOffsetUnits);
    if (nativegl::SupportsPolygonOffsetClamp(functions))
    {
        GetHelper(functions, GL_POLYGON_OFFSET_CLAMP_EXT, &state->polygonOffsetClamp);
    }
    if (nativegl::SupportsDepthClamp(functions))
    {
        GetEnabledHelper(functions, GL_DEPTH_CLAMP_EXT, &state->depthClampEnabled);
    }
    if (nativegl::SupportsRasterizerDiscard(functions))
    {
        GetEnabledHelper(functions, GL_RASTERIZER_DISCARD, &state->rasterizerDiscardEnabled);
    }
    GetHelper(functions, GL_LINE_WIDTH, &state->lineWidth);

    if (nativegl::SupportsPrimitiveRestartFixedIndex(functions))
    {
        GetEnabledHelper(functions, GL_PRIMITIVE_RESTART_FIXED_INDEX,
                         &state->primitiveRestartFixedIndexEnabled);
    }
    if (nativegl::SupportsPrimitiveRestart(functions))
    {
        GetEnabledHelper(functions, GL_PRIMITIVE_RESTART, &state->primitiveRestartEnabled);
        GetHelper(functions, GL_PRIMITIVE_RESTART_INDEX, &state->primitiveRestartIndex);
    }

    GetHelper(functions, GL_COLOR_CLEAR_VALUE, &state->clearColor);
    GetHelper(functions, GL_DEPTH_CLEAR_VALUE, &state->clearDepth);
    GetHelper(functions, GL_STENCIL_CLEAR_VALUE, &state->clearStencil);

    if (nativegl::SupportsSRGBWriteControl(functions))
    {
        GetEnabledHelper(functions, GL_FRAMEBUFFER_SRGB, &state->framebufferSRGBEnabled);
    }

    GetHelper(functions, GL_DITHER, &state->ditherEnabled);
    if (nativegl::SupportsSettingCubemapSeamless(functions))
    {
        GetEnabledHelper(functions, GL_TEXTURE_CUBE_MAP_SEAMLESS,
                         &state->textureCubemapSeamlessEnabled);
    }

    if (nativegl::SupportsMultisampleComatibility(functions))
    {
        GetEnabledHelper(functions, GL_MULTISAMPLE, &state->multisamplingEnabled);
        GetHelper(functions, GL_SAMPLE_ALPHA_TO_ONE, &state->sampleAlphaToOneEnabled);
    }

    if (nativegl::SupportsProvokingVertex(functions))
    {
        GetHelper(functions, GL_PROVOKING_VERTEX, &state->provokingVertex);
    }

    if (nativegl::SupportsClipCullDistance(functions))
    {
        GLint maxClipDistances = 0;
        GetHelper(functions, GL_MAX_CLIP_DISTANCES, &maxClipDistances);
        maxClipDistances =
            std::min(maxClipDistances, static_cast<GLint>(gl::IMPLEMENTATION_MAX_CLIP_DISTANCES));

        for (GLuint i = 0; i < static_cast<GLuint>(maxClipDistances); i++)
        {
            bool enabled = state->enabledClipDistances.test(i);
            GetEnabledHelper(functions, GL_CLIP_DISTANCE0 + i, &enabled);
            state->enabledClipDistances[i] = enabled;
        }
    }

    if (nativegl::SupportsLogicOp(functions))
    {
        GetEnabledHelper(functions, GL_COLOR_LOGIC_OP, &state->logicOpEnabled);
        GetHelper(functions, GL_LOGIC_OP_MODE, &state->logicOp);
    }
}

bool VertexAttribCurrentValuesEqual(const gl::VertexAttribCurrentValueData &a,
                                    const gl::VertexAttribCurrentValueData &b)
{
    // When comparing vertex attribute current values, only compare the data, not the type.
    return ANGLE_UNSAFE_BUFFERS(
               memcmp(&a.Values, &b.Values, sizeof(gl::VertexAttribCurrentValueData::Values))) == 0;
}

// Compute the mask of attributes that have different current values
gl::AttributesMask ComputeVertexAttribCurrentValueDiffMask(
    const gl::AttribArray<gl::VertexAttribCurrentValueData> &a,
    const gl::AttribArray<gl::VertexAttribCurrentValueData> &b)
{
    gl::AttributesMask diffMask;
    for (size_t i = 0; i < a.size(); i++)
    {
        diffMask.set(i, !VertexAttribCurrentValuesEqual(a[i], b[i]));
    }
    return diffMask;
}

std::optional<gl::state::DirtyBitType> GetBufferBindingDirtyBit(gl::BufferBinding binding)
{
    switch (binding)
    {
        case gl::BufferBinding::Array:
            // Array buffer bindings are set before vertex attrib calls.
            return std::nullopt;
        case gl::BufferBinding::AtomicCounter:
            return gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING;
        case gl::BufferBinding::CopyRead:
            // CopyRead does not affect any operations.
            return std::nullopt;
        case gl::BufferBinding::CopyWrite:
            // CopyWrite does not affect any operations.
            return std::nullopt;
        case gl::BufferBinding::DispatchIndirect:
            return gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING;
        case gl::BufferBinding::DrawIndirect:
            return gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING;
        case gl::BufferBinding::ElementArray:
            // Managed by the VAO
            return std::nullopt;
        case gl::BufferBinding::PixelPack:
            return gl::state::DIRTY_BIT_PACK_BUFFER_BINDING;
        case gl::BufferBinding::PixelUnpack:
            return gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING;
        case gl::BufferBinding::ShaderStorage:
            return gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING;
        case gl::BufferBinding::Texture:
            // Not implemented in the GL backend
            return std::nullopt;
        case gl::BufferBinding::TransformFeedback:
            // Transform feedback buffer bindings are tracked in TransformFeedbackGL
            return std::nullopt;
        case gl::BufferBinding::Uniform:
            return gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS;
        default:
            UNREACHABLE();
            return std::nullopt;
    }
}

template <typename T>
void SetDirtyBitIfStateDifferent(const T &a,
                                 const T &b,
                                 gl::state::DirtyBits *bits,
                                 gl::state::DirtyBitType bit)
{
    if (a != b)
    {
        bits->set(bit);
    }
}

template <typename T>
void SetDirtyBitExtIfStateDifferent(const T &a,
                                    const T &b,
                                    gl::state::DirtyBits *bits,
                                    gl::state::ExtendedDirtyBits *exBits,
                                    gl::state::ExtendedDirtyBitType exBit)
{
    if (a != b)
    {
        bits->set(gl::state::DIRTY_BIT_EXTENDED);
        exBits->set(exBit);
    }
}

// Compute the set of dirty bits needed to transition between two ContextStateGL objects.
[[maybe_unused]] void ComputeDirtyBitsBetweenStates(const ContextStateGL &a,
                                                    const ContextStateGL &b,
                                                    gl::state::DirtyBits *bits,
                                                    gl::state::ExtendedDirtyBits *exBits,
                                                    gl::AttributesMask *dirtyCurrentValues)
{
    SetDirtyBitIfStateDifferent(a.program, b.program, bits, gl::state::DIRTY_BIT_PROGRAM_BINDING);
    SetDirtyBitIfStateDifferent(a.vao, b.vao, bits, gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
    SetDirtyBitIfStateDifferent(a.defaultVAOState, b.defaultVAOState, bits,
                                gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
    {
        gl::AttributesMask currentValueDiff = ComputeVertexAttribCurrentValueDiffMask(
            a.vertexAttribCurrentValues, b.vertexAttribCurrentValues);
        if (currentValueDiff.any())
        {
            *dirtyCurrentValues |= currentValueDiff;
            bits->set(gl::state::DIRTY_BIT_CURRENT_VALUES);
        }
    }
    for (gl::BufferBinding bufferBinding : angle::AllEnums<gl::BufferBinding>())
    {
        std::optional<gl::state::DirtyBitType> bit = GetBufferBindingDirtyBit(bufferBinding);
        if (!bit.has_value())
        {
            continue;
        }

        SetDirtyBitIfStateDifferent(a.buffers[bufferBinding], b.buffers[bufferBinding], bits,
                                    bit.value());
        SetDirtyBitIfStateDifferent(a.indexedBuffers[bufferBinding],
                                    b.indexedBuffers[bufferBinding], bits, bit.value());
    }
    // No dirty bit for ContextStateGL::activeTexture
    SetDirtyBitIfStateDifferent(a.textures, b.textures, bits,
                                gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
    SetDirtyBitIfStateDifferent(a.samplers, b.samplers, bits,
                                gl::state::DIRTY_BIT_SAMPLER_BINDINGS);
    SetDirtyBitIfStateDifferent(a.images, b.images, bits, gl::state::DIRTY_BIT_IMAGE_BINDINGS);
    SetDirtyBitIfStateDifferent(a.transformFeedback, b.transformFeedback, bits,
                                gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
    SetDirtyBitIfStateDifferent(a.unpackState, b.unpackState, bits,
                                gl::state::DIRTY_BIT_UNPACK_STATE);
    SetDirtyBitIfStateDifferent(a.packState, b.packState, bits, gl::state::DIRTY_BIT_PACK_STATE);
    SetDirtyBitIfStateDifferent(a.framebuffers[angle::FramebufferBindingRead],
                                b.framebuffers[angle::FramebufferBindingRead], bits,
                                gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
    SetDirtyBitIfStateDifferent(a.framebuffers[angle::FramebufferBindingDraw],
                                b.framebuffers[angle::FramebufferBindingDraw], bits,
                                gl::state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
    SetDirtyBitIfStateDifferent(a.renderbuffer, b.renderbuffer, bits,
                                gl::state::DIRTY_BIT_RENDERBUFFER_BINDING);
    SetDirtyBitIfStateDifferent(a.scissorTestEnabled, b.scissorTestEnabled, bits,
                                gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED);
    SetDirtyBitIfStateDifferent(a.scissor, b.scissor, bits, gl::state::DIRTY_BIT_SCISSOR);
    SetDirtyBitIfStateDifferent(a.viewport, b.viewport, bits, gl::state::DIRTY_BIT_VIEWPORT);
    SetDirtyBitIfStateDifferent(a.near, b.near, bits, gl::state::DIRTY_BIT_DEPTH_RANGE);
    SetDirtyBitIfStateDifferent(a.far, b.far, bits, gl::state::DIRTY_BIT_DEPTH_RANGE);
    SetDirtyBitIfStateDifferent(a.clipOrigin, b.clipOrigin, bits,
                                gl::state::DIRTY_BIT_CLIP_CONTROL);
    SetDirtyBitIfStateDifferent(a.clipDepthMode, b.clipDepthMode, bits,
                                gl::state::DIRTY_BIT_CLIP_CONTROL);
    SetDirtyBitIfStateDifferent(a.blendColor, b.blendColor, bits, gl::state::DIRTY_BIT_BLEND_COLOR);
    SetDirtyBitIfStateDifferent(a.blendState.getAllEnabledMask(), b.blendState.getAllEnabledMask(),
                                bits, gl::state::DIRTY_BIT_COLOR_MASK);
    SetDirtyBitIfStateDifferent(a.blendState.getColorMaskBits(), b.blendState.getColorMaskBits(),
                                bits, gl::state::DIRTY_BIT_BLEND_ENABLED);
    SetDirtyBitIfStateDifferent(a.blendState.getSrcColorBits(), b.blendState.getSrcColorBits(),
                                bits, gl::state::DIRTY_BIT_BLEND_FUNCS);
    SetDirtyBitIfStateDifferent(a.blendState.getDstColorBits(), b.blendState.getDstColorBits(),
                                bits, gl::state::DIRTY_BIT_BLEND_FUNCS);
    SetDirtyBitIfStateDifferent(a.blendState.getSrcAlphaBits(), b.blendState.getSrcAlphaBits(),
                                bits, gl::state::DIRTY_BIT_BLEND_FUNCS);
    SetDirtyBitIfStateDifferent(a.blendState.getDstAlphaBits(), b.blendState.getDstAlphaBits(),
                                bits, gl::state::DIRTY_BIT_BLEND_FUNCS);
    SetDirtyBitIfStateDifferent(a.blendState.getEquationColorBits(),
                                b.blendState.getEquationColorBits(), bits,
                                gl::state::DIRTY_BIT_BLEND_EQUATIONS);
    SetDirtyBitIfStateDifferent(a.blendState.getEquationAlphaBits(),
                                b.blendState.getEquationAlphaBits(), bits,
                                gl::state::DIRTY_BIT_BLEND_EQUATIONS);
    SetDirtyBitExtIfStateDifferent(a.blendAdvancedCoherent, b.blendAdvancedCoherent, bits, exBits,
                                   gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT);
    SetDirtyBitIfStateDifferent(a.sampleAlphaToCoverageEnabled, b.sampleAlphaToCoverageEnabled,
                                bits, gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
    SetDirtyBitIfStateDifferent(a.sampleCoverageEnabled, b.sampleCoverageEnabled, bits,
                                gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
    SetDirtyBitIfStateDifferent(a.sampleCoverageValue, b.sampleCoverageValue, bits,
                                gl::state::DIRTY_BIT_SAMPLE_COVERAGE);
    SetDirtyBitIfStateDifferent(a.sampleCoverageInvert, b.sampleCoverageInvert, bits,
                                gl::state::DIRTY_BIT_SAMPLE_COVERAGE);
    SetDirtyBitIfStateDifferent(a.sampleMaskEnabled, b.sampleMaskEnabled, bits,
                                gl::state::DIRTY_BIT_SAMPLE_MASK_ENABLED);
    SetDirtyBitIfStateDifferent(a.sampleMaskValues, b.sampleMaskValues, bits,
                                gl::state::DIRTY_BIT_SAMPLE_MASK);
    SetDirtyBitIfStateDifferent(a.depthTestEnabled, b.depthTestEnabled, bits,
                                gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED);
    SetDirtyBitIfStateDifferent(a.depthFunc, b.depthFunc, bits, gl::state::DIRTY_BIT_DEPTH_FUNC);
    SetDirtyBitIfStateDifferent(a.depthMask, b.depthMask, bits, gl::state::DIRTY_BIT_DEPTH_MASK);
    SetDirtyBitIfStateDifferent(a.stencilTestEnabled, b.stencilTestEnabled, bits,
                                gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED);
    SetDirtyBitIfStateDifferent(a.stencilFrontFunc, b.stencilFrontFunc, bits,
                                gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
    SetDirtyBitIfStateDifferent(a.stencilFrontRef, b.stencilFrontRef, bits,
                                gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
    SetDirtyBitIfStateDifferent(a.stencilFrontValueMask, b.stencilFrontValueMask, bits,
                                gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
    SetDirtyBitIfStateDifferent(a.stencilFrontStencilFailOp, b.stencilFrontStencilFailOp, bits,
                                gl::state::DIRTY_BIT_STENCIL_OPS_FRONT);
    SetDirtyBitIfStateDifferent(a.stencilFrontStencilPassDepthFailOp,
                                b.stencilFrontStencilPassDepthFailOp, bits,
                                gl::state::DIRTY_BIT_STENCIL_OPS_FRONT);
    SetDirtyBitIfStateDifferent(a.stencilFrontStencilPassDepthPassOp,
                                b.stencilFrontStencilPassDepthPassOp, bits,
                                gl::state::DIRTY_BIT_STENCIL_OPS_FRONT);
    SetDirtyBitIfStateDifferent(a.stencilFrontWritemask, b.stencilFrontWritemask, bits,
                                gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
    SetDirtyBitIfStateDifferent(a.stencilBackFunc, b.stencilBackFunc, bits,
                                gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK);
    SetDirtyBitIfStateDifferent(a.stencilBackRef, b.stencilBackRef, bits,
                                gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK);
    SetDirtyBitIfStateDifferent(a.stencilBackValueMask, b.stencilBackValueMask, bits,
                                gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK);
    SetDirtyBitIfStateDifferent(a.stencilBackStencilFailOp, b.stencilBackStencilFailOp, bits,
                                gl::state::DIRTY_BIT_STENCIL_OPS_BACK);
    SetDirtyBitIfStateDifferent(a.stencilBackStencilPassDepthFailOp,
                                b.stencilBackStencilPassDepthFailOp, bits,
                                gl::state::DIRTY_BIT_STENCIL_OPS_BACK);
    SetDirtyBitIfStateDifferent(a.stencilBackStencilPassDepthPassOp,
                                b.stencilBackStencilPassDepthPassOp, bits,
                                gl::state::DIRTY_BIT_STENCIL_OPS_BACK);
    SetDirtyBitIfStateDifferent(a.stencilBackWritemask, b.stencilBackWritemask, bits,
                                gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
    SetDirtyBitIfStateDifferent(a.cullFaceEnabled, b.cullFaceEnabled, bits,
                                gl::state::DIRTY_BIT_CULL_FACE_ENABLED);
    SetDirtyBitIfStateDifferent(a.cullFace, b.cullFace, bits, gl::state::DIRTY_BIT_CULL_FACE);
    SetDirtyBitIfStateDifferent(a.frontFace, b.frontFace, bits, gl::state::DIRTY_BIT_FRONT_FACE);
    SetDirtyBitExtIfStateDifferent(a.polygonMode, b.polygonMode, bits, exBits,
                                   gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE);
    SetDirtyBitExtIfStateDifferent(a.polygonOffsetPointEnabled, b.polygonOffsetPointEnabled, bits,
                                   exBits,
                                   gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED);
    SetDirtyBitExtIfStateDifferent(a.polygonOffsetLineEnabled, b.polygonOffsetLineEnabled, bits,
                                   exBits,
                                   gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED);
    SetDirtyBitIfStateDifferent(a.polygonOffsetFillEnabled, b.polygonOffsetFillEnabled, bits,
                                gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
    SetDirtyBitIfStateDifferent(a.polygonOffsetFactor, b.polygonOffsetFactor, bits,
                                gl::state::DIRTY_BIT_POLYGON_OFFSET);
    SetDirtyBitIfStateDifferent(a.polygonOffsetUnits, b.polygonOffsetUnits, bits,
                                gl::state::DIRTY_BIT_POLYGON_OFFSET);
    SetDirtyBitIfStateDifferent(a.polygonOffsetClamp, b.polygonOffsetClamp, bits,
                                gl::state::DIRTY_BIT_POLYGON_OFFSET);
    SetDirtyBitExtIfStateDifferent(a.depthClampEnabled, b.depthClampEnabled, bits, exBits,
                                   gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED);
    SetDirtyBitIfStateDifferent(a.rasterizerDiscardEnabled, b.rasterizerDiscardEnabled, bits,
                                gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
    SetDirtyBitIfStateDifferent(a.lineWidth, b.lineWidth, bits, gl::state::DIRTY_BIT_LINE_WIDTH);
    SetDirtyBitIfStateDifferent(a.primitiveRestartFixedIndexEnabled,
                                b.primitiveRestartFixedIndexEnabled, bits,
                                gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
    SetDirtyBitIfStateDifferent(a.primitiveRestartEnabled, b.primitiveRestartEnabled, bits,
                                gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
    SetDirtyBitIfStateDifferent(a.primitiveRestartIndex, b.primitiveRestartIndex, bits,
                                gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
    SetDirtyBitIfStateDifferent(a.clearColor, b.clearColor, bits, gl::state::DIRTY_BIT_CLEAR_COLOR);
    SetDirtyBitIfStateDifferent(a.clearDepth, b.clearDepth, bits, gl::state::DIRTY_BIT_CLEAR_DEPTH);
    SetDirtyBitIfStateDifferent(a.clearStencil, b.clearStencil, bits,
                                gl::state::DIRTY_BIT_CLEAR_STENCIL);
    SetDirtyBitIfStateDifferent(a.framebufferSRGBEnabled, b.framebufferSRGBEnabled, bits,
                                gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
    SetDirtyBitIfStateDifferent(a.ditherEnabled, b.ditherEnabled, bits,
                                gl::state::DIRTY_BIT_DITHER_ENABLED);
    // No dirty bit for ContextStateGL::textureCubemapSeamlessEnabled
    SetDirtyBitIfStateDifferent(a.multisamplingEnabled, b.multisamplingEnabled, bits,
                                gl::state::DIRTY_BIT_MULTISAMPLING);
    SetDirtyBitIfStateDifferent(a.sampleAlphaToOneEnabled, b.sampleAlphaToOneEnabled, bits,
                                gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
    SetDirtyBitIfStateDifferent(a.provokingVertex, b.provokingVertex, bits,
                                gl::state::DIRTY_BIT_PROVOKING_VERTEX);
    SetDirtyBitExtIfStateDifferent(a.enabledClipDistances, b.enabledClipDistances, bits, exBits,
                                   gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES);
    SetDirtyBitExtIfStateDifferent(a.logicOpEnabled, b.logicOpEnabled, bits, exBits,
                                   gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED);
    SetDirtyBitExtIfStateDifferent(a.logicOp, b.logicOp, bits, exBits,
                                   gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP);
}

auto TieIndexedBufferBindingGL(const IndexedBufferBindingGL &binding)
{
    return std::tie(binding.offset, binding.size, binding.buffer);
}

auto TieImageUnitBindingGL(const ImageUnitBindingGL &binding)
{
    return std::tie(binding.texture, binding.level, binding.layered, binding.layer, binding.access,
                    binding.format);
}

auto TieContextStateGL(const ContextStateGL &state)
{
    // state.vertexAttribCurrentValues is omitted and handled specially in the comparison operator
    // state.Stencil(Front|Back)(WriteMask|ValueMask) is omitted and handled specifically in the
    // comparison operator because it must be masked
    return std::tie(
        state.program, state.vao, state.defaultVAOState,
        /*state.vertexAttribCurrentValues,*/ state.buffers, state.indexedBuffers,
        state.textureUnitIndex, state.textures, state.samplers, state.images,
        state.transformFeedback, state.unpackState, state.packState, state.framebuffers,
        state.renderbuffer, state.scissorTestEnabled, state.scissor, state.viewport, state.near,
        state.far, state.clipOrigin, state.clipDepthMode, state.blendColor, state.blendState,
        state.blendAdvancedCoherent, state.sampleAlphaToCoverageEnabled,
        state.sampleCoverageEnabled, state.sampleCoverageValue, state.sampleCoverageInvert,
        state.sampleMaskEnabled, state.sampleMaskValues, state.depthTestEnabled, state.depthFunc,
        state.depthMask, state.stencilTestEnabled, state.stencilFrontFunc, state.stencilFrontRef,
        /*state.stencilFrontValueMask,*/ state.stencilFrontStencilFailOp,
        state.stencilFrontStencilPassDepthFailOp, state.stencilFrontStencilPassDepthPassOp,
        /*state.stencilFrontWritemask,*/ state.stencilBackFunc, state.stencilBackRef,
        /*state.stencilBackValueMask,*/ state.stencilBackStencilFailOp,
        state.stencilBackStencilPassDepthFailOp, state.stencilBackStencilPassDepthPassOp,
        /*state.stencilBackWritemask,*/ state.cullFaceEnabled, state.cullFace, state.frontFace,
        state.polygonMode, state.polygonOffsetPointEnabled, state.polygonOffsetLineEnabled,
        state.polygonOffsetFillEnabled, state.polygonOffsetFactor, state.polygonOffsetUnits,
        state.polygonOffsetClamp, state.depthClampEnabled, state.rasterizerDiscardEnabled,
        state.lineWidth, state.primitiveRestartFixedIndexEnabled, state.primitiveRestartEnabled,
        state.primitiveRestartIndex, state.clearColor, state.clearDepth, state.clearStencil,
        state.framebufferSRGBEnabled, state.ditherEnabled, state.textureCubemapSeamlessEnabled,
        state.multisamplingEnabled, state.sampleAlphaToOneEnabled, state.provokingVertex,
        state.enabledClipDistances, state.logicOpEnabled, state.logicOp);
}

void Indent(std::ostream &os, size_t count)
{
    for (size_t indent = 0; indent < count; indent++)
    {
        os << " ";
    }
}

template <typename T>
void PrintCompressedArray(std::ostream &os,
                          const T &values,
                          size_t indentation,
                          bool wrapValueInParens)
{
    for (size_t i = 0; i < values.size(); i++)
    {
        size_t start = i;
        while (i + 1 < values.size() && values[i + 1] == values[i])
        {
            i++;
        }

        Indent(os, indentation);
        os << "[" << start;
        if (i > start)
        {
            os << ".." << i;
        }
        os << "] = ";
        if (wrapValueInParens)
        {
            os << "(";
        }
        os << values[i];
        if (wrapValueInParens)
        {
            os << ")";
        }
        os << std::endl;
    }
}

std::string PrintIndexedBlendState(const gl::BlendStateExt &blendState, size_t index)
{
    std::ostringstream os;
    os << "enabled = " << blendState.getEnabledMask().test(index) << ", ";
    bool r, g, b, a;
    blendState.getColorMaskIndexed(index, &r, &g, &b, &a);
    os << "mask = " << (r ? "R" : "_") << (g ? "G" : "_") << (b ? "B" : "_") << (a ? "A" : "_")
       << ",";
    os << "colorMode = " << blendState.getEquationColorIndexed(index) << ", ";
    os << "alphaMode = " << blendState.getEquationAlphaIndexed(index) << ", ";
    os << "srcColor = " << blendState.getSrcColorIndexed(index) << ", ";
    os << "dstColor = " << blendState.getDstColorIndexed(index) << ", ";
    os << "srcAlpha = " << blendState.getSrcAlphaIndexed(index) << ", ";
    os << "dstAlpha = " << blendState.getDstAlphaIndexed(index);
    return os.str();
}

void PrintCompressedBlendState(std::ostream &os,
                               const gl::BlendStateExt &blendState,
                               size_t indentation)
{
    for (size_t i = 0; i < blendState.getDrawBufferCount(); i++)
    {
        std::string printed = PrintIndexedBlendState(blendState, i);

        size_t start = i;
        while (i + 1 < blendState.getDrawBufferCount() &&
               PrintIndexedBlendState(blendState, i + 1) == printed)
        {
            i++;
        }

        Indent(os, indentation);
        os << "[" << start;
        if (i > start)
        {
            os << ".." << i;
        }
        os << "] = (" << printed << ")" << std::endl;
    }
}

void PrintCompressedVertexArrayState(std::ostream &os,
                                     const VertexArrayStateGL &state,
                                     size_t indentation)
{
    Indent(os, indentation);
    os << "elementArrayBuffer = " << state.elementArrayBuffer << std::endl;
    Indent(os, indentation);
    os << "attributes =" << std::endl;
    PrintCompressedArray(os, state.attributes, indentation + 4, true);
    Indent(os, indentation);
    os << "bindings =" << std::endl;
    PrintCompressedArray(os, state.bindings, indentation + 4, true);
}
}  // anonymous namespace

std::ostream &operator<<(std::ostream &os, const VertexAttributeGL &attribute)
{
    os << "enabled = " << attribute.enabled << ", size = " << attribute.format->channelCount
       << ", type = " << attribute.format->vertexAttribType
       << ", normalized = " << attribute.format->isNorm() << ", pointer = " << attribute.pointer
       << ", relativeOffset = " << attribute.relativeOffset
       << ", bindingIndex = " << attribute.bindingIndex;
    return os;
}

std::ostream &operator<<(std::ostream &os, const VertexBindingGL &binding)
{
    os << "stride = " << binding.stride << ", divisor = " << binding.divisor
       << ", offset = " << binding.offset << ", buffer = " << binding.buffer;
    return os;
}

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;
    }
}

std::ostream &operator<<(std::ostream &os, const VertexArrayStateGL &state)
{
    PrintCompressedVertexArrayState(os, state, 0);
    return os;
}

void QueryVertexArrayStateGL(const FunctionsGL *functions, VertexArrayStateGL *state)
{
    GetHelper(functions, GL_ELEMENT_ARRAY_BUFFER_BINDING, &state->elementArrayBuffer);
    GLint maxVertexAttribs = 0;
    GetHelper(functions, GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
    maxVertexAttribs = std::min(maxVertexAttribs, static_cast<GLint>(gl::MAX_VERTEX_ATTRIBS));

    for (GLint i = 0; i < maxVertexAttribs; i++)
    {
        VertexAttributeGL &attrib = state->attributes[i];

        GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &attrib.enabled);

        GLuint size = attrib.format->channelCount;
        GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size);

        gl::VertexAttribType type = attrib.format->vertexAttribType;
        GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type);

        bool normalized = attrib.format->isNorm();
        GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized);

        bool integer = attrib.format->isPureInt();
        GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_INTEGER, &integer);

        attrib.format = &angle::Format::Get(gl::GetVertexFormatID(type, normalized, size, integer));

        GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_POINTER,
                        const_cast<void **>(&attrib.pointer));

        if (nativegl::SupportsVertexAttributeBindings(functions))
        {
            GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &attrib.relativeOffset);
            GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_BINDING, &attrib.bindingIndex);
        }
        else
        {
            ASSERT(attrib.bindingIndex == static_cast<GLuint>(i));
        }
    }

    GLint maxVertexAttribBindings = maxVertexAttribs;
    if (nativegl::SupportsVertexAttributeBindings(functions))
    {
        GetHelper(functions, GL_MAX_VERTEX_ATTRIB_BINDINGS, &maxVertexAttribBindings);
        maxVertexAttribBindings =
            std::min(maxVertexAttribBindings, static_cast<GLint>(gl::MAX_VERTEX_ATTRIB_BINDINGS));
    }

    const bool supportsInstancing = nativegl::SupportsInstancing(functions);

    for (GLint i = 0; i < maxVertexAttribBindings; i++)
    {
        VertexBindingGL &binding = state->bindings[i];

        if (nativegl::SupportsVertexAttributeBindings(functions))
        {
            GetHelper(functions, GL_VERTEX_BINDING_STRIDE, i, &binding.stride);
            ASSERT(supportsInstancing);
            GetHelper(functions, GL_VERTEX_BINDING_DIVISOR, i, &binding.divisor);
            GetHelper(functions, GL_VERTEX_BINDING_OFFSET, i, &binding.offset);
            GetHelper(functions, GL_VERTEX_BINDING_BUFFER, i, &binding.buffer);
        }
        else
        {
            const VertexAttributeGL &attrib = state->attributes[i];

            GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &binding.stride);
            if (supportsInstancing)
            {
                GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &binding.divisor);
            }
            binding.offset = reinterpret_cast<GLintptr>(attrib.pointer);
            GetVertexHelper(functions, i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &binding.buffer);
        }

        // Driver return inconsistent results when querying the binding offset when client data
        // is used. The spec says glVertexAttribPointer on the default VAO with no buffer bound
        // should set an offset of 0.
        if (binding.buffer == 0)
        {
            binding.offset = 0;
        }
    }
}

bool operator==(const IndexedBufferBindingGL &a, const IndexedBufferBindingGL &b)
{
    return TieIndexedBufferBindingGL(a) == TieIndexedBufferBindingGL(b);
}

std::ostream &operator<<(std::ostream &os, const IndexedBufferBindingGL &binding)
{
    os << "offset = " << binding.offset << ", size = " << binding.size
       << ", buffer = " << binding.buffer;
    return os;
}

ImageUnitBindingGL::ImageUnitBindingGL(GLenum defaultFormat) : format(defaultFormat) {}

bool operator==(const ImageUnitBindingGL &a, const ImageUnitBindingGL &b)
{
    return TieImageUnitBindingGL(a) == TieImageUnitBindingGL(b);
}

std::ostream &operator<<(std::ostream &os, const ImageUnitBindingGL &binding)
{
    os << "texture = " << binding.texture << ", level = " << binding.level
       << ", layered = " << gl::ConvertToBool(binding.layered) << ", layer = " << binding.layer
       << ", access = " << gl::FmtHex(binding.access)
       << ", format = " << gl::FmtHex(binding.format);
    return os;
}

ContextStateGLCaps::ContextStateGLCaps(const FunctionsGL *functions, const gl::Caps &caps)
    : defaultFramebufferSrgbState(functions->standard == STANDARD_GL_ES),
      defaultImageBindingFormat(functions->standard == STANDARD_GL_ES ? GL_R32UI : GL_R8),
      maxVertexAttributes(
          std::min(caps.maxVertexAttributes, static_cast<GLint>(gl::MAX_VERTEX_ATTRIBS))),
      maxVertexAttribBindings(std::min(caps.maxVertexAttribBindings,
                                       static_cast<GLint>(gl::MAX_VERTEX_ATTRIB_BINDINGS))),
      maxImageUnits(
          std::min(caps.maxImageUnits, static_cast<GLint>(gl::IMPLEMENTATION_MAX_IMAGE_UNITS))),
      maxDrawBuffers(
          std::min(caps.maxDrawBuffers, static_cast<GLint>(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS))),
      maxUniformBufferBindings(caps.maxUniformBufferBindings),
      maxAtomicCounterBufferBindings(caps.maxAtomicCounterBufferBindings),
      maxShaderStorageBufferBindings(caps.maxShaderStorageBufferBindings)
{}

ContextStateGL::ContextStateGL(const ContextStateGLCaps &caps)
    : defaultVAOState(caps.maxVertexAttributes, caps.maxVertexAttribBindings),
      images(caps.maxImageUnits, ImageUnitBindingGL(caps.defaultImageBindingFormat)),
      blendState(caps.maxDrawBuffers),
      framebufferSRGBEnabled(caps.defaultFramebufferSrgbState)
{
    indexedBuffers[gl::BufferBinding::Uniform].resize(caps.maxUniformBufferBindings);
    indexedBuffers[gl::BufferBinding::AtomicCounter].resize(caps.maxAtomicCounterBufferBindings);
    indexedBuffers[gl::BufferBinding::ShaderStorage].resize(caps.maxShaderStorageBufferBindings);

    sampleMaskValues.fill(~GLbitfield(0));
}

bool operator==(const ContextStateGL &a, const ContextStateGL &b)
{
    if (TieContextStateGL(a) != TieContextStateGL(b))
    {
        return false;
    }

    if (ComputeVertexAttribCurrentValueDiffMask(a.vertexAttribCurrentValues,
                                                b.vertexAttribCurrentValues)
            .any())
    {
        return false;
    }

    auto makeStencilMaskTuple = [](const ContextStateGL &state) {
        return std::make_tuple(
            state.stencilFrontValueMask & 0xFF, state.stencilFrontWritemask & 0xFF,
            state.stencilBackValueMask & 0xFF, state.stencilBackWritemask & 0xFF);
    };
    if (makeStencilMaskTuple(a) != makeStencilMaskTuple(b))
    {
        return false;
    }

    return true;
}

bool operator!=(const ContextStateGL &a, const ContextStateGL &b)
{
    return !(a == b);
}

std::ostream &operator<<(std::ostream &os, const ContextStateGL &state)
{
    os << "program = " << state.program << std::endl;
    os << "vao = " << state.vao << std::endl;
    os << "defaultVAOState =" << std::endl;
    PrintCompressedVertexArrayState(os, state.defaultVAOState, 4);
    os << "vertexAttribCurrentValues =" << std::endl;
    PrintCompressedArray(os, state.vertexAttribCurrentValues, 4, true);
    os << "buffers =" << std::endl;
    for (gl::BufferBinding bufferBinding : angle::AllEnums<gl::BufferBinding>())
    {
        os << "    [" << bufferBinding << "] = " << state.buffers[bufferBinding] << std::endl;
    }
    os << "indexedBuffers =" << std::endl;
    for (gl::BufferBinding bufferBinding : angle::AllEnums<gl::BufferBinding>())
    {
        const std::vector<IndexedBufferBindingGL> &buffers = state.indexedBuffers[bufferBinding];
        if (buffers.empty())
        {
            continue;
        }
        os << "    [" << bufferBinding << "] =" << std::endl;
        PrintCompressedArray(os, buffers, 8, true);
    }
    os << "textureUnitIndex = " << state.textureUnitIndex << std::endl;
    os << "textures =" << std::endl;
    for (gl::TextureType textureType : angle::AllEnums<gl::TextureType>())
    {
        os << "    [" << textureType << "] =" << std::endl;
        PrintCompressedArray(os, state.textures[textureType], 8, false);
    }
    os << "samplers =" << std::endl;
    PrintCompressedArray(os, state.samplers, 4, false);
    os << "images =" << std::endl;
    PrintCompressedArray(os, state.images, 4, true);
    os << "transformFeedback = " << state.transformFeedback << std::endl;
    os << "unpackState = (" << state.unpackState << ")" << std::endl;
    os << "packState = (" << state.packState << ")" << std::endl;
    os << "framebuffers =" << std::endl;
    os << "    [GL_READ_FRAMEBUFFER] = " << state.framebuffers[angle::FramebufferBindingRead]
       << std::endl;
    os << "    [GL_DRAW_FRAMEBUFFER] = " << state.framebuffers[angle::FramebufferBindingDraw]
       << std::endl;
    os << "renderbuffer = " << state.renderbuffer << std::endl;
    os << "scissorTestEnabled = " << state.scissorTestEnabled << std::endl;
    os << "scissor = (" << state.scissor << ")" << std::endl;
    os << "viewport = (" << state.viewport << ")" << std::endl;
    os << "near = " << state.near << std::endl;
    os << "far = " << state.far << std::endl;
    os << "clipOrigin = " << state.clipOrigin << std::endl;
    os << "clipDepthMode = " << state.clipDepthMode << std::endl;
    os << "blendColor = (" << state.blendColor << ")" << std::endl;
    os << "blendState =" << std::endl;
    PrintCompressedBlendState(os, state.blendState, 4);
    os << "blendAdvancedCoherent = " << state.blendAdvancedCoherent << std::endl;
    os << "sampleAlphaToCoverageEnabled = " << state.sampleAlphaToCoverageEnabled << std::endl;
    os << "sampleCoverageEnabled = " << state.sampleCoverageEnabled << std::endl;
    os << "sampleCoverageValue = " << state.sampleCoverageValue << std::endl;
    os << "sampleCoverageInvert = " << state.sampleCoverageInvert << std::endl;
    os << "sampleMaskEnabled = " << state.sampleMaskEnabled << std::endl;
    os << "sampleMaskValues =" << std::endl;
    PrintCompressedArray(os, state.sampleMaskValues, 4, false);
    os << "depthTestEnabled = " << state.depthTestEnabled << std::endl;
    os << "depthFunc = " << gl::FmtHex(state.depthFunc) << std::endl;
    os << "depthMask = " << state.depthMask << std::endl;
    os << "stencilTestEnabled = " << state.stencilTestEnabled << std::endl;
    os << "stencilFrontFunc = " << gl::FmtHex(state.stencilFrontFunc) << std::endl;
    os << "stencilFrontRef = " << state.stencilFrontRef << std::endl;
    os << "stencilFrontValueMask = " << gl::FmtHex(state.stencilFrontValueMask) << std::endl;
    os << "stencilFrontStencilFailOp = " << gl::FmtHex(state.stencilFrontStencilFailOp)
       << std::endl;
    os << "stencilFrontStencilPassDepthFailOp = "
       << gl::FmtHex(state.stencilFrontStencilPassDepthFailOp) << std::endl;
    os << "stencilFrontStencilPassDepthPassOp = "
       << gl::FmtHex(state.stencilFrontStencilPassDepthPassOp) << std::endl;
    os << "stencilFrontWritemask = " << gl::FmtHex(state.stencilFrontWritemask) << std::endl;
    os << "stencilBackFunc = " << gl::FmtHex(state.stencilBackFunc) << std::endl;
    os << "stencilBackRef = " << state.stencilBackRef << std::endl;
    os << "stencilBackValueMask = " << gl::FmtHex(state.stencilBackValueMask) << std::endl;
    os << "stencilBackStencilFailOp = " << gl::FmtHex(state.stencilBackStencilFailOp) << std::endl;
    os << "stencilBackStencilPassDepthFailOp = "
       << gl::FmtHex(state.stencilBackStencilPassDepthFailOp) << std::endl;
    os << "stencilBackStencilPassDepthPassOp = "
       << gl::FmtHex(state.stencilBackStencilPassDepthPassOp) << std::endl;
    os << "stencilBackWritemask = " << gl::FmtHex(state.stencilBackWritemask) << std::endl;
    os << "cullFaceEnabled = " << state.cullFaceEnabled << std::endl;
    os << "cullFace = " << state.cullFace << std::endl;
    os << "frontFace = " << gl::FmtHex(state.frontFace) << std::endl;
    os << "polygonMode = " << state.polygonMode << std::endl;
    os << "polygonOffsetPointEnabled = " << state.polygonOffsetPointEnabled << std::endl;
    os << "polygonOffsetLineEnabled = " << state.polygonOffsetLineEnabled << std::endl;
    os << "polygonOffsetFillEnabled = " << state.polygonOffsetFillEnabled << std::endl;
    os << "polygonOffsetFactor = " << state.polygonOffsetFactor << std::endl;
    os << "polygonOffsetUnits = " << state.polygonOffsetUnits << std::endl;
    os << "polygonOffsetClamp = " << state.polygonOffsetClamp << std::endl;
    os << "depthClampEnabled = " << state.depthClampEnabled << std::endl;
    os << "rasterizerDiscardEnabled = " << state.rasterizerDiscardEnabled << std::endl;
    os << "lineWidth = " << state.lineWidth << std::endl;
    os << "primitiveRestartFixedIndexEnabled = " << state.primitiveRestartFixedIndexEnabled
       << std::endl;
    os << "primitiveRestartEnabled = " << state.primitiveRestartEnabled << std::endl;
    os << "primitiveRestartIndex = " << state.primitiveRestartIndex << std::endl;
    os << "clearColor = " << state.clearColor << std::endl;
    os << "clearDepth = " << state.clearDepth << std::endl;
    os << "clearStencil = " << state.clearStencil << std::endl;
    os << "framebufferSRGBEnabled = " << state.framebufferSRGBEnabled << std::endl;
    os << "ditherEnabled = " << state.ditherEnabled << std::endl;
    os << "textureCubemapSeamlessEnabled = " << state.textureCubemapSeamlessEnabled << std::endl;
    os << "multisamplingEnabled = " << state.multisamplingEnabled << std::endl;
    os << "sampleAlphaToOneEnabled = " << state.sampleAlphaToOneEnabled << std::endl;
    os << "provokingVertex = " << gl::FmtHex(state.provokingVertex) << std::endl;
    os << "enabledClipDistances =" << std::endl;
    PrintCompressedArray(os, state.enabledClipDistances, 4, false);
    os << "logicOpEnabled = " << state.logicOpEnabled << std::endl;
    os << "logicOp = " << state.logicOp << std::endl;
    return os;
}

StateManagerGL::StateManagerGL(const FunctionsGL *functions,
                               const gl::Caps &rendererCaps,
                               const gl::Extensions &extensions,
                               const angle::FeaturesGL &features)
    : mFunctions(functions),
      mFeatures(features),
      mCaps(functions, rendererCaps),
      mState(mCaps),
      mSupportsVertexArrayObjects(nativegl::SupportsVertexArrayObjects(functions)),
      mCurrentTransformFeedback(nullptr),
      mQueries(),
      mPrevDrawContext({0}),
      mIndependentBlendStates(extensions.drawBuffersIndexedAny()),
      mSampleCoverageEverChanged(false),
      mHasUnflushedQueries(false),
      mFramebufferSRGBAvailable(extensions.sRGBWriteControlEXT),
      mHasSeparateFramebufferBindings(nativegl::SupportsSeparateFramebufferBindings(functions)),
      mIsMultiviewEnabled(extensions.multiviewOVR),
      mMaxClipDistances(rendererCaps.maxClipDistances)
{
    ASSERT(mFunctions);
    ASSERT(rendererCaps.maxViews >= 1u);

    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);
        mState.primitiveRestartIndex = 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.syncAllVertexArraysToDefault.enabled ||
         features.syncDefaultVertexArraysToDefault.enabled) &&
        !nativegl::CanUseDefaultVertexArrayObject(mFunctions))
    {
        ASSERT(nativegl::SupportsVertexArrayObjects(mFunctions));
        mFunctions->genVertexArrays(1, &mDefaultVAO);
        mFunctions->bindVertexArray(mDefaultVAO);
        mState.vao = mDefaultVAO;
    }

    // By default, desktop GL clamps values read from normalized
    // color buffers to [0, 1], which does not match expected ES
    // behavior for signed normalized color buffers.
    if (mFunctions->clampColor)
    {
        mFunctions->clampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
    }

    // The initial viewport and scissor state is based on the surface that this context was first
    // made current with. Query it back.
    GetHelper(mFunctions, GL_SCISSOR_BOX, &mState.scissor);
    GetHelper(mFunctions, GL_VIEWPORT, &mState.viewport);
}

StateManagerGL::~StateManagerGL()
{
    if (mPlaceholderFbo != 0)
    {
        deleteFramebuffer(mPlaceholderFbo);
    }
    if (mPlaceholderFboColorRenderbuffer != 0)
    {
        deleteRenderbuffer(mPlaceholderFboColorRenderbuffer);
    }
    if (mPlaceholderFboDepthStencilRenderbuffer != 0)
    {
        deleteRenderbuffer(mPlaceholderFboDepthStencilRenderbuffer);
    }

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

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

        mFunctions->deleteProgram(program);
    }
}

void StateManagerGL::deleteVertexArray(GLuint vao)
{
    if (vao != 0)
    {
        if (mState.vao == vao)
        {
            bindVertexArray(0);
        }
        mFunctions->deleteVertexArrays(1, &vao);
        mVAOStates.erase(vao);
    }
}

void StateManagerGL::deleteTexture(GLuint texture)
{
    if (texture != 0)
    {
        for (gl::TextureType type : angle::AllEnums<gl::TextureType>())
        {
            const auto &textureVector = mState.textures[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 < mState.images.size(); imageUnitIndex++)
        {
            if (mState.images[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 < mState.samplers.size(); unit++)
        {
            if (mState.samplers[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 (mState.buffers[target] == buffer)
        {
            bindBuffer(target, 0);
        }

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

    VertexArrayStateGL *vaoState = getCurrentVAOState();
    if (vaoState)
    {
        if (vaoState->elementArrayBuffer == buffer)
        {
            vaoState->elementArrayBuffer = 0;
        }

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

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

void StateManagerGL::deleteFramebuffer(GLuint fbo)
{
    if (fbo != 0)
    {
        bool wasBound = false;
        if (mHasSeparateFramebufferBindings)
        {
            for (size_t binding = 0; binding < mState.framebuffers.size(); ++binding)
            {
                if (mState.framebuffers[binding] == fbo)
                {
                    GLenum enumValue = angle::FramebufferBindingToEnum(
                        static_cast<angle::FramebufferBinding>(binding));
                    bindFramebuffer(enumValue, 0);
                    wasBound = true;
                }
            }
        }
        else
        {
            ASSERT(mState.framebuffers[angle::FramebufferBindingRead] ==
                   mState.framebuffers[angle::FramebufferBindingDraw]);
            if (mState.framebuffers[angle::FramebufferBindingRead] == fbo)
            {
                bindFramebuffer(GL_FRAMEBUFFER, 0);
                wasBound = true;
            }
        }
        if (!wasBound && mHasUnflushedQueries &&
            mFeatures.flushQueriesBeforeDeletingOrUnbindingFbo.enabled)
        {
            forcefullyFlush();
        }
        mFunctions->deleteFramebuffers(1, &fbo);
    }
}

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

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

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

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

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

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

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

void StateManagerGL::bindVertexArray(GLuint vao)
{
    if (mState.vao != vao)
    {
        ASSERT(!mFeatures.syncAllVertexArraysToDefault.enabled);
        forceBindVertexArray(vao);
    }
}

void StateManagerGL::forceBindVertexArray(GLuint vao)
{
    VertexArrayStateGL *vaoState = getVAOState(vao);

    mState.vao                                      = vao;
    mState.buffers[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 (mState.buffers[target] != buffer)
    {
        mState.buffers[target] = buffer;
        mFunctions->bindBuffer(gl::ToGLenum(target), buffer);
        setBufferBindingDirty(target);

        if (target == gl::BufferBinding::ElementArray)
        {
            VertexArrayStateGL *vaoState = getCurrentVAOState();
            if (vaoState)
            {
                vaoState->elementArrayBuffer = 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 < mState.indexedBuffers[target].size());
    auto &binding = mState.indexedBuffers[target][index];
    if (binding.buffer != buffer || binding.offset != 0 || binding.size != 0)
    {
        binding.buffer         = buffer;
        binding.offset         = 0;
        binding.size           = 0;
        mState.buffers[target] = buffer;
        mFunctions->bindBufferBase(gl::ToGLenum(target), static_cast<GLuint>(index), buffer);
        setBufferBindingDirty(target);
    }
}

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

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

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

void StateManagerGL::bindTexture(gl::TextureType type, GLuint texture)
{
    if (mState.textures[type][mState.textureUnitIndex] != texture)
    {
        mState.textures[type][mState.textureUnitIndex] = texture;
        mFunctions->bindTexture(nativegl::GetTextureBindingTarget(type), texture);
        mLocalDirtyBits.set(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
    }
}

void StateManagerGL::bindTexture(gl::TextureType type, size_t unit, GLuint texture)
{
    if (mState.textures[type][unit] != texture)
    {
        activeTexture(unit);
        bindTexture(type, texture);
    }
}

void StateManagerGL::bindSampler(size_t unit, GLuint sampler)
{
    if (mState.samplers[unit] != sampler)
    {
        mState.samplers[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 = mState.images[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);
        mLocalDirtyBits.set(gl::state::DIRTY_BIT_IMAGE_BINDINGS);
    }
}

angle::Result StateManagerGL::setPixelUnpackState(const gl::Context *context,
                                                  const gl::PixelUnpackState &unpack)
{
    if (mState.unpackState == unpack)
    {
        return angle::Result::Continue;
    }

    if (mState.unpackState.alignment != unpack.alignment)
    {
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, unpack.alignment));
    }

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

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

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

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

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

    mState.unpackState = unpack;
    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 (mState.packState == pack)
    {
        return angle::Result::Continue;
    }

    if (mState.packState.alignment != pack.alignment)
    {
        ANGLE_GL_TRY(context, mFunctions->pixelStorei(GL_PACK_ALIGNMENT, pack.alignment));
    }

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

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

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

    mState.packState = pack;
    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 (mState.framebuffers[angle::FramebufferBindingRead] != framebuffer ||
                mState.framebuffers[angle::FramebufferBindingDraw] != framebuffer)
            {
                mState.framebuffers[angle::FramebufferBindingRead] = framebuffer;
                mState.framebuffers[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 (mState.framebuffers[angle::FramebufferBindingRead] != framebuffer)
            {
                mState.framebuffers[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 (mState.framebuffers[angle::FramebufferBindingDraw] != framebuffer)
            {
                mState.framebuffers[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)
    {
        if (mFeatures.flushOnFramebufferChange.enabled)
        {
            mFunctions->flush();
        }
        if (mHasUnflushedQueries && mFeatures.flushQueriesBeforeDeletingOrUnbindingFbo.enabled)
        {
            forcefullyFlush();
        }
    }
}

void StateManagerGL::onSyncedFlushOrFinish()
{
    mHasUnflushedQueries = false;
}

void StateManagerGL::forcefullyFlush()
{
    if (mFunctions->fenceSync != nullptr && mFunctions->clientWaitSync != nullptr &&
        mFunctions->deleteSync != nullptr)
    {
        GLsync sync = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
        if (sync != nullptr)
        {
            mFunctions->clientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
            mFunctions->deleteSync(sync);
            onSyncedFlushOrFinish();
            return;
        }
    }

    // Sync creation not supported or failed; fall back to finish()
    mFunctions->finish();
    onSyncedFlushOrFinish();
}

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

void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
{
    ASSERT(type == GL_TRANSFORM_FEEDBACK);
    if (mState.transformFeedback != 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;
        }

        mState.transformFeedback = transformFeedback;
        mFunctions->bindTransformFeedback(type, transformFeedback);
        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);

    GLuint oldFramebufferBindingDraw = mState.framebuffers[angle::FramebufferBindingDraw];
    if (mFeatures.bindCompleteFramebufferForTimerQueries.enabled &&
        (mState.framebuffers[angle::FramebufferBindingDraw] == 0 ||
         mFunctions->checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) &&
        (type == gl::QueryType::TimeElapsed || type == gl::QueryType::Timestamp))
    {
        ensurePlaceholderFramebuffer();
        bindFramebuffer(GL_DRAW_FRAMEBUFFER, mPlaceholderFbo);
    }

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

    if (oldFramebufferBindingDraw != mPlaceholderFbo)
    {
        bindFramebuffer(GL_DRAW_FRAMEBUFFER, oldFramebufferBindingDraw);
    }
}

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

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)
{
    angle::ResultAccumulator result;

    for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
    {
        QueryGL *pausedQuery          = mTemporaryPausedQueries[type];
        mTemporaryPausedQueries[type] = nullptr;

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

    return result;
}

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

    if (pausedQuery != nullptr)
    {
        ANGLE_TRY(pausedQuery->resume(context));
    }

    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->getClientVersion() >= gl::ES_3_0);

    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::ProgramExecutable *executable = glState.getProgramExecutable();

    for (size_t blockIndex = 0; blockIndex < executable->getShaderStorageBlocks().size();
         blockIndex++)
    {
        GLuint binding = executable->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 executable state
    const gl::State &glState                = context->getState();
    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
    ProgramExecutableGL *executableGL       = GetImplAs<ProgramExecutableGL>(executable);

    // If any calls to glUniformBlockBinding have been made, make them effective.  Note that if PPOs
    // are ever supported in this backend, this needs to look at the Program's attached to PPOs
    // instead of the PPOs own executable.  This is because glUniformBlockBinding operates on
    // programs directly.
    executableGL->syncUniformBlockBindings();

    for (size_t uniformBlockIndex = 0; uniformBlockIndex < executable->getUniformBlocks().size();
         uniformBlockIndex++)
    {
        GLuint binding = executable->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::ProgramExecutable *executable = glState.getProgramExecutable();

    const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
        executable->getAtomicCounterBuffers();
    for (size_t index = 0; index < atomicCounterBuffers.size(); ++index)
    {
        const GLuint binding = executable->getAtomicCounterBufferBinding(index);
        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();

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

    ASSERT(context->getClientVersion() >= gl::ES_3_1 ||
           context->getExtensions().shaderPixelLocalStorageANGLE ||
           executable->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)
        {
            // Do not set layer parameters for non-layered texture types to avoid driver bugs.
            const bool layered = IsLayeredTextureType(textureGL->getType());
            bindImageTexture(imageUnitIndex, textureGL->getTextureID(), imageUnit.level,
                             layered && imageUnit.layered, layered ? imageUnit.layer : 0,
                             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 (mState.vertexAttribCurrentValues[index] != data)
    {
        mState.vertexAttribCurrentValues[index] = data;
        switch (data.Type)
        {
            case gl::VertexAttribType::Float:
                mFunctions->vertexAttrib4fv(static_cast<GLuint>(index), data.Values.FloatValues);
                break;
            case gl::VertexAttribType::Int:
                mFunctions->vertexAttribI4iv(static_cast<GLuint>(index), data.Values.IntValues);
                break;
            case gl::VertexAttribType::UnsignedInt:
                mFunctions->vertexAttribI4uiv(static_cast<GLuint>(index),
                                              data.Values.UnsignedIntValues);
                break;
            default:
                UNREACHABLE();
        }

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

void StateManagerGL::setScissorTestEnabled(bool enabled)
{
    if (mState.scissorTestEnabled != enabled)
    {
        mState.scissorTestEnabled = enabled;
        SetGLBoolState(mFunctions, GL_SCISSOR_TEST, enabled);

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

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

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

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

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

void StateManagerGL::setDepthRange(float near, float far)
{
    mState.near = near;
    mState.far  = 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(near, far);
    }
    else
    {
        ASSERT(mFunctions->depthRange);
        mFunctions->depthRange(near, far);
    }

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

void StateManagerGL::setClipControl(gl::ClipOrigin origin, gl::ClipDepthMode depth)
{
    if (mState.clipOrigin == origin && mState.clipDepthMode == depth)
    {
        return;
    }

    mState.clipOrigin    = origin;
    mState.clipDepthMode = depth;

    ASSERT(mFunctions->clipControl);
    mFunctions->clipControl(ToGLenum(origin), ToGLenum(depth));

    if (mFeatures.resyncDepthRangeOnClipControl.enabled)
    {
        // Change and restore depth range to trigger internal transformation
        // state resync. This is needed to apply clip control on some drivers.
        const float near = mState.near;
        setDepthRange(near == 0.0f ? 1.0f : 0.0f, mState.far);
        setDepthRange(near, mState.far);
    }

    mLocalDirtyBits.set(gl::state::DIRTY_BIT_CLIP_CONTROL);
}

void StateManagerGL::setClipControlWithEmulatedClipOrigin(const gl::ProgramExecutable *executable,
                                                          GLenum frontFace,
                                                          gl::ClipOrigin origin,
                                                          gl::ClipDepthMode depth)
{
    ASSERT(mFeatures.emulateClipOrigin.enabled);
    if (executable)
    {
        updateEmulatedClipOriginUniform(executable, origin);
    }
    static_assert((GL_CW ^ GL_CCW) == static_cast<GLenum>(gl::ClipOrigin::UpperLeft));
    setFrontFace(frontFace ^ static_cast<GLenum>(origin));
    setClipControl(gl::ClipOrigin::LowerLeft, depth);
}

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

    SetGLBoolState(mFunctions, GL_BLEND, enabled);

    mState.blendState.setEnabled(enabled);
    mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_ENABLED);
}

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

    // Get DrawBufferMask of buffers with different blend enable state
    gl::DrawBufferMask diffMask = mState.blendState.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 ^ mState.blendState.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)
    {
        SetGLIndexedBoolState(mFunctions, GL_BLEND, static_cast<GLuint>(drawBufferIndex),
                              enabledMask.test(drawBufferIndex));
    }

    mState.blendState.setEnabledMask(enabledMask);
    mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_ENABLED);
}

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

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

void StateManagerGL::setBlendAdvancedCoherent(bool enabled)
{
    if (mState.blendAdvancedCoherent != enabled)
    {
        mState.blendAdvancedCoherent = enabled;

        SetGLBoolState(mFunctions, GL_BLEND_ADVANCED_COHERENT_KHR, enabled);

        mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
        mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT);
    }
}

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

    if (!mIndependentBlendStates)
    {
        mFunctions->blendFuncSeparate(
            ToGLenum(blendState.getSrcColorIndexed(0)), ToGLenum(blendState.getDstColorIndexed(0)),
            ToGLenum(blendState.getSrcAlphaIndexed(0)), ToGLenum(blendState.getDstAlphaIndexed(0)));
    }
    else
    {
        // Get DrawBufferMask of buffers with different blend factors
        gl::DrawBufferMask diffMask = mState.blendState.compareFactors(blendState);
        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 < mState.blendState.getDrawBufferCount() - 1; i++)
            {
                const gl::BlendStateExt::FactorStorage::Type tempCommonSrcColor =
                    blendState.expandSrcColorIndexed(i);
                const gl::BlendStateExt::FactorStorage::Type tempCommonDstColor =
                    blendState.expandDstColorIndexed(i);
                const gl::BlendStateExt::FactorStorage::Type tempCommonSrcAlpha =
                    blendState.expandSrcAlphaIndexed(i);
                const gl::BlendStateExt::FactorStorage::Type tempCommonDstAlpha =
                    blendState.expandDstAlphaIndexed(i);

                const gl::DrawBufferMask tempDiffMask = blendState.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),
                ToGLenum(blendState.getSrcColorIndexed(drawBufferIndex)),
                ToGLenum(blendState.getDstColorIndexed(drawBufferIndex)),
                ToGLenum(blendState.getSrcAlphaIndexed(drawBufferIndex)),
                ToGLenum(blendState.getDstAlphaIndexed(drawBufferIndex)));
        }
    }
    mState.blendState.setFactorBits(blendState.getSrcColorBits(), blendState.getDstColorBits(),
                                    blendState.getSrcAlphaBits(), blendState.getDstAlphaBits(),
                                    blendState.getUsesExtendedBlendFactorMask());
    mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_FUNCS);
}

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

    if (!mIndependentBlendStates)
    {
        mFunctions->blendEquationSeparate(ToGLenum(blendState.getEquationColorIndexed(0)),
                                          ToGLenum(blendState.getEquationAlphaIndexed(0)));
    }
    else
    {
        // Get DrawBufferMask of buffers with different blend equations
        gl::DrawBufferMask diffMask = mState.blendState.compareEquations(blendState);
        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 < mState.blendState.getDrawBufferCount() - 1; i++)
            {
                const gl::BlendStateExt::EquationStorage::Type tempCommonEquationColor =
                    blendState.expandEquationColorIndexed(i);
                const gl::BlendStateExt::EquationStorage::Type tempCommonEquationAlpha =
                    blendState.expandEquationAlphaIndexed(i);

                const gl::DrawBufferMask tempDiffMask =
                    blendState.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)
            {
                if (commonEquationColor == commonEquationAlpha)
                {
                    mFunctions->blendEquation(
                        ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
                            0, commonEquationColor)));
                }
                else
                {
                    mFunctions->blendEquationSeparate(
                        ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
                            0, commonEquationColor)),
                        ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
                            0, commonEquationAlpha)));
                }
            }
        }

        for (size_t drawBufferIndex : diffMask)
        {
            gl::BlendEquationType equationColor =
                blendState.getEquationColorIndexed(drawBufferIndex);
            gl::BlendEquationType equationAlpha =
                blendState.getEquationAlphaIndexed(drawBufferIndex);
            if (equationColor == equationAlpha)
            {
                mFunctions->blendEquationi(static_cast<GLuint>(drawBufferIndex),
                                           ToGLenum(equationColor));
            }
            else
            {
                mFunctions->blendEquationSeparatei(static_cast<GLuint>(drawBufferIndex),
                                                   ToGLenum(equationColor),
                                                   ToGLenum(equationAlpha));
            }
        }
    }
    mState.blendState.setEquationColorBits(blendState.getEquationColorBits(),
                                           blendState.getUsesAdvancedBlendEquationMask());
    mState.blendState.setEquationAlphaBits(blendState.getEquationAlphaBits());
    mLocalDirtyBits.set(gl::state::DIRTY_BIT_BLEND_EQUATIONS);
}

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

void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
{
    if (mState.sampleAlphaToCoverageEnabled != enabled)
    {
        mState.sampleAlphaToCoverageEnabled = enabled;
        SetGLBoolState(mFunctions, GL_SAMPLE_ALPHA_TO_COVERAGE, enabled);

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

void StateManagerGL::setSampleCoverageEnabled(bool enabled)
{
    if (mState.sampleCoverageEnabled != enabled)
    {
        mState.sampleCoverageEnabled = enabled;
        SetGLBoolState(mFunctions, GL_SAMPLE_COVERAGE, enabled);

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

void StateManagerGL::forceSetSampleCoverage(float value, bool invert)
{
    mState.sampleCoverageValue  = value;
    mState.sampleCoverageInvert = invert;
    mSampleCoverageEverChanged  = true;
    mFunctions->sampleCoverage(value, invert);
    mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_COVERAGE);
}

void StateManagerGL::setSampleCoverage(float value, bool invert)
{
    if (mState.sampleCoverageValue != value || mState.sampleCoverageInvert != invert)
    {
        forceSetSampleCoverage(value, invert);
    }
}

void StateManagerGL::setSampleMaskEnabled(bool enabled)
{
    if (mState.sampleMaskEnabled != enabled)
    {
        mState.sampleMaskEnabled = enabled;
        SetGLBoolState(mFunctions, GL_SAMPLE_MASK, enabled);

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

void StateManagerGL::setSampleMask(const gl::SampleMaskArray<GLbitfield> &maskValues)
{
    for (GLuint maskNumber = 0; maskNumber < maskValues.size(); maskNumber++)
    {
        setSampleMaski(maskNumber, maskValues[maskNumber]);
    }
}

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

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

void StateManagerGL::setDepthTestEnabled(bool enabled)
{
    if (mState.depthTestEnabled != enabled)
    {
        mState.depthTestEnabled = enabled;
        SetGLBoolState(mFunctions, GL_DEPTH_TEST, enabled);

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

void StateManagerGL::setDepthFunc(GLenum depthFunc)
{
    if (mState.depthFunc != depthFunc)
    {
        mState.depthFunc = depthFunc;
        mFunctions->depthFunc(depthFunc);

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

void StateManagerGL::setDepthMask(bool mask)
{
    if (mState.depthMask != mask)
    {
        mState.depthMask = mask;
        mFunctions->depthMask(mask);

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

void StateManagerGL::setStencilTestEnabled(bool enabled)
{
    if (mState.stencilTestEnabled != enabled)
    {
        mState.stencilTestEnabled = enabled;
        SetGLBoolState(mFunctions, GL_STENCIL_TEST, enabled);

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

void StateManagerGL::setStencilFrontWritemask(GLuint mask)
{
    GLuint clippedMask = mask & 0xFF;
    if (mState.stencilFrontWritemask != clippedMask)
    {
        mState.stencilFrontWritemask = clippedMask;
        mFunctions->stencilMaskSeparate(GL_FRONT, clippedMask);

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

void StateManagerGL::setStencilBackWritemask(GLuint mask)
{
    GLuint clippedMask = mask & 0xFF;
    if (mState.stencilBackWritemask != clippedMask)
    {
        mState.stencilBackWritemask = clippedMask;
        mFunctions->stencilMaskSeparate(GL_BACK, clippedMask);

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

void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
{
    GLuint clippedMask = mask & 0xFF;
    if (mState.stencilFrontFunc != func || mState.stencilFrontRef != ref ||
        mState.stencilFrontValueMask != clippedMask)
    {
        mState.stencilFrontFunc      = func;
        mState.stencilFrontRef       = ref;
        mState.stencilFrontValueMask = clippedMask;
        mFunctions->stencilFuncSeparate(GL_FRONT, func, ref, clippedMask);

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

void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
{
    GLuint clippedMask = mask & 0xFF;
    if (mState.stencilBackFunc != func || mState.stencilBackRef != ref ||
        mState.stencilBackValueMask != clippedMask)
    {
        mState.stencilBackFunc      = func;
        mState.stencilBackRef       = ref;
        mState.stencilBackValueMask = clippedMask;
        mFunctions->stencilFuncSeparate(GL_BACK, func, ref, clippedMask);

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

void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
{
    if (mState.stencilFrontStencilFailOp != sfail ||
        mState.stencilFrontStencilPassDepthFailOp != dpfail ||
        mState.stencilFrontStencilPassDepthPassOp != dppass)
    {
        mState.stencilFrontStencilFailOp          = sfail;
        mState.stencilFrontStencilPassDepthFailOp = dpfail;
        mState.stencilFrontStencilPassDepthPassOp = dppass;
        mFunctions->stencilOpSeparate(GL_FRONT, sfail, dpfail, dppass);

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

void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
{
    if (mState.stencilBackStencilFailOp != sfail ||
        mState.stencilBackStencilPassDepthFailOp != dpfail ||
        mState.stencilBackStencilPassDepthPassOp != dppass)
    {
        mState.stencilBackStencilFailOp          = sfail;
        mState.stencilBackStencilPassDepthFailOp = dpfail;
        mState.stencilBackStencilPassDepthPassOp = dppass;
        mFunctions->stencilOpSeparate(GL_BACK, sfail, dpfail, dppass);

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

void StateManagerGL::setCullFaceEnabled(bool enabled)
{
    if (mState.cullFaceEnabled != enabled)
    {
        mState.cullFaceEnabled = enabled;
        SetGLBoolState(mFunctions, GL_CULL_FACE, enabled);

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

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

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

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

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

void StateManagerGL::setPolygonMode(gl::PolygonMode mode)
{
    if (mState.polygonMode != mode)
    {
        mState.polygonMode = mode;
        if (mFunctions->standard == STANDARD_GL_DESKTOP)
        {
            mFunctions->polygonMode(GL_FRONT_AND_BACK, ToGLenum(mode));
        }
        else
        {
            ASSERT(mFunctions->polygonModeNV);
            mFunctions->polygonModeNV(GL_FRONT_AND_BACK, ToGLenum(mode));
        }

        mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
        mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE);
    }
}

void StateManagerGL::setPolygonOffsetPointEnabled(bool enabled)
{
    if (mState.polygonOffsetPointEnabled != enabled)
    {
        mState.polygonOffsetPointEnabled = enabled;
        SetGLBoolState(mFunctions, GL_POLYGON_OFFSET_POINT_NV, enabled);

        mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
        mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED);
    }
}

void StateManagerGL::setPolygonOffsetLineEnabled(bool enabled)
{
    if (mState.polygonOffsetLineEnabled != enabled)
    {
        mState.polygonOffsetLineEnabled = enabled;
        SetGLBoolState(mFunctions, GL_POLYGON_OFFSET_LINE_NV, enabled);

        mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
        mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED);
    }
}

void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
{
    if (mState.polygonOffsetFillEnabled != enabled)
    {
        mState.polygonOffsetFillEnabled = enabled;
        SetGLBoolState(mFunctions, GL_POLYGON_OFFSET_FILL, enabled);

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

void StateManagerGL::setPolygonOffset(float factor, float units, float clamp)
{
    if (mState.polygonOffsetFactor != factor || mState.polygonOffsetUnits != units ||
        mState.polygonOffsetClamp != clamp)
    {
        mState.polygonOffsetFactor = factor;
        mState.polygonOffsetUnits  = units;
        mState.polygonOffsetClamp  = clamp;

        if (clamp == 0.0f)
        {
            mFunctions->polygonOffset(factor, units);
        }
        else
        {
            ASSERT(mFunctions->polygonOffsetClampEXT);
            mFunctions->polygonOffsetClampEXT(factor, units, clamp);
        }

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

void StateManagerGL::setDepthClampEnabled(bool enabled)
{
    if (mState.depthClampEnabled != enabled)
    {
        mState.depthClampEnabled = enabled;
        SetGLBoolState(mFunctions, GL_DEPTH_CLAMP_EXT, enabled);

        mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
        mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED);
    }
}

void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
{
    if (mState.rasterizerDiscardEnabled != enabled)
    {
        mState.rasterizerDiscardEnabled = enabled;
        SetGLBoolState(mFunctions, GL_RASTERIZER_DISCARD, enabled);

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

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

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

angle::Result StateManagerGL::setPrimitiveRestartFixedIndexEnabled(const gl::Context *context,
                                                                   bool enabled)
{

    if (mState.primitiveRestartFixedIndexEnabled != enabled)
    {
        SetGLBoolState(mFunctions, GL_PRIMITIVE_RESTART_FIXED_INDEX, enabled);
        mState.primitiveRestartFixedIndexEnabled = enabled;

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

    return angle::Result::Continue;
}

angle::Result StateManagerGL::setPrimitiveRestartEnabled(const gl::Context *context, bool enabled)
{
    if (mState.primitiveRestartEnabled != enabled)
    {
        ASSERT(mFeatures.emulatePrimitiveRestartFixedIndex.enabled);

        SetGLBoolState(mFunctions, GL_PRIMITIVE_RESTART, enabled);
        mState.primitiveRestartEnabled = 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 (mState.primitiveRestartIndex != index)
    {
        ANGLE_GL_TRY(context, mFunctions->primitiveRestartIndex(index));
        mState.primitiveRestartIndex = index;

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

    return angle::Result::Continue;
}

void StateManagerGL::setClearDepth(float clearDepth)
{
    if (mState.clearDepth != clearDepth)
    {
        mState.clearDepth = 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(clearDepth);
        }
        else
        {
            ASSERT(mFunctions->clearDepth);
            mFunctions->clearDepth(clearDepth);
        }

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

void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
{
    if (mState.clearColor != clearColor)
    {
        mState.clearColor = clearColor;
        mFunctions->clearColor(clearColor.red, clearColor.green, clearColor.blue, clearColor.alpha);

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

void StateManagerGL::setClearStencil(GLint clearStencil)
{
    // Mask the clear stencil value to 1 byte before setting it.
    // The Desktop GL spec says the driver will mask when calling glClearStencil while the GLES spec
    // says it will only be masked when doing the clear. By masking it here, the value we track will
    // always be the same as what the driver tracks.
    GLint maskedClearValue = clearStencil & 0xFF;
    if (mState.clearStencil != maskedClearValue)
    {
        mState.clearStencil = maskedClearValue;
        mFunctions->clearStencil(maskedClearValue);

        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::ExtendedDirtyBits &extendedDirtyBits,
                                        const gl::state::ExtendedDirtyBits &extendedBitMask)
{
    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:
                if (mFeatures.emulateClipOrigin.enabled)
                {
                    static_assert((GL_CW ^ GL_CCW) ==
                                  static_cast<GLenum>(gl::ClipOrigin::UpperLeft));
                    setFrontFace(state.getRasterizerState().frontFace ^
                                 static_cast<GLenum>(state.getClipOrigin()));
                    break;
                }
                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,
                                 rasterizerState.polygonOffsetClamp);
                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:
                if (mFeatures.emulatePrimitiveRestartFixedIndex.enabled)
                {
                    ANGLE_TRY(
                        setPrimitiveRestartEnabled(context, state.isPrimitiveRestartEnabled()));
                }
                else
                {
                    ANGLE_TRY(setPrimitiveRestartFixedIndexEnabled(
                        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());
                GetImplAs<ContextGL>(context)->tickGC();
                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());

                GetImplAs<ContextGL>(context)->tickGC();

                if (mFeatures.resetSampleCoverageOnFBOChange.enabled && mSampleCoverageEverChanged)
                {
                    forceSetSampleCoverage(mState.sampleCoverageValue, mState.sampleCoverageInvert);
                }

                const gl::ProgramExecutable *executable = state.getProgramExecutable();
                if (executable)
                {
                    updateMultiviewBaseViewLayerIndexUniform(executable, 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());

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

                if (vaoGL->syncsToSharedState())
                {
                    // 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 (GLint attrib = 0; attrib < context->getCaps().maxVertexAttributes;
                         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 (GLint binding = 0; binding < context->getCaps().maxVertexAttribBindings;
                         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:
                syncProgramState(context);
                break;
            case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE:
            {
                const gl::ProgramExecutable *executable = state.getProgramExecutable();

                if (executable)
                {
                    iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);

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

                    if (executable->getShaderStorageBlocks().size() > 0)
                    {
                        iter.setLaterBit(gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
                    }

                    if (executable->getUniformBlocks().size() > 0)
                    {
                        iter.setLaterBit(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
                    }

                    if (executable->getAtomicCounterBuffers().size() > 0)
                    {
                        iter.setLaterBit(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
                    }

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

                    // If the current executable does not use clip distances, the related API
                    // state has to be disabled to avoid runtime failures on certain drivers.
                    // On other drivers, that state is always emulated via a special uniform,
                    // which needs to be updated when switching programs.
                    if (mMaxClipDistances > 0)
                    {
                        iter.setLaterBit(gl::state::DIRTY_BIT_EXTENDED);
                        mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES);
                    }

                    if (mFeatures.emulateClipOrigin.enabled)
                    {
                        updateEmulatedClipOriginUniform(executable, state.getClipOrigin());
                    }
                }

                if (!executable || !executable->hasLinkedShaderStage(gl::ShaderType::Compute))
                {
                    ANGLE_TRY(propagateProgramToVAO(
                        context, executable, 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_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);

                for (auto attribIndex : combinedMask)
                {
                    setAttributeCurrentData(attribIndex,
                                            state.getVertexAttribCurrentValue(attribIndex));
                }

                mLocalDirtyCurrentValues.reset();
                break;
            }
            case gl::state::DIRTY_BIT_PROVOKING_VERTEX:
                setProvokingVertex(ToGLenum(state.getProvokingVertex()));
                break;
            case gl::state::DIRTY_BIT_CLIP_CONTROL:
                if (mFeatures.emulateClipOrigin.enabled)
                {
                    setClipControlWithEmulatedClipOrigin(
                        state.getProgramExecutable(), state.getRasterizerState().frontFace,
                        state.getClipOrigin(), state.getClipDepthMode());
                    break;
                }
                setClipControl(state.getClipOrigin(), state.getClipDepthMode());
                break;
            case gl::state::DIRTY_BIT_EXTENDED:
            {
                const gl::state::ExtendedDirtyBits glAndLocalExtendedDirtyBits =
                    (extendedDirtyBits | mLocalExtendedDirtyBits) & extendedBitMask;
                for (size_t extendedDirtyBit : glAndLocalExtendedDirtyBits)
                {
                    switch (extendedDirtyBit)
                    {
                        case gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES:
                        {
                            const gl::ProgramExecutable *executable = state.getProgramExecutable();
                            if (executable && executable->hasClipDistance())
                            {
                                setClipDistancesEnable(state.getEnabledClipDistances());
                                if (mFeatures.emulateClipDistanceState.enabled)
                                {
                                    updateEmulatedClipDistanceState(
                                        executable, state.getEnabledClipDistances());
                                }
                            }
                            else
                            {
                                setClipDistancesEnable(gl::ClipDistanceEnableBits());
                            }
                            break;
                        }
                        case gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED:
                            setDepthClampEnabled(state.isDepthClampEnabled());
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED:
                            setLogicOpEnabled(state.isLogicOpEnabled());
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP:
                            setLogicOp(state.getLogicOp());
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT:
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE:
                            setPolygonMode(state.getPolygonMode());
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED:
                            setPolygonOffsetPointEnabled(state.isPolygonOffsetPointEnabled());
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED:
                            setPolygonOffsetLineEnabled(state.isPolygonOffsetLineEnabled());
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT:
                            // These hints aren't forwarded to GL yet.
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_QCOM:
                        case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE_EXT:
                            // Unimplemented extensions.
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT:
                            setBlendAdvancedCoherent(state.isBlendAdvancedCoherentEnabled());
                            break;
                        case gl::state::EXTENDED_DIRTY_BIT_FETCH_PER_SAMPLE_ENABLED:
                            break;
                        default:
                            UNREACHABLE();
                            break;
                    }
                    mLocalExtendedDirtyBits &= ~extendedBitMask;
                }
                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 (mState.framebufferSRGBEnabled != enabled)
    {
        mState.framebufferSRGBEnabled = enabled;
        SetGLBoolState(mFunctions, GL_FRAMEBUFFER_SRGB, enabled);
        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 &blendState,
                                                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)
    {
        blendState.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 (mState.blendState.getColorMaskBits() == blendState.getColorMaskBits())
    {
        return;
    }

    // Get DrawBufferMask of buffers with different color masks
    gl::DrawBufferMask diffMask = mState.blendState.compareColorMask(blendState.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 < mState.blendState.getDrawBufferCount() - 1; i++)
        {
            const gl::BlendStateExt::ColorMaskStorage::Type tempCommonColorMask =
                blendState.expandColorMaskIndexed(i);
            const gl::DrawBufferMask tempDiffMask =
                blendState.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)
    {
        blendState.getColorMaskIndexed(drawBufferIndex, &r, &g, &b, &a);
        mFunctions->colorMaski(static_cast<GLuint>(drawBufferIndex), r, g, b, a);
    }

    mState.blendState.setColorMaskBits(blendState.getColorMaskBits());
    mLocalDirtyBits.set(gl::state::DIRTY_BIT_COLOR_MASK);
}

void StateManagerGL::setDitherEnabled(bool enabled)
{
    if (mState.ditherEnabled != enabled)
    {
        mState.ditherEnabled = enabled;
        SetGLBoolState(mFunctions, GL_DITHER, enabled);
        mLocalDirtyBits.set(gl::state::DIRTY_BIT_DITHER_ENABLED);
    }
}

void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
{
    if (mState.multisamplingEnabled != enabled)
    {
        mState.multisamplingEnabled = enabled;
        SetGLBoolState(mFunctions, GL_MULTISAMPLE, enabled);
        mLocalDirtyBits.set(gl::state::DIRTY_BIT_MULTISAMPLING);
    }
}

void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
{
    if (mState.sampleAlphaToOneEnabled != enabled)
    {
        mState.sampleAlphaToOneEnabled = enabled;
        SetGLBoolState(mFunctions, GL_SAMPLE_ALPHA_TO_ONE, enabled);
        mLocalDirtyBits.set(gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
    }
}

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

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

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

    gl::ClipDistanceEnableBits diff = enables ^ mState.enabledClipDistances;
    for (size_t i : diff)
    {
        SetGLBoolState(mFunctions, GL_CLIP_DISTANCE0_EXT + static_cast<uint32_t>(i),
                       enables.test(i));
    }

    mState.enabledClipDistances = enables;
    mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
    mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES);
}

void StateManagerGL::setLogicOpEnabled(bool enabled)
{
    if (enabled == mState.logicOpEnabled)
    {
        return;
    }
    mState.logicOpEnabled = enabled;

    SetGLBoolState(mFunctions, GL_COLOR_LOGIC_OP, enabled);

    mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
    mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED);
}

void StateManagerGL::setLogicOp(gl::LogicalOperation opcode)
{
    if (opcode == mState.logicOp)
    {
        return;
    }
    mState.logicOp = opcode;

    mFunctions->logicOp(ToGLenum(opcode));

    mLocalDirtyBits.set(gl::state::DIRTY_BIT_EXTENDED);
    mLocalExtendedDirtyBits.set(gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED);
}

void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
{
    if (!nativegl::SupportsSettingCubemapSeamless(mFunctions))
    {
        return;
    }

    if (mState.textureCubemapSeamlessEnabled != enabled)
    {
        mState.textureCubemapSeamlessEnabled = enabled;
        SetGLBoolState(mFunctions, GL_TEXTURE_CUBE_MAP_SEAMLESS, enabled);
    }
}

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

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

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

    return angle::Result::Continue;
}

void StateManagerGL::updateMultiviewBaseViewLayerIndexUniformImpl(
    const gl::ProgramExecutable *executable,
    const gl::FramebufferState &drawFramebufferState) const
{
    ASSERT(mIsMultiviewEnabled && executable && executable->usesMultiview());
    const ProgramExecutableGL *executableGL = GetImplAs<ProgramExecutableGL>(executable);
    if (drawFramebufferState.isMultiview())
    {
        executableGL->enableLayeredRenderingPath(drawFramebufferState.getBaseViewIndex());
    }
}
void StateManagerGL::setDefaultVAOState(const VertexArrayStateGL &state)
{
    if (mState.defaultVAOState == state)
    {
        return;
    }

    bindVertexArray(0);

    const bool supportsBindings = nativegl::SupportsVertexAttributeBindings(mFunctions);
    const bool supportsInstancing = nativegl::SupportsInstancing(mFunctions);

    bindBuffer(gl::BufferBinding::ElementArray, state.elementArrayBuffer);
    for (GLint i = 0; i < mCaps.maxVertexAttributes; i++)
    {
        VertexAttributeGL &curAttrib       = mState.defaultVAOState.attributes[i];
        const VertexAttributeGL &newAttrib = state.attributes[i];
        if (curAttrib.enabled != newAttrib.enabled)
        {
            SetVertexAttribArrayEnabled(mFunctions, i, newAttrib.enabled);
            curAttrib.enabled = newAttrib.enabled;
        }

        // If vertex bindings are supported and the binding index has been changed, set all state
        // with the binding functions. Otherwise use the old glVertexAttribPointer setting
        // functions.
        if (supportsBindings && newAttrib.bindingIndex != curAttrib.bindingIndex)
        {
            mFunctions->vertexAttribBinding(i, newAttrib.bindingIndex);
            curAttrib.bindingIndex = newAttrib.bindingIndex;

            if (curAttrib.format != newAttrib.format ||
                curAttrib.relativeOffset != newAttrib.relativeOffset)
            {
                mFunctions->vertexAttribFormat(i, newAttrib.format->channelCount,
                                               gl::ToGLenum(newAttrib.format->vertexAttribType),
                                               newAttrib.format->isNorm(),
                                               newAttrib.relativeOffset);
                curAttrib.format         = newAttrib.format;
                curAttrib.relativeOffset = newAttrib.relativeOffset;
            }
        }
        else
        {
            VertexBindingGL &curBinding = mState.defaultVAOState.bindings[curAttrib.bindingIndex];
            const VertexBindingGL &newBinding = state.bindings[newAttrib.bindingIndex];

            ASSERT(newAttrib.bindingIndex == curAttrib.bindingIndex);

            if (curAttrib.format != newAttrib.format || curAttrib.pointer != newAttrib.pointer ||
                curBinding.buffer != newBinding.buffer || curBinding.stride != newBinding.stride)
            {
                bindBuffer(gl::BufferBinding::Array, newBinding.buffer);
                mFunctions->vertexAttribPointer(i, newAttrib.format->channelCount,
                                                gl::ToGLenum(newAttrib.format->vertexAttribType),
                                                newAttrib.format->isNorm(), newBinding.stride,
                                                newAttrib.pointer);
                curAttrib.format         = newAttrib.format;
                curAttrib.pointer        = newAttrib.pointer;
                curAttrib.relativeOffset = 0;
                curBinding.buffer        = newBinding.buffer;
                curBinding.offset =
                    newBinding.buffer ? reinterpret_cast<GLintptr>(newAttrib.pointer) : 0;
                curBinding.stride = newBinding.stride;
            }

            if (curBinding.divisor != newBinding.divisor)
            {
                ASSERT(supportsInstancing);
                mFunctions->vertexAttribDivisor(i, newBinding.divisor);
                curBinding.divisor = newBinding.divisor;
            }
        }
    }

    for (GLint i = 0; i < mCaps.maxVertexAttribBindings; i++)
    {
        VertexBindingGL &curBinding       = mState.defaultVAOState.bindings[i];
        const VertexBindingGL &newBinding = state.bindings[i];

        if (curBinding.buffer != newBinding.buffer || curBinding.offset != newBinding.offset ||
            curBinding.stride != newBinding.stride)
        {
            ASSERT(supportsBindings);
            mFunctions->bindVertexBuffer(i, newBinding.buffer, newBinding.offset,
                                         newBinding.stride);
            curBinding.buffer = newBinding.buffer;
            curBinding.stride = newBinding.stride;
            curBinding.offset = newBinding.offset;
        }

        if (curBinding.divisor != newBinding.divisor)
        {
            ASSERT(supportsBindings);
            ASSERT(supportsInstancing);
            mFunctions->vertexBindingDivisor(i, newBinding.divisor);
            curBinding.divisor = newBinding.divisor;
        }
    }

#if defined(ANGLE_EANBLE_ASSERTS)
    if (mState.defaultVAOState != state)
    {
        std::ostringstream msg;
        msg << "VAO state note equal after applying!" << std::endl;
        msg << "mState.defaultVAOState:" << std::endl
            << mState.defaultVAOState << std::endl
            << std::endl;
        msg << "state:" << std::endl << state << std::endl;
        FATAL() << msg.str();
    }
#endif

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

angle::Result StateManagerGL::setState(const gl::Context *context, const ContextStateGL &state)
{
    useProgram(state.program);
    setDefaultVAOState(
        state.defaultVAOState);  // Set default VAO state before binding the target vao
    bindVertexArray(state.vao);
    for (size_t attribIndex = 0; attribIndex < state.vertexAttribCurrentValues.size();
         attribIndex++)
    {
        setAttributeCurrentData(attribIndex, state.vertexAttribCurrentValues[attribIndex]);
    }
    for (gl::BufferBinding bufferBinding : angle::AllEnums<gl::BufferBinding>())
    {
        if (bufferBinding == gl::BufferBinding::TransformFeedback)
        {
            continue;
        }

        // Apply the indexed bindings first since they change the generic binding.
        const std::vector<IndexedBufferBindingGL> &indexedBindings =
            state.indexedBuffers[bufferBinding];
        for (size_t i = 0; i < indexedBindings.size(); i++)
        {
            const IndexedBufferBindingGL &binding = indexedBindings[i];
            if (binding.size == 0)
            {
                ASSERT(binding.offset == 0);
                bindBufferBase(bufferBinding, i, binding.buffer);
            }
            else
            {
                bindBufferRange(bufferBinding, i, binding.buffer, binding.offset, binding.size);
            }
        }

        bindBuffer(bufferBinding, state.buffers[bufferBinding]);
    }
    for (size_t textureUnit = 0; textureUnit < gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES;
         textureUnit++)
    {
        for (gl::TextureType textureType : angle::AllEnums<gl::TextureType>())
        {
            bindTexture(textureType, textureUnit, state.textures[textureType][textureUnit]);
        }

        bindSampler(textureUnit, state.samplers[textureUnit]);
    }
    // Apply the target texture type after syncing all textures
    activeTexture(state.textureUnitIndex);
    for (size_t imageUnit = 0; imageUnit < state.images.size(); imageUnit++)
    {
        const ImageUnitBindingGL &binding = state.images[imageUnit];
        bindImageTexture(imageUnit, binding.texture, binding.level, binding.layered, binding.layer,
                         binding.access, binding.format);
    }
    bindTransformFeedback(GL_TRANSFORM_FEEDBACK, state.transformFeedback);

    ANGLE_TRY(setPixelUnpackState(context, state.unpackState));
    ANGLE_TRY(setPixelPackState(context, state.packState));
    if (!mHasSeparateFramebufferBindings || state.framebuffers[angle::FramebufferBindingDraw] ==
                                                state.framebuffers[angle::FramebufferBindingRead])
    {
        bindFramebuffer(GL_FRAMEBUFFER, state.framebuffers[angle::FramebufferBindingDraw]);
    }
    else
    {
        bindFramebuffer(GL_DRAW_FRAMEBUFFER, state.framebuffers[angle::FramebufferBindingDraw]);
        bindFramebuffer(GL_READ_FRAMEBUFFER, state.framebuffers[angle::FramebufferBindingRead]);
    }
    bindRenderbuffer(GL_RENDERBUFFER, state.renderbuffer);
    setScissorTestEnabled(state.scissorTestEnabled);
    setScissor(state.scissor);
    setViewport(state.viewport);
    setDepthRange(state.near, state.far);
    setClipControl(state.clipOrigin, state.clipDepthMode);
    setBlendColor(state.blendColor);
    setBlendEnabledIndexed(state.blendState.getEnabledMask());
    setColorMaskForFramebuffer(state.blendState, false);
    setBlendFuncs(state.blendState);
    setBlendEquations(state.blendState);
    setBlendAdvancedCoherent(state.blendAdvancedCoherent);
    setSampleAlphaToCoverageEnabled(state.sampleAlphaToCoverageEnabled);
    setSampleCoverageEnabled(state.sampleCoverageEnabled);
    setSampleCoverage(state.sampleCoverageValue, state.sampleCoverageInvert);
    setSampleMaskEnabled(state.sampleMaskEnabled);
    setSampleMask(state.sampleMaskValues);
    setDepthTestEnabled(state.depthTestEnabled);
    setDepthFunc(state.depthFunc);
    setDepthMask(state.depthMask);
    setStencilTestEnabled(state.stencilTestEnabled);
    setStencilFrontFuncs(state.stencilFrontFunc, state.stencilFrontRef,
                         state.stencilFrontValueMask);
    setStencilFrontOps(state.stencilFrontStencilFailOp, state.stencilFrontStencilPassDepthFailOp,
                       state.stencilFrontStencilPassDepthPassOp);
    setStencilFrontWritemask(state.stencilFrontWritemask);
    setStencilBackFuncs(state.stencilBackFunc, state.stencilBackRef, state.stencilBackValueMask);
    setStencilBackOps(state.stencilBackStencilFailOp, state.stencilBackStencilPassDepthFailOp,
                      state.stencilBackStencilPassDepthPassOp);
    setStencilBackWritemask(state.stencilBackWritemask);
    setCullFaceEnabled(state.cullFaceEnabled);
    setCullFace(state.cullFace);
    setFrontFace(state.frontFace);
    setPolygonMode(state.polygonMode);
    setPolygonOffsetPointEnabled(state.polygonOffsetPointEnabled);
    setPolygonOffsetLineEnabled(state.polygonOffsetLineEnabled);
    setPolygonOffsetFillEnabled(state.polygonOffsetFillEnabled);
    setPolygonOffset(state.polygonOffsetFactor, state.polygonOffsetUnits, state.polygonOffsetClamp);
    setDepthClampEnabled(state.depthClampEnabled);
    setRasterizerDiscardEnabled(state.rasterizerDiscardEnabled);
    setLineWidth(state.lineWidth);
    ANGLE_TRY(
        setPrimitiveRestartFixedIndexEnabled(context, state.primitiveRestartFixedIndexEnabled));
    ANGLE_TRY(setPrimitiveRestartEnabled(context, state.primitiveRestartEnabled));
    ANGLE_TRY(setPrimitiveRestartIndex(context, state.primitiveRestartIndex));
    setClearColor(state.clearColor);
    setClearDepth(state.clearDepth);
    setClearStencil(state.clearStencil);
    setFramebufferSRGBEnabled(context, state.framebufferSRGBEnabled);
    setDitherEnabled(state.ditherEnabled);
    setTextureCubemapSeamlessEnabled(state.textureCubemapSeamlessEnabled);
    setMultisamplingStateEnabled(state.multisamplingEnabled);
    setSampleAlphaToOneStateEnabled(state.sampleAlphaToOneEnabled);
    setProvokingVertex(state.provokingVertex);
    setClipDistancesEnable(state.enabledClipDistances);
    setLogicOpEnabled(state.logicOpEnabled);
    setLogicOp(state.logicOp);

#if defined(ANGLE_ENABLE_ASSERTS)
    if (mState != state)
    {
        std::ostringstream msg;
        msg << "StateManagerGL::mState does not match new state after setState is called."
            << std::endl;
        msg << "StateManagerGL::mState:" << std::endl << mState << std::endl << std::endl;
        msg << "new state:" << std::endl << state << std::endl;
        FATAL() << msg.str();
    }
#endif

    return angle::Result::Continue;
}

void StateManagerGL::updateEmulatedClipDistanceState(const gl::ProgramExecutable *executable,
                                                     const gl::ClipDistanceEnableBits enables) const
{
    ASSERT(mFeatures.emulateClipDistanceState.enabled);
    ASSERT(executable && executable->hasClipDistance());
    const ProgramExecutableGL *executableGL = GetImplAs<ProgramExecutableGL>(executable);
    executableGL->updateEnabledClipDistances(static_cast<uint8_t>(enables.bits()));
}

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;
    }

    syncProgramState(context);
}

void StateManagerGL::syncProgramState(const gl::Context *context)
{
    gl::Program *program = context->getState().getProgram();
    if (program != nullptr)
    {
        ProgramGL *programGL = GetImplAs<ProgramGL>(program);
        useProgram(programGL->getProgramID());
    }
}

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

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

VertexArrayStateGL *StateManagerGL::getVAOState(GLuint vao)
{
    // Special case: The default VAO state is stored in ContextStateGL
    if (vao == mDefaultVAO)
    {
        return &mState.defaultVAOState;
    }

    auto iter = mVAOStates.find(vao);
    return (iter != mVAOStates.end()) ? &iter->second : nullptr;
}

VertexArrayStateGL *StateManagerGL::getOrCreateVAOState(GLuint vao)
{
    VertexArrayStateGL *vaoState = getVAOState(vao);
    if (vaoState != nullptr)
    {
        return vaoState;
    }

    auto insertResult = mVAOStates.insert(std::pair{
        vao, VertexArrayStateGL(mCaps.maxVertexAttributes, mCaps.maxVertexAttribBindings)});
    ASSERT(insertResult.second);
    return &insertResult.first->second;
}

VertexArrayStateGL *StateManagerGL::getCurrentVAOState()
{
    return getVAOState(mState.vao);
}

void StateManagerGL::validateState()
{
    ensurePlaceholderFramebuffer();

    ContextStateGL queriedState(mCaps);
    QueryContextStateGL(mFunctions, mPlaceholderFbo, &queriedState);
    if (mState != queriedState)
    {
        std::ostringstream msg;
        msg << "Queried state does not match tracked state!" << std::endl;
        msg << "Tracked state:" << std::endl << mState << std::endl << std::endl;
        msg << "Queried state:" << std::endl << queriedState << std::endl;
        FATAL() << msg.str();
    }
}
void StateManagerGL::setBufferBindingDirty(gl::BufferBinding binding)
{
    std::optional<gl::state::DirtyBitType> bit = GetBufferBindingDirtyBit(binding);
    if (bit.has_value())
    {
        mLocalDirtyBits.set(bit.value());
    }
}

std::unique_ptr<ContextStateGL> StateManagerGL::createContextStateGL() const
{
    return std::make_unique<ContextStateGL>(mCaps);
}

angle::Result StateManagerGL::syncFromNativeContext(const gl::Context *context,
                                                    ContextStateGL *outNativeContextState)
{
    auto *platform   = ANGLEPlatformCurrent();
    double startTime = platform->currentTime(platform);

    ensurePlaceholderFramebuffer();

    // Query the current driver state into outNativeContextState so that it can be restored later.
    QueryContextStateGL(mFunctions, mPlaceholderFbo, outNativeContextState);

    // Compute the dirty bits between the currently tracked state and the queried state in
    // outNativeContextState. This will ensure that all frontend states will be re-applied in the
    // next syncState.
    ComputeDirtyBitsBetweenStates(mState, *outNativeContextState, &mLocalDirtyBits,
                                  &mLocalExtendedDirtyBits, &mLocalDirtyCurrentValues);

    // Set the currently tracked state to the queried state so that our understanding of the driver
    // state is correct.
    mState = *outNativeContextState;

    double delta = platform->currentTime(platform) - startTime;
    int us       = static_cast<int>(delta * 1000000.0);
    ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.SyncFromNativeContextMicroseconds", us);

    return angle::Result::Continue;
}

angle::Result StateManagerGL::restoreNativeContext(const gl::Context *context,
                                                   const ContextStateGL &nativeContextState)
{
    // Simply apply all state from the external nativeContextState
    ANGLE_TRY(setState(context, nativeContextState));
    ASSERT(mState == nativeContextState);
    return angle::Result::Continue;
}

void StateManagerGL::ensurePlaceholderFramebuffer()
{
    if (mPlaceholderFbo)
    {
        return;
    }

    GLenum framebufferBinding =
        mHasSeparateFramebufferBindings ? GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
    mFunctions->genFramebuffers(1, &mPlaceholderFbo);
    mFunctions->bindFramebuffer(framebufferBinding, mPlaceholderFbo);

    mFunctions->genRenderbuffers(1, &mPlaceholderFboColorRenderbuffer);
    mFunctions->bindRenderbuffer(GL_RENDERBUFFER, mPlaceholderFboColorRenderbuffer);
    mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 2, 2);
    mFunctions->framebufferRenderbuffer(framebufferBinding, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
                                        mPlaceholderFboColorRenderbuffer);

    mFunctions->genRenderbuffers(1, &mPlaceholderFboDepthStencilRenderbuffer);
    mFunctions->bindRenderbuffer(GL_RENDERBUFFER, mPlaceholderFboDepthStencilRenderbuffer);
    mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 2, 2);
    mFunctions->framebufferRenderbuffer(framebufferBinding, GL_DEPTH_STENCIL_ATTACHMENT,
                                        GL_RENDERBUFFER, mPlaceholderFboDepthStencilRenderbuffer);

    // This ensures renderbuffer attachment is not lazy.
    mFunctions->checkFramebufferStatus(framebufferBinding);

    // Reset state
    mFunctions->bindFramebuffer(framebufferBinding,
                                mState.framebuffers[angle::FramebufferBindingDraw]);
    mFunctions->bindRenderbuffer(GL_RENDERBUFFER, mState.renderbuffer);
}

}  // namespace rx
