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

// Context.cpp: Implements the gl::Context class, managing all GL state and performing
// rendering operations. It is the GLES2 specific implementation of EGLContext.

#include "common/entry_points_enum_autogen.h"
#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/Context.inl.h"

#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#include <iterator>
#include <sstream>
#include <vector>

#include "common/PackedEnums.h"
#include "common/angle_version_info.h"
#include "common/hash_utils.h"
#include "common/matrix_utils.h"
#include "common/platform.h"
#include "common/string_utils.h"
#include "common/system_utils.h"
#include "common/tls.h"
#include "common/utilities.h"
#include "image_util/loadimage.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Display.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/Fence.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/MemoryObject.h"
#include "libANGLE/PixelLocalStorage.h"
#include "libANGLE/Program.h"
#include "libANGLE/ProgramPipeline.h"
#include "libANGLE/Query.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/ResourceManager.h"
#include "libANGLE/Sampler.h"
#include "libANGLE/Semaphore.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Texture.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/capture/FrameCapture.h"
#include "libANGLE/capture/serialize.h"
#include "libANGLE/context_private_call.inl.h"
#include "libANGLE/context_private_call_autogen.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/queryconversions.h"
#include "libANGLE/queryutils.h"
#include "libANGLE/renderer/DisplayImpl.h"
#include "libANGLE/renderer/Format.h"
#include "libANGLE/trace.h"
#include "libANGLE/validationES.h"

#if defined(ANGLE_PLATFORM_APPLE)
#    include <dispatch/dispatch.h>
#    include "common/tls.h"
#endif

namespace gl
{
namespace
{
constexpr state::DirtyObjects kDrawDirtyObjectsBase{
    state::DIRTY_OBJECT_ACTIVE_TEXTURES,
    state::DIRTY_OBJECT_DRAW_FRAMEBUFFER,
    state::DIRTY_OBJECT_VERTEX_ARRAY,
    state::DIRTY_OBJECT_TEXTURES,
    state::DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT,
    state::DIRTY_OBJECT_SAMPLERS,
    state::DIRTY_OBJECT_IMAGES,
};

// TexImage uses the unpack state
constexpr state::DirtyBits kTexImageDirtyBits{
    state::DIRTY_BIT_UNPACK_STATE,
    state::DIRTY_BIT_UNPACK_BUFFER_BINDING,
};
constexpr state::ExtendedDirtyBits kTexImageExtendedDirtyBits{};
constexpr state::DirtyObjects kTexImageDirtyObjects{};

// Readpixels uses the pack state and read FBO
constexpr state::DirtyBits kReadPixelsDirtyBits{
    state::DIRTY_BIT_PACK_STATE,
    state::DIRTY_BIT_PACK_BUFFER_BINDING,
    state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING,
};
constexpr state::ExtendedDirtyBits kReadPixelsExtendedDirtyBits{};
constexpr state::DirtyObjects kReadPixelsDirtyObjectsBase{state::DIRTY_OBJECT_READ_FRAMEBUFFER};

// We sync the draw Framebuffer manually in prepareForClear to allow the clear calls to do
// more custom handling for robust resource init.
constexpr state::DirtyBits kClearDirtyBits{
    state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED,
    state::DIRTY_BIT_SCISSOR_TEST_ENABLED,
    state::DIRTY_BIT_SCISSOR,
    state::DIRTY_BIT_VIEWPORT,
    state::DIRTY_BIT_CLEAR_COLOR,
    state::DIRTY_BIT_CLEAR_DEPTH,
    state::DIRTY_BIT_CLEAR_STENCIL,
    state::DIRTY_BIT_COLOR_MASK,
    state::DIRTY_BIT_DEPTH_MASK,
    state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT,
    state::DIRTY_BIT_STENCIL_WRITEMASK_BACK,
    state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
};
constexpr state::ExtendedDirtyBits kClearExtendedDirtyBits{};
constexpr state::DirtyObjects kClearDirtyObjects{state::DIRTY_OBJECT_DRAW_FRAMEBUFFER};

constexpr state::DirtyBits kBlitDirtyBits{
    state::DIRTY_BIT_SCISSOR_TEST_ENABLED,
    state::DIRTY_BIT_SCISSOR,
    state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE,
    state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING,
    state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
};
constexpr state::ExtendedDirtyBits kBlitExtendedDirtyBits{};
constexpr state::DirtyObjects kBlitDirtyObjectsBase{
    state::DIRTY_OBJECT_READ_FRAMEBUFFER,
    state::DIRTY_OBJECT_DRAW_FRAMEBUFFER,
};

constexpr state::DirtyBits kComputeDirtyBits{
    state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING,
    state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS,
    state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING,
    state::DIRTY_BIT_PROGRAM_BINDING,
    state::DIRTY_BIT_PROGRAM_EXECUTABLE,
    state::DIRTY_BIT_TEXTURE_BINDINGS,
    state::DIRTY_BIT_SAMPLER_BINDINGS,
    state::DIRTY_BIT_IMAGE_BINDINGS,
    state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING,
};
constexpr state::ExtendedDirtyBits kComputeExtendedDirtyBits{};
constexpr state::DirtyObjects kComputeDirtyObjectsBase{
    state::DIRTY_OBJECT_ACTIVE_TEXTURES,
    state::DIRTY_OBJECT_TEXTURES,
    state::DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT,
    state::DIRTY_OBJECT_IMAGES,
    state::DIRTY_OBJECT_SAMPLERS,
};

constexpr state::DirtyBits kCopyImageDirtyBitsBase{state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING};
constexpr state::ExtendedDirtyBits kCopyImageExtendedDirtyBits{};
constexpr state::DirtyObjects kCopyImageDirtyObjectsBase{state::DIRTY_OBJECT_READ_FRAMEBUFFER};

constexpr state::DirtyBits kReadInvalidateDirtyBits{state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING};
constexpr state::ExtendedDirtyBits kReadInvalidateExtendedDirtyBits{};

constexpr state::DirtyBits kDrawInvalidateDirtyBits{state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING};
constexpr state::ExtendedDirtyBits kDrawInvalidateExtendedDirtyBits{};

constexpr state::DirtyBits kTilingDirtyBits{state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING};
constexpr state::ExtendedDirtyBits kTilingExtendedDirtyBits{};
constexpr state::DirtyObjects kTilingDirtyObjectsBase{state::DIRTY_OBJECT_DRAW_FRAMEBUFFER};

constexpr bool kEnableAEPRequirementLogging = false;

// A helper to return strings as const GLubyte *, adding safety that the reinterpret_cast is applied
// only to const char *.
const GLubyte *AsGLubytePtr(const char *str)
{
    return reinterpret_cast<const GLubyte *>(str);
}

egl::ShareGroup *AllocateOrGetShareGroup(egl::Display *display, const gl::Context *shareContext)
{
    if (shareContext)
    {
        egl::ShareGroup *shareGroup = shareContext->getState().getShareGroup();
        shareGroup->addRef();
        return shareGroup;
    }
    else
    {
        return new egl::ShareGroup(display->getImplementation());
    }
}

egl::ContextMutex *AllocateOrUseContextMutex(egl::ContextMutex *sharedContextMutex)
{
    if (sharedContextMutex != nullptr)
    {
        ASSERT(egl::kIsContextMutexEnabled);
        ASSERT(sharedContextMutex->isReferenced());
        return sharedContextMutex;
    }
    return new egl::ContextMutex();
}

template <typename T>
angle::Result GetQueryObjectParameter(const Context *context,
                                      Query *query,
                                      QueryObjectParameter pnamePacked,
                                      T *params)
{
    if (ANGLE_UNLIKELY(query == nullptr))
    {
        // Some applications call into glGetQueryObjectuiv(...) prior to calling glBeginQuery(...)
        // This wouldn't be an issue since the validation layer will handle such a usecases but when
        // the app enables EGL_KHR_create_context_no_error extension, we skip the validation layer.
        switch (pnamePacked)
        {
            case QueryObjectParameter::QueryResult:
                *params = 0;
                break;
            case QueryObjectParameter::QueryResultAvailable:
                *params = GL_FALSE;
                if (context->isContextLost())
                {
                    context->contextLostErrorOnBlockingCall(angle::EntryPoint::GLGetQueryObjectuiv);
                    *params = GL_TRUE;
                }
                break;
            default:
                UNREACHABLE();
                return angle::Result::Stop;
        }
        return angle::Result::Continue;
    }

    switch (pnamePacked)
    {
        case QueryObjectParameter::QueryResult:
            return query->getResult(context, params);
        case QueryObjectParameter::QueryResultAvailable:
        {
            bool available = false;
            if (context->isContextLost())
            {
                context->contextLostErrorOnBlockingCall(angle::EntryPoint::GLGetQueryObjectuiv);
                available = true;
            }
            else
            {
                ANGLE_TRY(query->isResultAvailable(context, &available));
            }
            *params = static_cast<T>(available);
            return angle::Result::Continue;
        }
        default:
            UNREACHABLE();
            return angle::Result::Stop;
    }
}

// Attribute map queries.
EGLint GetClientMajorVersion(const egl::AttributeMap &attribs)
{
    return static_cast<EGLint>(attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1));
}

EGLint GetClientMinorVersion(const egl::AttributeMap &attribs)
{
    return static_cast<EGLint>(attribs.get(EGL_CONTEXT_MINOR_VERSION, 0));
}

bool GetBackwardCompatibleContext(const egl::AttributeMap &attribs)
{
    return attribs.get(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_TRUE) == EGL_TRUE;
}

bool GetWebGLContext(const egl::AttributeMap &attribs)
{
    return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE);
}

bool GetHardenedContext(const egl::AttributeMap &attribs)
{
    return (attribs.get(EGL_CONTEXT_HARDENED_ANGLE, EGL_FALSE) == EGL_TRUE);
}

Version GetClientVersion(egl::Display *display, const egl::AttributeMap &attribs)
{
    const Version requestedVersion(static_cast<uint8_t>(GetClientMajorVersion(attribs)),
                                   static_cast<uint8_t>(GetClientMinorVersion(attribs)));

    // We should return the requested version if the context is configured to disable backward
    // compatibility, or if it is a WebGL context (WebGL1 -> ES2.0, WebGL2 -> ES3.0)
    const bool isBackwardCompatible = GetBackwardCompatibleContext(attribs);
    const bool isWebGL              = GetWebGLContext(attribs);
    if (!isBackwardCompatible || isWebGL)
    {
        return requestedVersion;
    }

    // If the user requests an ES1 context, we cannot return an ES2+ context.
    if (requestedVersion < ES_2_0)
    {
        return ES_1_1;
    }

    // Always up the version to at least the max conformant version this display supports.
    // Only return a higher client version if requested.
    const Version conformantVersion =
        std::max(display->getImplementation()->getMaxConformantESVersion(), requestedVersion);

    return conformantVersion;
}

GLenum GetResetStrategy(const egl::AttributeMap &attribs)
{
    EGLAttrib resetStrategyExt =
        attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION);
    EGLAttrib resetStrategyCore =
        attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY, resetStrategyExt);

    switch (resetStrategyCore)
    {
        case EGL_NO_RESET_NOTIFICATION:
            return GL_NO_RESET_NOTIFICATION_EXT;
        case EGL_LOSE_CONTEXT_ON_RESET:
            return GL_LOSE_CONTEXT_ON_RESET_EXT;
        default:
            UNREACHABLE();
            return GL_NONE;
    }
}

bool GetRobustAccess(const egl::AttributeMap &attribs)
{
    EGLAttrib robustAccessExt  = attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE);
    EGLAttrib robustAccessCore = attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS, robustAccessExt);

    bool attribRobustAccess = (robustAccessCore == EGL_TRUE);
    bool contextFlagsRobustAccess =
        ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0);

    return (attribRobustAccess || contextFlagsRobustAccess);
}

bool GetDebug(const angle::FrontendFeatures &frontendFeatures, const egl::AttributeMap &attribs)
{
    return frontendFeatures.forceDebugContexts.enabled ||
           attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE ||
           (attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) != 0;
}

bool GetNoError(const egl::AttributeMap &attribs)
{
    return (attribs.get(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, EGL_FALSE) == EGL_TRUE);
}

bool GetExtensionsEnabled(const egl::AttributeMap &attribs, bool webGLContext)
{
    // If the context is WebGL, extensions are disabled by default
    EGLAttrib defaultValue = webGLContext ? EGL_FALSE : EGL_TRUE;
    return (attribs.get(EGL_EXTENSIONS_ENABLED_ANGLE, defaultValue) == EGL_TRUE);
}

bool GetBindGeneratesResource(const egl::AttributeMap &attribs)
{
    return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE);
}

bool GetClientArraysEnabled(const egl::AttributeMap &attribs)
{
    return (attribs.get(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE) == EGL_TRUE);
}

bool GetRobustResourceInit(egl::Display *display, const egl::AttributeMap &attribs)
{
    const angle::FrontendFeatures &frontendFeatures = display->getFrontendFeatures();
    return (frontendFeatures.forceRobustResourceInit.enabled ||
            attribs.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
}

EGLenum GetContextPriority(const egl::AttributeMap &attribs)
{
    return static_cast<EGLenum>(
        attribs.getAsInt(EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_MEDIUM_IMG));
}

bool GetProtectedContent(const egl::AttributeMap &attribs)
{
    return static_cast<bool>(attribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE));
}

bool GetPassthroughShaders(egl::Display *display, const egl::AttributeMap &attribs)
{
    const angle::FrontendFeatures &frontendFeatures = display->getFrontendFeatures();
    return frontendFeatures.forcePassthroughShaders.enabled ||
           static_cast<bool>(attribs.getAsInt(EGL_CONTEXT_PASSTHROUGH_SHADERS_ANGLE, EGL_FALSE));
}

std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
{
    std::string labelName;
    if (label != nullptr)
    {
        size_t labelLength = length < 0 ? strlen(label) : length;
        labelName          = std::string(label, labelLength);
    }
    return labelName;
}

void GetObjectLabelBase(const std::string &objectLabel,
                        GLsizei bufSize,
                        GLsizei *length,
                        GLchar *label)
{
    size_t writeLength = objectLabel.length();
    if (label != nullptr && bufSize > 0)
    {
        writeLength = std::min(static_cast<size_t>(bufSize) - 1, objectLabel.length());
        std::copy(objectLabel.begin(), objectLabel.begin() + writeLength, label);
        label[writeLength] = '\0';
    }

    if (length != nullptr)
    {
        *length = static_cast<GLsizei>(writeLength);
    }
}

GLsizei GetMarkerLength(GLsizei length, const char *marker, GLsizei maxLength)
{
    if (length == 0)
    {
        length = static_cast<GLsizei>(
            std::min<size_t>(strlen(marker), std::numeric_limits<GLsizei>::max()));
    }
    // https://crbug.com/524435922: Cap debug marker length to prevent driver or validation layer
    // issues with large labels.
    return std::min(length, maxLength);
}

enum SubjectIndexes : angle::SubjectIndex
{
    kTexture0SubjectIndex       = 0,
    kTextureMaxSubjectIndex     = kTexture0SubjectIndex + IMPLEMENTATION_MAX_ACTIVE_TEXTURES,
    kImage0SubjectIndex         = kTextureMaxSubjectIndex,
    kImageMaxSubjectIndex       = kImage0SubjectIndex + IMPLEMENTATION_MAX_IMAGE_UNITS,
    kUniformBuffer0SubjectIndex = kImageMaxSubjectIndex,
    kUniformBufferMaxSubjectIndex =
        kUniformBuffer0SubjectIndex + IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS,
    kAtomicCounterBuffer0SubjectIndex = kUniformBufferMaxSubjectIndex,
    kAtomicCounterBufferMaxSubjectIndex =
        kAtomicCounterBuffer0SubjectIndex + IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
    kShaderStorageBuffer0SubjectIndex = kAtomicCounterBufferMaxSubjectIndex,
    kShaderStorageBufferMaxSubjectIndex =
        kShaderStorageBuffer0SubjectIndex + IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
    kSampler0SubjectIndex    = kShaderStorageBufferMaxSubjectIndex,
    kSamplerMaxSubjectIndex  = kSampler0SubjectIndex + IMPLEMENTATION_MAX_ACTIVE_TEXTURES,
    kVertexArraySubjectIndex = kSamplerMaxSubjectIndex,
    kReadFramebufferSubjectIndex,
    kDrawFramebufferSubjectIndex,
    kProgramSubjectIndex,
    kProgramPipelineSubjectIndex,
};

bool IsClearBufferEnabled(const FramebufferState &fbState, GLenum buffer, GLint drawbuffer)
{
    return buffer != GL_COLOR || fbState.getEnabledDrawBuffers()[drawbuffer];
}

bool IsColorMaskedOut(const BlendStateExt &blendStateExt, const GLint drawbuffer)
{
    ASSERT(static_cast<size_t>(drawbuffer) < blendStateExt.getDrawBufferCount());
    return blendStateExt.getColorMaskIndexed(static_cast<size_t>(drawbuffer)) == 0;
}

bool GetIsExternal(const egl::AttributeMap &attribs)
{
    return (attribs.get(EGL_EXTERNAL_CONTEXT_ANGLE, EGL_FALSE) == EGL_TRUE);
}

void GetPerfMonitorString(const std::string &name,
                          GLsizei bufSize,
                          GLsizei *length,
                          GLchar *stringOut)
{
    GLsizei numCharsWritten = std::min(bufSize, static_cast<GLsizei>(name.size()));

    if (length)
    {
        if (bufSize == 0)
        {
            *length = static_cast<GLsizei>(name.size());
        }
        else
        {
            // Excludes null terminator.
            ASSERT(numCharsWritten > 0);
            *length = numCharsWritten - 1;
        }
    }

    if (stringOut)
    {
        memcpy(stringOut, name.c_str(), numCharsWritten);
    }
}

bool CanSupportAEP(const gl::Version &version, const gl::Extensions &extensions)
{
    // From the GL_ANDROID_extension_pack_es31a extension spec:
    // OpenGL ES 3.1 and GLSL ES 3.10 are required.
    // The following extensions are required:
    // * KHR_debug
    // * KHR_texture_compression_astc_ldr
    // * KHR_blend_equation_advanced
    // * OES_sample_shading
    // * OES_sample_variables
    // * OES_shader_image_atomic
    // * OES_shader_multisample_interpolation
    // * OES_texture_stencil8
    // * OES_texture_storage_multisample_2d_array
    // * EXT_copy_image
    // * EXT_draw_buffers_indexed
    // * EXT_geometry_shader
    // * EXT_gpu_shader5
    // * EXT_primitive_bounding_box
    // * EXT_shader_io_blocks
    // * EXT_tessellation_shader
    // * EXT_texture_border_clamp
    // * EXT_texture_buffer
    // * EXT_texture_cube_map_array
    // * EXT_texture_sRGB_decode
    std::pair<const char *, bool> requirements[] = {
        {"version >= ES_3_1", version >= ES_3_1},
        {"extensions.debugKHR", extensions.debugKHR},
        {"extensions.textureCompressionAstcLdrKHR", extensions.textureCompressionAstcLdrKHR},
        {"extensions.blendEquationAdvancedKHR", extensions.blendEquationAdvancedKHR},
        {"extensions.sampleShadingOES", extensions.sampleShadingOES},
        {"extensions.sampleVariablesOES", extensions.sampleVariablesOES},
        {"extensions.shaderImageAtomicOES", extensions.shaderImageAtomicOES},
        {"extensions.shaderMultisampleInterpolationOES",
         extensions.shaderMultisampleInterpolationOES},
        {"extensions.textureStencil8OES", extensions.textureStencil8OES},
        {"extensions.textureStorageMultisample2dArrayOES",
         extensions.textureStorageMultisample2dArrayOES},
        {"extensions.copyImageEXT", extensions.copyImageEXT},
        {"extensions.drawBuffersIndexedEXT", extensions.drawBuffersIndexedEXT},
        {"extensions.geometryShaderEXT", extensions.geometryShaderEXT},
        {"extensions.gpuShader5EXT", extensions.gpuShader5EXT},
        {"extensions.primitiveBoundingBoxEXT", extensions.primitiveBoundingBoxEXT},
        {"extensions.shaderIoBlocksEXT", extensions.shaderIoBlocksEXT},
        {"extensions.tessellationShaderEXT", extensions.tessellationShaderEXT},
        {"extensions.textureBorderClampEXT", extensions.textureBorderClampEXT},
        {"extensions.textureBufferEXT", extensions.textureBufferEXT},
        {"extensions.textureCubeMapArrayEXT", extensions.textureCubeMapArrayEXT},
        {"extensions.textureSRGBDecodeEXT", extensions.textureSRGBDecodeEXT},
    };

    bool result = true;
    for (const auto &req : requirements)
    {
        result = result && req.second;
    }

    if (kEnableAEPRequirementLogging && !result)
    {
        INFO() << "CanSupportAEP() check failed for missing the following requirements:\n";
        for (const auto &req : requirements)
        {
            if (!req.second)
            {
                INFO() << "- " << req.first << "\n";
            }
        }
    }

    return result;
}

// Temporarily turns off draw buffers being used for pixel local storage, and only if the PLS
// implementation is framebuffer fetch.
//
// NOTE: This is a little nonstandard because the glDrawBuffers entrypoint is supposed to disable
// PLS, but since we only call it when the implementation is
// ShPixelLocalStorageType::FramebufferFetch, it's not a problem.
class ScopedPLSFramebufferFetchDrawBuffersDisable
{
  public:
    ScopedPLSFramebufferFetchDrawBuffersDisable(Context *context) : mContext(context)
    {
        GLsizei nonPLSDrawBufferCount;
        if (mContext->getImplementation()->getNativePixelLocalStorageOptions().type ==
                ShPixelLocalStorageType::FramebufferFetch &&
            mContext->getPrivateState().hasActivelyOverriddenPLSDrawBuffers(&nonPLSDrawBufferCount))
        {
            // Turn off the PLS draw buffers.
            mHasPLSDrawBuffersWithFramebufferFetch = true;
            Framebuffer *drawFramebuffer           = mContext->getState().getDrawFramebuffer();
            // PLS isn't supported on the default framebuffer.
            ASSERT(!drawFramebuffer->isDefault());
            const DrawBuffersVector<GLenum> &drawBuffers = drawFramebuffer->getDrawBufferStates();
            ASSERT(drawBuffers.size() <= std::size(mOriginalDrawBufferState));
            std::copy(drawBuffers.begin(), drawBuffers.end(), mOriginalDrawBufferState.data());
            mOriginalDrawBufferCount = static_cast<GLsizei>(drawBuffers.size());
            // Turn off all non-PLS draw buffers.
            mContext->drawBuffers(std::min(mOriginalDrawBufferCount, nonPLSDrawBufferCount),
                                  mOriginalDrawBufferState.data());
        }
    }

    ~ScopedPLSFramebufferFetchDrawBuffersDisable()
    {
        if (mHasPLSDrawBuffersWithFramebufferFetch)
        {
            // Restore the PLS draw buffers.
            mContext->drawBuffers(mOriginalDrawBufferCount, mOriginalDrawBufferState.data());
        }
    }

  private:
    Context *const mContext;
    bool mHasPLSDrawBuffersWithFramebufferFetch = false;
    std::array<GLenum, IMPLEMENTATION_MAX_DRAW_BUFFERS> mOriginalDrawBufferState;
    GLsizei mOriginalDrawBufferCount;
};
}  // anonymous namespace

#if defined(ANGLE_PLATFORM_APPLE)
// TODO(http://anglebug.com/42264979): Due to a bug in Apple's dyld loader, `thread_local` will
// cause excessive memory use. Temporarily avoid it by using pthread's thread local storage instead.
static angle::TLSIndex GetCurrentValidContextTLSIndex()
{
    static angle::TLSIndex CurrentValidContextIndex = TLS_INVALID_INDEX;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
      ASSERT(CurrentValidContextIndex == TLS_INVALID_INDEX);
      CurrentValidContextIndex = angle::CreateTLSIndex(nullptr);
    });
    return CurrentValidContextIndex;
}
Context *GetCurrentValidContextTLS()
{
    angle::TLSIndex CurrentValidContextIndex = GetCurrentValidContextTLSIndex();
    ASSERT(CurrentValidContextIndex != TLS_INVALID_INDEX);
    return static_cast<Context *>(angle::GetTLSValue(CurrentValidContextIndex));
}
void SetCurrentValidContextTLS(Context *context)
{
    angle::TLSIndex CurrentValidContextIndex = GetCurrentValidContextTLSIndex();
    ASSERT(CurrentValidContextIndex != TLS_INVALID_INDEX);
    angle::SetTLSValue(CurrentValidContextIndex, context);
}
#elif defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
static thread_local Context *gCurrentValidContext = nullptr;
Context *GetCurrentValidContextTLS()
{
    return gCurrentValidContext;
}
void SetCurrentValidContextTLS(Context *context)
{
    gCurrentValidContext = context;
}
#else
thread_local Context *gCurrentValidContext = nullptr;
#endif

// Handle setting the current context in TLS on different platforms
extern void SetCurrentValidContext(Context *context)
{
#if defined(ANGLE_USE_ANDROID_TLS_SLOT)
    if (angle::gUseAndroidOpenGLTlsSlot)
    {
        ANGLE_ANDROID_GET_GL_TLS()[angle::kAndroidOpenGLTlsSlot] = static_cast<void *>(context);
        return;
    }
#endif

#if defined(ANGLE_PLATFORM_APPLE) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
    SetCurrentValidContextTLS(context);
#else
    gCurrentValidContext = context;
#endif
}

Context::Context(egl::Display *display,
                 const egl::Config *config,
                 const Context *shareContext,
                 TextureManager *shareTextures,
                 SemaphoreManager *shareSemaphores,
                 egl::ContextMutex *sharedContextMutex,
                 MemoryProgramCache *memoryProgramCache,
                 MemoryShaderCache *memoryShaderCache,
                 const egl::AttributeMap &attribs,
                 const egl::DisplayExtensions &displayExtensions,
                 const egl::ClientExtensions &clientExtensions)
    : mState(shareContext ? &shareContext->mState : nullptr,
             AllocateOrGetShareGroup(display, shareContext),
             shareTextures,
             shareSemaphores,
             AllocateOrUseContextMutex(sharedContextMutex),
             GetClientVersion(display, attribs),
             GetDebug(display->getFrontendFeatures(), attribs),
             GetBindGeneratesResource(attribs),
             GetClientArraysEnabled(attribs),
             GetRobustResourceInit(display, attribs),
             memoryProgramCache != nullptr,
             GetContextPriority(attribs),
             GetRobustAccess(attribs),
             GetProtectedContent(attribs),
             GetIsExternal(attribs),
             GetPassthroughShaders(display, attribs)),
      mShared(shareContext != nullptr || shareTextures != nullptr || shareSemaphores != nullptr),
      mSharedContext(shareContext != nullptr),
      mDisplayTextureShareGroup(shareTextures != nullptr),
      mDisplaySemaphoreShareGroup(shareSemaphores != nullptr),
      mErrors(&mState.getDebug(), display->getFrontendFeatures(), attribs),
      mImplementation(display->getImplementation()
                          ->createContext(mState, &mErrors, config, shareContext, attribs)),
      mLabel(nullptr),
      mCompiler(),
      mConfig(config),
      mFenceNVHandleAllocator(IMPLEMENTATION_MAX_OBJECT_HANDLES),
      mQueryHandleAllocator(IMPLEMENTATION_MAX_OBJECT_HANDLES),
      mTransformFeedbackHandleAllocator(IMPLEMENTATION_MAX_OBJECT_HANDLES),
      mHasBeenCurrent(false),
      mSurfacelessSupported(displayExtensions.surfacelessContext),
      mCurrentDrawSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
      mCurrentReadSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
      mDisplay(display),
      mWebGLContext(GetWebGLContext(attribs)),
      mHardenedContext(mWebGLContext || GetHardenedContext(attribs)),
      mBufferAccessValidationEnabled(false),
      mRequiresRobustBehavior(false),
      mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)),
      mMemoryProgramCache(memoryProgramCache),
      mMemoryShaderCache(memoryShaderCache),
      mVertexArrayObserverBinding(this, kVertexArraySubjectIndex),
      mDrawFramebufferObserverBinding(this, kDrawFramebufferSubjectIndex),
      mReadFramebufferObserverBinding(this, kReadFramebufferSubjectIndex),
      mProgramObserverBinding(this, kProgramSubjectIndex),
      mProgramPipelineObserverBinding(this, kProgramPipelineSubjectIndex),
      mFrameCapture(new angle::FrameCapture),
      mRefCount(0),
      mIsDestroyed(false),
      mDestroyedManagers(false)
{
    for (angle::SubjectIndex uboIndex = kUniformBuffer0SubjectIndex;
         uboIndex < kUniformBufferMaxSubjectIndex; ++uboIndex)
    {
        mUniformBufferObserverBindings.emplace_back(this, uboIndex);
    }

    for (angle::SubjectIndex acbIndex = kAtomicCounterBuffer0SubjectIndex;
         acbIndex < kAtomicCounterBufferMaxSubjectIndex; ++acbIndex)
    {
        mAtomicCounterBufferObserverBindings.emplace_back(this, acbIndex);
    }

    for (angle::SubjectIndex ssboIndex = kShaderStorageBuffer0SubjectIndex;
         ssboIndex < kShaderStorageBufferMaxSubjectIndex; ++ssboIndex)
    {
        mShaderStorageBufferObserverBindings.emplace_back(this, ssboIndex);
    }

    for (angle::SubjectIndex samplerIndex = kSampler0SubjectIndex;
         samplerIndex < kSamplerMaxSubjectIndex; ++samplerIndex)
    {
        mSamplerObserverBindings.emplace_back(this, samplerIndex);
    }

    for (angle::SubjectIndex imageIndex = kImage0SubjectIndex; imageIndex < kImageMaxSubjectIndex;
         ++imageIndex)
    {
        mImageObserverBindings.emplace_back(this, imageIndex);
    }

    // Implementations now require the display to be set at context creation.
    ASSERT(mDisplay);
}

egl::Error Context::initialize()
{
    if (!mImplementation)
    {
        return egl::Error(EGL_NOT_INITIALIZED, "native context creation failed");
    }

    // If the final context version created (with backwards compatibility possibly added in),
    // generate an error if it's higher than the maximum supported version for the display. This
    // validation is always done even with EGL validation disabled because it's not possible to
    // detect ahead of time if an ES 3.1 context is supported (no ES_31_BIT) or if
    // KHR_no_config_context is used.
    if (getClientVersion() > getDisplay()->getMaxSupportedESVersion())
    {
        return egl::Error(EGL_BAD_ATTRIBUTE, "Requested version is not supported");
    }

    return egl::NoError();
}

void Context::initializeDefaultResources()
{
    mImplementation->setMemoryProgramCache(mMemoryProgramCache);

    initCaps();

    mState.initialize(this);

    mDefaultFramebuffer = std::make_unique<Framebuffer>(this, mImplementation.get());

    // [OpenGL ES 2.0.24] section 3.7 page 83:
    // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have two-dimensional
    // and cube map texture state vectors respectively associated with them.
    // In order that access to these initial textures not be lost, they are treated as texture
    // objects all of whose names are 0.

    Texture *zeroTexture2D = new Texture(mImplementation.get(), {0}, TextureType::_2D);
    mZeroTextures[TextureType::_2D].set(this, zeroTexture2D);

    Texture *zeroTextureCube = new Texture(mImplementation.get(), {0}, TextureType::CubeMap);
    mZeroTextures[TextureType::CubeMap].set(this, zeroTextureCube);

    if (getClientVersion() >= Version(3, 0) || mSupportedExtensions.texture3DOES)
    {
        Texture *zeroTexture3D = new Texture(mImplementation.get(), {0}, TextureType::_3D);
        mZeroTextures[TextureType::_3D].set(this, zeroTexture3D);
    }
    if (getClientVersion() >= Version(3, 0))
    {
        Texture *zeroTexture2DArray =
            new Texture(mImplementation.get(), {0}, TextureType::_2DArray);
        mZeroTextures[TextureType::_2DArray].set(this, zeroTexture2DArray);
    }
    if (getClientVersion() >= Version(3, 1) || mSupportedExtensions.textureMultisampleANGLE)
    {
        Texture *zeroTexture2DMultisample =
            new Texture(mImplementation.get(), {0}, TextureType::_2DMultisample);
        mZeroTextures[TextureType::_2DMultisample].set(this, zeroTexture2DMultisample);
    }
    if (getClientVersion() >= Version(3, 2) ||
        mSupportedExtensions.textureStorageMultisample2dArrayOES)
    {
        Texture *zeroTexture2DMultisampleArray =
            new Texture(mImplementation.get(), {0}, TextureType::_2DMultisampleArray);
        mZeroTextures[TextureType::_2DMultisampleArray].set(this, zeroTexture2DMultisampleArray);
    }

    if (getClientVersion() >= Version(3, 1))
    {
        for (int i = 0; i < mState.getCaps().maxAtomicCounterBufferBindings; i++)
        {
            bindBufferRange(BufferBinding::AtomicCounter, i, {0}, 0, 0);
        }

        for (int i = 0; i < mState.getCaps().maxShaderStorageBufferBindings; i++)
        {
            bindBufferRange(BufferBinding::ShaderStorage, i, {0}, 0, 0);
        }
    }

    if (getClientVersion() >= Version(3, 2) || mSupportedExtensions.textureCubeMapArrayAny())
    {
        Texture *zeroTextureCubeMapArray =
            new Texture(mImplementation.get(), {0}, TextureType::CubeMapArray);
        mZeroTextures[TextureType::CubeMapArray].set(this, zeroTextureCubeMapArray);
    }

    if (getClientVersion() >= Version(3, 2) || mSupportedExtensions.textureBufferAny())
    {
        Texture *zeroTextureBuffer = new Texture(mImplementation.get(), {0}, TextureType::Buffer);
        mZeroTextures[TextureType::Buffer].set(this, zeroTextureBuffer);
    }

    if (mSupportedExtensions.textureRectangleANGLE)
    {
        Texture *zeroTextureRectangle =
            new Texture(mImplementation.get(), {0}, TextureType::Rectangle);
        mZeroTextures[TextureType::Rectangle].set(this, zeroTextureRectangle);
    }

    if (mSupportedExtensions.EGLImageExternalOES ||
        mSupportedExtensions.EGLStreamConsumerExternalNV)
    {
        Texture *zeroTextureExternal =
            new Texture(mImplementation.get(), {0}, TextureType::External);
        mZeroTextures[TextureType::External].set(this, zeroTextureExternal);
    }

    mState.initializeZeroTextures(this, mZeroTextures);

    ANGLE_CONTEXT_TRY(mImplementation->initialize(mDisplay->getImageLoadContext()));

    // Add context into the share group
    mState.getShareGroup()->addSharedContext(this);

    bindVertexArray({0});

    if (getClientVersion() >= Version(3, 0))
    {
        // [OpenGL ES 3.0.2] section 2.14.1 pg 85:
        // In the initial state, a default transform feedback object is bound and treated as
        // a transform feedback object with a name of zero. That object is bound any time
        // BindTransformFeedback is called with id of zero
        bindTransformFeedback(GL_TRANSFORM_FEEDBACK, {0});
    }

    for (auto type : angle::AllEnums<BufferBinding>())
    {
        bindBuffer(type, {0});
    }

    bindRenderbuffer(GL_RENDERBUFFER, {0});

    for (int i = 0; i < mState.getCaps().maxUniformBufferBindings; i++)
    {
        bindBufferRange(BufferBinding::Uniform, i, {0}, 0, 0);
    }

    // Initialize GLES1 renderer if appropriate.
    if (getClientVersion() < Version(2, 0))
    {
        mGLES1Renderer.reset(new GLES1Renderer());
    }

    // Initialize dirty bit masks (in addition to what updateCaps() might have set up).
    mDrawDirtyObjects |= kDrawDirtyObjectsBase;
    mTexImageDirtyObjects |= kTexImageDirtyObjects;
    mReadPixelsDirtyObjects |= kReadPixelsDirtyObjectsBase;
    mClearDirtyObjects |= kClearDirtyObjects;
    mBlitDirtyObjects |= kBlitDirtyObjectsBase;
    mComputeDirtyObjects |= kComputeDirtyObjectsBase;
    mCopyImageDirtyBits |= kCopyImageDirtyBitsBase;
    mCopyImageDirtyObjects |= kCopyImageDirtyObjectsBase;
    mTilingDirtyObjects |= kTilingDirtyObjectsBase;
}

egl::Error Context::onDestroy(const egl::Display *display)
{
    if (!mHasBeenCurrent)
    {
        // Shared objects and ShareGroup must be released regardless.
        releaseSharedObjects();
        mState.mShareGroup->release(display);
        // The context is never current, so default resources are not allocated.
        return egl::NoError();
    }

    mState.ensureNoPendingLink(this);

    // eglDestoryContext() must have been called for this Context and there must not be any Threads
    // that still have it current.
    ASSERT(mIsDestroyed == true && mRefCount == 0);

    ANGLE_TRY(unMakeCurrent(display));

    // Dump frame capture if enabled.
    getShareGroup()->getFrameCaptureShared()->onDestroyContext(this);

    // Remove context from the capture share group
    getShareGroup()->removeSharedContext(this);

    if (mGLES1Renderer)
    {
        mGLES1Renderer->onDestroy(this, &mState);
    }

    mDefaultFramebuffer->onDestroy(this);
    mDefaultFramebuffer.reset();

    for (auto fence : UnsafeResourceMapIter(mFenceNVMap))
    {
        if (fence.second)
        {
            fence.second->onDestroy(this);
        }
        SafeDelete(fence.second);
    }
    mFenceNVMap.clear();

    for (auto query : UnsafeResourceMapIter(mQueryMap))
    {
        if (query.second != nullptr)
        {
            query.second->release(this);
        }
    }
    mQueryMap.clear();

    for (auto vertexArray : UnsafeResourceMapIter(getPrivateState().getVertexArrayMap()))
    {
        if (vertexArray.second)
        {
            vertexArray.second->onDestroy(this);
        }
    }

    for (auto transformFeedback : UnsafeResourceMapIter(mTransformFeedbackMap))
    {
        if (transformFeedback.second != nullptr)
        {
            transformFeedback.second->release(this);
        }
    }
    mTransformFeedbackMap.clear();

    for (BindingPointer<Texture> &zeroTexture : mZeroTextures)
    {
        if (zeroTexture.get() != nullptr)
        {
            zeroTexture.set(this, nullptr);
        }
    }

    releaseShaderCompiler();

    mState.reset(this);

    releaseSharedObjects();

    mImplementation->onDestroy(this);

    // Backend requires implementation to be destroyed first to close down all the objects
    mState.mShareGroup->release(display);

    return egl::NoError();
}

void Context::releaseSharedObjects()
{
    mDestroyedManagers = true;

    mState.mBufferManager->release(this);
    mState.mBufferManager = nullptr;

    // mProgramPipelineManager must be before mShaderProgramManager to give each
    // PPO the chance to release any references they have to the Programs that
    // are bound to them before the Programs are released()'ed.
    mState.mProgramPipelineManager->release(this);
    mState.mProgramPipelineManager = nullptr;

    mState.mShaderProgramManager->release(this);
    mState.mShaderProgramManager = nullptr;

    mState.mTextureManager->release(this);
    mState.mTextureManager = nullptr;

    mState.mRenderbufferManager->release(this);
    mState.mRenderbufferManager = nullptr;

    mState.mSamplerManager->release(this);
    mState.mSamplerManager = nullptr;

    mState.mSyncManager->release(this);
    mState.mSyncManager = nullptr;

    mState.mFramebufferManager->release(this);
    mState.mFramebufferManager = nullptr;

    mState.mMemoryObjectManager->release(this);
    mState.mMemoryObjectManager = nullptr;

    mState.mSemaphoreManager->release(this);
    mState.mSemaphoreManager = nullptr;
}

Context::~Context() {}

void Context::setLabel(EGLLabelKHR label)
{
    mLabel = label;
}

EGLLabelKHR Context::getLabel() const
{
    return mLabel;
}

egl::Error Context::makeCurrent(egl::Display *display,
                                egl::Surface *drawSurface,
                                egl::Surface *readSurface)
{
    mDisplay = display;

    EGLint width  = 0;
    EGLint height = 0;

    angle::FrameCaptureShared *frameCaptureShared = getShareGroup()->getFrameCaptureShared();
    if ((frameCaptureShared->enabled() || !mHasBeenCurrent) && drawSurface != nullptr)
    {
        ANGLE_TRY(drawSurface->getUserSize(display, &width, &height));
    }

    if (!mHasBeenCurrent)
    {
        initializeDefaultResources();
        initRendererString();
        initVendorString();
        initVersionStrings();
        initExtensionStrings();

        ContextPrivateViewport(getMutablePrivateState(), getMutablePrivateStateCache(), 0, 0, width,
                               height);
        ContextPrivateScissor(getMutablePrivateState(), getMutablePrivateStateCache(), 0, 0, width,
                              height);

        mHasBeenCurrent = true;
    }

    ANGLE_TRY(unsetDefaultFramebuffer());

    frameCaptureShared->onMakeCurrent(this, drawSurface, width, height);

    // TODO(jmadill): Rework this when we support ContextImpl
    mState.setAllDirtyBits();
    mState.setAllDirtyObjects();

    ANGLE_TRY(setDefaultFramebuffer(drawSurface, readSurface));

    // Notify the renderer of a context switch.
    angle::Result implResult = mImplementation->onMakeCurrent(this);

    // If the implementation fails onMakeCurrent, unset the default framebuffer.
    if (implResult != angle::Result::Continue)
    {
        ANGLE_TRY(unsetDefaultFramebuffer());
        return angle::ResultToEGL(implResult);
    }

    return egl::NoError();
}

egl::Error Context::unMakeCurrent(const egl::Display *display)
{
    ANGLE_TRY(angle::ResultToEGL(mImplementation->onUnMakeCurrent(this)));

    ANGLE_TRY(unsetDefaultFramebuffer());

    // Return the scratch buffers to the display so they can be shared with other contexts while
    // this one is not current.
    if (mScratchBuffer.valid())
    {
        mDisplay->returnScratchBuffer(mScratchBuffer.release());
    }
    if (mZeroFilledBuffer.valid())
    {
        mDisplay->returnZeroFilledBuffer(mZeroFilledBuffer.release());
    }

    return egl::NoError();
}

void Context::contextLostErrorOnBlockingCall(angle::EntryPoint entryPoint) const
{
    mErrors.validationError(entryPoint, GL_CONTEXT_LOST, err::kContextLost);
}

void Context::handleExhaustionError(angle::EntryPoint entryPoint)
{
    mErrors.validationError(entryPoint, GL_OUT_OF_MEMORY, err::kHandleExhaustion);
}

bool Context::createBuffer(BufferID *outBuffer)
{
    return mState.mBufferManager->createBuffer(outBuffer);
}

GLuint Context::createProgram()
{
    ShaderProgramID id;
    if (!mState.mShaderProgramManager->createProgram(mImplementation.get(), &id))
    {
        handleExhaustionError(angle::EntryPoint::GLCreateProgram);
        return 0;
    }
    return id.value;
}

GLuint Context::createShader(ShaderType type)
{
    ShaderProgramID id;
    if (!mState.mShaderProgramManager->createShader(mImplementation.get(), mState.getLimitations(),
                                                    type, &id))
    {
        handleExhaustionError(angle::EntryPoint::GLCreateShader);
        return 0;
    }
    return id.value;
}

bool Context::createTexture(TextureID *outTexture)
{
    return mState.mTextureManager->createTexture(outTexture);
}

bool Context::createRenderbuffer(RenderbufferID *outRenderbuffer)
{
    return mState.mRenderbufferManager->createRenderbuffer(outRenderbuffer);
}

// Returns an unused framebuffer name
bool Context::createFramebuffer(FramebufferID *outFramebuffer)
{
    return mState.mFramebufferManager->createFramebuffer(outFramebuffer);
}

void Context::genFencesNV(GLsizei n, FenceNVID *fences)
{
    for (int i = 0; i < n; i++)
    {
        if (!mFenceNVHandleAllocator.allocate(&fences[i].value))
        {
            handleExhaustionError(angle::EntryPoint::GLGenFencesNV);
            return;
        }
        mFenceNVMap.assign(fences[i], new FenceNV(mImplementation.get()));
    }
}

bool Context::createProgramPipeline(ProgramPipelineID *outProgramPipeline)
{
    return mState.mProgramPipelineManager->createProgramPipeline(outProgramPipeline);
}

GLuint Context::createShaderProgramv(ShaderType type, GLsizei count, const GLchar *const *strings)
{
    const ShaderProgramID shaderID = PackParam<ShaderProgramID>(createShader(type));
    if (shaderID.value)
    {
        Shader *shaderObject = getShaderNoResolveCompile(shaderID);
        ASSERT(shaderObject);
        shaderObject->setSource(this, count, strings, nullptr);
        shaderObject->compile(this, angle::JobResultExpectancy::Immediate);
        const ShaderProgramID programID = PackParam<ShaderProgramID>(createProgram());
        if (programID.value)
        {
            gl::Program *programObject = getProgramNoResolveLink(programID);
            ASSERT(programObject);

            // Note: this call serializes the compilation with the following link.  For backends
            // that prefer parallel compile and link, it's more efficient to remove this check, and
            // let link fail instead.
            if (shaderObject->isCompiled(this))
            {
                // As per Khronos issue 2261:
                // https://gitlab.khronos.org/Tracker/vk-gl-cts/issues/2261
                // We must wait to mark the program separable until it's successfully compiled.
                programObject->setSeparable(this, true);

                programObject->attachShader(this, shaderObject);

                // Note: the result expectancy of this link could be turned to Future if
                // |detachShader| below is made not to resolve the link.
                if (programObject->link(this, angle::JobResultExpectancy::Immediate) !=
                    angle::Result::Continue)
                {
                    deleteShader(shaderID);
                    deleteProgram(programID);
                    return 0u;
                }

                programObject->detachShader(this, shaderObject);
            }

            InfoLog &programInfoLog = programObject->getInfoLog();
            programInfoLog << shaderObject->getInfoLogString();
        }

        deleteShader(shaderID);

        return programID.value;
    }

    return 0u;
}

bool Context::createMemoryObject(MemoryObjectID *outMemoryObject)
{
    return mState.mMemoryObjectManager->createMemoryObject(mImplementation.get(), outMemoryObject);
}

bool Context::createSemaphore(SemaphoreID *outSemaphore)
{
    return mState.mSemaphoreManager->createSemaphore(mImplementation.get(), outSemaphore);
}

void Context::deleteBuffer(BufferID bufferName)
{
    Buffer *buffer = mState.mBufferManager->getBuffer(bufferName);
    if (buffer)
    {
        detachBuffer(buffer);
    }

    mState.mBufferManager->deleteObject(this, bufferName);
}

bool Context::canProtectCoherentMemoryDirectly()
{
    BufferID bufferId;
    if (!createBuffer(&bufferId))
    {
        ERR() << "Failed to allocate buffer ID.";
        return false;
    }

    // Allocate 2 pages so we will always have a full aligned page to protect
    size_t pageSize = angle::GetPageSize();
    GLsizei size    = static_cast<GLsizei>(pageSize * 2);

    Buffer *buffer = mState.mBufferManager->checkBufferAllocation(mImplementation.get(), bufferId);
    if (!buffer)
    {
        ERR() << "Failed to get buffer object.";
        deleteBuffer(bufferId);
        return false;
    }

    if (buffer->bufferStorage(this, BufferBinding::Array, size, nullptr,
                              GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT |
                                  GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT) !=
        angle::Result::Continue)
    {
        ERR() << "Failed to allocate buffer storage.";
        deleteBuffer(bufferId);
        return false;
    }

    if (buffer->mapRange(this, 0, size,
                         GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT) !=
        angle::Result::Continue)
    {
        ERR() << "Failed to mapRange of buffer.";
        deleteBuffer(bufferId);
        return false;
    }

    void *map = buffer->getMapPointer();
    if (map == nullptr)
    {
        ERR() << "Failed to getMapPointer of buffer.";
        GLboolean unmapResult;
        (void)buffer->unmap(this, &unmapResult);
        deleteBuffer(bufferId);
        return false;
    }

    // Test mprotect
    auto start = reinterpret_cast<uintptr_t>(map);

    // Only protect a whole page inside the allocated memory
    uintptr_t protectionStart = rx::roundUpPow2(start, pageSize);
    uintptr_t protectionEnd   = protectionStart + pageSize;

    ASSERT(protectionStart < protectionEnd);

    angle::PageFaultCallback callback = [](uintptr_t address) {
        return angle::PageFaultHandlerRangeType::InRange;
    };

    std::unique_ptr<angle::PageFaultHandler> handler(angle::CreatePageFaultHandler(callback));

    if (!handler->enable())
    {
        GLboolean unmapResult;
        if (buffer->unmap(this, &unmapResult) != angle::Result::Continue)
        {
            ERR() << "Could not unmap buffer.";
        }
        deleteBuffer(bufferId);
        return false;
    }

    size_t protectionSize = protectionEnd - protectionStart;
    ASSERT(protectionSize == pageSize);

    bool canProtect = angle::ProtectMemory(protectionStart, protectionSize);
    if (canProtect)
    {
        angle::UnprotectMemory(protectionStart, protectionSize);
    }

    // Clean up
    handler->disable();

    GLboolean unmapResult;
    if (buffer->unmap(this, &unmapResult) != angle::Result::Continue)
    {
        ERR() << "Could not unmap buffer.";
    }
    deleteBuffer(bufferId);

    return canProtect;
}

void Context::deleteShader(ShaderProgramID shader)
{
    mState.mShaderProgramManager->deleteShader(this, shader);
}

void Context::deleteProgram(ShaderProgramID program)
{
    mState.mShaderProgramManager->deleteProgram(this, program);
}

void Context::deleteTexture(TextureID textureID)
{
    if (mState.isTextureBoundToActivePLS(textureID))
    {
        // If a texture object is deleted while its image is bound to a pixel local storage plane on
        // the currently bound draw framebuffer, and pixel local storage is active, then it is as if
        // EndPixelLocalStorageANGLE() had been called with
        // <n>=PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE and <storeops> of STORE_OP_STORE_ANGLE.
        endPixelLocalStorageImplicit();
    }

    Texture *texture = mState.mTextureManager->getTexture(textureID);
    if (texture != nullptr)
    {
        texture->onStateChange(angle::SubjectMessage::TextureIDDeleted);
        detachTexture(textureID);
    }

    mState.mTextureManager->deleteObject(this, textureID);
}

void Context::deleteRenderbuffer(RenderbufferID renderbuffer)
{
    if (mState.mRenderbufferManager->getRenderbuffer(renderbuffer))
    {
        detachRenderbuffer(renderbuffer);
    }

    mState.mRenderbufferManager->deleteObject(this, renderbuffer);
}

void Context::deleteSync(SyncID syncPacked)
{
    // The spec specifies the underlying Fence object is not deleted until all current
    // wait commands finish. However, since the name becomes invalid, we cannot query the fence,
    // and since our API is currently designed for being called from a single thread, we can delete
    // the fence immediately.
    mState.mSyncManager->deleteObject(this, syncPacked);
}

void Context::deleteProgramPipeline(ProgramPipelineID pipelineID)
{
    ProgramPipeline *pipeline = mState.mProgramPipelineManager->getProgramPipeline(pipelineID);
    if (pipeline)
    {
        detachProgramPipeline(pipelineID);
    }

    mState.mProgramPipelineManager->deleteObject(this, pipelineID);
}

void Context::deleteMemoryObject(MemoryObjectID memoryObject)
{
    mState.mMemoryObjectManager->deleteMemoryObject(this, memoryObject);
}

void Context::deleteSemaphore(SemaphoreID semaphore)
{
    mState.mSemaphoreManager->deleteSemaphore(this, semaphore);
}

// GL_CHROMIUM_lose_context
void Context::loseContext(GraphicsResetStatus current, GraphicsResetStatus other)
{
    // TODO(geofflang): mark the rest of the share group lost. Requires access to the entire share
    // group from a context. http://anglebug.com/42262046
    markContextLost(current);
}

void Context::deleteFramebuffer(FramebufferID framebufferID)
{
    // We are responsible for deleting the GL objects from the Framebuffer's pixel local storage.
    std::unique_ptr<PixelLocalStorage> plsToDelete;

    Framebuffer *framebuffer = mState.mFramebufferManager->getFramebuffer(framebufferID);
    if (framebuffer != nullptr)
    {
        if (mState.getPixelLocalStorageActivePlanes() != 0 &&
            framebuffer == mState.getDrawFramebuffer())
        {
            endPixelLocalStorageImplicit();
        }
        plsToDelete = framebuffer->detachPixelLocalStorage();
        detachFramebuffer(framebufferID);
    }

    mState.mFramebufferManager->deleteObject(this, framebufferID);

    // Delete the pixel local storage GL objects after the framebuffer, in order to avoid any
    // potential trickyness with orphaning.
    if (plsToDelete != nullptr)
    {
        plsToDelete->deleteContextObjects(this);
    }
}

void Context::deleteFencesNV(GLsizei n, const FenceNVID *fences)
{
    for (int i = 0; i < n; i++)
    {
        FenceNVID fence = fences[i];

        FenceNV *fenceObject = nullptr;
        if (mFenceNVMap.erase(fence, &fenceObject))
        {
            mFenceNVHandleAllocator.release(fence.value);
            if (fenceObject)
            {
                fenceObject->onDestroy(this);
            }
            delete fenceObject;
        }
    }
}

Buffer *Context::getBuffer(BufferID handle) const
{
    return mState.mBufferManager->getBuffer(handle);
}

Renderbuffer *Context::getRenderbuffer(RenderbufferID handle) const
{
    return mState.mRenderbufferManager->getRenderbuffer(handle);
}

EGLenum Context::getContextPriority() const
{
    return egl::ToEGLenum(mImplementation->getContextPriority());
}

Sync *Context::getSync(SyncID syncPacked) const
{
    return mState.mSyncManager->getSync(syncPacked);
}

Sampler *Context::getSampler(SamplerID handle) const
{
    return mState.mSamplerManager->getSampler(handle);
}

TransformFeedback *Context::getTransformFeedback(TransformFeedbackID handle) const
{
    return mTransformFeedbackMap.query(handle);
}

ProgramPipeline *Context::getProgramPipeline(ProgramPipelineID handle) const
{
    return mState.mProgramPipelineManager->getProgramPipeline(handle);
}

gl::LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
{
    switch (identifier)
    {
        case GL_BUFFER:
        case GL_BUFFER_OBJECT_EXT:
            return getBuffer({name});
        case GL_SHADER:
        case GL_SHADER_OBJECT_EXT:
            return getShaderNoResolveCompile({name});
        case GL_PROGRAM:
        case GL_PROGRAM_OBJECT_EXT:
            return getProgramNoResolveLink({name});
        case GL_VERTEX_ARRAY:
        case GL_VERTEX_ARRAY_OBJECT_EXT:
            return getPrivateState().getVertexArray({name});
        case GL_QUERY:
        case GL_QUERY_OBJECT_EXT:
            return getQuery({name});
        case GL_TRANSFORM_FEEDBACK:
            return getTransformFeedback({name});
        case GL_SAMPLER:
            return getSampler({name});
        case GL_TEXTURE:
            return getTexture({name});
        case GL_RENDERBUFFER:
            return getRenderbuffer({name});
        case GL_FRAMEBUFFER:
            return getFramebuffer({name});
        case GL_PROGRAM_PIPELINE:
        case GL_PROGRAM_PIPELINE_OBJECT_EXT:
            return getProgramPipeline({name});
        default:
            UNREACHABLE();
            return nullptr;
    }
}

gl::LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
{
    return getSync({unsafe_pointer_to_int_cast<uint32_t>(ptr)});
}

void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
{
    gl::LabeledObject *object = getLabeledObject(identifier, name);
    ASSERT(object != nullptr);

    std::string labelName = GetObjectLabelFromPointer(length, label);
    ANGLE_CONTEXT_TRY(object->setLabel(this, labelName));

    // TODO(jmadill): Determine if the object is dirty based on 'name'. Conservatively assume the
    // specified object is active until we do this.
    mState.setObjectDirty(identifier);
}

void Context::labelObject(GLenum type, GLuint object, GLsizei length, const GLchar *label)
{
    gl::LabeledObject *obj = getLabeledObject(type, object);
    ASSERT(obj != nullptr);

    std::string labelName = "";
    if (label != nullptr)
    {
        size_t labelLength = length == 0 ? strlen(label) : length;
        labelName          = std::string(label, labelLength);
    }
    ANGLE_CONTEXT_TRY(obj->setLabel(this, labelName));
    mState.setObjectDirty(type);
}

void Context::objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
{
    gl::LabeledObject *object = getLabeledObjectFromPtr(ptr);
    ASSERT(object != nullptr);

    std::string labelName = GetObjectLabelFromPointer(length, label);
    ANGLE_CONTEXT_TRY(object->setLabel(this, labelName));
}

void Context::getObjectLabel(GLenum identifier,
                             GLuint name,
                             GLsizei bufSize,
                             GLsizei *length,
                             GLchar *label)
{
    gl::LabeledObject *object = getLabeledObject(identifier, name);
    ASSERT(object != nullptr);

    const std::string &objectLabel = object->getLabel();
    GetObjectLabelBase(objectLabel, bufSize, length, label);
}

void Context::getObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label)
{
    gl::LabeledObject *object = getLabeledObjectFromPtr(ptr);
    ASSERT(object != nullptr);

    const std::string &objectLabel = object->getLabel();
    GetObjectLabelBase(objectLabel, bufSize, length, label);
}

GLboolean Context::isSampler(SamplerID samplerName) const
{
    return mState.mSamplerManager->isSampler(samplerName);
}

void Context::bindTexture(TextureType target, TextureID handle)
{
    // Some apps enable KHR_create_context_no_error but pass in an invalid texture type.
    // Workaround this by silently returning in such situations.
    if (target == TextureType::InvalidEnum)
    {
        return;
    }

    Texture *texture = nullptr;
    if (handle.value == 0)
    {
        texture = mZeroTextures[target].get();
    }
    else
    {
        texture =
            mState.mTextureManager->checkTextureAllocation(mImplementation.get(), handle, target);
    }

    ASSERT(texture);
    // Early return if rebinding the same texture
    if (texture == mState.getTargetTexture(target))
    {
        return;
    }

    mState.setSamplerTexture(this, target, texture);
    mStateCache.onActiveTextureChange(this);
}

void Context::bindReadFramebuffer(FramebufferID framebufferHandle)
{
    Framebuffer *framebuffer = mState.mFramebufferManager->checkFramebufferAllocation(
        mImplementation.get(), this, framebufferHandle);
    mState.setReadFramebufferBinding(framebuffer);
    mReadFramebufferObserverBinding.bind(framebuffer);
}

void Context::bindDrawFramebuffer(FramebufferID framebufferHandle)
{
    endTilingImplicit();
    if (mState.getPixelLocalStorageActivePlanes() != 0)
    {
        endPixelLocalStorageImplicit();
    }
    Framebuffer *framebuffer = mState.mFramebufferManager->checkFramebufferAllocation(
        mImplementation.get(), this, framebufferHandle);
    mState.setDrawFramebufferBinding(framebuffer);
    mDrawFramebufferObserverBinding.bind(framebuffer);
    mStateCache.onDrawFramebufferChange(this);
}

void Context::bindVertexArray(VertexArrayID vertexArrayHandle)
{
    VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle);
    mState.setVertexArrayBinding(this, vertexArray);
    mVertexArrayObserverBinding.bind(vertexArray);
    mPrivateStateCache.onVertexArrayBindingChange();
}

void Context::bindVertexBuffer(GLuint bindingIndex,
                               BufferID bufferHandle,
                               GLintptr offset,
                               GLsizei stride)
{
    Buffer *buffer =
        mState.mBufferManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
    mState.bindVertexBuffer(this, bindingIndex, buffer, offset, stride);
    mPrivateStateCache.onVertexArrayStateChange();
}

void Context::bindSampler(GLuint textureUnit, SamplerID samplerHandle)
{
    ASSERT(textureUnit < static_cast<GLuint>(mState.getCaps().maxCombinedTextureImageUnits));
    Sampler *sampler =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerHandle);

    // Early return if rebinding the same sampler
    if (sampler == mState.getSampler(textureUnit))
    {
        return;
    }

    mState.setSamplerBinding(this, textureUnit, sampler);
    mSamplerObserverBindings[textureUnit].bind(sampler);
    mStateCache.onActiveTextureChange(this);
}

void Context::bindImageTexture(GLuint unit,
                               TextureID texture,
                               GLint level,
                               GLboolean layered,
                               GLint layer,
                               GLenum access,
                               GLenum format)
{
    Texture *tex = mState.mTextureManager->getTexture(texture);
    // For robust init, make sure the texture is initialized before storage writes.
    if (tex != nullptr)
    {
        ANGLE_CONTEXT_TRY(tex->ensureInitialized(this, EnsureInitializedLevels::AllEnabledLevels));
    }
    mState.setImageUnit(this, unit, tex, level, layered, layer, access, format);
    mImageObserverBindings[unit].bind(tex);
}

void Context::useProgram(ShaderProgramID program)
{
    Program *programObject = getProgramResolveLink(program);
    ANGLE_CONTEXT_TRY(mState.setProgram(this, programObject));
    mStateCache.onProgramExecutableChange(this);
    mProgramObserverBinding.bind(programObject);
}

void Context::useProgramStages(ProgramPipelineID pipeline,
                               GLbitfield stages,
                               ShaderProgramID program)
{
    Program *shaderProgram = getProgramNoResolveLink(program);
    ProgramPipeline *programPipeline =
        mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
                                                                       pipeline);

    ASSERT(programPipeline);
    ANGLE_CONTEXT_TRY(programPipeline->useProgramStages(this, stages, shaderProgram));
}

void Context::bindTransformFeedback(GLenum target, TransformFeedbackID transformFeedbackHandle)
{
    ASSERT(target == GL_TRANSFORM_FEEDBACK);
    TransformFeedback *transformFeedback =
        checkTransformFeedbackAllocation(transformFeedbackHandle);
    mState.setTransformFeedbackBinding(this, transformFeedback);
    onActiveTransformFeedbackChange();
}

void Context::bindProgramPipeline(ProgramPipelineID pipelineHandle)
{
    ProgramPipeline *pipeline = mState.mProgramPipelineManager->checkProgramPipelineAllocation(
        mImplementation.get(), pipelineHandle);
    ANGLE_CONTEXT_TRY(mState.setProgramPipelineBinding(this, pipeline));
    mStateCache.onProgramExecutableChange(this);
    mProgramPipelineObserverBinding.bind(pipeline);
}

void Context::beginQuery(QueryType target, QueryID query)
{
    Query *queryObject = getOrCreateQuery(query, target);
    ASSERT(queryObject);

    // begin query
    ANGLE_CONTEXT_TRY(queryObject->begin(this));

    // set query as active for specified target only if begin succeeded
    mState.setActiveQuery(this, target, queryObject);
    mStateCache.onQueryChange(this);
}

void Context::endQuery(QueryType target)
{
    Query *queryObject = mState.getActiveQuery(target);
    ASSERT(queryObject);

    // Intentionally don't call try here. We don't want an early return.
    (void)(queryObject->end(this));

    // Always unbind the query, even if there was an error. This may delete the query object.
    mState.setActiveQuery(this, target, nullptr);
    mStateCache.onQueryChange(this);
}

void Context::queryCounter(QueryID id, QueryType target)
{
    ASSERT(target == QueryType::Timestamp);

    Query *queryObject = getOrCreateQuery(id, target);
    ASSERT(queryObject);

    ANGLE_CONTEXT_TRY(queryObject->queryCounter(this));
}

void Context::getQueryiv(QueryType targetPacked, QueryParameter pnamePacked, GLint *params)
{
    switch (pnamePacked)
    {
        case QueryParameter::CurrentQuery:
            *params = mState.getActiveQueryId(targetPacked).value;
            break;
        case QueryParameter::QueryCounterBits:
            switch (targetPacked)
            {
                case QueryType::AnySamples:
                case QueryType::AnySamplesConservative:
                    *params = 1;
                    break;
                case QueryType::PrimitivesGenerated:
                case QueryType::TransformFeedbackPrimitivesWritten:
                    *params = 32;
                    break;
                case QueryType::TimeElapsed:
                    *params = getCaps().queryCounterBitsTimeElapsed;
                    break;
                case QueryType::Timestamp:
                    *params = getCaps().queryCounterBitsTimestamp;
                    break;
                default:
                    UNREACHABLE();
                    break;
            }
            break;
        default:
            UNREACHABLE();
            break;
    }
}

void Context::getQueryivRobust(QueryType targetPacked,
                               QueryParameter pnamePacked,
                               GLsizei paramCount,
                               GLsizei *length,
                               GLint *params)
{
    getQueryiv(targetPacked, pnamePacked, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::getUnsignedBytev(GLenum pname, GLubyte *data)
{
    UNIMPLEMENTED();
}

void Context::getUnsignedBytei_v(GLenum target, GLuint index, GLubyte *data)
{
    UNIMPLEMENTED();
}

void Context::getQueryObjectiv(QueryID idPacked, QueryObjectParameter pnamePacked, GLint *params)
{
    ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(idPacked), pnamePacked, params));
}

void Context::getQueryObjectivRobust(QueryID idPacked,
                                     QueryObjectParameter pnamePacked,
                                     GLsizei paramCount,
                                     GLsizei *length,
                                     GLint *params)
{
    ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(idPacked), pnamePacked, params));

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::getQueryObjectuiv(QueryID idPacked, QueryObjectParameter pnamePacked, GLuint *params)
{
    ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(idPacked), pnamePacked, params));
}

void Context::getQueryObjectuivRobust(QueryID idPacked,
                                      QueryObjectParameter pnamePacked,
                                      GLsizei paramCount,
                                      GLsizei *length,
                                      GLuint *params)
{
    ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(idPacked), pnamePacked, params));

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::getQueryObjecti64v(QueryID idPacked,
                                 QueryObjectParameter pnamePacked,
                                 GLint64 *params)
{
    ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(idPacked), pnamePacked, params));
}

void Context::getQueryObjecti64vRobust(QueryID idPacked,
                                       QueryObjectParameter pnamePacked,
                                       GLsizei paramCount,
                                       GLsizei *length,
                                       GLint64 *params)
{
    ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(idPacked), pnamePacked, params));

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::getQueryObjectui64v(QueryID idPacked,
                                  QueryObjectParameter pnamePacked,
                                  GLuint64 *params)
{
    ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(idPacked), pnamePacked, params));
}

void Context::getQueryObjectui64vRobust(QueryID idPacked,
                                        QueryObjectParameter pnamePacked,
                                        GLsizei paramCount,
                                        GLsizei *length,
                                        GLuint64 *params)
{
    ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(idPacked), pnamePacked, params));

    if (length != nullptr)
    {
        *length = 1;
    }
}

Framebuffer *Context::getFramebuffer(FramebufferID handle) const
{
    return mState.mFramebufferManager->getFramebuffer(handle);
}

FenceNV *Context::getFenceNV(FenceNVID handle) const
{
    return mFenceNVMap.query(handle);
}

Query *Context::getOrCreateQuery(QueryID handle, QueryType type)
{
    if (!mQueryMap.contains(handle))
    {
        return nullptr;
    }

    Query *query = mQueryMap.query(handle);
    if (!query)
    {
        ASSERT(type != QueryType::InvalidEnum);
        query = new Query(mImplementation.get(), type, handle);
        query->addRef();
        mQueryMap.assign(handle, query);
    }
    return query;
}

Query *Context::getQuery(QueryID handle) const
{
    return mQueryMap.query(handle);
}

Texture *Context::getTextureByType(TextureType type) const
{
    ASSERT(ValidTextureTarget(this, type) || ValidTextureExternalTarget(this, type));
    return mState.getTargetTexture(type);
}

Texture *Context::getTextureByTarget(TextureTarget target) const
{
    return getTextureByType(TextureTargetToType(target));
}

Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const
{
    return mState.getSamplerTexture(sampler, type);
}

Compiler *Context::getCompiler() const
{
    if (mCompiler.get() == nullptr)
    {
        mCompiler.set(this, new Compiler(mImplementation.get(), mState));
    }
    return mCompiler.get();
}

void Context::getBooleanvImpl(GLenum pname, GLboolean *params) const
{
    switch (pname)
    {
        case GL_SHADER_COMPILER:
            *params = GL_TRUE;
            break;
        case GL_CONTEXT_ROBUST_ACCESS_EXT:
            *params = ConvertToGLBoolean(mState.hasRobustAccess());
            break;
        case GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT:
            *params =
                mState.getCaps()
                    .fragmentShadingRateProperties.fragmentShadingRateNonTrivialCombinersSupport;
            break;

        default:
            mState.getBooleanv(pname, params);
            break;
    }
}

void Context::getFloatvImpl(GLenum pname, GLfloat *params) const
{
    // Queries about context capabilities and maximums are answered by Context.
    // Queries about current GL state values are answered by State.
    switch (pname)
    {
        case GL_ALIASED_LINE_WIDTH_RANGE:
            params[0] = mState.getCaps().minAliasedLineWidth;
            params[1] = mState.getCaps().maxAliasedLineWidth;
            break;
        case GL_ALIASED_POINT_SIZE_RANGE:
            params[0] = mState.getCaps().minAliasedPointSize;
            params[1] = mState.getCaps().maxAliasedPointSize;
            break;
        case GL_SMOOTH_POINT_SIZE_RANGE:
            params[0] = mState.getCaps().minSmoothPointSize;
            params[1] = mState.getCaps().maxSmoothPointSize;
            break;
        case GL_SMOOTH_LINE_WIDTH_RANGE:
            params[0] = mState.getCaps().minSmoothLineWidth;
            params[1] = mState.getCaps().maxSmoothLineWidth;
            break;
        case GL_MULTISAMPLE_LINE_WIDTH_RANGE:
            params[0] = mState.getCaps().minMultisampleLineWidth;
            params[1] = mState.getCaps().maxMultisampleLineWidth;
            break;
        case GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY:
            *params = mState.getCaps().lineWidthGranularity;
            break;
        case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
            ASSERT(mState.getExtensions().textureFilterAnisotropicEXT);
            *params = mState.getCaps().maxTextureAnisotropy;
            break;
        case GL_MAX_TEXTURE_LOD_BIAS:
            *params = mState.getCaps().maxLODBias;
            break;
        case GL_MIN_FRAGMENT_INTERPOLATION_OFFSET:
            *params = mState.getCaps().minInterpolationOffset;
            break;
        case GL_MAX_FRAGMENT_INTERPOLATION_OFFSET:
            *params = mState.getCaps().maxInterpolationOffset;
            break;
        case GL_PRIMITIVE_BOUNDING_BOX:
            params[0] = mState.getBoundingBoxMinX();
            params[1] = mState.getBoundingBoxMinY();
            params[2] = mState.getBoundingBoxMinZ();
            params[3] = mState.getBoundingBoxMinW();
            params[4] = mState.getBoundingBoxMaxX();
            params[5] = mState.getBoundingBoxMaxY();
            params[6] = mState.getBoundingBoxMaxZ();
            params[7] = mState.getBoundingBoxMaxW();
            break;
        default:
            mState.getFloatv(pname, params);
            break;
    }
}

void Context::getIntegervImpl(GLenum pname, GLint *params) const
{
    // Queries about context capabilities and maximums are answered by Context.
    // Queries about current GL state values are answered by State.

    switch (pname)
    {
        case GL_MAX_VERTEX_ATTRIBS:
            *params = mState.getCaps().maxVertexAttributes;
            break;
        case GL_MAX_VERTEX_UNIFORM_VECTORS:
            *params = mState.getCaps().maxVertexUniformVectors;
            break;
        case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
            *params = mState.getCaps().maxShaderUniformComponents[ShaderType::Vertex];
            break;
        case GL_MAX_VARYING_VECTORS:
            *params = mState.getCaps().maxVaryingVectors;
            break;
        case GL_MAX_VARYING_COMPONENTS:
            *params = mState.getCaps().maxVaryingVectors * 4;
            break;
        case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
            *params = mState.getCaps().maxCombinedTextureImageUnits;
            break;
        case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
            *params = mState.getCaps().maxShaderTextureImageUnits[ShaderType::Vertex];
            break;
        case GL_MAX_TEXTURE_IMAGE_UNITS:
            *params = mState.getCaps().maxShaderTextureImageUnits[ShaderType::Fragment];
            break;
        case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
            *params = mState.getCaps().maxFragmentUniformVectors;
            break;
        case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
            *params = mState.getCaps().maxShaderUniformComponents[ShaderType::Fragment];
            break;
        case GL_MAX_RENDERBUFFER_SIZE:
            *params = mState.getCaps().maxRenderbufferSize;
            break;
        case GL_MAX_COLOR_ATTACHMENTS_EXT:
            *params = mState.getCaps().maxColorAttachments;
            break;
        case GL_MAX_DRAW_BUFFERS_EXT:
            *params = mState.getCaps().maxDrawBuffers;
            break;
        case GL_SUBPIXEL_BITS:
            *params = mState.getCaps().subPixelBits;
            break;
        case GL_MAX_TEXTURE_SIZE:
            *params = mState.getCaps().max2DTextureSize;
            break;
        case GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE:
            *params = mState.getCaps().maxRectangleTextureSize;
            break;
        case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
            *params = mState.getCaps().maxCubeMapTextureSize;
            break;
        case GL_MAX_3D_TEXTURE_SIZE:
            *params = mState.getCaps().max3DTextureSize;
            break;
        case GL_MAX_ARRAY_TEXTURE_LAYERS:
            *params = mState.getCaps().maxArrayTextureLayers;
            break;
        case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
            *params = mState.getCaps().uniformBufferOffsetAlignment;
            break;
        case GL_MAX_UNIFORM_BUFFER_BINDINGS:
            *params = mState.getCaps().maxUniformBufferBindings;
            break;
        case GL_MAX_VERTEX_UNIFORM_BLOCKS:
            *params = mState.getCaps().maxShaderUniformBlocks[ShaderType::Vertex];
            break;
        case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
            *params = mState.getCaps().maxShaderUniformBlocks[ShaderType::Fragment];
            break;
        case GL_MAX_COMBINED_UNIFORM_BLOCKS:
            *params = mState.getCaps().maxCombinedUniformBlocks;
            break;
        case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
            *params = mState.getCaps().maxVertexOutputComponents;
            break;
        case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
            *params = mState.getCaps().maxFragmentInputComponents;
            break;
        case GL_MIN_PROGRAM_TEXEL_OFFSET:
            *params = mState.getCaps().minProgramTexelOffset;
            break;
        case GL_MAX_PROGRAM_TEXEL_OFFSET:
            *params = mState.getCaps().maxProgramTexelOffset;
            break;
        case GL_MAJOR_VERSION:
            *params = getClientVersion().getMajor();
            break;
        case GL_MINOR_VERSION:
            *params = getClientVersion().getMinor();
            break;
        case GL_MAX_ELEMENTS_INDICES:
            *params = mState.getCaps().maxElementsIndices;
            break;
        case GL_MAX_ELEMENTS_VERTICES:
            *params = mState.getCaps().maxElementsVertices;
            break;
        case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
            *params = mState.getCaps().maxTransformFeedbackInterleavedComponents;
            break;
        case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
            *params = mState.getCaps().maxTransformFeedbackSeparateAttributes;
            break;
        case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
            *params = mState.getCaps().maxTransformFeedbackSeparateComponents;
            break;
        case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
            *params = static_cast<GLint>(mState.getCaps().compressedTextureFormats.size());
            break;
        case GL_MAX_SAMPLES_ANGLE:
            *params = mState.getCaps().maxSamples;
            break;
        case GL_MAX_VIEWPORT_DIMS:
        {
            params[0] = mState.getCaps().maxViewportWidth;
            params[1] = mState.getCaps().maxViewportHeight;
        }
        break;
        case GL_COMPRESSED_TEXTURE_FORMATS:
            std::copy(mState.getCaps().compressedTextureFormats.begin(),
                      mState.getCaps().compressedTextureFormats.end(), params);
            break;
        case GL_RESET_NOTIFICATION_STRATEGY_EXT:
            *params = mErrors.getResetStrategy();
            break;
        case GL_NUM_SHADER_BINARY_FORMATS:
            *params = static_cast<GLint>(mState.getCaps().shaderBinaryFormats.size());
            break;
        case GL_SHADER_BINARY_FORMATS:
            std::copy(mState.getCaps().shaderBinaryFormats.begin(),
                      mState.getCaps().shaderBinaryFormats.end(), params);
            break;
        case GL_NUM_PROGRAM_BINARY_FORMATS:
            *params = static_cast<GLint>(mState.getCaps().programBinaryFormats.size());
            break;
        case GL_PROGRAM_BINARY_FORMATS:
            std::copy(mState.getCaps().programBinaryFormats.begin(),
                      mState.getCaps().programBinaryFormats.end(), params);
            break;
        case GL_NUM_EXTENSIONS:
            *params = static_cast<GLint>(mExtensionStrings.size());
            break;

        // GLES3.2 client flags
        case GL_CONTEXT_FLAGS:
        {
            GLint contextFlags = 0;
            if (mState.hasProtectedContent())
            {
                contextFlags |= GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT;
            }

            if (mState.isDebugContext())
            {
                contextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT_KHR;
            }

            if (mState.hasRobustAccess())
            {
                contextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT;
            }
            *params = contextFlags;
        }
        break;

        // GL_ANGLE_request_extension
        case GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE:
            *params = static_cast<GLint>(mRequestableExtensionStrings.size());
            break;

        // GL_KHR_debug
        case GL_MAX_DEBUG_MESSAGE_LENGTH:
            *params = mState.getCaps().maxDebugMessageLength;
            break;
        case GL_MAX_DEBUG_LOGGED_MESSAGES:
            *params = mState.getCaps().maxDebugLoggedMessages;
            break;
        case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
            *params = mState.getCaps().maxDebugGroupStackDepth;
            break;
        case GL_MAX_LABEL_LENGTH:
            *params = mState.getCaps().maxLabelLength;
            break;

        // GL_OVR_multiview
        case GL_MAX_VIEWS_OVR:
            *params = mState.getCaps().maxViews;
            break;

        // GL_EXT_disjoint_timer_query
        case GL_GPU_DISJOINT_EXT:
            *params = mImplementation->getGPUDisjoint();
            break;
        case GL_MAX_FRAMEBUFFER_WIDTH:
            *params = mState.getCaps().maxFramebufferWidth;
            break;
        case GL_MAX_FRAMEBUFFER_HEIGHT:
            *params = mState.getCaps().maxFramebufferHeight;
            break;
        case GL_MAX_FRAMEBUFFER_SAMPLES:
            *params = mState.getCaps().maxFramebufferSamples;
            break;
        case GL_MAX_SAMPLE_MASK_WORDS:
            *params = mState.getCaps().maxSampleMaskWords;
            break;
        case GL_MAX_COLOR_TEXTURE_SAMPLES:
            *params = mState.getCaps().maxColorTextureSamples;
            break;
        case GL_MAX_DEPTH_TEXTURE_SAMPLES:
            *params = mState.getCaps().maxDepthTextureSamples;
            break;
        case GL_MAX_INTEGER_SAMPLES:
            *params = mState.getCaps().maxIntegerSamples;
            break;
        case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
            *params = mState.getCaps().maxVertexAttribRelativeOffset;
            break;
        case GL_MAX_VERTEX_ATTRIB_BINDINGS:
            *params = mState.getCaps().maxVertexAttribBindings;
            break;
        case GL_MAX_VERTEX_ATTRIB_STRIDE:
            *params = mState.getCaps().maxVertexAttribStride;
            break;
        case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
            *params = mState.getCaps().maxShaderAtomicCounterBuffers[ShaderType::Vertex];
            break;
        case GL_MAX_VERTEX_ATOMIC_COUNTERS:
            *params = mState.getCaps().maxShaderAtomicCounters[ShaderType::Vertex];
            break;
        case GL_MAX_VERTEX_IMAGE_UNIFORMS:
            *params = mState.getCaps().maxShaderImageUniforms[ShaderType::Vertex];
            break;
        case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
            *params = mState.getCaps().maxShaderStorageBlocks[ShaderType::Vertex];
            break;
        case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
            *params = mState.getCaps().maxShaderAtomicCounterBuffers[ShaderType::Fragment];
            break;
        case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
            *params = mState.getCaps().maxShaderAtomicCounters[ShaderType::Fragment];
            break;
        case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
            *params = mState.getCaps().maxShaderImageUniforms[ShaderType::Fragment];
            break;
        case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
            *params = mState.getCaps().maxShaderStorageBlocks[ShaderType::Fragment];
            break;
        case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
            *params = mState.getCaps().minProgramTextureGatherOffset;
            break;
        case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
            *params = mState.getCaps().maxProgramTextureGatherOffset;
            break;
        case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
            *params = mState.getCaps().maxComputeWorkGroupInvocations;
            break;
        case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
            *params = mState.getCaps().maxShaderUniformBlocks[ShaderType::Compute];
            break;
        case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
            *params = mState.getCaps().maxShaderTextureImageUnits[ShaderType::Compute];
            break;
        case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
            *params = mState.getCaps().maxComputeSharedMemorySize;
            break;
        case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
            *params = mState.getCaps().maxShaderUniformComponents[ShaderType::Compute];
            break;
        case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
            *params = mState.getCaps().maxShaderAtomicCounterBuffers[ShaderType::Compute];
            break;
        case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
            *params = mState.getCaps().maxShaderAtomicCounters[ShaderType::Compute];
            break;
        case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
            *params = mState.getCaps().maxShaderImageUniforms[ShaderType::Compute];
            break;
        case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
            *params = static_cast<GLint>(
                mState.getCaps().maxCombinedShaderUniformComponents[ShaderType::Compute]);
            break;
        case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
            *params = mState.getCaps().maxShaderStorageBlocks[ShaderType::Compute];
            break;
        case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
            *params = mState.getCaps().maxCombinedShaderOutputResources;
            break;
        case GL_MAX_UNIFORM_LOCATIONS:
            *params = mState.getCaps().maxUniformLocations;
            break;
        case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
            *params = mState.getCaps().maxAtomicCounterBufferBindings;
            break;
        case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
            *params = mState.getCaps().maxAtomicCounterBufferSize;
            break;
        case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
            *params = mState.getCaps().maxCombinedAtomicCounterBuffers;
            break;
        case GL_MAX_COMBINED_ATOMIC_COUNTERS:
            *params = mState.getCaps().maxCombinedAtomicCounters;
            break;
        case GL_MAX_IMAGE_UNITS:
            *params = mState.getCaps().maxImageUnits;
            break;
        case GL_MAX_COMBINED_IMAGE_UNIFORMS:
            *params = mState.getCaps().maxCombinedImageUniforms;
            break;
        case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
            *params = mState.getCaps().maxShaderStorageBufferBindings;
            break;
        case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
            *params = mState.getCaps().maxCombinedShaderStorageBlocks;
            break;
        case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
            *params = mState.getCaps().shaderStorageBufferOffsetAlignment;
            break;

        // GL_EXT_geometry_shader
        case GL_MAX_FRAMEBUFFER_LAYERS_EXT:
            *params = mState.getCaps().maxFramebufferLayers;
            break;
        case GL_LAYER_PROVOKING_VERTEX_EXT:
            *params = mState.getCaps().layerProvokingVertex;
            break;
        case GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT:
            *params = mState.getCaps().maxShaderUniformComponents[ShaderType::Geometry];
            break;
        case GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT:
            *params = mState.getCaps().maxShaderUniformBlocks[ShaderType::Geometry];
            break;
        case GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT:
            *params = static_cast<GLint>(
                mState.getCaps().maxCombinedShaderUniformComponents[ShaderType::Geometry]);
            break;
        case GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT:
            *params = mState.getCaps().maxGeometryInputComponents;
            break;
        case GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT:
            *params = mState.getCaps().maxGeometryOutputComponents;
            break;
        case GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT:
            *params = mState.getCaps().maxGeometryOutputVertices;
            break;
        case GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT:
            *params = mState.getCaps().maxGeometryTotalOutputComponents;
            break;
        case GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT:
            *params = mState.getCaps().maxGeometryShaderInvocations;
            break;
        case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT:
            *params = mState.getCaps().maxShaderTextureImageUnits[ShaderType::Geometry];
            break;
        case GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT:
            *params = mState.getCaps().maxShaderAtomicCounterBuffers[ShaderType::Geometry];
            break;
        case GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT:
            *params = mState.getCaps().maxShaderAtomicCounters[ShaderType::Geometry];
            break;
        case GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT:
            *params = mState.getCaps().maxShaderImageUniforms[ShaderType::Geometry];
            break;
        case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT:
            *params = mState.getCaps().maxShaderStorageBlocks[ShaderType::Geometry];
            break;
        // GL_EXT_tessellation_shader
        case GL_MAX_PATCH_VERTICES_EXT:
            *params = mState.getCaps().maxPatchVertices;
            break;
        case GL_MAX_TESS_GEN_LEVEL_EXT:
            *params = mState.getCaps().maxTessGenLevel;
            break;
        case GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT:
            *params = mState.getCaps().maxShaderUniformComponents[ShaderType::TessControl];
            break;
        case GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT:
            *params = mState.getCaps().maxShaderUniformComponents[ShaderType::TessEvaluation];
            break;
        case GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT:
            *params = mState.getCaps().maxShaderTextureImageUnits[ShaderType::TessControl];
            break;
        case GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT:
            *params = mState.getCaps().maxShaderTextureImageUnits[ShaderType::TessEvaluation];
            break;
        case GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT:
            *params = mState.getCaps().maxTessControlOutputComponents;
            break;
        case GL_MAX_TESS_PATCH_COMPONENTS_EXT:
            *params = mState.getCaps().maxTessPatchComponents;
            break;
        case GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT:
            *params = mState.getCaps().maxTessControlTotalOutputComponents;
            break;
        case GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT:
            *params = mState.getCaps().maxTessEvaluationOutputComponents;
            break;
        case GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT:
            *params = mState.getCaps().maxShaderUniformBlocks[ShaderType::TessControl];
            break;
        case GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT:
            *params = mState.getCaps().maxShaderUniformBlocks[ShaderType::TessEvaluation];
            break;
        case GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT:
            *params = mState.getCaps().maxTessControlInputComponents;
            break;
        case GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT:
            *params = mState.getCaps().maxTessEvaluationInputComponents;
            break;
        case GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT:
            *params = static_cast<GLint>(
                mState.getCaps().maxCombinedShaderUniformComponents[ShaderType::TessControl]);
            break;
        case GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT:
            *params = static_cast<GLint>(
                mState.getCaps().maxCombinedShaderUniformComponents[ShaderType::TessEvaluation]);
            break;
        case GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT:
            *params = mState.getCaps().maxShaderAtomicCounterBuffers[ShaderType::TessControl];
            break;
        case GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT:
            *params = mState.getCaps().maxShaderAtomicCounterBuffers[ShaderType::TessEvaluation];
            break;
        case GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT:
            *params = mState.getCaps().maxShaderAtomicCounters[ShaderType::TessControl];
            break;
        case GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT:
            *params = mState.getCaps().maxShaderAtomicCounters[ShaderType::TessEvaluation];
            break;
        case GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT:
            *params = mState.getCaps().maxShaderImageUniforms[ShaderType::TessControl];
            break;
        case GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT:
            *params = mState.getCaps().maxShaderImageUniforms[ShaderType::TessEvaluation];
            break;
        case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT:
            *params = mState.getCaps().maxShaderStorageBlocks[ShaderType::TessControl];
            break;
        case GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT:
            *params = mState.getCaps().maxShaderStorageBlocks[ShaderType::TessEvaluation];
            break;
        // GLES1 emulation: Caps queries
        case GL_MAX_TEXTURE_UNITS:
            *params = mState.getCaps().maxMultitextureUnits;
            break;
        case GL_MAX_MODELVIEW_STACK_DEPTH:
            *params = mState.getCaps().maxModelviewMatrixStackDepth;
            break;
        case GL_MAX_PROJECTION_STACK_DEPTH:
            *params = mState.getCaps().maxProjectionMatrixStackDepth;
            break;
        case GL_MAX_TEXTURE_STACK_DEPTH:
            *params = mState.getCaps().maxTextureMatrixStackDepth;
            break;
        case GL_MAX_LIGHTS:
            *params = mState.getCaps().maxLights;
            break;

        // case GL_MAX_CLIP_DISTANCES_EXT:  Conflict enum value
        case GL_MAX_CLIP_PLANES:
            if (getClientVersion() >= ES_2_0)
            {
                // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
                *params = mState.getCaps().maxClipDistances;
            }
            else
            {
                *params = mState.getCaps().maxClipPlanes;
            }
            break;
        case GL_MAX_CULL_DISTANCES_EXT:
            *params = mState.getCaps().maxCullDistances;
            break;
        case GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT:
            *params = mState.getCaps().maxCombinedClipAndCullDistances;
            break;
        // GLES1 emulation: Vertex attribute queries
        case GL_VERTEX_ARRAY_BUFFER_BINDING:
        case GL_NORMAL_ARRAY_BUFFER_BINDING:
        case GL_COLOR_ARRAY_BUFFER_BINDING:
        case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
        case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
            getIntegerVertexAttribImpl(pname, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, params);
            break;
        case GL_VERTEX_ARRAY_STRIDE:
        case GL_NORMAL_ARRAY_STRIDE:
        case GL_COLOR_ARRAY_STRIDE:
        case GL_POINT_SIZE_ARRAY_STRIDE_OES:
        case GL_TEXTURE_COORD_ARRAY_STRIDE:
            getIntegerVertexAttribImpl(pname, GL_VERTEX_ATTRIB_ARRAY_STRIDE, params);
            break;
        case GL_VERTEX_ARRAY_SIZE:
        case GL_COLOR_ARRAY_SIZE:
        case GL_TEXTURE_COORD_ARRAY_SIZE:
            getIntegerVertexAttribImpl(pname, GL_VERTEX_ATTRIB_ARRAY_SIZE, params);
            break;
        case GL_VERTEX_ARRAY_TYPE:
        case GL_COLOR_ARRAY_TYPE:
        case GL_NORMAL_ARRAY_TYPE:
        case GL_POINT_SIZE_ARRAY_TYPE_OES:
        case GL_TEXTURE_COORD_ARRAY_TYPE:
            getIntegerVertexAttribImpl(pname, GL_VERTEX_ATTRIB_ARRAY_TYPE, params);
            break;

        // GL_KHR_parallel_shader_compile
        case GL_MAX_SHADER_COMPILER_THREADS_KHR:
            *params = mState.getMaxShaderCompilerThreads();
            break;

        // GL_EXT_blend_func_extended
        case GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT:
            *params = mState.getCaps().maxDualSourceDrawBuffers;
            break;

        // OES_shader_multisample_interpolation
        case GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES:
            *params = mState.getCaps().subPixelInterpolationOffsetBits;
            break;

        // GL_OES_texture_buffer
        case GL_MAX_TEXTURE_BUFFER_SIZE:
            *params = mState.getCaps().maxTextureBufferSize;
            break;
        case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
            *params = mState.getCaps().textureBufferOffsetAlignment;
            break;

        // ANGLE_shader_pixel_local_storage
        case GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE:
            *params = mState.getCaps().maxPixelLocalStoragePlanes;
            break;
        case GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE:
            *params = mState.getCaps().maxCombinedDrawBuffersAndPixelLocalStoragePlanes;
            break;

        case GL_QUERY_COUNTER_BITS_EXT:
            *params = mState.getCaps().queryCounterBitsTimestamp;
            break;

        case GL_SHADING_RATE_EXT:
            *params = ToGLenum(mState.getShadingRateEXT());
            break;

        default:
            ANGLE_CONTEXT_TRY(mState.getIntegerv(this, pname, params));
            break;
    }
}

void Context::getIntegerVertexAttribImpl(GLenum pname, GLenum attribpname, GLint *params) const
{
    getVertexAttribivImpl(static_cast<GLuint>(vertexArrayIndex(ParamToVertexArrayType(pname))),
                          attribpname, params);
}

void Context::getInteger64vImpl(GLenum pname, GLint64 *params) const
{
    // Queries about context capabilities and maximums are answered by Context.
    // Queries about current GL state values are answered by State.
    switch (pname)
    {
        case GL_MAX_ELEMENT_INDEX:
            *params = mState.getCaps().maxElementIndex;
            break;
        case GL_MAX_UNIFORM_BLOCK_SIZE:
            *params = mState.getCaps().maxUniformBlockSize;
            break;
        case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
            *params = mState.getCaps().maxCombinedShaderUniformComponents[ShaderType::Vertex];
            break;
        case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
            *params = mState.getCaps().maxCombinedShaderUniformComponents[ShaderType::Fragment];
            break;
        case GL_MAX_SERVER_WAIT_TIMEOUT:
            *params = mState.getCaps().maxServerWaitTimeout;
            break;

        // GL_EXT_disjoint_timer_query
        case GL_TIMESTAMP_EXT:
            *params = mImplementation->getTimestamp();
            break;

        case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
            *params = mState.getCaps().maxShaderStorageBlockSize;
            break;
        default:
            UNREACHABLE();
            break;
    }
}

void Context::getPointerv(GLenum pname, void **params)
{
    mState.getPointerv(this, pname, params);
}

void Context::getIntegeri_v(GLenum target, GLuint index, GLint *data)
{
    getIntegeri_vRobust(target, index, 0, nullptr, data);
}

void Context::getIntegeri_vRobust(GLenum target,
                                  GLuint index,
                                  GLsizei paramCount,
                                  GLsizei *length,
                                  GLint *data)
{
    // Queries about context capabilities and maximums are answered by Context.
    // Queries about current GL state values are answered by State.

    GLenum nativeType;
    unsigned int numParams;
    const bool paramFound = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
    ASSERT(paramFound);

    if (nativeType == GL_INT)
    {
        switch (target)
        {
            case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
                ASSERT(index < 3u);
                *data = mState.getCaps().maxComputeWorkGroupCount[index];
                break;
            case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
                ASSERT(index < 3u);
                *data = mState.getCaps().maxComputeWorkGroupSize[index];
                break;
            default:
                mState.getIntegeri_v(target, index, data);
        }
    }
    else
    {
        CastIndexedStateValues(this, nativeType, target, index, numParams, data);
    }

    if (length != nullptr)
    {
        *length = numParams;
    }
}

void Context::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
{
    getInteger64i_vRobust(target, index, 0, nullptr, data);
}

void Context::getInteger64i_vRobust(GLenum target,
                                    GLuint index,
                                    GLsizei paramCount,
                                    GLsizei *length,
                                    GLint64 *data)
{
    // Queries about context capabilities and maximums are answered by Context.
    // Queries about current GL state values are answered by State.

    GLenum nativeType;
    unsigned int numParams;
    const bool paramFound = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
    ASSERT(paramFound);

    if (nativeType == GL_INT64)
    {
        mState.getInteger64i_v(target, index, data);
    }
    else
    {
        CastIndexedStateValues(this, nativeType, target, index, numParams, data);
    }

    if (length != nullptr)
    {
        *length = numParams;
    }
}

void Context::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
{
    // Queries about context capabilities and maximums are answered by Context.
    // Queries about current GL state values are answered by State.

    GLenum nativeType;
    unsigned int numParams;
    const bool paramFound = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
    ASSERT(paramFound);

    if (nativeType == GL_BOOL)
    {
        mState.getBooleani_v(target, index, data);
    }
    else
    {
        CastIndexedStateValues(this, nativeType, target, index, numParams, data);
    }
}

void Context::getBufferParameteriv(BufferBinding target, BufferParam pnamePacked, GLint *params)
{
    Buffer *buffer = mState.getTargetBuffer(target);
    QueryBufferParameteriv(buffer, pnamePacked, params);
}

void Context::getBufferParameterivRobust(BufferBinding target,
                                         BufferParam pnamePacked,
                                         GLsizei paramCount,
                                         GLsizei *length,
                                         GLint *params)
{
    getBufferParameteriv(target, pnamePacked, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::getFramebufferAttachmentParameteriv(GLenum target,
                                                  GLenum attachment,
                                                  GLenum pname,
                                                  GLint *params)
{
    const Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    QueryFramebufferAttachmentParameteriv(this, framebuffer, attachment, pname, params);
}

void Context::getFramebufferAttachmentParameterivRobust(GLenum target,
                                                        GLenum attachment,
                                                        GLenum pname,
                                                        GLsizei paramCount,
                                                        GLsizei *length,
                                                        GLint *params)
{
    getFramebufferAttachmentParameteriv(target, attachment, pname, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::getRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
{
    Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
    QueryRenderbufferiv(this, renderbuffer, pname, params);
}

void Context::getRenderbufferParameterivRobust(GLenum target,
                                               GLenum pname,
                                               GLsizei paramCount,
                                               GLsizei *length,
                                               GLint *params)
{
    getRenderbufferParameteriv(target, pname, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::texBuffer(TextureType target, GLenum internalformat, BufferID buffer)
{
    ASSERT(target == TextureType::Buffer);

    Texture *texture  = getTextureByType(target);
    Buffer *bufferObj = mState.mBufferManager->getBuffer(buffer);
    ANGLE_CONTEXT_TRY(texture->setBuffer(this, bufferObj, internalformat));
}

void Context::texBufferRange(TextureType target,
                             GLenum internalformat,
                             BufferID buffer,
                             GLintptr offset,
                             GLsizeiptr size)
{
    ASSERT(target == TextureType::Buffer);

    Texture *texture  = getTextureByType(target);
    Buffer *bufferObj = mState.mBufferManager->getBuffer(buffer);
    ANGLE_CONTEXT_TRY(texture->setBufferRange(this, bufferObj, internalformat, offset, size));
}

void Context::getTexParameterfv(TextureType targetPacked, GLenum pname, GLfloat *params)
{
    const Texture *const texture = getTextureByType(targetPacked);
    QueryTexParameterfv(this, texture, pname, params);
}

void Context::getTexParameterfvRobust(TextureType targetPacked,
                                      GLenum pname,
                                      GLsizei paramCount,
                                      GLsizei *length,
                                      GLfloat *params)
{
    getTexParameterfv(targetPacked, pname, params);

    if (length != nullptr)
    {
        *length = (pname == GL_TEXTURE_BORDER_COLOR) ? 4 : 1;
    }
}

void Context::getTexParameteriv(TextureType targetPacked, GLenum pname, GLint *params)
{
    const Texture *const texture = getTextureByType(targetPacked);
    QueryTexParameteriv(this, texture, pname, params);
}

void Context::getTexParameterIiv(TextureType targetPacked, GLenum pname, GLint *params)
{
    const Texture *const texture = getTextureByType(targetPacked);
    QueryTexParameterIiv(this, texture, pname, params);
}

void Context::getTexParameterIuiv(TextureType targetPacked, GLenum pname, GLuint *params)
{
    const Texture *const texture = getTextureByType(targetPacked);
    QueryTexParameterIuiv(this, texture, pname, params);
}

void Context::getTexParameterivRobust(TextureType targetPacked,
                                      GLenum pname,
                                      GLsizei paramCount,
                                      GLsizei *length,
                                      GLint *params)
{
    getTexParameteriv(targetPacked, pname, params);

    if (length != nullptr)
    {
        *length = (pname == GL_TEXTURE_BORDER_COLOR) ? 4 : 1;
    }
}

void Context::getTexLevelParameteriv(TextureTarget targetPacked,
                                     GLint level,
                                     TextureImageParameter pnamePacked,
                                     GLint *params)
{
    Texture *texture = getTextureByTarget(targetPacked);
    QueryTexLevelParameteriv(texture, targetPacked, level, pnamePacked, params);
}

void Context::getTexLevelParameterivRobust(TextureTarget targetPacked,
                                           GLint level,
                                           TextureImageParameter pnamePacked,
                                           GLsizei paramCount,
                                           GLsizei *length,
                                           GLint *params)
{
    getTexLevelParameteriv(targetPacked, level, pnamePacked, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::getTexLevelParameterfv(TextureTarget targetPacked,
                                     GLint level,
                                     TextureImageParameter pnamePacked,
                                     GLfloat *params)
{
    Texture *texture = getTextureByTarget(targetPacked);
    QueryTexLevelParameterfv(texture, targetPacked, level, pnamePacked, params);
}

void Context::getTexLevelParameterfvRobust(TextureTarget targetPacked,
                                           GLint level,
                                           TextureImageParameter pnamePacked,
                                           GLsizei paramCount,
                                           GLsizei *length,
                                           GLfloat *params)
{
    getTexLevelParameterfv(targetPacked, level, pnamePacked, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::texParameterf(TextureType targetPacked, GLenum pname, GLfloat param)
{
    Texture *const texture = getTextureByType(targetPacked);
    SetTexParameterf(this, texture, pname, param);
}

void Context::texParameterfv(TextureType targetPacked, GLenum pname, const GLfloat *params)
{
    Texture *const texture = getTextureByType(targetPacked);
    SetTexParameterfv(this, texture, pname, params);
}

void Context::texParameterfvRobust(TextureType targetPacked,
                                   GLenum pname,
                                   GLsizei paramCount,
                                   const GLfloat *params)
{
    texParameterfv(targetPacked, pname, params);
}

void Context::texParameteri(TextureType targetPacked, GLenum pname, GLint param)
{
    // Some apps enable KHR_create_context_no_error but pass in an invalid texture type.
    // Workaround this by silently returning in such situations.
    if (targetPacked == TextureType::InvalidEnum)
    {
        return;
    }

    Texture *const texture = getTextureByType(targetPacked);
    SetTexParameteri(this, texture, pname, param);
}

void Context::texParameteriv(TextureType targetPacked, GLenum pname, const GLint *params)
{
    Texture *const texture = getTextureByType(targetPacked);
    SetTexParameteriv(this, texture, pname, params);
}

void Context::texParameterIiv(TextureType targetPacked, GLenum pname, const GLint *params)
{
    Texture *const texture = getTextureByType(targetPacked);
    SetTexParameterIiv(this, texture, pname, params);
}

void Context::texParameterIuiv(TextureType targetPacked, GLenum pname, const GLuint *params)
{
    Texture *const texture = getTextureByType(targetPacked);
    SetTexParameterIuiv(this, texture, pname, params);
}

void Context::texParameterivRobust(TextureType targetPacked,
                                   GLenum pname,
                                   GLsizei paramCount,
                                   const GLint *params)
{
    texParameteriv(targetPacked, pname, params);
}

void Context::drawArraysInstanced(PrimitiveMode mode,
                                  GLint first,
                                  GLsizei count,
                                  GLsizei instanceCount)
{
    // No-op if count draws no primitives for given mode
    if (noopDrawInstanced(mode, count, instanceCount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(
        mImplementation->drawArraysInstanced(this, mode, first, count, instanceCount));
    MarkTransformFeedbackBufferUsage(this, count, instanceCount);
    MarkShaderStorageUsage(this);
}

void Context::drawElementsInstanced(PrimitiveMode mode,
                                    GLsizei count,
                                    DrawElementsType type,
                                    const void *indices,
                                    GLsizei instances)
{
    // No-op if count draws no primitives for given mode
    if (noopDrawInstanced(mode, count, instances))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(
        mImplementation->drawElementsInstanced(this, mode, count, type, indices, instances));
    MarkShaderStorageUsage(this);
}

void Context::drawElementsBaseVertex(PrimitiveMode mode,
                                     GLsizei count,
                                     DrawElementsType type,
                                     const void *indices,
                                     GLint basevertex)
{
    // No-op if count draws no primitives for given mode
    if (noopDraw(mode, count))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(
        mImplementation->drawElementsBaseVertex(this, mode, count, type, indices, basevertex));
    MarkShaderStorageUsage(this);
}

void Context::drawElementsInstancedBaseVertex(PrimitiveMode mode,
                                              GLsizei count,
                                              DrawElementsType type,
                                              const void *indices,
                                              GLsizei instancecount,
                                              GLint basevertex)
{
    // No-op if count draws no primitives for given mode
    if (noopDrawInstanced(mode, count, instancecount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstancedBaseVertex(
        this, mode, count, type, indices, instancecount, basevertex));
    MarkShaderStorageUsage(this);
}

void Context::drawRangeElements(PrimitiveMode mode,
                                GLuint start,
                                GLuint end,
                                GLsizei count,
                                DrawElementsType type,
                                const void *indices)
{
    // No-op if count draws no primitives for given mode
    if (noopDraw(mode, count))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(
        mImplementation->drawRangeElements(this, mode, start, end, count, type, indices));
    MarkShaderStorageUsage(this);
}

void Context::drawRangeElementsBaseVertex(PrimitiveMode mode,
                                          GLuint start,
                                          GLuint end,
                                          GLsizei count,
                                          DrawElementsType type,
                                          const void *indices,
                                          GLint basevertex)
{
    // No-op if count draws no primitives for given mode
    if (noopDraw(mode, count))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->drawRangeElementsBaseVertex(this, mode, start, end, count,
                                                                   type, indices, basevertex));
    MarkShaderStorageUsage(this);
}

void Context::drawArraysIndirect(PrimitiveMode mode, const void *indirect)
{
    if (noopDrawProgram())
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->drawArraysIndirect(this, mode, indirect));
    MarkShaderStorageUsage(this);
}

void Context::drawElementsIndirect(PrimitiveMode mode, DrawElementsType type, const void *indirect)
{
    if (noopDrawProgram())
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->drawElementsIndirect(this, mode, type, indirect));
    MarkShaderStorageUsage(this);
}

void Context::flush()
{
    ANGLE_CONTEXT_TRY(mImplementation->flush(this));
}

void Context::finish()
{
    ANGLE_CONTEXT_TRY(mImplementation->finish(this));
}

void Context::insertEventMarker(GLsizei length, const char *marker)
{
    if (length < 0 || marker == nullptr)
    {
        return;  // no-op, not an error
    }

    // If <length> is 0 then <marker> is assumed to be null-terminated.
    ANGLE_CONTEXT_TRY(mImplementation->insertEventMarker(
        GetMarkerLength(length, marker, static_cast<GLsizei>(getCaps().maxDebugMessageLength)),
        marker));
}

void Context::pushGroupMarker(GLsizei length, const char *marker)
{
    ASSERT(mState.getGroupMarkerCount() < getCaps().maxDebugGroupStackDepth);
    if (length < 0)
    {
        return;  // no-op, not an error
    }

    if (marker == nullptr)
    {
        // If <marker> is null then an empty string is pushed on the stack.
        ANGLE_CONTEXT_TRY(mImplementation->pushGroupMarker(0, ""));
    }
    else
    {
        // If <length> is 0 then <marker> is assumed to be null-terminated.
        ANGLE_CONTEXT_TRY(mImplementation->pushGroupMarker(
            GetMarkerLength(length, marker, static_cast<GLsizei>(getCaps().maxDebugMessageLength)),
            marker));
    }
    mState.incrementGroupMarkers();
}

void Context::popGroupMarker()
{
    // According to the spec, if there is no group marker to pop, the pop command should be ignored.
    if (mState.getGroupMarkerCount() == 0)
    {
        return;
    }
    ANGLE_CONTEXT_TRY(mImplementation->popGroupMarker());
    mState.decrementGroupMarkers();
}

void Context::bindUniformLocation(ShaderProgramID program,
                                  UniformLocation location,
                                  const GLchar *name)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);

    programObject->bindUniformLocation(this, location, name);
}

GLuint Context::getProgramResourceIndex(ShaderProgramID program,
                                        GLenum programInterface,
                                        const GLchar *name)
{
    const Program *programObject = getProgramResolveLink(program);
    return QueryProgramResourceIndex(programObject, programInterface, name);
}

void Context::getProgramResourceName(ShaderProgramID program,
                                     GLenum programInterface,
                                     GLuint index,
                                     GLsizei bufSize,
                                     GLsizei *length,
                                     GLchar *name)
{
    const Program *programObject = getProgramResolveLink(program);
    QueryProgramResourceName(this, programObject, programInterface, index, bufSize, length, name);
}

GLint Context::getProgramResourceLocation(ShaderProgramID program,
                                          GLenum programInterface,
                                          const GLchar *name)
{
    const Program *programObject = getProgramResolveLink(program);
    return QueryProgramResourceLocation(programObject, programInterface, name);
}

void Context::getProgramResourceiv(ShaderProgramID program,
                                   GLenum programInterface,
                                   GLuint index,
                                   GLsizei propCount,
                                   const GLenum *props,
                                   GLsizei count,
                                   GLsizei *length,
                                   GLint *params)
{
    const Program *programObject = getProgramResolveLink(program);
    QueryProgramResourceiv(programObject, programInterface, {index}, propCount, props, count,
                           length, params);
}

void Context::getProgramInterfaceiv(ShaderProgramID program,
                                    GLenum programInterface,
                                    GLenum pname,
                                    GLint *params)
{
    const Program *programObject = getProgramResolveLink(program);
    QueryProgramInterfaceiv(programObject, programInterface, pname, params);
}

void Context::handleError(GLenum errorCode,
                          const char *message,
                          const char *file,
                          const char *function,
                          unsigned int line)
{
    mErrors.handleError(errorCode, message, file, function, line);
}

// Get one of the recorded errors and clear its flag, if any.
// [OpenGL ES 2.0.24] section 2.5 page 13.
GLenum Context::getError()
{
    if (mErrors.empty())
    {
        return GL_NO_ERROR;
    }
    else
    {
        return mErrors.popError();
    }
}

GLenum Context::getGraphicsResetStatus()
{
    return mErrors.getGraphicsResetStatus(mImplementation.get());
}

bool Context::isResetNotificationEnabled() const
{
    return mErrors.getResetStrategy() == GL_LOSE_CONTEXT_ON_RESET_EXT;
}

EGLenum Context::getRenderBuffer() const
{
    const Framebuffer *framebuffer =
        mState.mFramebufferManager->getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
    if (framebuffer == nullptr)
    {
        return EGL_NONE;
    }

    const FramebufferAttachment *backAttachment = framebuffer->getAttachment(this, GL_BACK);
    ASSERT(backAttachment != nullptr);
    return backAttachment->getSurface()->getRenderBuffer();
}

// This function should only be called by the thread where the context is current (i.e., it's not
// thread safe).
VertexArray *Context::checkVertexArrayAllocation(VertexArrayID vertexArrayHandle)
{
    // Only called after a prior call to Gen.
    VertexArray *vertexArray = getPrivateState().getVertexArray(vertexArrayHandle);
    if (!vertexArray)
    {
        vertexArray = new VertexArray(mImplementation.get(), vertexArrayHandle,
                                      mState.getCaps().maxVertexAttributes,
                                      mState.getCaps().maxVertexAttribBindings);
        vertexArray->setRobustBufferAccessEnabled(mRequiresRobustBehavior);

        getMutablePrivateState()->setVertexArray(vertexArrayHandle, vertexArray);
    }

    return vertexArray;
}

TransformFeedback *Context::checkTransformFeedbackAllocation(
    TransformFeedbackID transformFeedbackHandle)
{
    // Only called after a prior call to Gen.
    TransformFeedback *transformFeedback = getTransformFeedback(transformFeedbackHandle);
    if (!transformFeedback)
    {
        transformFeedback =
            new TransformFeedback(mImplementation.get(), transformFeedbackHandle, mState.getCaps());
        transformFeedback->addRef();
        mTransformFeedbackMap.assign(transformFeedbackHandle, transformFeedback);
    }

    return transformFeedback;
}

bool Context::isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const
{
    ASSERT(mTransformFeedbackMap.contains({0}));
    return mTransformFeedbackMap.contains(transformFeedback);
}

bool Context::isZeroTextureBound(TextureType textureType) const
{
    Texture *texture = mState.getTargetTexture(textureType);
    return mZeroTextures[textureType].get() == texture;
}

void Context::detachTexture(TextureID texture)
{
    // The State cannot unbind image observers itself, they are owned by the Context
    Texture *tex = mState.mTextureManager->getTexture(texture);
    for (auto &imageBinding : mImageObserverBindings)
    {
        if (imageBinding.getSubject() == tex)
        {
            imageBinding.reset();
        }
    }

    // Simple pass-through to State's detachTexture method, as textures do not require
    // allocation map management either here or in the resource manager at detach time.
    // Zero textures are held by the Context, and we don't attempt to request them from
    // the State.
    mState.detachTexture(this, mZeroTextures, texture);
}

void Context::detachBuffer(Buffer *buffer)
{
    // Simple pass-through to State's detachBuffer method, since
    // only buffer attachments to container objects that are bound to the current context
    // should be detached. And all those are available in State.

    // [OpenGL ES 3.2] section 5.1.2 page 45:
    // Attachments to unbound container objects, such as
    // deletion of a buffer attached to a vertex array object which is not bound to the context,
    // are not affected and continue to act as references on the deleted object
    ANGLE_CONTEXT_TRY(mState.detachBuffer(this, buffer));
}

void Context::detachFramebuffer(FramebufferID framebuffer)
{
    // Framebuffer detachment is handled by Context, because 0 is a valid
    // Framebuffer object, and a pointer to it must be passed from Context
    // to State at binding time.

    // [OpenGL ES 2.0.24] section 4.4 page 107:
    // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as
    // though BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of
    // zero.

    if (mState.removeReadFramebufferBinding(framebuffer) && framebuffer.value != 0)
    {
        bindReadFramebuffer({0});
    }

    if (mState.removeDrawFramebufferBinding(framebuffer) && framebuffer.value != 0)
    {
        bindDrawFramebuffer({0});
    }
}

void Context::detachRenderbuffer(RenderbufferID renderbuffer)
{
    mState.detachRenderbuffer(this, renderbuffer);
}

void Context::detachVertexArray(VertexArrayID vertexArray)
{
    // Vertex array detachment is handled by Context, because 0 is a valid
    // VAO, and a pointer to it must be passed from Context to State at
    // binding time.

    // [OpenGL ES 3.0.2] section 2.10 page 43:
    // If a vertex array object that is currently bound is deleted, the binding
    // for that object reverts to zero and the default vertex array becomes current.
    if (mState.removeVertexArrayBinding(this, vertexArray))
    {
        bindVertexArray({0});
    }
}

void Context::detachTransformFeedback(TransformFeedbackID transformFeedback)
{
    // Transform feedback detachment is handled by Context, because 0 is a valid
    // transform feedback, and a pointer to it must be passed from Context to State at
    // binding time.

    // The OpenGL specification doesn't mention what should happen when the currently bound
    // transform feedback object is deleted. Since it is a container object, we treat it like
    // VAOs and FBOs and set the current bound transform feedback back to 0.
    if (mState.removeTransformFeedbackBinding(this, transformFeedback))
    {
        bindTransformFeedback(GL_TRANSFORM_FEEDBACK, {0});
        onActiveTransformFeedbackChange();
    }
}

void Context::detachSampler(SamplerID sampler)
{
    mState.detachSampler(this, sampler);
}

void Context::detachProgramPipeline(ProgramPipelineID pipeline)
{
    mState.detachProgramPipeline(this, pipeline);
}

void Context::samplerParameteri(SamplerID samplerPacked, SamplerParameter pnamePacked, GLint param)
{
    Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    SetSamplerParameteriv(this, samplerObject, pnamePacked, &param);
}

void Context::samplerParameteriv(SamplerID samplerPacked,
                                 SamplerParameter pnamePacked,
                                 const GLint *param)
{
    Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    SetSamplerParameteriv(this, samplerObject, pnamePacked, param);
}

void Context::samplerParameterIiv(SamplerID samplerPacked,
                                  SamplerParameter pnamePacked,
                                  const GLint *param)
{
    Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    SetSamplerParameterIiv(this, samplerObject, pnamePacked, param);
}

void Context::samplerParameterIuiv(SamplerID samplerPacked,
                                   SamplerParameter pnamePacked,
                                   const GLuint *param)
{
    Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    SetSamplerParameterIuiv(this, samplerObject, pnamePacked, param);
}

void Context::samplerParameterivRobust(SamplerID samplerPacked,
                                       SamplerParameter pnamePacked,
                                       GLsizei paramCount,
                                       const GLint *param)
{
    samplerParameteriv(samplerPacked, pnamePacked, param);
}

void Context::samplerParameterf(SamplerID samplerPacked,
                                SamplerParameter pnamePacked,
                                GLfloat param)
{
    Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    SetSamplerParameterfv(this, samplerObject, pnamePacked, &param);
}

void Context::samplerParameterfv(SamplerID samplerPacked,
                                 SamplerParameter pnamePacked,
                                 const GLfloat *param)
{
    Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    SetSamplerParameterfv(this, samplerObject, pnamePacked, param);
}

void Context::samplerParameterfvRobust(SamplerID samplerPacked,
                                       SamplerParameter pnamePacked,
                                       GLsizei paramCount,
                                       const GLfloat *param)
{
    samplerParameterfv(samplerPacked, pnamePacked, param);
}

void Context::getSamplerParameteriv(SamplerID samplerPacked,
                                    SamplerParameter pnamePacked,
                                    GLint *params)
{
    const Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    QuerySamplerParameteriv(samplerObject, pnamePacked, params);
}

void Context::getSamplerParameterIiv(SamplerID samplerPacked,
                                     SamplerParameter pnamePacked,
                                     GLint *params)
{
    const Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    QuerySamplerParameterIiv(samplerObject, pnamePacked, params);
}

void Context::getSamplerParameterIuiv(SamplerID samplerPacked,
                                      SamplerParameter pnamePacked,
                                      GLuint *params)
{
    const Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    QuerySamplerParameterIuiv(samplerObject, pnamePacked, params);
}

void Context::getSamplerParameterivRobust(SamplerID samplerPacked,
                                          SamplerParameter pnamePacked,
                                          GLsizei paramCount,
                                          GLsizei *length,
                                          GLint *params)
{
    getSamplerParameteriv(samplerPacked, pnamePacked, params);

    if (length != nullptr)
    {
        *length = (pnamePacked == SamplerParameter::BorderColor) ? 4 : 1;
    }
}

void Context::getSamplerParameterfv(SamplerID samplerPacked,
                                    SamplerParameter pnamePacked,
                                    GLfloat *params)
{
    const Sampler *const samplerObject =
        mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerPacked);
    QuerySamplerParameterfv(samplerObject, pnamePacked, params);
}

void Context::getSamplerParameterfvRobust(SamplerID samplerPacked,
                                          SamplerParameter pnamePacked,
                                          GLsizei paramCount,
                                          GLsizei *length,
                                          GLfloat *params)
{
    getSamplerParameterfv(samplerPacked, pnamePacked, params);

    if (length != nullptr)
    {
        *length = (pnamePacked == SamplerParameter::BorderColor) ? 4 : 1;
    }
}

void Context::programParameteri(ShaderProgramID program, GLenum pname, GLint value)
{
    gl::Program *programObject = getProgramResolveLink(program);
    SetProgramParameteri(this, programObject, pname, value);
}

const char *Context::makeStaticString(const std::string &str)
{
    auto it = mStaticStrings.find(str);
    if (it != mStaticStrings.end())
    {
        return it->c_str();
    }

    return mStaticStrings.insert(str).first->c_str();
}

void Context::initRendererString()
{
    std::ostringstream frontendRendererString;

    constexpr char kRendererString[]        = "ANGLE_GL_RENDERER";
    constexpr char kAndroidRendererString[] = "debug.angle.gl_renderer";

    std::string overrideRenderer =
        angle::GetEnvironmentVarOrAndroidProperty(kRendererString, kAndroidRendererString);
    if (!overrideRenderer.empty())
    {
        frontendRendererString << overrideRenderer;
    }
    else
    {
        std::string vendorString(mDisplay->getBackendVendorString());
        std::string rendererString(mDisplay->getBackendRendererDescription());
        std::string versionString(mDisplay->getBackendVersionString(!isWebGL()));
        // Commas are used as a separator in ANGLE's renderer string, so remove commas from each
        // element.
        vendorString.erase(std::remove(vendorString.begin(), vendorString.end(), ','),
                           vendorString.end());
        rendererString.erase(std::remove(rendererString.begin(), rendererString.end(), ','),
                             rendererString.end());
        versionString.erase(std::remove(versionString.begin(), versionString.end(), ','),
                            versionString.end());
        frontendRendererString << "ANGLE (";
        frontendRendererString << vendorString;
        frontendRendererString << ", ";
        frontendRendererString << rendererString;
        frontendRendererString << ", ";
        frontendRendererString << versionString;
        frontendRendererString << ")";
    }

    mRendererString = makeStaticString(frontendRendererString.str());
}

void Context::initVendorString()
{
    std::ostringstream vendorString;

    constexpr char kVendorString[]        = "ANGLE_GL_VENDOR";
    constexpr char kAndroidVendorString[] = "debug.angle.gl_vendor";

    std::string overrideVendor =
        angle::GetEnvironmentVarOrAndroidProperty(kVendorString, kAndroidVendorString);

    if (!overrideVendor.empty())
    {
        vendorString << overrideVendor;
    }
    else
    {
        vendorString << mDisplay->getVendorString();
    }

    mVendorString = makeStaticString(vendorString.str());
}

void Context::initVersionStrings()
{
    const Version &clientVersion = getClientVersion();

    std::ostringstream versionString;

    constexpr char kVersionString[]        = "ANGLE_GL_VERSION";
    constexpr char kAndroidVersionString[] = "debug.angle.gl_version";

    std::string overrideVersion =
        angle::GetEnvironmentVarOrAndroidProperty(kVersionString, kAndroidVersionString);

    if (!overrideVersion.empty())
    {
        versionString << overrideVersion;
    }
    else
    {
        versionString << "OpenGL ES ";
        versionString << clientVersion.getMajor() << "." << clientVersion.getMinor() << " (ANGLE "
                      << angle::GetANGLEVersionString() << ")";
    }

    mVersionString = makeStaticString(versionString.str());

    std::ostringstream shadingLanguageVersionString;
    shadingLanguageVersionString << "OpenGL ES GLSL ES ";
    shadingLanguageVersionString << (clientVersion.getMajor() == 2 ? 1 : clientVersion.getMajor())
                                 << "." << clientVersion.getMinor() << "0 (ANGLE "
                                 << angle::GetANGLEVersionString() << ")";
    mShadingLanguageString = makeStaticString(shadingLanguageVersionString.str());
}

void Context::initExtensionStrings()
{
    auto mergeExtensionStrings = [this](const std::vector<const char *> &strings) {
        std::ostringstream combinedStringStream;
        std::copy(strings.begin(), strings.end(),
                  std::ostream_iterator<const char *>(combinedStringStream, " "));
        return makeStaticString(combinedStringStream.str());
    };

    mExtensionStrings.clear();
    for (const auto &extensionString : mState.getExtensions().getStrings())
    {
        mExtensionStrings.push_back(makeStaticString(extensionString));
    }
    mExtensionString = mergeExtensionStrings(mExtensionStrings);

    mRequestableExtensionStrings.clear();
    for (const auto &extensionInfo : GetExtensionInfoMap())
    {
        if (extensionInfo.second.Requestable &&
            !(mState.getExtensions().*(extensionInfo.second.ExtensionsMember)) &&
            mSupportedExtensions.*(extensionInfo.second.ExtensionsMember))
        {
            mRequestableExtensionStrings.push_back(makeStaticString(extensionInfo.first));
        }
    }
    mRequestableExtensionString = mergeExtensionStrings(mRequestableExtensionStrings);
}

const GLubyte *Context::getString(GLenum name)
{
    return static_cast<const Context *>(this)->getString(name);
}

const GLubyte *Context::getStringi(GLenum name, GLuint index)
{
    return static_cast<const Context *>(this)->getStringi(name, index);
}

const GLubyte *Context::getString(GLenum name) const
{
    switch (name)
    {
        case GL_VENDOR:
            return AsGLubytePtr(mVendorString);

        case GL_RENDERER:
            return AsGLubytePtr(mRendererString);

        case GL_VERSION:
            return AsGLubytePtr(mVersionString);

        case GL_SHADING_LANGUAGE_VERSION:
            return AsGLubytePtr(mShadingLanguageString);

        case GL_EXTENSIONS:
            return AsGLubytePtr(mExtensionString);

        case GL_REQUESTABLE_EXTENSIONS_ANGLE:
            return AsGLubytePtr(mRequestableExtensionString);

        case GL_SERIALIZED_CONTEXT_STRING_ANGLE:
            if (angle::SerializeContextToString(this, &mCachedSerializedStateString) ==
                angle::Result::Continue)
            {
                return AsGLubytePtr(mCachedSerializedStateString.c_str());
            }
            else
            {
                return nullptr;
            }

        default:
            UNREACHABLE();
            return nullptr;
    }
}

const GLubyte *Context::getStringi(GLenum name, GLuint index) const
{
    switch (name)
    {
        case GL_EXTENSIONS:
            return AsGLubytePtr(mExtensionStrings[index]);

        case GL_REQUESTABLE_EXTENSIONS_ANGLE:
            return AsGLubytePtr(mRequestableExtensionStrings[index]);

        default:
            UNREACHABLE();
            return nullptr;
    }
}

size_t Context::getExtensionStringCount() const
{
    return mExtensionStrings.size();
}

bool Context::isExtensionRequestable(const char *name) const
{
    const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
    auto extension                         = extensionInfos.find(name);

    return extension != extensionInfos.end() && extension->second.Requestable &&
           mSupportedExtensions.*(extension->second.ExtensionsMember);
}

void Context::requestExtension(const char *name)
{
    const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
    ASSERT(extensionInfos.find(name) != extensionInfos.end());
    const auto &extension = extensionInfos.at(name);
    ASSERT(extension.Requestable);
    ASSERT(isExtensionRequestable(name));

    if (mState.getExtensions().*(extension.ExtensionsMember))
    {
        // No change
        return;
    }

    mState.getMutableExtensions()->*(extension.ExtensionsMember) = true;

    // Handle extension dependencies
    {
        if (strcmp(name, "GL_OVR_multiview2") == 0)
        {
            // OVR_multiview is implicitly enabled when OVR_multiview2 is enabled
            requestExtension("GL_OVR_multiview");
        }
        else if (strcmp(name, "GL_OES_texture_storage_multisample_2d_array") == 0)
        {
            // This extension implies that the context supports multisample 2D textures
            // so ANGLE_texture_multisample must be enabled implicitly here.
            requestExtension("GL_ANGLE_texture_multisample");
        }
        else if (strcmp(name, "GL_ANGLE_shader_pixel_local_storage") == 0 ||
                 strcmp(name, "GL_ANGLE_shader_pixel_local_storage_coherent") == 0)
        {
            // ANGLE_shader_pixel_local_storage/ANGLE_shader_pixel_local_storage_coherent have
            // various dependency extensions, including each other.
            const auto enableIfRequestable = [this](const char *extensionName) {
                for (const char *requestableExtension : mRequestableExtensionStrings)
                {
                    if (strcmp(extensionName, requestableExtension) == 0)
                    {
                        requestExtension(extensionName);
                        return;
                    }
                }
            };
            enableIfRequestable("GL_OES_draw_buffers_indexed");
            enableIfRequestable("GL_EXT_draw_buffers_indexed");
            enableIfRequestable("GL_EXT_shader_framebuffer_fetch_non_coherent");
            enableIfRequestable("GL_ANGLE_shader_pixel_local_storage_coherent");
            enableIfRequestable("GL_ANGLE_shader_pixel_local_storage");
        }
    }

    reinitializeAfterExtensionsChanged();
}

void Context::reinitializeAfterExtensionsChanged()
{
    updateCaps();
    initExtensionStrings();

    // Release the shader compiler so it will be re-created with the requested extensions enabled.
    releaseShaderCompiler();

    // Invalidate all textures and framebuffer. Some extensions make new formats renderable or
    // sampleable.
    mState.mTextureManager->signalAllTexturesDirty();
    for (auto &zeroTexture : mZeroTextures)
    {
        if (zeroTexture.get() != nullptr)
        {
            zeroTexture->signalDirtyStorage(InitState::Initialized);
        }
    }

    mState.mFramebufferManager->invalidateFramebufferCompletenessCache();
}

size_t Context::getRequestableExtensionStringCount() const
{
    return mRequestableExtensionStrings.size();
}

void Context::beginTransformFeedback(PrimitiveMode primitiveMode)
{
    TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback();
    ASSERT(transformFeedback != nullptr);
    ASSERT(!transformFeedback->isPaused());

    // TODO: http://anglebug.com/42265705: Handle PPOs
    // Since programs should override PPOs, no PPO is passed to the transform feedback if a program
    // is active.
    Program *program                 = mState.getProgram();
    ProgramPipeline *programPipeline = program == nullptr ? mState.getProgramPipeline() : nullptr;
    ANGLE_CONTEXT_TRY(transformFeedback->begin(this, primitiveMode, program, programPipeline));
    onActiveTransformFeedbackChange();
}

bool Context::hasActiveTransformFeedback(ShaderProgramID program) const
{
    // Note: transform feedback objects are private to context and so the map doesn't need locking
    for (auto pair : UnsafeResourceMapIter(mTransformFeedbackMap))
    {
        if (pair.second != nullptr && pair.second->hasBoundProgram(program))
        {
            return true;
        }
    }
    return false;
}

Extensions Context::generateSupportedExtensions() const
{
    Extensions supportedExtensions = mImplementation->getNativeExtensions();

    if (getClientVersion() < ES_2_0)
    {
        // Default extensions for GLES1
        supportedExtensions.blendSubtractOES         = true;
        supportedExtensions.pointSizeArrayOES        = true;
        supportedExtensions.textureCubeMapOES        = true;
        supportedExtensions.textureMirroredRepeatOES = true;
        supportedExtensions.pointSpriteOES           = true;
        supportedExtensions.drawTextureOES           = true;
        supportedExtensions.framebufferObjectOES     = true;
        supportedExtensions.stencil8OES              = true;
        supportedExtensions.parallelShaderCompileKHR = false;
        supportedExtensions.texture3DOES             = false;
        supportedExtensions.clipDistanceAPPLE        = false;
        supportedExtensions.disjointTimerQueryEXT    = false;
        supportedExtensions.robustnessKHR            = false;

        supportedExtensions.blendEquationAdvancedKHR         = false;
        supportedExtensions.blendEquationAdvancedCoherentKHR = false;
    }

    if (getClientVersion() < ES_3_0)
    {
        // Disable ES3+ extensions
        supportedExtensions.colorBufferFloatEXT                     = false;
        supportedExtensions.EGLImageExternalEssl3OES                = false;
        supportedExtensions.multiviewOVR                            = false;
        supportedExtensions.multiview2OVR                           = false;
        supportedExtensions.multiviewMultisampleANGLE               = false;
        supportedExtensions.multiviewMultisampledRenderToTextureOVR = false;
        supportedExtensions.copyTexture3dANGLE                      = false;
        supportedExtensions.textureMultisampleANGLE                 = false;
        supportedExtensions.textureQueryLodEXT                      = false;
        supportedExtensions.textureShadowLodEXT                     = false;
        supportedExtensions.textureStorageCompressionEXT            = false;
        supportedExtensions.textureStencil8OES                      = false;
        supportedExtensions.conservativeDepthEXT                    = false;
        supportedExtensions.drawBuffersIndexedEXT                   = false;
        supportedExtensions.drawBuffersIndexedOES                   = false;
        supportedExtensions.EGLImageArrayEXT                        = false;
        supportedExtensions.stencilTexturingANGLE                   = false;
        supportedExtensions.textureFormatSRGBOverrideEXT            = false;
        supportedExtensions.renderSharedExponentQCOM                = false;
        supportedExtensions.renderSnormEXT                          = false;
        supportedExtensions.textureNorm16EXT                        = false;

        // Requires immutable textures
        supportedExtensions.yuvInternalFormatANGLE = false;

        // Require ESSL 3.0
        supportedExtensions.shaderMultisampleInterpolationOES  = false;
        supportedExtensions.shaderNoperspectiveInterpolationNV = false;
        supportedExtensions.sampleVariablesOES                 = false;

        // Require RED and RG formats
        supportedExtensions.textureSRGBR8EXT  = false;
        supportedExtensions.textureSRGBRG8EXT = false;

        // Requires glCompressedTexImage3D
        supportedExtensions.textureCompressionAstcOES = false;

        // Don't expose GL_EXT_texture_sRGB_decode without sRGB texture support
        if (!supportedExtensions.sRGBEXT)
        {
            supportedExtensions.textureSRGBDecodeEXT = false;
        }

        // Don't expose GL_OES_texture_float_linear without full legacy float texture support
        // The renderer may report OES_texture_float_linear without OES_texture_float
        // This is valid in a GLES 3.0 context, but not in a GLES 2.0 context
        if (!(supportedExtensions.textureFloatOES && supportedExtensions.textureHalfFloatOES))
        {
            supportedExtensions.textureFloatLinearOES     = false;
            supportedExtensions.textureHalfFloatLinearOES = false;
        }

        // Because of the difference in the SNORM to FLOAT conversion formula
        // between GLES 2.0 and 3.0, vertex type 10_10_10_2 is disabled
        // when the context version is lower than 3.0
        supportedExtensions.vertexType1010102OES = false;

        // GL_EXT_EGL_image_storage requires ESSL3
        supportedExtensions.EGLImageStorageEXT = false;

        // GL_EXT_YUV_target requires ESSL3
        supportedExtensions.YUVTargetEXT = false;

        // GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance require ESSL3
        supportedExtensions.clipCullDistanceEXT   = false;
        supportedExtensions.clipCullDistanceANGLE = false;

        // ANGLE_shader_pixel_local_storage requires ES3
        supportedExtensions.shaderPixelLocalStorageANGLE         = false;
        supportedExtensions.shaderPixelLocalStorageCoherentANGLE = false;

        // Multisample arrays could be supported on ES 3.0
        // although the extension spec requires ES 3.1.
        supportedExtensions.textureStorageMultisample2dArrayOES = false;
    }

    if (getClientVersion() < ES_3_1)
    {
        // Disable ES3.1+ extensions
        supportedExtensions.geometryShaderEXT       = false;
        supportedExtensions.geometryShaderOES       = false;
        supportedExtensions.gpuShader5EXT           = false;
        supportedExtensions.gpuShader5OES           = false;
        supportedExtensions.multiDrawIndirectEXT    = false;
        supportedExtensions.primitiveBoundingBoxEXT = false;
        supportedExtensions.primitiveBoundingBoxOES = false;
        supportedExtensions.shaderImageAtomicOES    = false;
        supportedExtensions.shaderIoBlocksEXT       = false;
        supportedExtensions.shaderIoBlocksOES       = false;
        supportedExtensions.tessellationShaderEXT   = false;
        supportedExtensions.tessellationShaderOES   = false;
        supportedExtensions.textureBufferEXT        = false;
        supportedExtensions.textureBufferOES        = false;
        supportedExtensions.textureCubeMapArrayEXT  = false;
        supportedExtensions.textureCubeMapArrayOES  = false;
    }

    if (getClientVersion() > ES_2_0)
    {
        // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
        // supportedExtensions.sRGB = false;

        // If colorBufferFloatEXT is disabled but colorBufferHalfFloatEXT is enabled, then we will
        // expose some floating-point formats as color buffer targets but reject blits between
        // fixed-point and floating-point formats (this behavior is only enabled in
        // colorBufferFloatEXT, and must be rejected if only colorBufferHalfFloatEXT is enabled).
        // dEQP does not check for this, and will assume that floating-point and fixed-point formats
        // can be blit onto each other if the format is available.
        // We require colorBufferFloatEXT to be present in order to enable colorBufferHalfFloatEXT,
        // so that blitting is always allowed if the requested formats are exposed and have the
        // correct feature capabilities. WebGL 2 wants to support colorBufferHalfFloatEXT without
        // colorBufferFloatEXT.
        if (!supportedExtensions.colorBufferFloatEXT && !mWebGLContext)
        {
            supportedExtensions.colorBufferHalfFloatEXT = false;
        }

        // Disable support for CHROMIUM_color_buffer_float_rgb[a] in ES 3.0+, these extensions are
        // non-conformant in ES 3.0 and superseded by EXT_color_buffer_float.
        supportedExtensions.colorBufferFloatRgbCHROMIUM  = false;
        supportedExtensions.colorBufferFloatRgbaCHROMIUM = false;

        // In WebGL2, WebGL1 extensions whose functionality is present in core are not exposed.
        // This information can be found by comparing
        // WebGLRenderingContext::RegisterContextExtensions() and
        // WebGL2RenderingContext::RegisterContextExtensions() in Blink code.
        if (mWebGLContext)
        {
            supportedExtensions.instancedArraysANGLE         = false;
            supportedExtensions.blendMinmaxEXT               = false;
            supportedExtensions.fragDepthEXT                 = false;
            supportedExtensions.shaderTextureLodEXT          = false;
            supportedExtensions.sRGBEXT                      = false;
            supportedExtensions.elementIndexUintOES          = false;
            supportedExtensions.fboRenderMipmapOES           = false;
            supportedExtensions.standardDerivativesOES       = false;
            supportedExtensions.textureFloatOES              = false;
            supportedExtensions.textureHalfFloatLinearOES    = false;
            supportedExtensions.vertexArrayObjectOES         = false;
            supportedExtensions.colorBufferFloatRgbCHROMIUM  = false;
            supportedExtensions.colorBufferFloatRgbaCHROMIUM = false;
            supportedExtensions.depthTextureANGLE            = false;
            supportedExtensions.drawBuffersEXT               = false;
        }
    }

    if (getClientVersion() >= ES_3_0)
    {
        // Enable this extension for GLES3+.
        supportedExtensions.renderabilityValidationANGLE = true;
    }

    if (getFrontendFeatures().disableAnisotropicFiltering.enabled)
    {
        supportedExtensions.textureFilterAnisotropicEXT = false;
    }

    if (!getFrontendFeatures().emulatePixelLocalStorage.enabled)
    {
        supportedExtensions.shaderPixelLocalStorageANGLE         = false;
        supportedExtensions.shaderPixelLocalStorageCoherentANGLE = false;
    }

    // Some extensions are always available because they are implemented in the GL layer.
    supportedExtensions.bindUniformLocationCHROMIUM      = true;
    supportedExtensions.vertexArrayObjectOES             = true;
    supportedExtensions.bindGeneratesResourceCHROMIUM    = true;
    supportedExtensions.clientArraysANGLE                = true;
    supportedExtensions.requestExtensionANGLE            = true;
    supportedExtensions.multiDrawANGLE                   = true;
    supportedExtensions.programBinaryReadinessQueryANGLE = true;

    const Limitations &limitations                  = getLimitations();
    const angle::FrontendFeatures &frontendFeatures = mDisplay->getFrontendFeatures();

    if (limitations.multidrawEmulated &&
        !frontendFeatures.alwaysEnableEmulatedMultidrawExtensions.enabled && !mWebGLContext)
    {
        supportedExtensions.multiDrawANGLE       = false;
        supportedExtensions.multiDrawIndirectEXT = false;
    }

    if (limitations.baseInstanceBaseVertexEmulated &&
        !frontendFeatures.alwaysEnableEmulatedMultidrawExtensions.enabled && !mWebGLContext)
    {
        supportedExtensions.baseVertexBaseInstanceANGLE = false;
    }

    // Enable the no error extension if the context was created with the flag.
    supportedExtensions.noErrorKHR = skipValidation();

    // Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
    supportedExtensions.surfacelessContextOES = mSurfacelessSupported;

    // Explicitly enable GL_KHR_debug
    supportedExtensions.debugKHR = true;

    // Explicitly enable GL_EXT_debug_label
    supportedExtensions.debugLabelEXT = true;

    // Explicitly enable GL_ANGLE_robust_client_memory if the context supports validation.
    supportedExtensions.robustClientMemoryANGLE = !skipValidation();

    // Determine robust resource init availability from EGL.
    supportedExtensions.robustResourceInitializationANGLE = mState.isRobustResourceInitEnabled();

    // mState.getExtensions().robustBufferAccessBehaviorKHR is true only if robust access is true
    // and the backend supports it.
    supportedExtensions.robustBufferAccessBehaviorKHR =
        mState.hasRobustAccess() && supportedExtensions.robustBufferAccessBehaviorKHR;

    // Enable the cache control query unconditionally.
    supportedExtensions.programCacheControlANGLE = true;

    // If EGL_KHR_fence_sync is not enabled, don't expose GL_OES_EGL_sync.
    ASSERT(mDisplay);
    if (!mDisplay->getExtensions().fenceSync)
    {
        supportedExtensions.EGLSyncOES = false;
    }

    if (mDisplay->getExtensions().robustnessVideoMemoryPurgeNV)
    {
        supportedExtensions.robustnessVideoMemoryPurgeNV = true;
    }

    supportedExtensions.memorySizeANGLE = true;

    // GL_CHROMIUM_lose_context is implemented in the frontend
    supportedExtensions.loseContextCHROMIUM = true;

    // The ASTC texture extensions have dependency requirements.
    if (supportedExtensions.textureCompressionAstcHdrKHR ||
        supportedExtensions.textureCompressionAstcSliced3dKHR)
    {
        // GL_KHR_texture_compression_astc_hdr cannot be exposed without also exposing
        // GL_KHR_texture_compression_astc_ldr
        ASSERT(supportedExtensions.textureCompressionAstcLdrKHR);
    }

    if (supportedExtensions.textureCompressionAstcOES)
    {
        // GL_OES_texture_compression_astc cannot be exposed without also exposing
        // GL_KHR_texture_compression_astc_ldr and GL_KHR_texture_compression_astc_hdr
        ASSERT(supportedExtensions.textureCompressionAstcLdrKHR);
        ASSERT(supportedExtensions.textureCompressionAstcHdrKHR);
    }

    if (supportedExtensions.textureCompressionAstcDecodeModeEXT ||
        supportedExtensions.textureCompressionAstcDecodeModeRgb9e5EXT)
    {
        // GL_KHR_texture_compression_astc_hdr,
        // GL_KHR_texture_compression_astc_ldr,
        // or GL_OES_texture_compression_astc is required.
        ASSERT(supportedExtensions.textureCompressionAstcOES ||
               supportedExtensions.textureCompressionAstcLdrKHR ||
               supportedExtensions.textureCompressionAstcHdrKHR);
    }

    // GL_KHR_protected_textures
    // If EGL_KHR_protected_content is not supported then GL_EXT_protected_texture
    // can not be supported.
    if (!mDisplay->getExtensions().protectedContentEXT)
    {
        supportedExtensions.protectedTexturesEXT = false;
    }

    // GL_ANGLE_get_tex_level_parameter is implemented in the front-end
    supportedExtensions.getTexLevelParameterANGLE = true;

    // Always enabled. Will return a default string if capture is not enabled.
    supportedExtensions.getSerializedContextStringANGLE = true;

    // Performance counter queries are always supported. Different groups exist on each back-end.
    supportedExtensions.performanceMonitorAMD = true;

    // GL_ANDROID_extension_pack_es31a
    supportedExtensions.extensionPackEs31aANDROID =
        CanSupportAEP(getClientVersion(), supportedExtensions);

    // Blob cache extension is provided by the ANGLE frontend
    supportedExtensions.blobCacheANGLE = true;

    // Disable extensions that are implemented through shader compiler transformations or require
    // shader translator reflection data
    if (mState.usesPassthroughShaders())
    {
        supportedExtensions.multiDrawANGLE                       = false;
        supportedExtensions.shaderPixelLocalStorageANGLE         = false;
        supportedExtensions.shaderPixelLocalStorageCoherentANGLE = false;
        supportedExtensions.blendFuncExtendedEXT                 = false;
        if (frontendFeatures.clipCullDistanceBrokenWithPassthroughShaders.enabled)
        {
            supportedExtensions.clipCullDistanceEXT = false;
        }
        if (frontendFeatures.noperspectiveInterpolationBrokenWithPassthroughShaders.enabled)
        {
            supportedExtensions.shaderNoperspectiveInterpolationNV = false;
        }
    }

// Disable the explicit context extension if the entry points are not compiled.
#if !defined(ANGLE_ENABLE_EXPLICIT_CONTEXT)
    supportedExtensions.explicitContextANGLE = false;
#endif

    return supportedExtensions;
}

void Context::initCaps()
{
    Caps *caps = mState.getMutableCaps();
    *caps      = mImplementation->getNativeCaps();

    // Update limitations before evaluating extension support
    {
        gl::Limitations implementationLimitations = mImplementation->getNativeLimitations();

        if (mDisplay->getFrontendFeatures().limitMaxBufferBytesTo1MB.enabled)
        {
            implementationLimitations.maxBufferBytes = 1 << 20;
        }
        if (mDisplay->getFrontendFeatures().limitMaxTextureBytesTo1MB.enabled)
        {
            implementationLimitations.maxTextureBytes = 1 << 20;
        }
        *mState.getMutableLimitations() = implementationLimitations;
    }

    // TODO (http://anglebug.com/42264543): mSupportedExtensions should not be modified here
    mSupportedExtensions = generateSupportedExtensions();

    if (!mDisplay->getFrontendFeatures().allowCompressedFormats.enabled)
    {
        INFO() << "Limiting compressed format support.\n";

        mSupportedExtensions.compressedETC1RGB8SubTextureEXT                 = false;
        mSupportedExtensions.compressedETC1RGB8TextureOES                    = false;
        mSupportedExtensions.compressedTextureEtcANGLE                       = false;
        mSupportedExtensions.textureCompressionPvrtcIMG                      = false;
        mSupportedExtensions.pvrtcSRGBEXT                                    = false;
        mSupportedExtensions.copyCompressedTextureCHROMIUM                   = false;
        mSupportedExtensions.textureCompressionAstcHdrKHR                    = false;
        mSupportedExtensions.textureCompressionAstcLdrKHR                    = false;
        mSupportedExtensions.textureCompressionAstcOES                       = false;
        mSupportedExtensions.textureCompressionBptcEXT                       = false;
        mSupportedExtensions.textureCompressionDxt1EXT                       = false;
        mSupportedExtensions.textureCompressionDxt3ANGLE                     = false;
        mSupportedExtensions.textureCompressionDxt5ANGLE                     = false;
        mSupportedExtensions.textureCompressionRgtcEXT                       = false;
        mSupportedExtensions.textureCompressionS3tcSrgbEXT                   = false;
        mSupportedExtensions.textureCompressionAstcSliced3dKHR               = false;

        caps->compressedTextureFormats.clear();
    }

    Extensions *extensions = mState.getMutableExtensions();
    *extensions            = mSupportedExtensions;

    // GLES1 emulation: Initialize caps (Table 6.20 / 6.22 in the ES 1.1 spec)
    if (getClientVersion() < Version(2, 0))
    {
        caps->maxMultitextureUnits          = 4;
        caps->maxClipPlanes                 = 6;
        caps->maxLights                     = 8;
        caps->maxModelviewMatrixStackDepth  = Caps::GlobalMatrixStackDepth;
        caps->maxProjectionMatrixStackDepth = Caps::GlobalMatrixStackDepth;
        caps->maxTextureMatrixStackDepth    = Caps::GlobalMatrixStackDepth;
        caps->minSmoothPointSize            = 1.0f;
        caps->maxSmoothPointSize            = 1.0f;
        caps->minSmoothLineWidth            = 1.0f;
        caps->maxSmoothLineWidth            = 1.0f;
    }

    caps->maxDebugMessageLength   = 1024;
    caps->maxDebugLoggedMessages  = 1024;
    caps->maxDebugGroupStackDepth = 1024;
    caps->maxLabelLength          = 1024;

    if (getClientVersion() < Version(3, 0))
    {
        caps->maxViews = 1u;
    }

#if 0
// This logging can generate a lot of spam in test suites that create many contexts
#    define ANGLE_LOG_LIMITED_CAP(cap, limit)                                               \
        INFO() << "Limiting " << #cap << " to implementation limit " << (limit) << " (was " \
               << (cap) << ")."
#else
#    define ANGLE_LOG_LIMITED_CAP(cap, limit)
#endif

#define ANGLE_LIMIT_CAP(cap, limit)            \
    do                                         \
    {                                          \
        if ((cap) > (limit))                   \
        {                                      \
            ANGLE_LOG_LIMITED_CAP(cap, limit); \
            (cap) = (limit);                   \
        }                                      \
    } while (0)

    // Apply/Verify implementation limits.
    //
    // GLES requires that draw buffers are mapped to color attachments with an identical index (in
    // glDrawBuffers), and so draw buffers and color attachments are frequently interchanged in the
    // codebase.  The same limit is thus used for both.
    const GLint maxDrawBuffersAndColorAttachments = std::min<GLint>(
        std::min(caps->maxDrawBuffers, caps->maxColorAttachments), IMPLEMENTATION_MAX_DRAW_BUFFERS);
    ANGLE_LIMIT_CAP(caps->maxDrawBuffers, maxDrawBuffersAndColorAttachments);
    ANGLE_LIMIT_CAP(caps->maxFramebufferWidth, IMPLEMENTATION_MAX_FRAMEBUFFER_SIZE);
    ANGLE_LIMIT_CAP(caps->maxFramebufferHeight, IMPLEMENTATION_MAX_FRAMEBUFFER_SIZE);
    ANGLE_LIMIT_CAP(caps->maxRenderbufferSize, IMPLEMENTATION_MAX_RENDERBUFFER_SIZE);
    ANGLE_LIMIT_CAP(caps->maxColorAttachments, maxDrawBuffersAndColorAttachments);
    ANGLE_LIMIT_CAP(caps->maxVertexAttributes, MAX_VERTEX_ATTRIBS);
    if (mDisplay->getFrontendFeatures().forceMinimumMaxVertexAttributes.enabled &&
        getClientVersion() <= Version(2, 0))
    {
        // Only limit GL_MAX_VERTEX_ATTRIBS on ES2 or lower, the ES3+ cap is already at the minimum
        // (16)
        static_assert(MAX_VERTEX_ATTRIBS == 16);
        ANGLE_LIMIT_CAP(caps->maxVertexAttributes, 8);
    }
    ANGLE_LIMIT_CAP(caps->maxVertexAttribStride,
                    static_cast<GLint>(limits::kMaxVertexAttribStride));

    ASSERT(caps->minAliasedPointSize >= 1.0f);

    if (getClientVersion() < ES_3_1)
    {
        caps->maxVertexAttribBindings = caps->maxVertexAttributes;
    }
    else
    {
        ANGLE_LIMIT_CAP(caps->maxVertexAttribBindings, MAX_VERTEX_ATTRIB_BINDINGS);
    }

    const Limitations &limitations = getLimitations();

    if (mWebGLContext && limitations.webGLTextureSizeLimit > 0)
    {
        ANGLE_LIMIT_CAP(caps->max2DTextureSize, limitations.webGLTextureSizeLimit);
        ANGLE_LIMIT_CAP(caps->max3DTextureSize, limitations.webGLTextureSizeLimit);
        ANGLE_LIMIT_CAP(caps->maxCubeMapTextureSize, limitations.webGLTextureSizeLimit);
        ANGLE_LIMIT_CAP(caps->maxArrayTextureLayers, limitations.webGLTextureSizeLimit);
        ANGLE_LIMIT_CAP(caps->maxRectangleTextureSize, limitations.webGLTextureSizeLimit);
    }

    ANGLE_LIMIT_CAP(caps->max2DTextureSize, IMPLEMENTATION_MAX_2D_TEXTURE_SIZE);
    ANGLE_LIMIT_CAP(caps->maxCubeMapTextureSize, IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
    ANGLE_LIMIT_CAP(caps->max3DTextureSize, IMPLEMENTATION_MAX_3D_TEXTURE_SIZE);
    ANGLE_LIMIT_CAP(caps->maxArrayTextureLayers, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS);
    ANGLE_LIMIT_CAP(caps->maxRectangleTextureSize, IMPLEMENTATION_MAX_2D_TEXTURE_SIZE);

    ANGLE_LIMIT_CAP(caps->maxShaderUniformBlocks[ShaderType::Vertex],
                    IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS);
    ANGLE_LIMIT_CAP(caps->maxShaderUniformBlocks[ShaderType::Geometry],
                    IMPLEMENTATION_MAX_GEOMETRY_SHADER_UNIFORM_BUFFERS);
    ANGLE_LIMIT_CAP(caps->maxShaderUniformBlocks[ShaderType::Fragment],
                    IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS);
    ANGLE_LIMIT_CAP(caps->maxShaderUniformBlocks[ShaderType::Compute],
                    IMPLEMENTATION_MAX_COMPUTE_SHADER_UNIFORM_BUFFERS);
    ANGLE_LIMIT_CAP(caps->maxCombinedUniformBlocks,
                    IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
    ANGLE_LIMIT_CAP(caps->maxUniformBufferBindings, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS);

    ANGLE_LIMIT_CAP(caps->maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
    ANGLE_LIMIT_CAP(caps->maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);

    ANGLE_LIMIT_CAP(caps->maxTransformFeedbackInterleavedComponents,
                    IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
    ANGLE_LIMIT_CAP(caps->maxTransformFeedbackSeparateAttributes,
                    IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
    ANGLE_LIMIT_CAP(caps->maxTransformFeedbackSeparateComponents,
                    IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);

    if (getClientVersion() < ES_3_2 && !extensions->tessellationShaderAny())
    {
        ANGLE_LIMIT_CAP(caps->maxCombinedTextureImageUnits,
                        IMPLEMENTATION_MAX_ES31_ACTIVE_TEXTURES);
    }
    else
    {
        ANGLE_LIMIT_CAP(caps->maxCombinedTextureImageUnits, IMPLEMENTATION_MAX_ACTIVE_TEXTURES);
    }

    for (ShaderType shaderType : AllShaderTypes())
    {
        ANGLE_LIMIT_CAP(caps->maxShaderTextureImageUnits[shaderType],
                        IMPLEMENTATION_MAX_SHADER_TEXTURES);
    }

    ANGLE_LIMIT_CAP(caps->maxImageUnits, IMPLEMENTATION_MAX_IMAGE_UNITS);
    ANGLE_LIMIT_CAP(caps->maxCombinedImageUniforms, IMPLEMENTATION_MAX_IMAGE_UNITS);
    for (ShaderType shaderType : AllShaderTypes())
    {
        ANGLE_LIMIT_CAP(caps->maxShaderImageUniforms[shaderType], IMPLEMENTATION_MAX_IMAGE_UNITS);
    }

    for (ShaderType shaderType : AllShaderTypes())
    {
        ANGLE_LIMIT_CAP(caps->maxShaderAtomicCounterBuffers[shaderType],
                        IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
    }
    ANGLE_LIMIT_CAP(caps->maxAtomicCounterBufferBindings,
                    IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
    ANGLE_LIMIT_CAP(caps->maxCombinedAtomicCounterBuffers,
                    IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);

    for (ShaderType shaderType : AllShaderTypes())
    {
        ANGLE_LIMIT_CAP(caps->maxShaderStorageBlocks[shaderType],
                        IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
    }
    ANGLE_LIMIT_CAP(caps->maxShaderStorageBufferBindings,
                    IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
    ANGLE_LIMIT_CAP(caps->maxCombinedShaderStorageBlocks,
                    IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS);

    ANGLE_LIMIT_CAP(caps->maxClipDistances, IMPLEMENTATION_MAX_CLIP_DISTANCES);

    ANGLE_LIMIT_CAP(caps->maxFramebufferLayers, IMPLEMENTATION_MAX_FRAMEBUFFER_LAYERS);

    ANGLE_LIMIT_CAP(caps->maxSampleMaskWords, IMPLEMENTATION_MAX_SAMPLE_MASK_WORDS);
    ANGLE_LIMIT_CAP(caps->maxSamples, IMPLEMENTATION_MAX_SAMPLES);
    ANGLE_LIMIT_CAP(caps->maxFramebufferSamples, IMPLEMENTATION_MAX_SAMPLES);
    ANGLE_LIMIT_CAP(caps->maxColorTextureSamples, IMPLEMENTATION_MAX_SAMPLES);
    ANGLE_LIMIT_CAP(caps->maxDepthTextureSamples, IMPLEMENTATION_MAX_SAMPLES);
    ANGLE_LIMIT_CAP(caps->maxIntegerSamples, IMPLEMENTATION_MAX_SAMPLES);

    ANGLE_LIMIT_CAP(caps->maxViews, IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS);

    ANGLE_LIMIT_CAP(caps->maxDualSourceDrawBuffers, IMPLEMENTATION_MAX_DUAL_SOURCE_DRAW_BUFFERS);

    // Disallow using UINT_MAX as an index. This would allow for a draw count of UINT_MAX + 1,
    // overflowing a 32-bit integer.
    constexpr GLint64 kMaxElementIndex = std::numeric_limits<GLuint>::max() - 1;
    ANGLE_LIMIT_CAP(caps->maxElementIndex, kMaxElementIndex);

    // WebGL compatibility
    extensions->webglCompatibilityANGLE = mWebGLContext;
    for (const auto &extensionInfo : GetExtensionInfoMap())
    {
        // If the user has requested that extensions start disabled and they are requestable,
        // disable them.
        if (!mExtensionsEnabled && extensionInfo.second.Requestable)
        {
            extensions->*(extensionInfo.second.ExtensionsMember) = false;
        }
    }

    // Hide emulated ETC1 extension from WebGL contexts.
    if (mWebGLContext && limitations.emulatedEtc1)
    {
        mSupportedExtensions.compressedETC1RGB8SubTextureEXT = false;
        mSupportedExtensions.compressedETC1RGB8TextureOES    = false;
    }

    if (limitations.emulatedAstc)
    {
        // Hide emulated ASTC extension from WebGL contexts.
        if (mWebGLContext)
        {
            mSupportedExtensions.textureCompressionAstcLdrKHR = false;
            extensions->textureCompressionAstcLdrKHR          = false;
        }
#if !defined(ANGLE_HAS_ASTCENC)
        // ASTC shouldn't be exposed if decoder is not built.
        ASSERT(!mSupportedExtensions.textureCompressionAstcLdrKHR);
        ASSERT(!extensions->textureCompressionAstcLdrKHR);
#endif
    }

    // If we're capturing application calls for replay, apply some feature limits to increase
    // portability of the trace.
    if (getShareGroup()->getFrameCaptureShared()->enabled() ||
        getFrontendFeatures().enableCaptureLimits.enabled)
    {
        INFO() << "Limit some features because "
               << (getShareGroup()->getFrameCaptureShared()->enabled()
                       ? "FrameCapture is enabled"
                       : "FrameCapture limits were forced")
               << std::endl;

        if (!getFrontendFeatures().enableProgramBinaryForCapture.enabled)
        {
            // Some apps insist on being able to use glProgramBinary. For those, we'll allow the
            // extension to remain on. Otherwise, force the extension off.
            INFO() << "Disabling GL_OES_get_program_binary for trace portability";
            mDisplay->overrideFrontendFeatures({"disable_program_binary"}, true);
        }

        // Set to the most common limit per gpuinfo.org. Required for several platforms we test.
        constexpr GLint maxImageUnits = 8;
        INFO() << "Limiting image unit count to " << maxImageUnits;
        ANGLE_LIMIT_CAP(caps->maxImageUnits, maxImageUnits);
        for (ShaderType shaderType : AllShaderTypes())
        {
            ANGLE_LIMIT_CAP(caps->maxShaderImageUniforms[shaderType], maxImageUnits);
        }

        // Set a large uniform buffer offset alignment that works on multiple platforms.
        // The offset used by the trace needs to be divisible by the device's actual value.
        // Values seen during development: ARM (16), Intel (32), Qualcomm (128), Nvidia (256)
        constexpr GLint uniformBufferOffsetAlignment = 256;
        ASSERT(uniformBufferOffsetAlignment % caps->uniformBufferOffsetAlignment == 0);
        INFO() << "Setting uniform buffer offset alignment to " << uniformBufferOffsetAlignment;
        caps->uniformBufferOffsetAlignment = uniformBufferOffsetAlignment;

        // Also limit texture buffer offset alignment, if enabled
        if (extensions->textureBufferAny())
        {
            constexpr GLint textureBufferOffsetAlignment =
                gl::limits::kMinTextureBufferOffsetAlignment;
            ASSERT(textureBufferOffsetAlignment % caps->textureBufferOffsetAlignment == 0);
            INFO() << "Setting texture buffer offset alignment to " << textureBufferOffsetAlignment;
            caps->textureBufferOffsetAlignment = textureBufferOffsetAlignment;
        }

        INFO() << "Disabling GL_EXT_map_buffer_range and GL_OES_mapbuffer during capture, which "
                  "are not supported on some native drivers";
        extensions->mapBufferRangeEXT = false;
        extensions->mapbufferOES      = false;

        INFO() << "Disabling GL_CHROMIUM_bind_uniform_location during capture, which is not "
                  "supported on native drivers";
        extensions->bindUniformLocationCHROMIUM = false;

        INFO() << "Disabling GL_NV_shader_noperspective_interpolation during capture, which is not "
                  "supported on some native drivers";
        extensions->shaderNoperspectiveInterpolationNV = false;

        INFO() << "Disabling GL_NV_framebuffer_blit during capture, which is not "
                  "supported on some native drivers";
        extensions->framebufferBlitNV = false;

        INFO() << "Disabling GL_EXT_texture_mirror_clamp_to_edge during capture, which is not "
                  "supported on some native drivers";
        extensions->textureMirrorClampToEdgeEXT = false;

        // Modern content is starting to require 6
        constexpr GLint maxDrawBuffers = 6;
        INFO() << "Limiting draw buffer count to " << maxDrawBuffers;
        ANGLE_LIMIT_CAP(caps->maxDrawBuffers, maxDrawBuffers);

        // Unity based applications are sending down GL streams with undefined behavior.
        // Disabling EGL_KHR_create_context_no_error (which enables a new EGL attrib) prevents that,
        // but we don't have the infrastructure for disabling EGL extensions yet.
        // Instead, disable GL_KHR_no_error (which disables exposing the GL extension), which
        // prevents writing invalid calls to the capture.
        INFO() << "Enabling validation to prevent invalid calls from being captured. This "
                  "effectively disables GL_KHR_no_error and enables GL_ANGLE_robust_client_memory.";
        mErrors.forceValidation();
        extensions->noErrorKHR              = skipValidation();
        extensions->robustClientMemoryANGLE = !skipValidation();

        INFO() << "Disabling GL_OES_depth32 during capture, which is not widely supported on "
                  "mobile";
        extensions->depth32OES = false;

        // https://issuetracker.google.com/445241477
        INFO() << "Disabling GL_EXT_texture_norm16 during capture, which is not widely supported";
        extensions->textureNorm16EXT = false;

        // The corresponding Vulkan extension is presently limited to ARM and Qualcomm
        INFO()
            << "Disabling GL_EXT_texture_compression_astc_decode_mode and "
               "GL_EXT_texture_compression_astc_decode_mode_rgb9e5 during capture, which are not "
               "yet widely supported";
        extensions->textureCompressionAstcDecodeModeEXT       = false;
        extensions->textureCompressionAstcDecodeModeRgb9e5EXT = false;

        // Pixel 4 (Qualcomm) only supports 6 atomic counter buffer bindings.
        constexpr GLint maxAtomicCounterBufferBindings = 6;
        INFO() << "Limiting max atomic counter buffer bindings to "
               << maxAtomicCounterBufferBindings;
        ANGLE_LIMIT_CAP(caps->maxAtomicCounterBufferBindings, maxAtomicCounterBufferBindings);
        for (gl::ShaderType shaderType : gl::AllShaderTypes())
        {
            ANGLE_LIMIT_CAP(caps->maxShaderAtomicCounterBuffers[shaderType],
                            maxAtomicCounterBufferBindings);
        }

        // SwiftShader only supports 12 shader storage buffer bindings.
        constexpr GLint maxShaderStorageBufferBindings = 12;
        INFO() << "Limiting max shader storage buffer bindings to "
               << maxShaderStorageBufferBindings;
        ANGLE_LIMIT_CAP(caps->maxShaderStorageBufferBindings, maxShaderStorageBufferBindings);
        for (gl::ShaderType shaderType : gl::AllShaderTypes())
        {
            ANGLE_LIMIT_CAP(caps->maxShaderStorageBlocks[shaderType],
                            maxShaderStorageBufferBindings);
        }

        // Pixel 7 MAX_TEXTURE_SIZE is 16K
        constexpr GLint max2DTextureSize = 16383;
        INFO() << "Limiting GL_MAX_TEXTURE_SIZE to " << max2DTextureSize;
        ANGLE_LIMIT_CAP(caps->max2DTextureSize, max2DTextureSize);

        // Pixel 4 only supports GL_MAX_SAMPLES of 4
        constexpr GLint maxSamples = 4;
        INFO() << "Limiting GL_MAX_SAMPLES to " << maxSamples;
        ANGLE_LIMIT_CAP(caps->maxSamples, maxSamples);

        // Test if we require shadow memory for coherent buffer tracking
        getShareGroup()->getFrameCaptureShared()->determineMemoryProtectionSupport(this);
    }

    // Disable support for OES_get_program_binary
    if (mDisplay->getFrontendFeatures().disableProgramBinary.enabled)
    {
        extensions->getProgramBinaryOES = false;
        caps->shaderBinaryFormats.clear();
        caps->programBinaryFormats.clear();
        mMemoryProgramCache = nullptr;
    }

    // Initialize ANGLE_shader_pixel_local_storage caps based on frontend GL queries.
    //
    // The backend may have already initialized these caps with its own custom values, in which case
    // maxPixelLocalStoragePlanes will already be nonzero and we can skip this step.
    if (mSupportedExtensions.shaderPixelLocalStorageANGLE && caps->maxPixelLocalStoragePlanes == 0)
    {
        int maxDrawableAttachments = std::min(caps->maxDrawBuffers, caps->maxColorAttachments);
        switch (mImplementation->getNativePixelLocalStorageOptions().type)
        {
            case ShPixelLocalStorageType::ImageLoadStore:
                caps->maxPixelLocalStoragePlanes =
                    caps->maxShaderImageUniforms[ShaderType::Fragment];
                ANGLE_LIMIT_CAP(caps->maxPixelLocalStoragePlanes,
                                IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
                caps->maxCombinedDrawBuffersAndPixelLocalStoragePlanes =
                    std::min<GLint>(caps->maxPixelLocalStoragePlanes +
                                        std::min(caps->maxDrawBuffers, caps->maxColorAttachments),
                                    caps->maxCombinedShaderOutputResources);
                break;

            case ShPixelLocalStorageType::FramebufferFetch:
                // When pixel local storage is implemented as framebuffer attachments, we need
                // draw_buffers_indexed in order to control the blend & color mask state
                // on the PLS planes independently.
                ASSERT(mSupportedExtensions.drawBuffersIndexedAny());
                caps->maxPixelLocalStoragePlanes = maxDrawableAttachments;
                ANGLE_LIMIT_CAP(caps->maxPixelLocalStoragePlanes,
                                IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
                caps->maxCombinedDrawBuffersAndPixelLocalStoragePlanes = maxDrawableAttachments;
                break;

            case ShPixelLocalStorageType::NotSupported:
                UNREACHABLE();
                break;
        }
    }
    // Validate that pixel local storage caps were initialized within implementation limits. We
    // can't just clamp this value here since it would potentially impact other caps.
    ASSERT(caps->maxPixelLocalStoragePlanes <= IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);

#undef ANGLE_LIMIT_CAP
#undef ANGLE_LOG_CAP_LIMIT

    // Generate texture caps
    updateCaps();
}

void Context::updateCaps()
{
    Caps *caps                  = mState.getMutableCaps();
    TextureCapsMap *textureCaps = mState.getMutableTextureCaps();

    caps->compressedTextureFormats.clear();
    textureCaps->clear();

    for (GLenum sizedInternalFormat : GetAllSizedInternalFormats())
    {
        TextureCaps formatCaps = mImplementation->getNativeTextureCaps().get(sizedInternalFormat);
        const InternalFormat &formatInfo = GetSizedInternalFormatInfo(sizedInternalFormat);

        // Update the format caps based on the client version and extensions.
        // Caps are AND'd with the renderer caps because some core formats are still unsupported in
        // ES3.
        formatCaps.texturable =
            formatCaps.texturable &&
            formatInfo.textureSupport(getClientVersion(), mState.getExtensions());
        formatCaps.filterable =
            formatCaps.filterable &&
            formatInfo.filterSupport(getClientVersion(), mState.getExtensions());
        formatCaps.textureAttachment =
            formatCaps.textureAttachment &&
            formatInfo.textureAttachmentSupport(getClientVersion(), mState.getExtensions());
        formatCaps.renderbuffer =
            formatCaps.renderbuffer &&
            formatInfo.renderbufferSupport(getClientVersion(), mState.getExtensions());
        formatCaps.blendable = formatCaps.blendable &&
                               formatInfo.blendSupport(getClientVersion(), mState.getExtensions());

        const bool isIntColorFormat = formatInfo.isInt() && formatInfo.stencilBits == 0;

        // OpenGL ES does not support multisampling with non-rendererable formats
        // OpenGL ES 3.0 or prior does not support multisampling with integer formats
        if (!formatCaps.renderbuffer ||
            (getClientVersion() < ES_3_1 && !mState.getExtensions().textureMultisampleANGLE &&
             isIntColorFormat))
        {
            formatCaps.sampleCounts.clear();
        }
        else
        {
            // We may have limited the max samples for some required renderbuffer formats due to
            // non-conformant formats. In this case MAX_SAMPLES needs to be lowered accordingly.
            GLuint formatMaxSamples = formatCaps.sampleCounts.getMaxSamples();

            // GLES 3.0.5 section 4.4.2.2: "Implementations must support creation of renderbuffers
            // in these required formats with up to the value of MAX_SAMPLES multisamples, with the
            // exception of signed and unsigned integer formats."
            if (!isIntColorFormat && formatInfo.isRequiredRenderbufferFormat(getClientVersion()))
            {
                ASSERT(getClientVersion() < ES_3_0 || formatMaxSamples >= 4);
                caps->maxSamples =
                    std::min(static_cast<GLuint>(caps->maxSamples), formatMaxSamples);
            }

            // Handle GLES 3.1 MAX_*_SAMPLES values similarly to MAX_SAMPLES.
            if (getClientVersion() >= ES_3_1 || mState.getExtensions().textureMultisampleANGLE)
            {
                // GLES 3.1 section 9.2.5: "Implementations must support creation of renderbuffers
                // in these required formats with up to the value of MAX_SAMPLES multisamples, with
                // the exception that the signed and unsigned integer formats are required only to
                // support creation of renderbuffers with up to the value of MAX_INTEGER_SAMPLES
                // multisamples, which must be at least one."
                if (isIntColorFormat)
                {
                    caps->maxIntegerSamples =
                        std::min(static_cast<GLuint>(caps->maxIntegerSamples), formatMaxSamples);
                }

                // GLES 3.1 section 19.3.1.
                if (formatCaps.texturable)
                {
                    if (formatInfo.depthBits > 0)
                    {
                        caps->maxDepthTextureSamples = std::min(
                            static_cast<GLuint>(caps->maxDepthTextureSamples), formatMaxSamples);
                    }
                    else if (formatInfo.redBits > 0)
                    {
                        caps->maxColorTextureSamples = std::min(
                            static_cast<GLuint>(caps->maxColorTextureSamples), formatMaxSamples);
                    }
                }
            }
        }

        if (formatCaps.texturable && (formatInfo.compressed || formatInfo.paletted))
        {
            caps->compressedTextureFormats.push_back(sizedInternalFormat);
        }

        textureCaps->insert(sizedInternalFormat, formatCaps);
    }

    // If program binary is disabled, blank out the memory cache pointer.
    if (!mSupportedExtensions.getProgramBinaryOES)
    {
        mMemoryProgramCache = nullptr;
    }

    // Compute which buffer types are allowed
    mValidBufferBindings.reset();
    mValidBufferBindings.set(BufferBinding::ElementArray);
    mValidBufferBindings.set(BufferBinding::Array);

    if (mState.getExtensions().pixelBufferObjectNV || getClientVersion() >= ES_3_0)
    {
        mValidBufferBindings.set(BufferBinding::PixelPack);
        mValidBufferBindings.set(BufferBinding::PixelUnpack);
    }

    if (getClientVersion() >= ES_3_0)
    {
        mValidBufferBindings.set(BufferBinding::CopyRead);
        mValidBufferBindings.set(BufferBinding::CopyWrite);
        mValidBufferBindings.set(BufferBinding::TransformFeedback);
        mValidBufferBindings.set(BufferBinding::Uniform);
    }

    if (getClientVersion() >= ES_3_1)
    {
        mValidBufferBindings.set(BufferBinding::AtomicCounter);
        mValidBufferBindings.set(BufferBinding::ShaderStorage);
        mValidBufferBindings.set(BufferBinding::DrawIndirect);
        mValidBufferBindings.set(BufferBinding::DispatchIndirect);
    }

    if (getClientVersion() >= ES_3_2 || mState.getExtensions().textureBufferAny())
    {
        mValidBufferBindings.set(BufferBinding::Texture);
    }

    // Reinitialize some dirty bits that depend on extensions.
    if (mState.isRobustResourceInitEnabled())
    {
        mDrawDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS);
        mDrawDirtyObjects.set(state::DIRTY_OBJECT_TEXTURES_INIT);
        mDrawDirtyObjects.set(state::DIRTY_OBJECT_IMAGES_INIT);
        mClearDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS);
        mBlitDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS);
        mBlitDirtyObjects.set(state::DIRTY_OBJECT_READ_ATTACHMENTS);
        mComputeDirtyObjects.set(state::DIRTY_OBJECT_TEXTURES_INIT);
        mComputeDirtyObjects.set(state::DIRTY_OBJECT_IMAGES_INIT);
        mReadPixelsDirtyObjects.set(state::DIRTY_OBJECT_READ_ATTACHMENTS);
        mCopyImageDirtyBits.set(state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
        mCopyImageDirtyObjects.set(state::DIRTY_OBJECT_READ_ATTACHMENTS);
        mTilingDirtyObjects.set(state::DIRTY_OBJECT_DRAW_ATTACHMENTS);
    }

    // If we are in a WebGL or robust access context and the back-end does not support robust buffer
    // access behaviour, we need to validate the buffer bounds manually.
    mRequiresRobustBehavior = mState.isWebGL() || mState.hasRobustAccess();
    mBufferAccessValidationEnabled =
        !mSupportedExtensions.robustBufferAccessBehaviorKHR && mRequiresRobustBehavior;

    // Cache this in the VertexArrays. They need to check it in state change notifications.
    // Note: vertex array objects are private to context and so the map doesn't need locking
    for (auto vaoIter : UnsafeResourceMapIter(getPrivateState().getVertexArrayMap()))
    {
        VertexArray *vao = vaoIter.second;
        vao->setRobustBufferAccessEnabled(mRequiresRobustBehavior);
    }

    // Reinitialize state cache after extension changes.
    mStateCache.initialize(this);
    mPrivateStateCache.initialize(this);
}

angle::Result Context::prepareForClear(GLbitfield mask)
{
    // Sync the draw framebuffer manually after the clear attachments.
    ANGLE_TRY(mState.getDrawFramebuffer()->ensureClearAttachmentsInitialized(this, mask));
    return syncStateForClear();
}

angle::Result Context::prepareForClearBuffer(GLenum buffer, GLint drawbuffer)
{
    // Sync the draw framebuffer manually after the clear attachments.
    ANGLE_TRY(mState.getDrawFramebuffer()->ensureClearBufferAttachmentsInitialized(this, buffer,
                                                                                   drawbuffer));
    return syncStateForClear();
}

ANGLE_INLINE angle::Result Context::prepareForCopyImage()
{
    ANGLE_TRY(syncDirtyObjects(mCopyImageDirtyObjects, Command::CopyImage));
    return syncDirtyBits(mCopyImageDirtyBits, kCopyImageExtendedDirtyBits, Command::CopyImage);
}

ANGLE_INLINE angle::Result Context::prepareForDispatch()
{
    // Converting a PPO from graphics to compute requires re-linking it.
    // The compute shader must have successfully linked before being included in the PPO, so no link
    // errors that would have been caught during validation should be possible when re-linking the
    // PPO with the compute shader.
    Program *program          = mState.getProgram();
    ProgramPipeline *pipeline = mState.getProgramPipeline();
    if (!program && pipeline)
    {
        // Linking the PPO can't fail due to a validation error within the compute program,
        // since it successfully linked already in order to become part of the PPO in the first
        // place.
        pipeline->resolveLink(this);
        ANGLE_CHECK(this, pipeline->isLinked(), err::kProgramPipelineLinkFailed,
                    GL_INVALID_OPERATION);
    }

    ANGLE_TRY(syncDirtyObjects(mComputeDirtyObjects, Command::Dispatch));
    return syncDirtyBits(kComputeDirtyBits, kComputeExtendedDirtyBits, Command::Dispatch);
}

angle::Result Context::prepareForInvalidate(GLenum target)
{
    // Only sync the FBO that's being invalidated.  Per the GLES3 spec, GL_FRAMEBUFFER is equivalent
    // to GL_DRAW_FRAMEBUFFER for the purposes of invalidation.
    GLenum effectiveTarget = target;
    if (effectiveTarget == GL_FRAMEBUFFER)
    {
        effectiveTarget = GL_DRAW_FRAMEBUFFER;
    }
    ANGLE_TRY(mState.syncDirtyObject(this, effectiveTarget, Command::Invalidate));
    const state::DirtyBits dirtyBits                 = effectiveTarget == GL_READ_FRAMEBUFFER
                                                           ? kReadInvalidateDirtyBits
                                                           : kDrawInvalidateDirtyBits;
    const state::ExtendedDirtyBits extendedDirtyBits = effectiveTarget == GL_READ_FRAMEBUFFER
                                                           ? kReadInvalidateExtendedDirtyBits
                                                           : kDrawInvalidateExtendedDirtyBits;
    return syncDirtyBits(dirtyBits, extendedDirtyBits, Command::Invalidate);
}

angle::Result Context::syncState(const state::DirtyBits bitMask,
                                 const state::ExtendedDirtyBits extendedBitMask,
                                 const state::DirtyObjects &objectMask,
                                 Command command)
{
    ANGLE_TRY(syncDirtyObjects(objectMask, command));
    ANGLE_TRY(syncDirtyBits(bitMask, extendedBitMask, command));
    return angle::Result::Continue;
}

void Context::blitFramebuffer(GLint srcX0,
                              GLint srcY0,
                              GLint srcX1,
                              GLint srcY1,
                              GLint dstX0,
                              GLint dstY0,
                              GLint dstX1,
                              GLint dstY1,
                              GLbitfield mask,
                              GLenum filter)
{
    if (mask == 0)
    {
        // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
        // buffers are copied.
        return;
    }

    Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
    Framebuffer *readFramebuffer = mState.getReadFramebuffer();
    ASSERT(drawFramebuffer);
    ASSERT(readFramebuffer);

    // Note that blitting is called against draw framebuffer.
    // See the code in gl::Context::blitFramebuffer.
    if ((mask & GL_COLOR_BUFFER_BIT) && (!drawFramebuffer->hasEnabledDrawBuffer() ||
                                         readFramebuffer->getReadColorAttachment() == nullptr))
    {
        mask &= ~GL_COLOR_BUFFER_BIT;
    }

    if ((mask & GL_STENCIL_BUFFER_BIT) &&
        (drawFramebuffer->getState().getStencilAttachment() == nullptr ||
         readFramebuffer->getState().getStencilAttachment() == nullptr))
    {
        mask &= ~GL_STENCIL_BUFFER_BIT;
    }

    if ((mask & GL_DEPTH_BUFFER_BIT) &&
        (drawFramebuffer->getState().getDepthAttachment() == nullptr ||
         readFramebuffer->getState().getDepthAttachment() == nullptr))
    {
        mask &= ~GL_DEPTH_BUFFER_BIT;
    }

    // Early out if none of the specified attachments exist or are enabled.
    if (mask == 0)
    {
        ANGLE_PERF_WARNING(mState.getDebug(), GL_DEBUG_SEVERITY_LOW,
                           "BlitFramebuffer called for non-existing buffers");
        return;
    }

    Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
    Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);

    if (dstArea.width == 0 || dstArea.height == 0)
    {
        return;
    }

    ANGLE_CONTEXT_TRY(syncStateForBlit(mask));
    ANGLE_CONTEXT_TRY(drawFramebuffer->blit(this, srcArea, dstArea, mask, filter));
}

void Context::clear(GLbitfield mask)
{
    if (mState.isRasterizerDiscardEnabled())
    {
        return;
    }

    // If we have active PLS using framebuffer fetch, disable those draw buffers so we don't clear
    // the pixel local store.
    ScopedPLSFramebufferFetchDrawBuffersDisable scopedPLSFramebufferFetchDrawBuffersDisable(this);

    // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
    // color/depth/stencil masks make the clear ineffective we skip it altogether.

    // If all color channels in all draw buffers are masked, don't attempt to clear color.
    if (mState.allActiveDrawBufferChannelsMasked())
    {
        mask &= ~GL_COLOR_BUFFER_BIT;
    }

    // If depth write is disabled, don't attempt to clear depth.
    if (mState.getDrawFramebuffer()->getDepthAttachment() == nullptr ||
        mState.getDepthStencilState().isDepthMaskedOut())
    {
        mask &= ~GL_DEPTH_BUFFER_BIT;
    }

    // If all stencil bits are masked, don't attempt to clear stencil.
    if (mState.getDepthStencilState().isStencilMaskedOut(
            mState.getDrawFramebuffer()->getStencilBitCount()))
    {
        mask &= ~GL_STENCIL_BUFFER_BIT;
    }

    if (mask == 0)
    {
        ANGLE_PERF_WARNING(mState.getDebug(), GL_DEBUG_SEVERITY_LOW,
                           "Clear called for non-existing buffers");
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForClear(mask));
    ANGLE_CONTEXT_TRY(mState.getDrawFramebuffer()->clear(this, mask));
}

bool Context::isClearBufferMaskedOut(GLenum buffer,
                                     GLint drawbuffer,
                                     GLuint framebufferStencilSize) const
{
    switch (buffer)
    {
        case GL_COLOR:
            return IsColorMaskedOut(mState.getBlendStateExt(), drawbuffer);
        case GL_DEPTH:
            return mState.getDepthStencilState().isDepthMaskedOut();
        case GL_STENCIL:
            return mState.getDepthStencilState().isStencilMaskedOut(framebufferStencilSize);
        case GL_DEPTH_STENCIL:
            return mState.getDepthStencilState().isDepthMaskedOut() &&
                   mState.getDepthStencilState().isStencilMaskedOut(framebufferStencilSize);
        default:
            UNREACHABLE();
            return true;
    }
}

bool Context::noopClearBuffer(GLenum buffer, GLint drawbuffer) const
{
    Framebuffer *framebufferObject = mState.getDrawFramebuffer();

    if (buffer == GL_COLOR && getPrivateState().isActivelyOverriddenPLSDrawBuffer(drawbuffer))
    {
        // If pixel local storage is active and currently overriding the drawbuffer, do nothing.
        // From the client's perspective, there is effectively no buffer bound.
        return true;
    }

    return !IsClearBufferEnabled(framebufferObject->getState(), buffer, drawbuffer) ||
           mState.isRasterizerDiscardEnabled() ||
           isClearBufferMaskedOut(buffer, drawbuffer, framebufferObject->getStencilBitCount());
}

void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
{
    if (noopClearBuffer(buffer, drawbuffer))
    {
        return;
    }

    Framebuffer *framebufferObject          = mState.getDrawFramebuffer();
    const FramebufferAttachment *attachment = nullptr;
    GLfloat clampedDepth;
    if (buffer == GL_DEPTH)
    {
        clampedDepth = clamp01(values[0]);
        values       = &clampedDepth;
        attachment   = framebufferObject->getDepthAttachment();
    }
    else if (buffer == GL_COLOR &&
             static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorAttachments())
    {
        attachment = framebufferObject->getColorAttachment(drawbuffer);
    }
    // It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
    // that the backend doesn't need to take this case into account.
    if (!attachment)
    {
        return;
    }
    ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
    ANGLE_CONTEXT_TRY(framebufferObject->clearBufferfv(this, buffer, drawbuffer, values));
}

void Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
{
    if (noopClearBuffer(buffer, drawbuffer))
    {
        return;
    }

    Framebuffer *framebufferObject          = mState.getDrawFramebuffer();
    const FramebufferAttachment *attachment = nullptr;
    if (buffer == GL_COLOR &&
        static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorAttachments())
    {
        attachment = framebufferObject->getColorAttachment(drawbuffer);
    }
    // It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
    // that the backend doesn't need to take this case into account.
    if (!attachment)
    {
        return;
    }
    ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
    ANGLE_CONTEXT_TRY(framebufferObject->clearBufferuiv(this, buffer, drawbuffer, values));
}

void Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
{
    if (noopClearBuffer(buffer, drawbuffer))
    {
        return;
    }

    Framebuffer *framebufferObject          = mState.getDrawFramebuffer();
    const FramebufferAttachment *attachment = nullptr;
    if (buffer == GL_STENCIL)
    {
        attachment = framebufferObject->getStencilAttachment();
    }
    else if (buffer == GL_COLOR &&
             static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorAttachments())
    {
        attachment = framebufferObject->getColorAttachment(drawbuffer);
    }
    // It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
    // that the backend doesn't need to take this case into account.
    if (!attachment)
    {
        return;
    }
    ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
    ANGLE_CONTEXT_TRY(framebufferObject->clearBufferiv(this, buffer, drawbuffer, values));
}

void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
{
    if (noopClearBuffer(buffer, drawbuffer))
    {
        return;
    }

    Framebuffer *framebufferObject = mState.getDrawFramebuffer();
    ASSERT(framebufferObject);

    // If a buffer is not present, the clear has no effect
    if (framebufferObject->getDepthAttachment() == nullptr &&
        framebufferObject->getStencilAttachment() == nullptr)
    {
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
    ANGLE_CONTEXT_TRY(
        framebufferObject->clearBufferfi(this, buffer, drawbuffer, clamp01(depth), stencil));
}

ANGLE_INLINE angle::Result Context::readPixelsImpl(GLint x,
                                                   GLint y,
                                                   GLsizei width,
                                                   GLsizei height,
                                                   GLenum format,
                                                   GLenum type,
                                                   void *pixels)
{
    // Zero dimensions are no-ops and negative dimensions must be blocked by validation.
    // Exit early in both cases to avoid backend failures when validation is disabled.
    if (ANGLE_UNLIKELY(width <= 0 || height <= 0))
    {
        return angle::Result::Continue;
    }

    ANGLE_TRY(syncStateForReadPixels());

    Framebuffer *readFBO = mState.getReadFramebuffer();
    ASSERT(readFBO);

    Rectangle area(x, y, width, height);
    PixelPackState packState = mState.getPackState();
    Buffer *packBuffer       = mState.getTargetBuffer(gl::BufferBinding::PixelPack);
    ANGLE_TRY(readFBO->readPixels(this, area, format, type, packState, packBuffer, pixels));

    return angle::Result::Continue;
}

void Context::readPixels(GLint x,
                         GLint y,
                         GLsizei width,
                         GLsizei height,
                         GLenum format,
                         GLenum type,
                         void *pixels)
{
    ANGLE_CONTEXT_TRY(readPixelsImpl(x, y, width, height, format, type, pixels));
}

void Context::readPixelsRobust(GLint x,
                               GLint y,
                               GLsizei width,
                               GLsizei height,
                               GLenum format,
                               GLenum type,
                               GLsizei bufSize,
                               GLsizei *length,
                               GLsizei *columns,
                               GLsizei *rows,
                               void *pixels)
{
    ANGLE_CONTEXT_TRY(readPixelsImpl(x, y, width, height, format, type, pixels));

    if (length != nullptr)
    {
        if (mState.getTargetBuffer(BufferBinding::PixelPack) == nullptr)
        {
            const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);

            GLuint endByte   = 0;
            const bool valid = formatInfo.computePackUnpackEndByte(
                type, Extents(width, height, 1), mState.getPackState(), false, &endByte);
            ASSERT(valid);
            ASSERT(endByte <= static_cast<GLuint>(std::numeric_limits<GLsizei>::max()));

            *length = static_cast<GLsizei>(endByte);
        }
        else
        {
            *length = 0;
        }
    }

    GLsizei columnsValue = 0;
    GLsizei rowsValue    = 0;
    // If the call above exited early due to width or height being zero,
    // the read buffer dimensions might remain unresolved at this point.
    // There is no need to compute output dimensions in that case.
    if (ANGLE_LIKELY(width > 0 && height > 0))
    {
        const Extents readBufferSize =
            mState.getReadFramebuffer()->getState().getReadPixelsAttachment(format)->getSize();
        ASSERT(readBufferSize.width >= 0 && readBufferSize.height >= 0);
        ASSERT(angle::base::CheckAdd<GLint>(x, width).IsValid());
        ASSERT(angle::base::CheckAdd<GLint>(y, height).IsValid());

        // These expressions cannot overflow with the assertions above.
        // Minuend is the clipped end; subtrahend is the clipped start.
        columnsValue = std::min<GLsizei>(x + width, readBufferSize.width) - std::max(0, x);
        rowsValue    = std::min<GLsizei>(y + height, readBufferSize.height) - std::max(0, y);

        // If any computed dimension is not positive, the intersection is empty.
        if (columnsValue <= 0 || rowsValue <= 0)
        {
            columnsValue = 0;
            rowsValue    = 0;
        }
    }

    if (columns != nullptr)
    {
        *columns = columnsValue;
    }

    if (rows != nullptr)
    {
        *rows = rowsValue;
    }
}

void Context::copyTexImage2D(TextureTarget target,
                             GLint level,
                             GLenum internalformat,
                             GLint x,
                             GLint y,
                             GLsizei width,
                             GLsizei height,
                             GLint border)
{
    if (ANGLE_UNLIKELY(width == 0 || height == 0))
    {
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForCopyImage());

    Rectangle sourceArea(x, y, width, height);

    Framebuffer *framebuffer = mState.getReadFramebuffer();
    Texture *texture         = getTextureByTarget(target);
    ANGLE_CONTEXT_TRY(
        texture->copyImage(this, target, level, sourceArea, internalformat, framebuffer));
}

void Context::copyTexSubImage2D(TextureTarget target,
                                GLint level,
                                GLint xoffset,
                                GLint yoffset,
                                GLint x,
                                GLint y,
                                GLsizei width,
                                GLsizei height)
{
    if (ANGLE_UNLIKELY(width == 0 || height == 0))
    {
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForCopyImage());

    Offset destOffset(xoffset, yoffset, 0);
    Rectangle sourceArea(x, y, width, height);

    ImageIndex index = ImageIndex::MakeFromTarget(target, level, 1);

    Framebuffer *framebuffer = mState.getReadFramebuffer();
    Texture *texture         = getTextureByTarget(target);
    ANGLE_CONTEXT_TRY(texture->copySubImage(this, index, destOffset, sourceArea, framebuffer));
}

void Context::copyTexSubImage3D(TextureTarget target,
                                GLint level,
                                GLint xoffset,
                                GLint yoffset,
                                GLint zoffset,
                                GLint x,
                                GLint y,
                                GLsizei width,
                                GLsizei height)
{
    if (ANGLE_UNLIKELY(width == 0 || height == 0))
    {
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForCopyImage());

    Offset destOffset(xoffset, yoffset, zoffset);
    Rectangle sourceArea(x, y, width, height);

    ImageIndex index = ImageIndex::MakeFromType(TextureTargetToType(target), level, zoffset);

    Framebuffer *framebuffer = mState.getReadFramebuffer();
    Texture *texture         = getTextureByTarget(target);
    ANGLE_CONTEXT_TRY(texture->copySubImage(this, index, destOffset, sourceArea, framebuffer));
}

void Context::copyImageSubData(GLuint srcName,
                               GLenum srcTarget,
                               GLint srcLevel,
                               GLint srcX,
                               GLint srcY,
                               GLint srcZ,
                               GLuint dstName,
                               GLenum dstTarget,
                               GLint dstLevel,
                               GLint dstX,
                               GLint dstY,
                               GLint dstZ,
                               GLsizei srcWidth,
                               GLsizei srcHeight,
                               GLsizei srcDepth)
{
    // if copy region is zero, the copy is a successful no-op
    if ((srcWidth == 0) || (srcHeight == 0) || (srcDepth == 0))
    {
        return;
    }

    ASSERT(srcTarget != GL_RENDERER || (srcLevel == 0 && srcZ == 0 && srcDepth == 1));
    ASSERT(dstTarget != GL_RENDERER || (dstLevel == 0 && dstZ == 0 && srcDepth == 1));

    if (srcTarget == GL_RENDERBUFFER)
    {
        // Source target is a Renderbuffer
        Renderbuffer *readBuffer = getRenderbuffer(PackParam<RenderbufferID>(srcName));
        if (dstTarget == GL_RENDERBUFFER)
        {
            // Destination target is a Renderbuffer
            Renderbuffer *writeBuffer = getRenderbuffer(PackParam<RenderbufferID>(dstName));

            // Copy Renderbuffer to Renderbuffer
            ANGLE_CONTEXT_TRY(writeBuffer->copyRenderbufferSubData(
                this, readBuffer, srcX, srcY, dstX, dstY, srcWidth, srcHeight));
        }
        else
        {
            // Destination target is a Texture
            ASSERT(dstTarget == GL_TEXTURE_2D || dstTarget == GL_TEXTURE_2D_ARRAY ||
                   dstTarget == GL_TEXTURE_3D || dstTarget == GL_TEXTURE_CUBE_MAP ||
                   dstTarget == GL_TEXTURE_CUBE_MAP_ARRAY);

            Texture *writeTexture = getTexture(PackParam<TextureID>(dstName));
            ANGLE_CONTEXT_TRY(syncTextureForCopy(writeTexture));

            // Copy Renderbuffer to Texture
            ANGLE_CONTEXT_TRY(writeTexture->copyRenderbufferSubData(
                this, readBuffer, srcX, srcY, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight));
        }
    }
    else
    {
        // Source target is a Texture
        ASSERT(srcTarget == GL_TEXTURE_2D || srcTarget == GL_TEXTURE_2D_ARRAY ||
               srcTarget == GL_TEXTURE_3D || srcTarget == GL_TEXTURE_CUBE_MAP ||
               srcTarget == GL_TEXTURE_CUBE_MAP_ARRAY || srcTarget == GL_TEXTURE_EXTERNAL_OES ||
               srcTarget == GL_TEXTURE_2D_MULTISAMPLE ||
               srcTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES);

        Texture *readTexture = getTexture(PackParam<TextureID>(srcName));
        ANGLE_CONTEXT_TRY(syncTextureForCopy(readTexture));

        if (dstTarget == GL_RENDERBUFFER)
        {
            // Destination target is a Renderbuffer
            Renderbuffer *writeBuffer = getRenderbuffer(PackParam<RenderbufferID>(dstName));

            // Copy Texture to Renderbuffer
            ANGLE_CONTEXT_TRY(writeBuffer->copyTextureSubData(
                this, readTexture, srcLevel, srcX, srcY, srcZ, dstX, dstY, srcWidth, srcHeight));
        }
        else
        {
            // Destination target is a Texture
            ASSERT(dstTarget == GL_TEXTURE_2D || dstTarget == GL_TEXTURE_2D_ARRAY ||
                   dstTarget == GL_TEXTURE_3D || dstTarget == GL_TEXTURE_CUBE_MAP ||
                   dstTarget == GL_TEXTURE_CUBE_MAP_ARRAY || dstTarget == GL_TEXTURE_EXTERNAL_OES ||
                   dstTarget == GL_TEXTURE_2D_MULTISAMPLE ||
                   dstTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES);

            Texture *writeTexture = getTexture(PackParam<TextureID>(dstName));
            ANGLE_CONTEXT_TRY(syncTextureForCopy(writeTexture));

            // Copy Texture to Texture
            ANGLE_CONTEXT_TRY(writeTexture->copyTextureSubData(
                this, readTexture, srcLevel, srcX, srcY, srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
                srcHeight, srcDepth));
        }
    }
}

void Context::framebufferTexture2D(GLenum target,
                                   GLenum attachment,
                                   TextureTarget textarget,
                                   TextureID texture,
                                   GLint level)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (texture.value != 0)
    {
        Texture *textureObj = getTexture(texture);
        ImageIndex index    = ImageIndex::MakeFromTarget(textarget, level, 1);
        framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
    }
    else
    {
        framebuffer->resetAttachment(this, attachment);
    }

    mState.setObjectDirty(target);
}

void Context::framebufferTexture3D(GLenum target,
                                   GLenum attachment,
                                   TextureTarget textargetPacked,
                                   TextureID texture,
                                   GLint level,
                                   GLint zoffset)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (texture.value != 0)
    {
        Texture *textureObj = getTexture(texture);
        ImageIndex index    = ImageIndex::Make3D(level, zoffset);
        framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
    }
    else
    {
        framebuffer->resetAttachment(this, attachment);
    }

    mState.setObjectDirty(target);
}

void Context::framebufferRenderbuffer(GLenum target,
                                      GLenum attachment,
                                      GLenum renderbuffertarget,
                                      RenderbufferID renderbuffer)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (renderbuffer.value != 0)
    {
        Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer);
        GLsizei rbSamples                = renderbufferObject->getState().getSamples();

        framebuffer->setAttachmentMultisample(this, GL_RENDERBUFFER, attachment, gl::ImageIndex(),
                                              renderbufferObject, rbSamples);
    }
    else
    {
        framebuffer->resetAttachment(this, attachment);
    }

    mState.setObjectDirty(target);
}

void Context::framebufferTextureLayer(GLenum target,
                                      GLenum attachment,
                                      TextureID texture,
                                      GLint level,
                                      GLint layer)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (texture.value != 0)
    {
        Texture *textureObject = getTexture(texture);
        ImageIndex index       = ImageIndex::MakeFromType(textureObject->getType(), level, layer);
        framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObject);
    }
    else
    {
        framebuffer->resetAttachment(this, attachment);
    }

    mState.setObjectDirty(target);
}

void Context::framebufferTextureMultiview(GLenum target,
                                          GLenum attachment,
                                          TextureID texture,
                                          GLint level,
                                          GLint baseViewIndex,
                                          GLsizei numViews)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (texture.value != 0)
    {
        Texture *textureObj = getTexture(texture);

        ImageIndex index;
        if (textureObj->getType() == TextureType::_2DArray)
        {
            index = ImageIndex::Make2DArrayRange(level, baseViewIndex, numViews);
        }
        else
        {
            ASSERT(textureObj->getType() == TextureType::_2DMultisampleArray);
            ASSERT(level == 0);
            index = ImageIndex::Make2DMultisampleArrayRange(baseViewIndex, numViews);
        }
        framebuffer->setAttachmentMultiview(this, GL_TEXTURE, attachment, index, textureObj,
                                            numViews, baseViewIndex);
    }
    else
    {
        framebuffer->resetAttachment(this, attachment);
    }

    mState.setObjectDirty(target);
}

void Context::framebufferTextureMultisampleMultiview(GLenum target,
                                                     GLenum attachment,
                                                     TextureID texturePacked,
                                                     GLint level,
                                                     GLsizei samples,
                                                     GLint baseViewIndex,
                                                     GLsizei numViews)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (texturePacked.value != 0)
    {
        Texture *textureObj = getTexture(texturePacked);

        ImageIndex index;
        ASSERT(textureObj->getType() == TextureType::_2DArray);
        index = ImageIndex::Make2DArrayRange(level, baseViewIndex, numViews);
        framebuffer->setAttachmentMultisampleMultiview(
            this, GL_TEXTURE, attachment, index, textureObj, samples, numViews, baseViewIndex);
        textureObj->onBindToMSRTTFramebuffer();
    }
    else
    {
        framebuffer->resetAttachment(this, attachment);
    }
    mState.setObjectDirty(target);
}

void Context::framebufferTexture(GLenum target, GLenum attachment, TextureID texture, GLint level)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (texture.value != 0)
    {
        Texture *textureObj = getTexture(texture);

        ImageIndex index = ImageIndex::MakeFromType(
            textureObj->getType(), level, ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
        framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
    }
    else
    {
        framebuffer->resetAttachment(this, attachment);
    }

    mState.setObjectDirty(target);
}

void Context::drawBuffers(GLsizei n, const GLenum *bufs)
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    framebuffer->setDrawBuffers(n, bufs);
    mState.setDrawFramebufferDirty();
    mStateCache.onDrawFramebufferChange(this);
}

void Context::readBuffer(GLenum mode)
{
    Framebuffer *readFBO = mState.getReadFramebuffer();
    readFBO->setReadBuffer(mode);
    mState.setObjectDirty(GL_READ_FRAMEBUFFER);
}

void Context::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
{
    // The specification isn't clear what should be done when the framebuffer isn't complete.
    // We threat it the same way as GLES3 glInvalidateFramebuffer.
    invalidateFramebuffer(target, numAttachments, attachments);
}

void Context::invalidateFramebuffer(GLenum target,
                                    GLsizei numAttachments,
                                    const GLenum *attachments)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    // No-op incomplete FBOs.
    if (!framebuffer->isComplete(this))
    {
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForInvalidate(target));
    ANGLE_CONTEXT_TRY(framebuffer->invalidate(this, numAttachments, attachments));
}

void Context::invalidateSubFramebuffer(GLenum target,
                                       GLsizei numAttachments,
                                       const GLenum *attachments,
                                       GLint x,
                                       GLint y,
                                       GLsizei width,
                                       GLsizei height)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (!framebuffer->isComplete(this))
    {
        return;
    }

    Rectangle area(x, y, width, height);
    ANGLE_CONTEXT_TRY(prepareForInvalidate(target));
    ANGLE_CONTEXT_TRY(framebuffer->invalidateSub(this, numAttachments, attachments, area));
}

void Context::texImage2D(TextureTarget target,
                         GLint level,
                         GLint internalformat,
                         GLsizei width,
                         GLsizei height,
                         GLint border,
                         GLenum format,
                         GLenum type,
                         const void *pixels)
{
    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);

    Extents size(width, height, 1);
    Texture *texture = getTextureByTarget(target);
    ANGLE_CONTEXT_TRY(texture->setImage(this, mState.getUnpackState(), unpackBuffer, target, level,
                                        internalformat, size, format, type,
                                        static_cast<const uint8_t *>(pixels)));
}

void Context::texImage2DRobust(TextureTarget target,
                               GLint level,
                               GLint internalformat,
                               GLsizei width,
                               GLsizei height,
                               GLint border,
                               GLenum format,
                               GLenum type,
                               GLsizei bufSize,
                               const void *pixels)
{
    texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
}

void Context::texImage3D(TextureTarget target,
                         GLint level,
                         GLint internalformat,
                         GLsizei width,
                         GLsizei height,
                         GLsizei depth,
                         GLint border,
                         GLenum format,
                         GLenum type,
                         const void *pixels)
{
    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);

    Extents size(width, height, depth);
    Texture *texture = getTextureByTarget(target);
    ANGLE_CONTEXT_TRY(texture->setImage(this, mState.getUnpackState(), unpackBuffer, target, level,
                                        internalformat, size, format, type,
                                        static_cast<const uint8_t *>(pixels)));
}

void Context::texImage3DRobust(TextureTarget target,
                               GLint level,
                               GLint internalformat,
                               GLsizei width,
                               GLsizei height,
                               GLsizei depth,
                               GLint border,
                               GLenum format,
                               GLenum type,
                               GLsizei bufSize,
                               const void *pixels)
{
    texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
}

void Context::texSubImage2D(TextureTarget target,
                            GLint level,
                            GLint xoffset,
                            GLint yoffset,
                            GLsizei width,
                            GLsizei height,
                            GLenum format,
                            GLenum type,
                            const void *pixels)
{
    // Zero sized uploads are valid but no-ops
    if (width == 0 || height == 0)
    {
        return;
    }

    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    Box area(xoffset, yoffset, 0, width, height, 1);
    Texture *texture = getTextureByTarget(target);

    gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);

    ANGLE_CONTEXT_TRY(texture->setSubImage(this, mState.getUnpackState(), unpackBuffer, target,
                                           level, area, format, type,
                                           static_cast<const uint8_t *>(pixels)));
}

void Context::texSubImage2DRobust(TextureTarget target,
                                  GLint level,
                                  GLint xoffset,
                                  GLint yoffset,
                                  GLsizei width,
                                  GLsizei height,
                                  GLenum format,
                                  GLenum type,
                                  GLsizei bufSize,
                                  const void *pixels)
{
    texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
}

void Context::texSubImage3D(TextureTarget target,
                            GLint level,
                            GLint xoffset,
                            GLint yoffset,
                            GLint zoffset,
                            GLsizei width,
                            GLsizei height,
                            GLsizei depth,
                            GLenum format,
                            GLenum type,
                            const void *pixels)
{
    // Zero sized uploads are valid but no-ops
    if (width == 0 || height == 0 || depth == 0)
    {
        return;
    }

    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    Box area(xoffset, yoffset, zoffset, width, height, depth);
    Texture *texture = getTextureByTarget(target);

    gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);

    ANGLE_CONTEXT_TRY(texture->setSubImage(this, mState.getUnpackState(), unpackBuffer, target,
                                           level, area, format, type,
                                           static_cast<const uint8_t *>(pixels)));
}

void Context::texSubImage3DRobust(TextureTarget target,
                                  GLint level,
                                  GLint xoffset,
                                  GLint yoffset,
                                  GLint zoffset,
                                  GLsizei width,
                                  GLsizei height,
                                  GLsizei depth,
                                  GLenum format,
                                  GLenum type,
                                  GLsizei bufSize,
                                  const void *pixels)
{
    texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type,
                  pixels);
}

void Context::compressedTexImage2D(TextureTarget target,
                                   GLint level,
                                   GLenum internalformat,
                                   GLsizei width,
                                   GLsizei height,
                                   GLint border,
                                   GLsizei imageSize,
                                   const void *data)
{
    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    Extents size(width, height, 1);
    Texture *texture = getTextureByTarget(target);
    // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
    // image. So we use an empty PixelUnpackState.
    ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
                                                  internalformat, size, imageSize,
                                                  static_cast<const uint8_t *>(data)));
}

void Context::compressedTexImage3D(TextureTarget target,
                                   GLint level,
                                   GLenum internalformat,
                                   GLsizei width,
                                   GLsizei height,
                                   GLsizei depth,
                                   GLint border,
                                   GLsizei imageSize,
                                   const void *data)
{
    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    Extents size(width, height, depth);
    Texture *texture = getTextureByTarget(target);
    // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
    // image. So we use an empty PixelUnpackState.
    ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
                                                  internalformat, size, imageSize,
                                                  static_cast<const uint8_t *>(data)));
}

void Context::compressedTexSubImage2D(TextureTarget target,
                                      GLint level,
                                      GLint xoffset,
                                      GLint yoffset,
                                      GLsizei width,
                                      GLsizei height,
                                      GLenum format,
                                      GLsizei imageSize,
                                      const void *data)
{
    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    Box area(xoffset, yoffset, 0, width, height, 1);
    Texture *texture = getTextureByTarget(target);
    // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
    // image. So we use an empty PixelUnpackState.
    ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
                                                     format, imageSize,
                                                     static_cast<const uint8_t *>(data)));
}

void Context::compressedTexSubImage3D(TextureTarget target,
                                      GLint level,
                                      GLint xoffset,
                                      GLint yoffset,
                                      GLint zoffset,
                                      GLsizei width,
                                      GLsizei height,
                                      GLsizei depth,
                                      GLenum format,
                                      GLsizei imageSize,
                                      const void *data)
{
    // Zero sized uploads are valid but no-ops
    if (width == 0 || height == 0)
    {
        return;
    }

    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    Box area(xoffset, yoffset, zoffset, width, height, depth);
    Texture *texture = getTextureByTarget(target);
    // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
    // image. So we use an empty PixelUnpackState.
    ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
                                                     format, imageSize,
                                                     static_cast<const uint8_t *>(data)));
}

void Context::generateMipmap(TextureType target)
{
    Texture *texture = getTextureByType(target);
    ANGLE_CONTEXT_TRY(texture->generateMipmap(this));
}

void Context::copyTexture(TextureID sourceId,
                          GLint sourceLevel,
                          TextureTarget destTarget,
                          TextureID destId,
                          GLint destLevel,
                          GLint internalFormat,
                          GLenum destType,
                          GLboolean unpackFlipY,
                          GLboolean unpackPremultiplyAlpha,
                          GLboolean unpackUnmultiplyAlpha)
{
    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    gl::Texture *sourceTexture = getTexture(sourceId);
    gl::Texture *destTexture   = getTexture(destId);
    ANGLE_CONTEXT_TRY(
        destTexture->copyTexture(this, destTarget, destLevel, internalFormat, destType, sourceLevel,
                                 ConvertToBool(unpackFlipY), ConvertToBool(unpackPremultiplyAlpha),
                                 ConvertToBool(unpackUnmultiplyAlpha), sourceTexture));
}

void Context::copySubTexture(TextureID sourceId,
                             GLint sourceLevel,
                             TextureTarget destTarget,
                             TextureID destId,
                             GLint destLevel,
                             GLint xoffset,
                             GLint yoffset,
                             GLint x,
                             GLint y,
                             GLsizei width,
                             GLsizei height,
                             GLboolean unpackFlipY,
                             GLboolean unpackPremultiplyAlpha,
                             GLboolean unpackUnmultiplyAlpha)
{
    // Zero sized copies are valid but no-ops
    if (width == 0 || height == 0)
    {
        return;
    }

    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    gl::Texture *sourceTexture = getTexture(sourceId);
    gl::Texture *destTexture   = getTexture(destId);
    Offset offset(xoffset, yoffset, 0);
    Box box(x, y, 0, width, height, 1);
    ANGLE_CONTEXT_TRY(destTexture->copySubTexture(
        this, destTarget, destLevel, offset, sourceLevel, box, ConvertToBool(unpackFlipY),
        ConvertToBool(unpackPremultiplyAlpha), ConvertToBool(unpackUnmultiplyAlpha),
        sourceTexture));
}

void Context::copyTexture3D(TextureID sourceId,
                            GLint sourceLevel,
                            TextureTarget destTarget,
                            TextureID destId,
                            GLint destLevel,
                            GLint internalFormat,
                            GLenum destType,
                            GLboolean unpackFlipY,
                            GLboolean unpackPremultiplyAlpha,
                            GLboolean unpackUnmultiplyAlpha)
{
    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    Texture *sourceTexture = getTexture(sourceId);
    Texture *destTexture   = getTexture(destId);
    ANGLE_CONTEXT_TRY(
        destTexture->copyTexture(this, destTarget, destLevel, internalFormat, destType, sourceLevel,
                                 ConvertToBool(unpackFlipY), ConvertToBool(unpackPremultiplyAlpha),
                                 ConvertToBool(unpackUnmultiplyAlpha), sourceTexture));
}

void Context::copySubTexture3D(TextureID sourceId,
                               GLint sourceLevel,
                               TextureTarget destTarget,
                               TextureID destId,
                               GLint destLevel,
                               GLint xoffset,
                               GLint yoffset,
                               GLint zoffset,
                               GLint x,
                               GLint y,
                               GLint z,
                               GLsizei width,
                               GLsizei height,
                               GLsizei depth,
                               GLboolean unpackFlipY,
                               GLboolean unpackPremultiplyAlpha,
                               GLboolean unpackUnmultiplyAlpha)
{
    // Zero sized copies are valid but no-ops
    if (width == 0 || height == 0 || depth == 0)
    {
        return;
    }

    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    Texture *sourceTexture = getTexture(sourceId);
    Texture *destTexture   = getTexture(destId);
    Offset offset(xoffset, yoffset, zoffset);
    Box box(x, y, z, width, height, depth);
    ANGLE_CONTEXT_TRY(destTexture->copySubTexture(
        this, destTarget, destLevel, offset, sourceLevel, box, ConvertToBool(unpackFlipY),
        ConvertToBool(unpackPremultiplyAlpha), ConvertToBool(unpackUnmultiplyAlpha),
        sourceTexture));
}

void Context::compressedCopyTexture(TextureID sourceId, TextureID destId)
{
    ANGLE_CONTEXT_TRY(syncStateForTexImage());

    gl::Texture *sourceTexture = getTexture(sourceId);
    gl::Texture *destTexture   = getTexture(destId);
    ANGLE_CONTEXT_TRY(destTexture->copyCompressedTexture(this, sourceTexture));
}

void Context::getBufferPointerv(BufferBinding targetPacked, GLenum pname, void **params)
{
    const Buffer *buffer = mState.getTargetBuffer(targetPacked);
    ASSERT(buffer != nullptr);
    ASSERT(pname == GL_BUFFER_MAP_POINTER);
    *params = buffer->getMapPointer();
}

void Context::getBufferPointervRobust(BufferBinding targetPacked,
                                      GLenum pname,
                                      GLsizei paramCount,
                                      GLsizei *length,
                                      void **params)
{
    getBufferPointerv(targetPacked, pname, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void *Context::mapBuffer(BufferBinding target, GLenum access)
{
    Buffer *buffer = mState.getTargetBuffer(target);
    ASSERT(buffer);

    if (buffer->map(this, access) == angle::Result::Stop)
    {
        return nullptr;
    }

    return buffer->getMapPointer();
}

GLboolean Context::unmapBuffer(BufferBinding target)
{
    Buffer *buffer = mState.getTargetBuffer(target);
    ASSERT(buffer);

    GLboolean result;
    if (buffer->unmap(this, &result) == angle::Result::Stop)
    {
        return GL_FALSE;
    }

    return result;
}

void *Context::mapBufferRange(BufferBinding target,
                              GLintptr offset,
                              GLsizeiptr length,
                              GLbitfield access)
{
    Buffer *buffer = mState.getTargetBuffer(target);
    ASSERT(buffer);

    if (buffer->mapRange(this, offset, length, access) == angle::Result::Stop)
    {
        return nullptr;
    }

    return buffer->getMapPointer();
}

void Context::flushMappedBufferRange(BufferBinding /*target*/,
                                     GLintptr /*offset*/,
                                     GLsizeiptr /*length*/)
{
    // We do not currently support a non-trivial implementation of FlushMappedBufferRange
}

angle::Result Context::syncStateForReadPixels()
{
    return syncState(kReadPixelsDirtyBits, kReadPixelsExtendedDirtyBits, mReadPixelsDirtyObjects,
                     Command::ReadPixels);
}

angle::Result Context::syncStateForTexImage()
{
    return syncState(kTexImageDirtyBits, kTexImageExtendedDirtyBits, mTexImageDirtyObjects,
                     Command::TexImage);
}

angle::Result Context::syncStateForBlit(GLbitfield mask)
{
    uint32_t commandMask = 0;
    if ((mask & GL_COLOR_BUFFER_BIT) != 0)
    {
        commandMask |= CommandBlitBufferColor;
    }
    if ((mask & GL_DEPTH_BUFFER_BIT) != 0)
    {
        commandMask |= CommandBlitBufferDepth;
    }
    if ((mask & GL_STENCIL_BUFFER_BIT) != 0)
    {
        commandMask |= CommandBlitBufferStencil;
    }

    Command command = static_cast<Command>(static_cast<uint32_t>(Command::Blit) + commandMask);

    return syncState(kBlitDirtyBits, kBlitExtendedDirtyBits, mBlitDirtyObjects, command);
}

angle::Result Context::syncStateForClear()
{
    return syncState(kClearDirtyBits, kClearExtendedDirtyBits, mClearDirtyObjects, Command::Clear);
}

angle::Result Context::syncTextureForCopy(Texture *texture)
{
    ASSERT(texture);
    // Sync texture not active but scheduled for a copy
    if (texture->hasAnyDirtyBit())
    {
        return texture->syncState(this, Command::Other);
    }

    return angle::Result::Continue;
}

void Context::activeShaderProgram(ProgramPipelineID pipeline, ShaderProgramID program)
{
    Program *shaderProgram = getProgramNoResolveLink(program);
    ProgramPipeline *programPipeline =
        mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
                                                                       pipeline);
    ASSERT(programPipeline);

    programPipeline->activeShaderProgram(shaderProgram);
}

void Context::blendBarrier()
{
    mImplementation->blendBarrier();
}

void Context::vertexAttribIPointer(GLuint index,
                                   GLint size,
                                   VertexAttribType type,
                                   GLsizei stride,
                                   const void *pointer)
{
    bool vertexAttribDirty = false;
    mState.setVertexAttribIPointer(this, index, mState.getTargetBuffer(BufferBinding::Array), size,
                                   type, stride, pointer, &vertexAttribDirty);
    if (vertexAttribDirty)
    {
        mPrivateStateCache.onVertexArrayStateChange();
    }
}

void Context::getVertexAttribivImpl(GLuint index, GLenum pname, GLint *params) const
{
    const VertexAttribCurrentValueData &currentValues =
        getState().getVertexAttribCurrentValue(index);
    const VertexArray *vao = getState().getVertexArray();
    size_t bindingIndex    = vao->getBindingIndexFromAttribIndex(index);
    QueryVertexAttribiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
                        vao->getVertexArrayBuffer(bindingIndex), currentValues, pname, params);
}

void Context::getVertexAttribiv(GLuint index, GLenum pname, GLint *params)
{
    return getVertexAttribivImpl(index, pname, params);
}

void Context::getVertexAttribivRobust(GLuint index,
                                      GLenum pname,
                                      GLsizei paramCount,
                                      GLsizei *length,
                                      GLint *params)
{
    getVertexAttribiv(index, pname, params);

    if (length != nullptr)
    {
        *length = (pname == GL_CURRENT_VERTEX_ATTRIB) ? 4 : 1;
    }
}

void Context::getVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
{
    const VertexAttribCurrentValueData &currentValues =
        getState().getVertexAttribCurrentValue(index);
    const VertexArray *vao = getState().getVertexArray();
    size_t bindingIndex    = vao->getBindingIndexFromAttribIndex(index);
    QueryVertexAttribfv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
                        vao->getVertexArrayBuffer(bindingIndex), currentValues, pname, params);
}

void Context::getVertexAttribfvRobust(GLuint index,
                                      GLenum pname,
                                      GLsizei paramCount,
                                      GLsizei *length,
                                      GLfloat *params)
{
    getVertexAttribfv(index, pname, params);

    if (length != nullptr)
    {
        *length = (pname == GL_CURRENT_VERTEX_ATTRIB) ? 4 : 1;
    }
}

void Context::getVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
{
    const VertexAttribCurrentValueData &currentValues =
        getState().getVertexAttribCurrentValue(index);
    const VertexArray *vao = getState().getVertexArray();
    size_t bindingIndex    = vao->getBindingIndexFromAttribIndex(index);
    QueryVertexAttribIiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
                         vao->getVertexArrayBuffer(bindingIndex), currentValues, pname, params);
}

void Context::getVertexAttribIivRobust(GLuint index,
                                       GLenum pname,
                                       GLsizei paramCount,
                                       GLsizei *length,
                                       GLint *params)
{
    getVertexAttribIiv(index, pname, params);

    if (length != nullptr)
    {
        *length = (pname == GL_CURRENT_VERTEX_ATTRIB) ? 4 : 1;
    }
}

void Context::getVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
{
    const VertexAttribCurrentValueData &currentValues =
        getState().getVertexAttribCurrentValue(index);
    const VertexArray *vao = getState().getVertexArray();
    size_t bindingIndex    = vao->getBindingIndexFromAttribIndex(index);
    QueryVertexAttribIuiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
                          vao->getVertexArrayBuffer(bindingIndex), currentValues, pname, params);
}

void Context::getVertexAttribIuivRobust(GLuint index,
                                        GLenum pname,
                                        GLsizei paramCount,
                                        GLsizei *length,
                                        GLuint *params)
{
    getVertexAttribIuiv(index, pname, params);

    if (length != nullptr)
    {
        *length = (pname == GL_CURRENT_VERTEX_ATTRIB) ? 4 : 1;
    }
}

void Context::getVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
{
    ASSERT(pname == GL_VERTEX_ATTRIB_ARRAY_POINTER);
    const VertexAttribute &attrib = getState().getVertexArray()->getVertexAttribute(index);
    *pointer                      = const_cast<void *>(attrib.pointer);
}

void Context::getVertexAttribPointervRobust(GLuint index,
                                            GLenum pname,
                                            GLsizei paramCount,
                                            GLsizei *length,
                                            void **pointer)
{
    getVertexAttribPointerv(index, pname, pointer);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::debugMessageControl(GLenum source,
                                  GLenum type,
                                  GLenum severity,
                                  GLsizei count,
                                  const GLuint *ids,
                                  GLboolean enabled)
{
    std::vector<GLuint> idVector(ids, ids + count);
    mState.getDebug().setMessageControl(source, type, severity, std::move(idVector),
                                        ConvertToBool(enabled));
}

void Context::debugMessageInsert(GLenum source,
                                 GLenum type,
                                 GLuint id,
                                 GLenum severity,
                                 GLsizei length,
                                 const GLchar *buf)
{
    if (!mState.getDebug().isOutputEnabled())
    {
        // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
        // not generate an error.
        return;
    }

    ASSERT(buf != nullptr);
    const std::string msg(buf, (length < 0) ? strlen(buf) : static_cast<size_t>(length));
    mState.getDebug().insertMessage(source, type, id, severity, std::move(msg), gl::LOG_INFO);
}

void Context::debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam)
{
    mState.getDebug().setCallback(callback, userParam);
}

GLuint Context::getDebugMessageLog(GLuint count,
                                   GLsizei bufSize,
                                   GLenum *sources,
                                   GLenum *types,
                                   GLuint *ids,
                                   GLenum *severities,
                                   GLsizei *lengths,
                                   GLchar *messageLog)
{
    return static_cast<GLuint>(mState.getDebug().getMessages(count, bufSize, sources, types, ids,
                                                             severities, lengths, messageLog));
}

void Context::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message)
{
    ASSERT(message != nullptr);
    std::string msg(message, (length < 0) ? strlen(message) : static_cast<size_t>(length));
    ANGLE_CONTEXT_TRY(mImplementation->pushDebugGroup(this, source, id, msg));
    mState.getDebug().pushGroup(source, id, std::move(msg));
}

angle::Result Context::handleNoopDrawEvent()
{
    return (mImplementation->handleNoopDrawEvent());
}

void Context::popDebugGroup()
{
    mState.getDebug().popGroup();
    ANGLE_CONTEXT_TRY(mImplementation->popDebugGroup(this));
}

void Context::bufferStorage(BufferBinding target,
                            GLsizeiptr size,
                            const void *data,
                            GLbitfield flags)
{
    Buffer *buffer = mState.getTargetBuffer(target);
    ASSERT(buffer);
    ANGLE_CONTEXT_TRY(buffer->bufferStorage(this, target, size, data, flags));
}

void Context::bufferStorageExternal(BufferBinding target,
                                    GLintptr offset,
                                    GLsizeiptr size,
                                    GLeglClientBufferEXT clientBuffer,
                                    GLbitfield flags)
{
    Buffer *buffer = mState.getTargetBuffer(target);
    ASSERT(buffer);

    ANGLE_CONTEXT_TRY(buffer->bufferStorageExternal(this, target, size, clientBuffer, flags));
}

void Context::getFragmentShadingRates(GLsizei samples,
                                      GLsizei maxCount,
                                      GLsizei *count,
                                      GLenum *shadingRates)
{
    // If <count> is NULL then it is ignored.
    if (count == nullptr)
    {
        return;
    }

    uint32_t shadingRatesCounts = 0;
    angle::ShadingRateMap SupportedFragmentShadingRateSampleCounts =
        mImplementation->getSupportedFragmentShadingRateEXTSampleCounts();
    uint32_t supportedShadingRateCounts = SupportedFragmentShadingRateSampleCounts.size();

    for (uint32_t i = 1; i < supportedShadingRateCounts; i++)
    {
        gl::ShadingRate shadingRate = static_cast<gl::ShadingRate>(i);
        ASSERT(shadingRate > gl::ShadingRate::Undefined &&
               shadingRate < gl::ShadingRate::InvalidEnum);
        // Assert samples is a power of two.
        ASSERT(samples >= 1 && (samples & (samples - 1)) == 0);
        if ((SupportedFragmentShadingRateSampleCounts[shadingRate] & samples) == samples)
        {
            if (shadingRates == nullptr)
            {
                shadingRatesCounts++;
            }
            else
            {
                shadingRates[shadingRatesCounts++] = ToGLenum(shadingRate);
                if (maxCount <= static_cast<GLsizei>(shadingRatesCounts))
                {
                    break;
                }
            }
        }
    }
    *count = shadingRatesCounts;
}

void Context::framebufferShadingRate(GLenum target,
                                     GLenum attachment,
                                     GLuint texture,
                                     GLint baseLayer,
                                     GLsizei numLayers,
                                     GLsizei texelWidth,
                                     GLsizei texelHeight)
{
    return;
}

void Context::bufferData(BufferBinding target, GLsizeiptr size, const void *data, BufferUsage usage)
{
    Buffer *buffer = mState.getTargetBuffer(target);
    ASSERT(buffer);
    ANGLE_CONTEXT_TRY(buffer->bufferData(this, target, data, size, usage));
}

void Context::bufferSubData(BufferBinding target,
                            GLintptr offset,
                            GLsizeiptr size,
                            const void *data)
{
    if (data == nullptr || size == 0)
    {
        return;
    }

    Buffer *buffer = mState.getTargetBuffer(target);
    ASSERT(buffer);
    ANGLE_CONTEXT_TRY(buffer->bufferSubData(this, target, data, size, offset));
}

void Context::attachShader(ShaderProgramID program, ShaderProgramID shader)
{
    Program *programObject = mState.mShaderProgramManager->getProgram(program);
    Shader *shaderObject   = mState.mShaderProgramManager->getShader(shader);
    ASSERT(programObject && shaderObject);
    programObject->attachShader(this, shaderObject);
}

void Context::copyBufferSubData(BufferBinding readTarget,
                                BufferBinding writeTarget,
                                GLintptr readOffset,
                                GLintptr writeOffset,
                                GLsizeiptr size)
{
    // if size is zero, the copy is a successful no-op
    if (size == 0)
    {
        return;
    }

    // TODO(jmadill): cache these.
    Buffer *readBuffer  = mState.getTargetBuffer(readTarget);
    Buffer *writeBuffer = mState.getTargetBuffer(writeTarget);

    ANGLE_CONTEXT_TRY(
        writeBuffer->copyBufferSubData(this, readBuffer, readOffset, writeOffset, size));
}

void Context::bindAttribLocation(ShaderProgramID program, GLuint index, const GLchar *name)
{
    // Ideally we could share the program query with the validation layer if possible.
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->bindAttributeLocation(this, index, name);
}

void Context::bindBufferBase(BufferBinding target, GLuint index, BufferID buffer)
{
    bindBufferRange(target, index, buffer, 0, 0);
}

void Context::bindBufferRange(BufferBinding target,
                              GLuint index,
                              BufferID buffer,
                              GLintptr offset,
                              GLsizeiptr size)
{
    Buffer *object = mState.mBufferManager->checkBufferAllocation(mImplementation.get(), buffer);
    ANGLE_CONTEXT_TRY(mState.setIndexedBufferBinding(this, target, index, object, offset, size));
    if (target == BufferBinding::Uniform)
    {
        mUniformBufferObserverBindings[index].bind(object);
        mStateCache.onUniformBufferStateChange(this);
    }
    else if (target == BufferBinding::AtomicCounter)
    {
        mAtomicCounterBufferObserverBindings[index].bind(object);
        mStateCache.onAtomicCounterBufferStateChange(this);
    }
    else if (target == BufferBinding::ShaderStorage)
    {
        mShaderStorageBufferObserverBindings[index].bind(object);
        mStateCache.onShaderStorageBufferStateChange(this);
    }
    else
    {
        mPrivateStateCache.onBufferBindingChange();
    }

    if (object && isWebGL())
    {
        object->onBind(this, target);
    }
}

void Context::bindFramebuffer(GLenum target, FramebufferID framebuffer)
{
    if (target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
    {
        bindReadFramebuffer(framebuffer);
    }

    if (target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
    {
        bindDrawFramebuffer(framebuffer);
    }
}

void Context::bindRenderbuffer(GLenum target, RenderbufferID renderbuffer)
{
    ASSERT(target == GL_RENDERBUFFER);
    Renderbuffer *object = mState.mRenderbufferManager->checkRenderbufferAllocation(
        mImplementation.get(), renderbuffer);
    mState.setRenderbufferBinding(this, object);
}

void Context::texStorage2DMultisample(TextureType target,
                                      GLsizei samples,
                                      GLenum internalformat,
                                      GLsizei width,
                                      GLsizei height,
                                      GLboolean fixedsamplelocations)
{
    Extents size(width, height, 1);
    Texture *texture = getTextureByType(target);
    ANGLE_CONTEXT_TRY(texture->setStorageMultisample(this, target, samples, internalformat, size,
                                                     ConvertToBool(fixedsamplelocations)));
}

void Context::texStorage3DMultisample(TextureType target,
                                      GLsizei samples,
                                      GLenum internalformat,
                                      GLsizei width,
                                      GLsizei height,
                                      GLsizei depth,
                                      GLboolean fixedsamplelocations)
{
    Extents size(width, height, depth);
    Texture *texture = getTextureByType(target);
    ANGLE_CONTEXT_TRY(texture->setStorageMultisample(this, target, samples, internalformat, size,
                                                     ConvertToBool(fixedsamplelocations)));
}

void Context::getMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
{
    // According to spec 3.1 Table 20.49: Framebuffer Dependent Values,
    // the sample position should be queried by DRAW_FRAMEBUFFER.
    ANGLE_CONTEXT_TRY(mState.syncDirtyObject(this, GL_DRAW_FRAMEBUFFER, Command::GetMultisample));

    ASSERT(pname == GL_SAMPLE_POSITION);
    ANGLE_CONTEXT_TRY(mState.getDrawFramebuffer()->getSamplePosition(this, index, val));
}

void Context::getMultisamplefvRobust(GLenum pname,
                                     GLuint index,
                                     GLsizei paramCount,
                                     GLsizei *length,
                                     GLfloat *val)
{
    getMultisamplefv(pname, index, val);

    if (length != nullptr)
    {
        ASSERT(pname == GL_SAMPLE_POSITION);
        *length = 2;
    }
}

void Context::renderbufferStorage(GLenum target,
                                  GLenum internalformat,
                                  GLsizei width,
                                  GLsizei height)
{
    // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
    GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);

    Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
    ANGLE_CONTEXT_TRY(renderbuffer->setStorage(this, convertedInternalFormat, width, height));
}

void Context::renderbufferStorageMultisample(GLenum target,
                                             GLsizei samples,
                                             GLenum internalformat,
                                             GLsizei width,
                                             GLsizei height)
{
    renderbufferStorageMultisampleImpl(target, samples, internalformat, width, height,
                                       MultisamplingMode::Regular);
}

void Context::renderbufferStorageMultisampleEXT(GLenum target,
                                                GLsizei samples,
                                                GLenum internalformat,
                                                GLsizei width,
                                                GLsizei height)
{
    renderbufferStorageMultisampleImpl(target, samples, internalformat, width, height,
                                       MultisamplingMode::MultisampledRenderToTexture);
}

void Context::renderbufferStorageMultisampleImpl(GLenum target,
                                                 GLsizei samples,
                                                 GLenum internalformat,
                                                 GLsizei width,
                                                 GLsizei height,
                                                 MultisamplingMode mode)
{
    // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
    GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);

    Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
    ANGLE_CONTEXT_TRY(renderbuffer->setStorageMultisample(this, samples, convertedInternalFormat,
                                                          width, height, mode));
}

void Context::framebufferTexture2DMultisample(GLenum target,
                                              GLenum attachment,
                                              TextureTarget textarget,
                                              TextureID texture,
                                              GLint level,
                                              GLsizei samples)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (texture.value != 0)
    {
        Texture *textureObj = getTexture(texture);
        ImageIndex index    = ImageIndex::MakeFromTarget(textarget, level, 1);
        framebuffer->setAttachmentMultisample(this, GL_TEXTURE, attachment, index, textureObj,
                                              samples);
        textureObj->onBindToMSRTTFramebuffer();
    }
    else
    {
        framebuffer->resetAttachment(this, attachment);
    }

    mState.setObjectDirty(target);
}

void Context::getSynciv(SyncID syncPacked,
                        GLenum pname,
                        GLsizei count,
                        GLsizei *length,
                        GLint *values)
{
    const Sync *syncObject = nullptr;
    if (!isContextLost())
    {
        syncObject = getSync(syncPacked);
    }
    ANGLE_CONTEXT_TRY(QuerySynciv(this, syncObject, pname, count, length, values));
}

void Context::getFramebufferParameteriv(GLenum target,
                                        FramebufferParameter pnamePacked,
                                        GLint *params)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    QueryFramebufferParameteriv(framebuffer, pnamePacked, params);
}

void Context::framebufferParameteri(GLenum target, FramebufferParameter pnamePacked, GLint param)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    SetFramebufferParameteri(this, framebuffer, pnamePacked, param);
}

bool Context::getScratchBuffer(size_t requstedSizeBytes,
                               angle::MemoryBuffer **scratchBufferOut) const
{
    if (!mScratchBuffer.valid())
    {
        mScratchBuffer = mDisplay->requestScratchBuffer();
    }

    ASSERT(mScratchBuffer.valid());
    return mScratchBuffer.value().get(requstedSizeBytes, scratchBufferOut);
}

angle::ScratchBuffer *Context::getScratchBuffer() const
{
    if (!mScratchBuffer.valid())
    {
        mScratchBuffer = mDisplay->requestScratchBuffer();
    }

    ASSERT(mScratchBuffer.valid());
    return &mScratchBuffer.value();
}

bool Context::getZeroFilledBuffer(size_t requstedSizeBytes,
                                  const angle::MemoryBuffer **zeroBufferOut) const
{
    if (!mZeroFilledBuffer.valid())
    {
        mZeroFilledBuffer = mDisplay->requestZeroFilledBuffer();
    }

    ASSERT(mZeroFilledBuffer.valid());

    angle::MemoryBuffer *memoryBuffer = nullptr;
    if (!mZeroFilledBuffer.value().getInitialized(requstedSizeBytes, &memoryBuffer, 0))
    {
        return false;
    }

    *zeroBufferOut = memoryBuffer;
    return true;
}

void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
{
    if (numGroupsX == 0u || numGroupsY == 0u || numGroupsZ == 0u)
    {
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDispatch());

    angle::Result result =
        mImplementation->dispatchCompute(this, numGroupsX, numGroupsY, numGroupsZ);

    // This must be called before convertPpoToComputeOrDraw() so it uses the PPO's compute values
    // before convertPpoToComputeOrDraw() reverts the PPO back to graphics.
    MarkShaderStorageUsage(this);

    if (ANGLE_UNLIKELY(IsError(result)))
    {
        return;
    }
}

void Context::dispatchComputeIndirect(GLintptr indirect)
{
    ANGLE_CONTEXT_TRY(prepareForDispatch());
    ANGLE_CONTEXT_TRY(mImplementation->dispatchComputeIndirect(this, indirect));

    MarkShaderStorageUsage(this);
}

void Context::texStorage2D(TextureType target,
                           GLsizei levels,
                           GLenum internalFormat,
                           GLsizei width,
                           GLsizei height)
{
    Extents size(width, height, 1);
    Texture *texture = getTextureByType(target);
    ANGLE_CONTEXT_TRY(texture->setStorage(this, target, levels, internalFormat, size));
}

void Context::texStorage3D(TextureType target,
                           GLsizei levels,
                           GLenum internalFormat,
                           GLsizei width,
                           GLsizei height,
                           GLsizei depth)
{
    Extents size(width, height, depth);
    Texture *texture = getTextureByType(target);
    ANGLE_CONTEXT_TRY(texture->setStorage(this, target, levels, internalFormat, size));
}

void Context::memoryBarrier(GLbitfield barriers)
{
    ANGLE_CONTEXT_TRY(mImplementation->memoryBarrier(this, barriers));
}

void Context::memoryBarrierByRegion(GLbitfield barriers)
{
    ANGLE_CONTEXT_TRY(mImplementation->memoryBarrierByRegion(this, barriers));
}

void Context::multiDrawArrays(PrimitiveMode mode,
                              const GLint *firsts,
                              const GLsizei *counts,
                              GLsizei drawcount)
{
    if (noopMultiDraw(drawcount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->multiDrawArrays(this, mode, firsts, counts, drawcount));
}

void Context::multiDrawArraysInstanced(PrimitiveMode mode,
                                       const GLint *firsts,
                                       const GLsizei *counts,
                                       const GLsizei *instanceCounts,
                                       GLsizei drawcount)
{
    if (noopMultiDraw(drawcount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->multiDrawArraysInstanced(this, mode, firsts, counts,
                                                                instanceCounts, drawcount));
}

void Context::multiDrawArraysIndirect(PrimitiveMode mode,
                                      const void *indirect,
                                      GLsizei drawcount,
                                      GLsizei stride)
{
    if (noopMultiDraw(drawcount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(
        mImplementation->multiDrawArraysIndirect(this, mode, indirect, drawcount, stride));
    MarkShaderStorageUsage(this);
}

void Context::multiDrawElements(PrimitiveMode mode,
                                const GLsizei *counts,
                                DrawElementsType type,
                                const GLvoid *const *indices,
                                GLsizei drawcount)
{
    if (noopMultiDraw(drawcount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(
        mImplementation->multiDrawElements(this, mode, counts, type, indices, drawcount));
}

void Context::multiDrawElementsInstanced(PrimitiveMode mode,
                                         const GLsizei *counts,
                                         DrawElementsType type,
                                         const GLvoid *const *indices,
                                         const GLsizei *instanceCounts,
                                         GLsizei drawcount)
{
    if (noopMultiDraw(drawcount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->multiDrawElementsInstanced(this, mode, counts, type, indices,
                                                                  instanceCounts, drawcount));
}

void Context::multiDrawElementsIndirect(PrimitiveMode mode,
                                        DrawElementsType type,
                                        const void *indirect,
                                        GLsizei drawcount,
                                        GLsizei stride)
{
    if (noopMultiDraw(drawcount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(
        mImplementation->multiDrawElementsIndirect(this, mode, type, indirect, drawcount, stride));
    MarkShaderStorageUsage(this);
}

void Context::drawArraysInstancedBaseInstance(PrimitiveMode mode,
                                              GLint first,
                                              GLsizei count,
                                              GLsizei instanceCount,
                                              GLuint baseInstance)
{
    if (noopDrawInstanced(mode, count, instanceCount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ProgramExecutable *executable = mState.getLinkedProgramExecutable(this);

    const bool hasBaseInstance = executable->hasBaseInstanceUniform();
    if (hasBaseInstance)
    {
        executable->setBaseInstanceUniform(baseInstance);
    }

    rx::ResetBaseVertexBaseInstance resetUniforms(executable, false, hasBaseInstance);

    // The input gl_InstanceID does not follow the baseinstance. gl_InstanceID always falls on
    // the half-open range [0, instancecount). No need to set other stuff. Except for Vulkan.

    ANGLE_CONTEXT_TRY(mImplementation->drawArraysInstancedBaseInstance(
        this, mode, first, count, instanceCount, baseInstance));
    MarkTransformFeedbackBufferUsage(this, count, 1);
}

void Context::drawElementsInstancedBaseInstance(PrimitiveMode mode,
                                                GLsizei count,
                                                DrawElementsType type,
                                                const void *indices,
                                                GLsizei instanceCount,
                                                GLuint baseInstance)
{
    drawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instanceCount, 0,
                                                baseInstance);
}

void Context::drawElementsInstancedBaseVertexBaseInstance(PrimitiveMode mode,
                                                          GLsizei count,
                                                          DrawElementsType type,
                                                          const GLvoid *indices,
                                                          GLsizei instanceCount,
                                                          GLint baseVertex,
                                                          GLuint baseInstance)
{
    if (noopDrawInstanced(mode, count, instanceCount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ProgramExecutable *executable = mState.getLinkedProgramExecutable(this);

    const bool hasBaseVertex   = executable->hasBaseVertexUniform();
    const bool hasBaseInstance = executable->hasBaseInstanceUniform();

    if (hasBaseVertex)
    {
        executable->setBaseVertexUniform(baseVertex);
    }

    if (hasBaseInstance)
    {
        executable->setBaseInstanceUniform(baseInstance);
    }

    rx::ResetBaseVertexBaseInstance resetUniforms(executable, hasBaseVertex, hasBaseInstance);

    ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstancedBaseVertexBaseInstance(
        this, mode, count, type, indices, instanceCount, baseVertex, baseInstance));
}

void Context::multiDrawArraysInstancedBaseInstance(PrimitiveMode mode,
                                                   const GLint *firsts,
                                                   const GLsizei *counts,
                                                   const GLsizei *instanceCounts,
                                                   const GLuint *baseInstances,
                                                   GLsizei drawcount)
{
    if (noopMultiDraw(drawcount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->multiDrawArraysInstancedBaseInstance(
        this, mode, firsts, counts, instanceCounts, baseInstances, drawcount));
}

void Context::multiDrawElementsBaseVertex(PrimitiveMode mode,
                                          const GLsizei *count,
                                          DrawElementsType type,
                                          const void *const *indices,
                                          GLsizei drawcount,
                                          const GLint *basevertex)
{
    UNIMPLEMENTED();
}

void Context::multiDrawElementsInstancedBaseVertexBaseInstance(PrimitiveMode mode,
                                                               const GLsizei *counts,
                                                               DrawElementsType type,
                                                               const GLvoid *const *indices,
                                                               const GLsizei *instanceCounts,
                                                               const GLint *baseVertices,
                                                               const GLuint *baseInstances,
                                                               GLsizei drawcount)
{
    if (noopMultiDraw(drawcount))
    {
        ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
        return;
    }

    ANGLE_CONTEXT_TRY(prepareForDraw(mode));
    ANGLE_CONTEXT_TRY(mImplementation->multiDrawElementsInstancedBaseVertexBaseInstance(
        this, mode, counts, type, indices, instanceCounts, baseVertices, baseInstances, drawcount));
}

GLenum Context::checkFramebufferStatus(GLenum target)
{
    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
    ASSERT(framebuffer);
    return framebuffer->checkStatus(this).status;
}

void Context::compileShader(ShaderProgramID shader)
{
    Shader *shaderObject = getShaderNoResolveCompile(shader);
    ASSERT(shaderObject != nullptr);
    shaderObject->compile(this, angle::JobResultExpectancy::Future);
}

void Context::deleteBuffers(GLsizei n, const BufferID *buffers)
{
    for (int i = 0; i < n; i++)
    {
        deleteBuffer(buffers[i]);
    }
}

void Context::deleteFramebuffers(GLsizei n, const FramebufferID *framebuffers)
{
    for (int i = 0; i < n; i++)
    {
        if (framebuffers[i].value != 0)
        {
            deleteFramebuffer(framebuffers[i]);
        }
    }
}

void Context::deleteRenderbuffers(GLsizei n, const RenderbufferID *renderbuffers)
{
    for (int i = 0; i < n; i++)
    {
        deleteRenderbuffer(renderbuffers[i]);
    }
}

void Context::deleteTextures(GLsizei n, const TextureID *textures)
{
    for (int i = 0; i < n; i++)
    {
        if (textures[i].value != 0)
        {
            deleteTexture(textures[i]);
        }
    }
}

void Context::detachShader(ShaderProgramID program, ShaderProgramID shader)
{
    Program *programObject = getProgramNoResolveLink(program);
    ASSERT(programObject);

    Shader *shaderObject = getShaderNoResolveCompile(shader);
    ASSERT(shaderObject);

    programObject->detachShader(this, shaderObject);
}

void Context::genBuffers(GLsizei n, BufferID *buffers)
{
    for (int i = 0; i < n; i++)
    {
        if (!createBuffer(&buffers[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLGenBuffers);
            return;
        }
    }
}

void Context::genFramebuffers(GLsizei n, FramebufferID *framebuffers)
{
    for (int i = 0; i < n; i++)
    {
        if (!createFramebuffer(&framebuffers[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLGenFramebuffers);
            return;
        }
    }
}

void Context::genRenderbuffers(GLsizei n, RenderbufferID *renderbuffers)
{
    for (int i = 0; i < n; i++)
    {
        if (!createRenderbuffer(&renderbuffers[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLGenRenderbuffers);
            return;
        }
    }
}

void Context::genTextures(GLsizei n, TextureID *textures)
{
    for (int i = 0; i < n; i++)
    {
        if (!createTexture(&textures[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLGenTextures);
            return;
        }
    }
}

void Context::getActiveAttrib(ShaderProgramID program,
                              GLuint index,
                              GLsizei bufsize,
                              GLsizei *length,
                              GLint *size,
                              GLenum *type,
                              GLchar *name)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().getActiveAttribute(index, bufsize, length, size, type, name);
}

void Context::getActiveUniform(ShaderProgramID program,
                               GLuint index,
                               GLsizei bufsize,
                               GLsizei *length,
                               GLint *size,
                               GLenum *type,
                               GLchar *name)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().getActiveUniform(index, bufsize, length, size, type, name);
}

void Context::getAttachedShaders(ShaderProgramID program,
                                 GLsizei maxcount,
                                 GLsizei *count,
                                 ShaderProgramID *shaders)
{
    Program *programObject = getProgramNoResolveLink(program);
    ASSERT(programObject);
    programObject->getAttachedShaders(maxcount, count, shaders);
}

GLint Context::getAttribLocation(ShaderProgramID program, const GLchar *name)
{
    if (ANGLE_UNLIKELY(nameStartsWithReservedPrefix(name)))
    {
        return -1;
    }

    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    return programObject->getExecutable().getAttributeLocation(name);
}

void Context::getBooleanv(GLenum pname, GLboolean *data)
{
    getBooleanvRobust(pname, 0, nullptr, data);
}

void Context::getBooleanvRobust(GLenum pname, GLsizei paramCount, GLsizei *length, GLboolean *data)
{
    GLenum nativeType;
    unsigned int numParams;
    const bool paramFound = getQueryParameterInfo(pname, &nativeType, &numParams);
    if (ANGLE_UNLIKELY(!paramFound))
    {
        return;  // Avoid crashing with invalid apps running with no validation.
    }

    if (nativeType == GL_BOOL)
    {
        getBooleanvImpl(pname, data);
    }
    else
    {
        CastStateValues(this, nativeType, pname, numParams, data);
    }

    if (length != nullptr)
    {
        *length = numParams;
    }
}

void Context::getFloatv(GLenum pname, GLfloat *data)
{
    getFloatvRobust(pname, 0, nullptr, data);
}

void Context::getFloatvRobust(GLenum pname, GLsizei paramCount, GLsizei *length, GLfloat *data)
{
    GLenum nativeType;
    unsigned int numParams;
    const bool paramFound = getQueryParameterInfo(pname, &nativeType, &numParams);
    if (ANGLE_UNLIKELY(!paramFound))
    {
        return;  // Avoid crashing with invalid apps running with no validation.
    }

    if (nativeType == GL_FLOAT)
    {
        getFloatvImpl(pname, data);
    }
    else
    {
        CastStateValues(this, nativeType, pname, numParams, data);
    }

    if (length != nullptr)
    {
        *length = numParams;
    }
}

void Context::getIntegerv(GLenum pname, GLint *data)
{
    getIntegervRobust(pname, 0, nullptr, data);
}

void Context::getIntegervRobust(GLenum pname, GLsizei paramCount, GLsizei *length, GLint *data)
{
    GLenum nativeType;
    unsigned int numParams;
    const bool paramFound = getQueryParameterInfo(pname, &nativeType, &numParams);
    if (ANGLE_UNLIKELY(!paramFound))
    {
        return;  // Avoid crashing with invalid apps running with no validation.
    }

    if (nativeType == GL_INT)
    {
        getIntegervImpl(pname, data);
    }
    else
    {
        CastStateValues(this, nativeType, pname, numParams, data);
    }

    if (length != nullptr)
    {
        *length = numParams;
    }
}

void Context::getProgramiv(ShaderProgramID programPacked, GLenum pname, GLint *params)
{
    // Don't resolve link if checking the link completion status.
    Program *programObject = getProgramNoResolveLink(programPacked);
    if (!isContextLost() && pname != GL_COMPLETION_STATUS_KHR)
    {
        programObject = getProgramResolveLink(programPacked);
    }
    ASSERT(programObject != nullptr);
    QueryProgramiv(this, programObject, pname, params);
}

void Context::getProgramivRobust(ShaderProgramID programPacked,
                                 GLenum pname,
                                 GLsizei paramCount,
                                 GLsizei *length,
                                 GLint *params)
{
    getProgramiv(programPacked, pname, params);

    if (length != nullptr)
    {
        *length = (pname == GL_COMPUTE_WORK_GROUP_SIZE) ? 3 : 1;
    }
}

void Context::getProgramPipelineiv(ProgramPipelineID pipeline, GLenum pname, GLint *params)
{
    ProgramPipeline *programPipeline = nullptr;
    if (!isContextLost())
    {
        programPipeline = mState.mProgramPipelineManager->checkProgramPipelineAllocation(
            mImplementation.get(), pipeline);
    }
    QueryProgramPipelineiv(this, programPipeline, pname, params);
}

MemoryObject *Context::getMemoryObject(MemoryObjectID handle) const
{
    return mState.mMemoryObjectManager->getMemoryObject(handle);
}

Semaphore *Context::getSemaphore(SemaphoreID handle) const
{
    return mState.mSemaphoreManager->getSemaphore(handle);
}

void Context::getProgramInfoLog(ShaderProgramID program,
                                GLsizei bufsize,
                                GLsizei *length,
                                GLchar *infolog)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getInfoLog(bufsize, length, infolog);
}

void Context::getProgramPipelineInfoLog(ProgramPipelineID pipeline,
                                        GLsizei bufSize,
                                        GLsizei *length,
                                        GLchar *infoLog)
{
    ProgramPipeline *programPipeline = getProgramPipeline(pipeline);
    if (programPipeline)
    {
        programPipeline->getInfoLog(bufSize, length, infoLog);
    }
    else
    {
        if (length)
        {
            *length = 0;
        }
        if (infoLog)
        {
            *infoLog = '\0';
        }
    }
}

void Context::getShaderiv(ShaderProgramID shaderPacked, ShaderParameter pnamePacked, GLint *params)
{
    Shader *shaderObject = nullptr;
    if (!isContextLost())
    {
        shaderObject = getShaderNoResolveCompile(shaderPacked);
        ASSERT(shaderObject != nullptr);
    }
    QueryShaderiv(this, shaderObject, pnamePacked, params);
}

void Context::getShaderivRobust(ShaderProgramID shaderPacked,
                                ShaderParameter pnamePacked,
                                GLsizei paramCount,
                                GLsizei *length,
                                GLint *params)
{
    getShaderiv(shaderPacked, pnamePacked, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::getShaderInfoLog(ShaderProgramID shader,
                               GLsizei bufsize,
                               GLsizei *length,
                               GLchar *infolog)
{
    Shader *shaderObject = getShaderNoResolveCompile(shader);
    ASSERT(shaderObject);
    shaderObject->getInfoLog(this, bufsize, length, infolog);
}

void Context::getShaderPrecisionFormat(GLenum shadertype,
                                       GLenum precisiontype,
                                       GLint *range,
                                       GLint *precision)
{
    ASSERT(range != nullptr && precision != nullptr);

    switch (shadertype)
    {
        case GL_VERTEX_SHADER:
            switch (precisiontype)
            {
                case GL_LOW_FLOAT:
                    mState.getCaps().vertexLowpFloat.get(range, precision);
                    break;
                case GL_MEDIUM_FLOAT:
                    mState.getCaps().vertexMediumpFloat.get(range, precision);
                    break;
                case GL_HIGH_FLOAT:
                    mState.getCaps().vertexHighpFloat.get(range, precision);
                    break;

                case GL_LOW_INT:
                    mState.getCaps().vertexLowpInt.get(range, precision);
                    break;
                case GL_MEDIUM_INT:
                    mState.getCaps().vertexMediumpInt.get(range, precision);
                    break;
                case GL_HIGH_INT:
                    mState.getCaps().vertexHighpInt.get(range, precision);
                    break;

                default:
                    UNREACHABLE();
                    return;
            }
            break;

        case GL_FRAGMENT_SHADER:
            switch (precisiontype)
            {
                case GL_LOW_FLOAT:
                    mState.getCaps().fragmentLowpFloat.get(range, precision);
                    break;
                case GL_MEDIUM_FLOAT:
                    mState.getCaps().fragmentMediumpFloat.get(range, precision);
                    break;
                case GL_HIGH_FLOAT:
                    mState.getCaps().fragmentHighpFloat.get(range, precision);
                    break;

                case GL_LOW_INT:
                    mState.getCaps().fragmentLowpInt.get(range, precision);
                    break;
                case GL_MEDIUM_INT:
                    mState.getCaps().fragmentMediumpInt.get(range, precision);
                    break;
                case GL_HIGH_INT:
                    mState.getCaps().fragmentHighpInt.get(range, precision);
                    break;

                default:
                    UNREACHABLE();
                    return;
            }
            break;

        default:
            UNREACHABLE();
            return;
    }
}

void Context::getShaderSource(ShaderProgramID shader,
                              GLsizei bufsize,
                              GLsizei *length,
                              GLchar *source)
{
    Shader *shaderObject = getShaderNoResolveCompile(shader);
    ASSERT(shaderObject);
    shaderObject->getSource(bufsize, length, source);
}

void Context::getUniformfv(ShaderProgramID programPacked,
                           UniformLocation locationPacked,
                           GLfloat *params)
{
    getUniformfvRobust(programPacked, locationPacked, 0, nullptr, params);
}

void Context::getUniformfvRobust(ShaderProgramID programPacked,
                                 UniformLocation locationPacked,
                                 GLsizei bufSize,
                                 GLsizei *length,
                                 GLfloat *params)
{
    const Program *programObject = getProgramResolveLink(programPacked);
    ASSERT(programObject != nullptr);
    const ProgramExecutable &executable = programObject->getExecutable();

    executable.getUniformfv(this, locationPacked, params);

    if (length != nullptr)
    {
        *length = VariableComponentCount(executable.getUniformByLocation(locationPacked).getType());
    }
}

void Context::getUniformiv(ShaderProgramID programPacked,
                           UniformLocation locationPacked,
                           GLint *params)
{
    getUniformivRobust(programPacked, locationPacked, 0, nullptr, params);
}

void Context::getUniformivRobust(ShaderProgramID programPacked,
                                 UniformLocation locationPacked,
                                 GLsizei bufSize,
                                 GLsizei *length,
                                 GLint *params)
{
    const Program *programObject = getProgramResolveLink(programPacked);
    ASSERT(programObject != nullptr);
    const ProgramExecutable &executable = programObject->getExecutable();

    executable.getUniformiv(this, locationPacked, params);

    if (length != nullptr)
    {
        *length = VariableComponentCount(executable.getUniformByLocation(locationPacked).getType());
    }
}

GLint Context::getUniformLocation(ShaderProgramID program, const GLchar *name)
{
    if (ANGLE_UNLIKELY(nameStartsWithReservedPrefix(name)))
    {
        return -1;
    }

    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    return programObject->getExecutable().getUniformLocation(name).value;
}

GLboolean Context::isBuffer(BufferID buffer) const
{
    if (buffer.value == 0)
    {
        return GL_FALSE;
    }

    return ConvertToGLBoolean(getBuffer(buffer));
}

GLboolean Context::isFramebuffer(FramebufferID framebuffer) const
{
    if (framebuffer.value == 0)
    {
        return GL_FALSE;
    }

    return ConvertToGLBoolean(getFramebuffer(framebuffer));
}

GLboolean Context::isProgram(ShaderProgramID program) const
{
    if (program.value == 0)
    {
        return GL_FALSE;
    }

    return ConvertToGLBoolean(getProgramNoResolveLink(program));
}

GLboolean Context::isRenderbuffer(RenderbufferID renderbuffer) const
{
    if (renderbuffer.value == 0)
    {
        return GL_FALSE;
    }

    return ConvertToGLBoolean(getRenderbuffer(renderbuffer));
}

GLboolean Context::isShader(ShaderProgramID shader) const
{
    if (shader.value == 0)
    {
        return GL_FALSE;
    }

    return ConvertToGLBoolean(getShaderNoResolveCompile(shader));
}

GLboolean Context::isTexture(TextureID texture) const
{
    if (texture.value == 0)
    {
        return GL_FALSE;
    }

    return ConvertToGLBoolean(getTexture(texture));
}

void Context::linkProgram(ShaderProgramID program)
{
    Program *programObject = getProgramNoResolveLink(program);
    ASSERT(programObject);
    ANGLE_CONTEXT_TRY(programObject->link(this, angle::JobResultExpectancy::Future));
}

void Context::releaseShaderCompiler()
{
    mCompiler.set(this, nullptr);
}

void Context::shaderBinary(GLsizei n,
                           const ShaderProgramID *shaders,
                           GLenum binaryformat,
                           const void *binary,
                           GLsizei length)
{
    Shader *shaderObject = getShaderNoResolveCompile(*shaders);
    ASSERT(shaderObject != nullptr);
    ANGLE_CONTEXT_TRY(
        shaderObject->loadShaderBinary(this, binary, length, angle::JobResultExpectancy::Future));
}

void Context::bindFragDataLocationIndexed(ShaderProgramID program,
                                          GLuint colorNumber,
                                          GLuint index,
                                          const char *name)
{
    Program *programObject = getProgramNoResolveLink(program);
    programObject->bindFragmentOutputLocation(this, colorNumber, name);
    programObject->bindFragmentOutputIndex(this, index, name);
}

void Context::bindFragDataLocation(ShaderProgramID program, GLuint colorNumber, const char *name)
{
    bindFragDataLocationIndexed(program, colorNumber, 0u, name);
}

int Context::getFragDataIndex(ShaderProgramID program, const char *name)
{
    Program *programObject = getProgramResolveLink(program);
    return programObject->getExecutable().getFragDataIndex(name);
}

int Context::getProgramResourceLocationIndex(ShaderProgramID program,
                                             GLenum programInterface,
                                             const char *name)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programInterface == GL_PROGRAM_OUTPUT);
    return programObject->getExecutable().getFragDataIndex(name);
}

void Context::shaderSource(ShaderProgramID shader,
                           GLsizei count,
                           const GLchar *const *string,
                           const GLint *length)
{
    Shader *shaderObject = getShaderNoResolveCompile(shader);
    ASSERT(shaderObject);
    shaderObject->setSource(this, count, string, length);
}

Program *Context::getActiveLinkedProgramPPO() const
{
    ProgramPipeline *programPipelineObject = mState.getProgramPipeline();
    if (programPipelineObject)
    {
        return programPipelineObject->getLinkedActiveShaderProgram(this);
    }

    return nullptr;
}

void Context::onSamplerUniformChange(size_t textureUnitIndex)
{
    mState.onActiveTextureChange(this, textureUnitIndex);
    mStateCache.onActiveTextureChange(this);
}

void Context::uniformMatrix2fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value)
{
    Program *program = getActiveLinkedProgram();
    program->getExecutable().setUniformMatrix2fv(location, count, transpose, value);
}

void Context::uniformMatrix3fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value)
{
    Program *program = getActiveLinkedProgram();
    program->getExecutable().setUniformMatrix3fv(location, count, transpose, value);
}

void Context::uniformMatrix4fv(UniformLocation location,
                               GLsizei count,
                               GLboolean transpose,
                               const GLfloat *value)
{
    Program *program = getActiveLinkedProgram();
    program->getExecutable().setUniformMatrix4fv(location, count, transpose, value);
}

void Context::validateProgram(ShaderProgramID program)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->validate(mState.getCaps());
}

void Context::validateProgramPipeline(ProgramPipelineID pipeline)
{
    // GLES spec 3.2, Section 7.4 "Program Pipeline Objects"
    // If pipeline is a name that has been generated (without subsequent deletion) by
    // GenProgramPipelines, but refers to a program pipeline object that has not been
    // previously bound, the GL first creates a new state vector in the same manner as
    // when BindProgramPipeline creates a new program pipeline object.
    //
    // void BindProgramPipeline( uint pipeline );
    // pipeline is the program pipeline object name. The resulting program pipeline
    // object is a new state vector, comprising all the state and with the same initial values
    // listed in table 21.20.
    ProgramPipeline *programPipeline =
        mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
                                                                       pipeline);
    ASSERT(programPipeline);

    programPipeline->validate(this);
}

void Context::getProgramBinary(ShaderProgramID program,
                               GLsizei bufSize,
                               GLsizei *length,
                               GLenum *binaryFormat,
                               void *binary)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject != nullptr);

    ANGLE_CONTEXT_TRY(programObject->getBinary(this, binaryFormat, binary, bufSize, length));
}

void Context::programBinary(ShaderProgramID program,
                            GLenum binaryFormat,
                            const void *binary,
                            GLsizei length)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject != nullptr);

    ANGLE_CONTEXT_TRY(programObject->setBinary(this, binaryFormat, binary, length));
}

void Context::genQueries(GLsizei n, QueryID *ids)
{
    for (GLsizei i = 0; i < n; i++)
    {
        if (!mQueryHandleAllocator.allocate(&ids[i].value))
        {
            handleExhaustionError(angle::EntryPoint::GLGenQueries);
            return;
        }
        mQueryMap.assign(ids[i], nullptr);
    }
}

void Context::deleteQueries(GLsizei n, const QueryID *ids)
{
    for (int i = 0; i < n; i++)
    {
        QueryID query = ids[i];

        Query *queryObject = nullptr;
        if (mQueryMap.erase(query, &queryObject))
        {
            mQueryHandleAllocator.release(query.value);
            if (queryObject)
            {
                queryObject->release(this);
            }
        }
    }
}

bool Context::isQueryGenerated(QueryID query) const
{
    return mQueryMap.contains(query);
}

GLboolean Context::isQuery(QueryID id) const
{
    return ConvertToGLBoolean(getQuery(id) != nullptr);
}

void Context::deleteVertexArrays(GLsizei n, const VertexArrayID *arrays)
{
    for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
    {
        VertexArrayID vertexArray = arrays[arrayIndex];

        if (arrays[arrayIndex].value != 0)
        {
            VertexArray *vertexArrayObject = nullptr;
            getMutablePrivateState()->eraseVertexArray(vertexArray, &vertexArrayObject);
            if (vertexArrayObject != nullptr)
            {
                detachVertexArray(vertexArray);
                vertexArrayObject->onDestroy(this);
            }
        }
    }
}

void Context::endTransformFeedback()
{
    TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback();
    ANGLE_CONTEXT_TRY(transformFeedback->end(this));
    onActiveTransformFeedbackChange();
}

void Context::transformFeedbackVaryings(ShaderProgramID program,
                                        GLsizei count,
                                        const GLchar *const *varyings,
                                        GLenum bufferMode)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->setTransformFeedbackVaryings(this, count, varyings, bufferMode);
}

void Context::getTransformFeedbackVarying(ShaderProgramID program,
                                          GLuint index,
                                          GLsizei bufSize,
                                          GLsizei *length,
                                          GLsizei *size,
                                          GLenum *type,
                                          GLchar *name)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().getTransformFeedbackVarying(index, bufSize, length, size, type,
                                                               name);
}

void Context::deleteTransformFeedbacks(GLsizei n, const TransformFeedbackID *ids)
{
    for (int i = 0; i < n; i++)
    {
        TransformFeedbackID transformFeedback = ids[i];
        if (transformFeedback.value == 0)
        {
            continue;
        }

        TransformFeedback *transformFeedbackObject = nullptr;
        if (mTransformFeedbackMap.erase(transformFeedback, &transformFeedbackObject))
        {
            if (transformFeedbackObject != nullptr)
            {
                detachTransformFeedback(transformFeedback);
                transformFeedbackObject->release(this);
            }

            mTransformFeedbackHandleAllocator.release(transformFeedback.value);
        }
    }
}

void Context::genTransformFeedbacks(GLsizei n, TransformFeedbackID *ids)
{
    for (int i = 0; i < n; i++)
    {
        if (!mTransformFeedbackHandleAllocator.allocate(&ids[i].value))
        {
            handleExhaustionError(angle::EntryPoint::GLGenTransformFeedbacks);
            return;
        }
        mTransformFeedbackMap.assign(ids[i], nullptr);
    }
}

void Context::genVertexArrays(GLsizei n, VertexArrayID *ids)
{
    PrivateState *privState = getMutablePrivateState();
    for (int i = 0; i < n; i++)
    {
        if (!privState->allocateVertexID(&ids[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLGenVertexArrays);
            return;
        }
    }
}

GLboolean Context::isTransformFeedback(TransformFeedbackID id) const
{
    if (id.value == 0)
    {
        // The 3.0.4 spec [section 6.1.11] states that if ID is zero, IsTransformFeedback
        // returns FALSE
        return GL_FALSE;
    }

    const TransformFeedback *transformFeedback = getTransformFeedback(id);
    return ConvertToGLBoolean(transformFeedback != nullptr);
}

void Context::pauseTransformFeedback()
{
    TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback();
    ANGLE_CONTEXT_TRY(transformFeedback->pause(this));
    onActiveTransformFeedbackChange();
}

void Context::resumeTransformFeedback()
{
    TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback();
    ANGLE_CONTEXT_TRY(transformFeedback->resume(this));
    onActiveTransformFeedbackChange();
}

void Context::getUniformuiv(ShaderProgramID programPacked,
                            UniformLocation locationPacked,
                            GLuint *params)
{
    getUniformuivRobust(programPacked, locationPacked, 0, nullptr, params);
}

void Context::getUniformuivRobust(ShaderProgramID programPacked,
                                  UniformLocation locationPacked,
                                  GLsizei bufSize,
                                  GLsizei *length,
                                  GLuint *params)
{
    const Program *programObject = getProgramResolveLink(programPacked);
    ASSERT(programObject != nullptr);
    const ProgramExecutable &executable = programObject->getExecutable();

    executable.getUniformuiv(this, locationPacked, params);

    if (length != nullptr)
    {
        *length = VariableComponentCount(executable.getUniformByLocation(locationPacked).getType());
    }
}

GLint Context::getFragDataLocation(ShaderProgramID program, const GLchar *name)
{
    const Program *programObject = getProgramResolveLink(program);
    return programObject->getExecutable().getFragDataLocation(name);
}

void Context::getUniformIndices(ShaderProgramID program,
                                GLsizei uniformCount,
                                const GLchar *const *uniformNames,
                                GLuint *uniformIndices)
{
    const Program *programObject = getProgramResolveLink(program);
    if (!programObject->isLinked())
    {
        for (int uniformId = 0; uniformId < uniformCount; uniformId++)
        {
            uniformIndices[uniformId] = GL_INVALID_INDEX;
        }
    }
    else
    {
        for (int uniformId = 0; uniformId < uniformCount; uniformId++)
        {
            uniformIndices[uniformId] =
                programObject->getExecutable().getUniformIndex(uniformNames[uniformId]);
        }
    }
}

void Context::getActiveUniformsiv(ShaderProgramID program,
                                  GLsizei uniformCount,
                                  const GLuint *uniformIndices,
                                  GLenum pname,
                                  GLint *params)
{
    const Program *programObject = getProgramResolveLink(program);
    for (int uniformId = 0; uniformId < uniformCount; uniformId++)
    {
        const GLuint index = uniformIndices[uniformId];
        params[uniformId]  = GetUniformResourceProperty(programObject, index, pname);
    }
}

GLuint Context::getUniformBlockIndex(ShaderProgramID program, const GLchar *uniformBlockName)
{
    const Program *programObject = getProgramResolveLink(program);
    return programObject->getExecutable().getUniformBlockIndex(uniformBlockName);
}

void Context::getActiveUniformBlockiv(ShaderProgramID programPacked,
                                      UniformBlockIndex uniformBlockIndexPacked,
                                      UniformBlockParameter pnamePacked,
                                      GLint *params)
{
    const Program *programObject = getProgramResolveLink(programPacked);
    QueryActiveUniformBlockiv(programObject, uniformBlockIndexPacked, pnamePacked, nullptr, params);
}

void Context::getActiveUniformBlockivRobust(ShaderProgramID programPacked,
                                            UniformBlockIndex uniformBlockIndexPacked,
                                            UniformBlockParameter pnamePacked,
                                            GLsizei paramCount,
                                            GLsizei *length,
                                            GLint *params)
{
    const Program *programObject = getProgramResolveLink(programPacked);
    QueryActiveUniformBlockiv(programObject, uniformBlockIndexPacked, pnamePacked, length, params);
}

void Context::getActiveUniformBlockName(ShaderProgramID program,
                                        UniformBlockIndex uniformBlockIndex,
                                        GLsizei bufSize,
                                        GLsizei *length,
                                        GLchar *uniformBlockName)
{
    const Program *programObject = getProgramResolveLink(program);
    programObject->getExecutable().getActiveUniformBlockName(this, uniformBlockIndex, bufSize,
                                                             length, uniformBlockName);
}

void Context::uniformBlockBinding(ShaderProgramID program,
                                  UniformBlockIndex uniformBlockIndex,
                                  GLuint uniformBlockBinding)
{
    Program *programObject = getProgramResolveLink(program);
    programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
}

GLsync Context::fenceSync(GLenum condition, GLbitfield flags)
{
    SyncID syncHandle;
    if (!mState.mSyncManager->createSync(mImplementation.get(), &syncHandle))
    {
        handleExhaustionError(angle::EntryPoint::GLFenceSync);
        return nullptr;
    }

    Sync *syncObject = getSync(syncHandle);
    if (syncObject->set(this, condition, flags) == angle::Result::Stop)
    {
        deleteSync(syncHandle);
        return nullptr;
    }

    return unsafe_int_to_pointer_cast<GLsync>(syncHandle.value);
}

GLboolean Context::isSync(SyncID syncPacked) const
{
    return (getSync(syncPacked) != nullptr);
}

GLenum Context::clientWaitSync(SyncID syncPacked, GLbitfield flags, GLuint64 timeout)
{
    Sync *syncObject = getSync(syncPacked);

    GLenum result = GL_WAIT_FAILED;
    if (syncObject->clientWait(this, flags, timeout, &result) == angle::Result::Stop)
    {
        return GL_WAIT_FAILED;
    }
    return result;
}

void Context::waitSync(SyncID syncPacked, GLbitfield flags, GLuint64 timeout)
{
    Sync *syncObject = getSync(syncPacked);
    ANGLE_CONTEXT_TRY(syncObject->serverWait(this, flags, timeout));
}

void Context::getInteger64v(GLenum pname, GLint64 *data)
{
    getInteger64vRobust(pname, 0, nullptr, data);
}

void Context::getInteger64vRobust(GLenum pname, GLsizei paramCount, GLsizei *length, GLint64 *data)
{
    GLenum nativeType;
    unsigned int numParams;
    const bool paramFound = getQueryParameterInfo(pname, &nativeType, &numParams);
    if (ANGLE_UNLIKELY(!paramFound))
    {
        return;  // Avoid crashing with invalid apps running with no validation.
    }

    if (nativeType == GL_INT64)
    {
        getInteger64vImpl(pname, data);
    }
    else
    {
        CastStateValues(this, nativeType, pname, numParams, data);
    }

    if (length != nullptr)
    {
        *length = numParams;
    }
}

void Context::getBufferParameteri64v(BufferBinding target, BufferParam pnamePacked, GLint64 *params)
{
    Buffer *buffer = mState.getTargetBuffer(target);
    QueryBufferParameteri64v(buffer, pnamePacked, params);
}

void Context::getBufferParameteri64vRobust(BufferBinding target,
                                           BufferParam pnamePacked,
                                           GLsizei paramCount,
                                           GLsizei *length,
                                           GLint64 *params)
{
    getBufferParameteri64v(target, pnamePacked, params);

    if (length != nullptr)
    {
        *length = 1;
    }
}

void Context::genSamplers(GLsizei count, SamplerID *samplers)
{
    for (int i = 0; i < count; i++)
    {
        if (!mState.mSamplerManager->createSampler(&samplers[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLGenSamplers);
            return;
        }
    }
}

void Context::deleteSamplers(GLsizei count, const SamplerID *samplers)
{
    for (int i = 0; i < count; i++)
    {
        SamplerID sampler = samplers[i];

        if (mState.mSamplerManager->getSampler(sampler))
        {
            detachSampler(sampler);
        }

        mState.mSamplerManager->deleteObject(this, sampler);
    }
}

void Context::getInternalformativ(GLenum target,
                                  GLenum internalformat,
                                  GLenum pname,
                                  GLsizei count,
                                  GLint *params)
{
    Texture *texture    = nullptr;
    TextureType textype = FromGLenum<TextureType>(target);
    if (textype != TextureType::InvalidEnum)
    {
        texture = getTextureByType(textype);
    }
    const TextureCaps &formatCaps = mState.getTextureCap(internalformat);
    QueryInternalFormativ(this, texture, internalformat, formatCaps, pname, count, params);
}

void Context::getInternalformativRobust(GLenum target,
                                        GLenum internalformat,
                                        GLenum pname,
                                        GLsizei paramCount,
                                        GLsizei *length,
                                        GLint *params)
{
    getInternalformativ(target, internalformat, pname, paramCount, params);

    if (length != nullptr)
    {
        if (pname == GL_SAMPLES)
        {
            *length = clampCast<GLsizei>(mState.getTextureCap(internalformat).sampleCounts.size());
        }
        else
        {
            ASSERT(pname != GL_SURFACE_COMPRESSION_EXT);
            *length = 1;
        }
    }
}

void Context::programUniform1i(ShaderProgramID program, UniformLocation location, GLint v0)
{
    programUniform1iv(program, location, 1, &v0);
}

void Context::programUniform2i(ShaderProgramID program,
                               UniformLocation location,
                               GLint v0,
                               GLint v1)
{
    GLint xy[2] = {v0, v1};
    programUniform2iv(program, location, 1, xy);
}

void Context::programUniform3i(ShaderProgramID program,
                               UniformLocation location,
                               GLint v0,
                               GLint v1,
                               GLint v2)
{
    GLint xyz[3] = {v0, v1, v2};
    programUniform3iv(program, location, 1, xyz);
}

void Context::programUniform4i(ShaderProgramID program,
                               UniformLocation location,
                               GLint v0,
                               GLint v1,
                               GLint v2,
                               GLint v3)
{
    GLint xyzw[4] = {v0, v1, v2, v3};
    programUniform4iv(program, location, 1, xyzw);
}

void Context::programUniform1ui(ShaderProgramID program, UniformLocation location, GLuint v0)
{
    programUniform1uiv(program, location, 1, &v0);
}

void Context::programUniform2ui(ShaderProgramID program,
                                UniformLocation location,
                                GLuint v0,
                                GLuint v1)
{
    GLuint xy[2] = {v0, v1};
    programUniform2uiv(program, location, 1, xy);
}

void Context::programUniform3ui(ShaderProgramID program,
                                UniformLocation location,
                                GLuint v0,
                                GLuint v1,
                                GLuint v2)
{
    GLuint xyz[3] = {v0, v1, v2};
    programUniform3uiv(program, location, 1, xyz);
}

void Context::programUniform4ui(ShaderProgramID program,
                                UniformLocation location,
                                GLuint v0,
                                GLuint v1,
                                GLuint v2,
                                GLuint v3)
{
    GLuint xyzw[4] = {v0, v1, v2, v3};
    programUniform4uiv(program, location, 1, xyzw);
}

void Context::programUniform1f(ShaderProgramID program, UniformLocation location, GLfloat v0)
{
    programUniform1fv(program, location, 1, &v0);
}

void Context::programUniform2f(ShaderProgramID program,
                               UniformLocation location,
                               GLfloat v0,
                               GLfloat v1)
{
    GLfloat xy[2] = {v0, v1};
    programUniform2fv(program, location, 1, xy);
}

void Context::programUniform3f(ShaderProgramID program,
                               UniformLocation location,
                               GLfloat v0,
                               GLfloat v1,
                               GLfloat v2)
{
    GLfloat xyz[3] = {v0, v1, v2};
    programUniform3fv(program, location, 1, xyz);
}

void Context::programUniform4f(ShaderProgramID program,
                               UniformLocation location,
                               GLfloat v0,
                               GLfloat v1,
                               GLfloat v2,
                               GLfloat v3)
{
    GLfloat xyzw[4] = {v0, v1, v2, v3};
    programUniform4fv(program, location, 1, xyzw);
}

void Context::programUniform1iv(ShaderProgramID program,
                                UniformLocation location,
                                GLsizei count,
                                const GLint *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    setUniform1iImpl(programObject, location, count, value);
}

void Context::programUniform2iv(ShaderProgramID program,
                                UniformLocation location,
                                GLsizei count,
                                const GLint *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform2iv(location, count, value);
}

void Context::programUniform3iv(ShaderProgramID program,
                                UniformLocation location,
                                GLsizei count,
                                const GLint *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform3iv(location, count, value);
}

void Context::programUniform4iv(ShaderProgramID program,
                                UniformLocation location,
                                GLsizei count,
                                const GLint *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform4iv(location, count, value);
}

void Context::programUniform1uiv(ShaderProgramID program,
                                 UniformLocation location,
                                 GLsizei count,
                                 const GLuint *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform1uiv(location, count, value);
}

void Context::programUniform2uiv(ShaderProgramID program,
                                 UniformLocation location,
                                 GLsizei count,
                                 const GLuint *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform2uiv(location, count, value);
}

void Context::programUniform3uiv(ShaderProgramID program,
                                 UniformLocation location,
                                 GLsizei count,
                                 const GLuint *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform3uiv(location, count, value);
}

void Context::programUniform4uiv(ShaderProgramID program,
                                 UniformLocation location,
                                 GLsizei count,
                                 const GLuint *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform4uiv(location, count, value);
}

void Context::programUniform1fv(ShaderProgramID program,
                                UniformLocation location,
                                GLsizei count,
                                const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform1fv(location, count, value);
}

void Context::programUniform2fv(ShaderProgramID program,
                                UniformLocation location,
                                GLsizei count,
                                const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform2fv(location, count, value);
}

void Context::programUniform3fv(ShaderProgramID program,
                                UniformLocation location,
                                GLsizei count,
                                const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform3fv(location, count, value);
}

void Context::programUniform4fv(ShaderProgramID program,
                                UniformLocation location,
                                GLsizei count,
                                const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniform4fv(location, count, value);
}

void Context::programUniformMatrix2fv(ShaderProgramID program,
                                      UniformLocation location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix2fv(location, count, transpose, value);
}

void Context::programUniformMatrix3fv(ShaderProgramID program,
                                      UniformLocation location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix3fv(location, count, transpose, value);
}

void Context::programUniformMatrix4fv(ShaderProgramID program,
                                      UniformLocation location,
                                      GLsizei count,
                                      GLboolean transpose,
                                      const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix4fv(location, count, transpose, value);
}

void Context::programUniformMatrix2x3fv(ShaderProgramID program,
                                        UniformLocation location,
                                        GLsizei count,
                                        GLboolean transpose,
                                        const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix2x3fv(location, count, transpose, value);
}

void Context::programUniformMatrix3x2fv(ShaderProgramID program,
                                        UniformLocation location,
                                        GLsizei count,
                                        GLboolean transpose,
                                        const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix3x2fv(location, count, transpose, value);
}

void Context::programUniformMatrix2x4fv(ShaderProgramID program,
                                        UniformLocation location,
                                        GLsizei count,
                                        GLboolean transpose,
                                        const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix2x4fv(location, count, transpose, value);
}

void Context::programUniformMatrix4x2fv(ShaderProgramID program,
                                        UniformLocation location,
                                        GLsizei count,
                                        GLboolean transpose,
                                        const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix4x2fv(location, count, transpose, value);
}

void Context::programUniformMatrix3x4fv(ShaderProgramID program,
                                        UniformLocation location,
                                        GLsizei count,
                                        GLboolean transpose,
                                        const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix3x4fv(location, count, transpose, value);
}

void Context::programUniformMatrix4x3fv(ShaderProgramID program,
                                        UniformLocation location,
                                        GLsizei count,
                                        GLboolean transpose,
                                        const GLfloat *value)
{
    Program *programObject = getProgramResolveLink(program);
    ASSERT(programObject);
    programObject->getExecutable().setUniformMatrix4x3fv(location, count, transpose, value);
}

bool Context::isCurrentTransformFeedback(const TransformFeedback *tf) const
{
    return mState.isCurrentTransformFeedback(tf);
}

void Context::genProgramPipelines(GLsizei count, ProgramPipelineID *pipelines)
{
    for (int i = 0; i < count; i++)
    {
        if (!createProgramPipeline(&pipelines[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLGenProgramPipelines);
            return;
        }
    }
}

void Context::deleteProgramPipelines(GLsizei count, const ProgramPipelineID *pipelines)
{
    for (int i = 0; i < count; i++)
    {
        if (pipelines[i].value != 0)
        {
            deleteProgramPipeline(pipelines[i]);
        }
    }
}

GLboolean Context::isProgramPipeline(ProgramPipelineID pipeline) const
{
    if (pipeline.value == 0)
    {
        return GL_FALSE;
    }

    if (getProgramPipeline(pipeline))
    {
        return GL_TRUE;
    }

    return GL_FALSE;
}

void Context::finishFenceNV(FenceNVID fence)
{
    FenceNV *fenceObject = getFenceNV(fence);

    ASSERT(fenceObject && fenceObject->isSet());
    ANGLE_CONTEXT_TRY(fenceObject->finish(this));
}

void Context::getFenceivNV(FenceNVID fence, GLenum pname, GLint *params)
{
    FenceNV *fenceObject = getFenceNV(fence);

    ASSERT(fenceObject && fenceObject->isSet());

    switch (pname)
    {
        case GL_FENCE_STATUS_NV:
        {
            // GL_NV_fence spec:
            // Once the status of a fence has been finished (via FinishFenceNV) or tested and
            // the returned status is TRUE (via either TestFenceNV or GetFenceivNV querying the
            // FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
            GLboolean status = GL_TRUE;
            if (fenceObject->getStatus() != GL_TRUE)
            {
                ANGLE_CONTEXT_TRY(fenceObject->test(this, &status));
            }
            *params = status;
            break;
        }

        case GL_FENCE_CONDITION_NV:
        {
            *params = static_cast<GLint>(fenceObject->getCondition());
            break;
        }

        default:
            UNREACHABLE();
    }
}

void Context::getTranslatedShaderSource(ShaderProgramID shader,
                                        GLsizei bufsize,
                                        GLsizei *length,
                                        GLchar *source)
{
    Shader *shaderObject = getShaderNoResolveCompile(shader);
    ASSERT(shaderObject);
    shaderObject->getTranslatedSourceWithDebugInfo(this, bufsize, length, source);
}

void Context::getnUniformfv(ShaderProgramID programPacked,
                            UniformLocation locationPacked,
                            GLsizei bufSize,
                            GLfloat *params)
{
    getUniformfvRobust(programPacked, locationPacked, bufSize, nullptr, params);
}

void Context::getnUniformiv(ShaderProgramID programPacked,
                            UniformLocation locationPacked,
                            GLsizei bufSize,
                            GLint *params)
{
    getUniformivRobust(programPacked, locationPacked, bufSize, nullptr, params);
}

void Context::getnUniformuiv(ShaderProgramID programPacked,
                             UniformLocation locationPacked,
                             GLsizei bufSize,
                             GLuint *params)
{
    getUniformuivRobust(programPacked, locationPacked, bufSize, nullptr, params);
}

GLboolean Context::isFenceNV(FenceNVID fence) const
{
    FenceNV *fenceObject = getFenceNV(fence);

    if (fenceObject == nullptr)
    {
        return GL_FALSE;
    }

    // GL_NV_fence spec:
    // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an
    // existing fence.
    return fenceObject->isSet();
}

void Context::readnPixels(GLint x,
                          GLint y,
                          GLsizei width,
                          GLsizei height,
                          GLenum format,
                          GLenum type,
                          GLsizei bufSize,
                          void *data)
{
    return readPixels(x, y, width, height, format, type, data);
}

void Context::setFenceNV(FenceNVID fence, GLenum condition)
{
    ASSERT(condition == GL_ALL_COMPLETED_NV);

    FenceNV *fenceObject = getFenceNV(fence);
    ASSERT(fenceObject != nullptr);
    ANGLE_CONTEXT_TRY(fenceObject->set(this, condition));
}

GLboolean Context::testFenceNV(FenceNVID fence)
{
    FenceNV *fenceObject = getFenceNV(fence);

    ASSERT(fenceObject != nullptr);
    ASSERT(fenceObject->isSet() == GL_TRUE);

    GLboolean result = GL_TRUE;
    if (fenceObject->test(this, &result) == angle::Result::Stop)
    {
        return GL_TRUE;
    }

    return result;
}

void Context::deleteMemoryObjects(GLsizei n, const MemoryObjectID *memoryObjects)
{
    for (int i = 0; i < n; i++)
    {
        deleteMemoryObject(memoryObjects[i]);
    }
}

GLboolean Context::isMemoryObject(MemoryObjectID memoryObject) const
{
    if (memoryObject.value == 0)
    {
        return GL_FALSE;
    }

    return ConvertToGLBoolean(getMemoryObject(memoryObject));
}

void Context::createMemoryObjects(GLsizei n, MemoryObjectID *memoryObjects)
{
    for (int i = 0; i < n; i++)
    {
        if (!createMemoryObject(&memoryObjects[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLCreateMemoryObjectsEXT);
            return;
        }
    }
}

void Context::memoryObjectParameteriv(MemoryObjectID memory, GLenum pname, const GLint *params)
{
    MemoryObject *memoryObject = getMemoryObject(memory);
    ASSERT(memoryObject);
    ANGLE_CONTEXT_TRY(SetMemoryObjectParameteriv(this, memoryObject, pname, params));
}

void Context::getMemoryObjectParameteriv(MemoryObjectID memory, GLenum pname, GLint *params)
{
    const MemoryObject *memoryObject = getMemoryObject(memory);
    ASSERT(memoryObject);
    QueryMemoryObjectParameteriv(memoryObject, pname, params);
}

void Context::texStorageMem2D(TextureType target,
                              GLsizei levels,
                              GLenum internalFormat,
                              GLsizei width,
                              GLsizei height,
                              MemoryObjectID memory,
                              GLuint64 offset)
{
    texStorageMemFlags2D(target, levels, internalFormat, width, height, memory, offset,
                         std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(),
                         nullptr);
}

void Context::texStorageMem2DMultisample(TextureType target,
                                         GLsizei samples,
                                         GLenum internalFormat,
                                         GLsizei width,
                                         GLsizei height,
                                         GLboolean fixedSampleLocations,
                                         MemoryObjectID memory,
                                         GLuint64 offset)
{
    UNIMPLEMENTED();
}

void Context::texStorageMem3D(TextureType target,
                              GLsizei levels,
                              GLenum internalFormat,
                              GLsizei width,
                              GLsizei height,
                              GLsizei depth,
                              MemoryObjectID memory,
                              GLuint64 offset)
{
    UNIMPLEMENTED();
}

void Context::texStorageMem3DMultisample(TextureType target,
                                         GLsizei samples,
                                         GLenum internalFormat,
                                         GLsizei width,
                                         GLsizei height,
                                         GLsizei depth,
                                         GLboolean fixedSampleLocations,
                                         MemoryObjectID memory,
                                         GLuint64 offset)
{
    UNIMPLEMENTED();
}

void Context::bufferStorageMem(TextureType target,
                               GLsizeiptr size,
                               MemoryObjectID memory,
                               GLuint64 offset)
{
    UNIMPLEMENTED();
}

void Context::importMemoryFd(MemoryObjectID memory, GLuint64 size, HandleType handleType, GLint fd)
{
    MemoryObject *memoryObject = getMemoryObject(memory);
    ASSERT(memoryObject != nullptr);
    ANGLE_CONTEXT_TRY(memoryObject->importFd(this, size, handleType, fd));
}

void Context::texStorageMemFlags2D(TextureType target,
                                   GLsizei levels,
                                   GLenum internalFormat,
                                   GLsizei width,
                                   GLsizei height,
                                   MemoryObjectID memory,
                                   GLuint64 offset,
                                   GLbitfield createFlags,
                                   GLbitfield usageFlags,
                                   const void *imageCreateInfoPNext)
{
    MemoryObject *memoryObject = getMemoryObject(memory);
    ASSERT(memoryObject);
    Extents size(width, height, 1);
    Texture *texture = getTextureByType(target);
    ANGLE_CONTEXT_TRY(texture->setStorageExternalMemory(this, target, levels, internalFormat, size,
                                                        memoryObject, offset, createFlags,
                                                        usageFlags, imageCreateInfoPNext));
}

void Context::texStorageMemFlags2DMultisample(TextureType target,
                                              GLsizei samples,
                                              GLenum internalFormat,
                                              GLsizei width,
                                              GLsizei height,
                                              GLboolean fixedSampleLocations,
                                              MemoryObjectID memory,
                                              GLuint64 offset,
                                              GLbitfield createFlags,
                                              GLbitfield usageFlags,
                                              const void *imageCreateInfoPNext)
{
    UNIMPLEMENTED();
}

void Context::texStorageMemFlags3D(TextureType target,
                                   GLsizei levels,
                                   GLenum internalFormat,
                                   GLsizei width,
                                   GLsizei height,
                                   GLsizei depth,
                                   MemoryObjectID memory,
                                   GLuint64 offset,
                                   GLbitfield createFlags,
                                   GLbitfield usageFlags,
                                   const void *imageCreateInfoPNext)
{
    UNIMPLEMENTED();
}

void Context::texStorageMemFlags3DMultisample(TextureType target,
                                              GLsizei samples,
                                              GLenum internalFormat,
                                              GLsizei width,
                                              GLsizei height,
                                              GLsizei depth,
                                              GLboolean fixedSampleLocations,
                                              MemoryObjectID memory,
                                              GLuint64 offset,
                                              GLbitfield createFlags,
                                              GLbitfield usageFlags,
                                              const void *imageCreateInfoPNext)
{
    UNIMPLEMENTED();
}

void Context::importMemoryZirconHandle(MemoryObjectID memory,
                                       GLuint64 size,
                                       HandleType handleType,
                                       GLuint handle)
{
    MemoryObject *memoryObject = getMemoryObject(memory);
    ASSERT(memoryObject != nullptr);
    ANGLE_CONTEXT_TRY(memoryObject->importZirconHandle(this, size, handleType, handle));
}

void Context::genSemaphores(GLsizei n, SemaphoreID *semaphores)
{
    for (int i = 0; i < n; i++)
    {
        if (!createSemaphore(&semaphores[i]))
        {
            handleExhaustionError(angle::EntryPoint::GLGenSemaphoresEXT);
            return;
        }
    }
}

void Context::deleteSemaphores(GLsizei n, const SemaphoreID *semaphores)
{
    for (int i = 0; i < n; i++)
    {
        deleteSemaphore(semaphores[i]);
    }
}

GLboolean Context::isSemaphore(SemaphoreID semaphore) const
{
    if (semaphore.value == 0)
    {
        return GL_FALSE;
    }

    return ConvertToGLBoolean(getSemaphore(semaphore));
}

void Context::semaphoreParameterui64v(SemaphoreID semaphore, GLenum pname, const GLuint64 *params)
{
    UNIMPLEMENTED();
}

void Context::getSemaphoreParameterui64v(SemaphoreID semaphore, GLenum pname, GLuint64 *params)
{
    UNIMPLEMENTED();
}

void Context::acquireTextures(GLuint numTextures,
                              const TextureID *textureIds,
                              const GLenum *layouts)
{
    TextureBarrierVector textureBarriers(numTextures);
    for (size_t i = 0; i < numTextures; i++)
    {
        textureBarriers[i].texture = getTexture(textureIds[i]);
        textureBarriers[i].layout  = layouts[i];
    }
    ANGLE_CONTEXT_TRY(mImplementation->acquireTextures(this, textureBarriers));
}

void Context::releaseTextures(GLuint numTextures, const TextureID *textureIds, GLenum *layouts)
{
    TextureBarrierVector textureBarriers(numTextures);
    for (size_t i = 0; i < numTextures; i++)
    {
        textureBarriers[i].texture = getTexture(textureIds[i]);
    }
    ANGLE_CONTEXT_TRY(mImplementation->releaseTextures(this, &textureBarriers));
    for (size_t i = 0; i < numTextures; i++)
    {
        layouts[i] = textureBarriers[i].layout;
    }
}

void Context::waitSemaphore(SemaphoreID semaphoreHandle,
                            GLuint numBufferBarriers,
                            const BufferID *buffers,
                            GLuint numTextureBarriers,
                            const TextureID *textures,
                            const GLenum *srcLayouts)
{
    Semaphore *semaphore = getSemaphore(semaphoreHandle);
    ASSERT(semaphore);

    BufferBarrierVector bufferBarriers(numBufferBarriers);
    for (GLuint bufferBarrierIdx = 0; bufferBarrierIdx < numBufferBarriers; bufferBarrierIdx++)
    {
        bufferBarriers[bufferBarrierIdx] = getBuffer(buffers[bufferBarrierIdx]);
    }

    TextureBarrierVector textureBarriers(numTextureBarriers);
    for (GLuint textureBarrierIdx = 0; textureBarrierIdx < numTextureBarriers; textureBarrierIdx++)
    {
        textureBarriers[textureBarrierIdx].texture = getTexture(textures[textureBarrierIdx]);
        textureBarriers[textureBarrierIdx].layout  = srcLayouts[textureBarrierIdx];
    }

    ANGLE_CONTEXT_TRY(semaphore->wait(this, bufferBarriers, textureBarriers));
}

void Context::signalSemaphore(SemaphoreID semaphoreHandle,
                              GLuint numBufferBarriers,
                              const BufferID *buffers,
                              GLuint numTextureBarriers,
                              const TextureID *textures,
                              const GLenum *dstLayouts)
{
    Semaphore *semaphore = getSemaphore(semaphoreHandle);
    ASSERT(semaphore);

    BufferBarrierVector bufferBarriers(numBufferBarriers);
    for (GLuint bufferBarrierIdx = 0; bufferBarrierIdx < numBufferBarriers; bufferBarrierIdx++)
    {
        bufferBarriers[bufferBarrierIdx] = getBuffer(buffers[bufferBarrierIdx]);
    }

    TextureBarrierVector textureBarriers(numTextureBarriers);
    for (GLuint textureBarrierIdx = 0; textureBarrierIdx < numTextureBarriers; textureBarrierIdx++)
    {
        textureBarriers[textureBarrierIdx].texture = getTexture(textures[textureBarrierIdx]);
        textureBarriers[textureBarrierIdx].layout  = dstLayouts[textureBarrierIdx];
    }

    ANGLE_CONTEXT_TRY(semaphore->signal(this, bufferBarriers, textureBarriers));
}

void Context::importSemaphoreFd(SemaphoreID semaphore, HandleType handleType, GLint fd)
{
    Semaphore *semaphoreObject = getSemaphore(semaphore);
    ASSERT(semaphoreObject != nullptr);
    ANGLE_CONTEXT_TRY(semaphoreObject->importFd(this, handleType, fd));
}

void Context::importSemaphoreZirconHandle(SemaphoreID semaphore,
                                          HandleType handleType,
                                          GLuint handle)
{
    Semaphore *semaphoreObject = getSemaphore(semaphore);
    ASSERT(semaphoreObject != nullptr);
    ANGLE_CONTEXT_TRY(semaphoreObject->importZirconHandle(this, handleType, handle));
}

void Context::framebufferMemorylessPixelLocalStorage(GLint plane,
                                                     GLenum internalformat,
                                                     GLbitfield usage)
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);

    PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);

    if (internalformat == GL_NONE)
    {
        pls.deinitialize(this, plane);
    }
    else
    {
        pls.setMemoryless(this, plane, internalformat, usage);
    }
}

void Context::framebufferTexturePixelLocalStorage(GLint plane,
                                                  TextureID backingtexture,
                                                  GLint level,
                                                  GLint layer,
                                                  GLbitfield usage)
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);

    PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);

    if (backingtexture.value == 0)
    {
        pls.deinitialize(this, plane);
    }
    else
    {
        Texture *tex = getTexture(backingtexture);
        ASSERT(tex);  // Validation guarantees this.
        pls.setTextureBacked(this, plane, tex, level, layer, usage);
    }
}

void Context::framebufferPixelLocalClearValuefv(GLint plane, const GLfloat value[])
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
    pls.setClearValuef(plane, value);
}

void Context::framebufferPixelLocalClearValueiv(GLint plane, const GLint value[])
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
    pls.setClearValuei(plane, value);
}

void Context::framebufferPixelLocalClearValueuiv(GLint plane, const GLuint value[])
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
    pls.setClearValueui(plane, value);
}

void Context::beginPixelLocalStorage(GLsizei n, const GLenum loadops[])
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);

    pls.begin(this, n, loadops);
    getMutablePrivateState()->setPixelLocalStorageActivePlanes(n);
}

void Context::endPixelLocalStorage(GLsizei n, const GLenum storeops[])
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);

    ASSERT(n == mState.getPixelLocalStorageActivePlanes());
    getMutablePrivateState()->setPixelLocalStorageActivePlanes(0);
    pls.end(this, n, storeops);
}

void Context::endPixelLocalStorageImplicit()
{
    // Ends the currently active pixel local storage session with GL_STORE_OP_STORE on all planes.
    GLsizei n = mState.getPixelLocalStorageActivePlanes();
    if (n == 0)
    {
        // This command may be called when PLS is not active.
        return;
    }
    angle::FixedVector<GLenum, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES> storeops(
        n, GL_STORE_OP_STORE_ANGLE);
    endPixelLocalStorage(n, storeops.data());
}

bool Context::areBlobCacheFuncsSet() const
{
    return mState.getBlobCacheCallbacks().getFunction && mState.getBlobCacheCallbacks().setFunction;
}

void Context::pixelLocalStorageBarrier()
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);

    pls.barrier(this);
}

void Context::framebufferPixelLocalStorageInterrupt()
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    if (framebuffer->id().value != 0)
    {
        PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
        pls.interrupt(this);
    }
}

void Context::framebufferPixelLocalStorageRestore()
{
    Framebuffer *framebuffer = mState.getDrawFramebuffer();
    ASSERT(framebuffer);
    if (framebuffer->id().value != 0)
    {
        PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
        pls.restore(this);
    }
}

void Context::getFramebufferPixelLocalStorageParameterfv(GLint plane,
                                                         PlaneParameter pnamePacked,
                                                         GLfloat *params)
{
    QueryFramebufferPixelLocalStorageParameterfv(this, plane, pnamePacked, nullptr, params);
}

void Context::getFramebufferPixelLocalStorageParameteriv(GLint plane,
                                                         PlaneParameter pnamePacked,
                                                         GLint *params)
{
    QueryFramebufferPixelLocalStorageParameteriv(this, plane, pnamePacked, nullptr, params);
}

void Context::getFramebufferPixelLocalStorageParameteruiv(GLint plane,
                                                          PlaneParameter pnamePacked,
                                                          GLuint *params)
{
    QueryFramebufferPixelLocalStorageParameteruiv(this, plane, pnamePacked, nullptr, params);
}

void Context::getFramebufferPixelLocalStorageParameterfvRobust(GLint plane,
                                                               PlaneParameter pnamePacked,
                                                               GLsizei paramCount,
                                                               GLsizei *length,
                                                               GLfloat *params)
{
    QueryFramebufferPixelLocalStorageParameterfv(this, plane, pnamePacked, length, params);
}

void Context::getFramebufferPixelLocalStorageParameterivRobust(GLint plane,
                                                               PlaneParameter pnamePacked,
                                                               GLsizei paramCount,
                                                               GLsizei *length,
                                                               GLint *params)
{
    QueryFramebufferPixelLocalStorageParameteriv(this, plane, pnamePacked, length, params);
}

void Context::getFramebufferPixelLocalStorageParameteruivRobust(GLint plane,
                                                                PlaneParameter pnamePacked,
                                                                GLsizei paramCount,
                                                                GLsizei *length,
                                                                GLuint *params)
{
    QueryFramebufferPixelLocalStorageParameteruiv(this, plane, pnamePacked, length, params);
}

void Context::eGLImageTargetTexStorage(GLenum target, egl::ImageID image, const GLint *attrib_list)
{
    Texture *texture        = getTextureByType(FromGLenum<TextureType>(target));
    egl::Image *imageObject = mDisplay->getImage(image);
    ANGLE_CONTEXT_TRY(texture->setStorageEGLImageTarget(this, FromGLenum<TextureType>(target),
                                                        imageObject, attrib_list));
}

void Context::eGLImageTargetTexture2D(TextureType target, egl::ImageID image)
{
    Texture *texture        = getTextureByType(target);
    egl::Image *imageObject = mDisplay->getImage(image);
    ANGLE_CONTEXT_TRY(texture->setEGLImageTarget(this, target, imageObject));
}

void Context::eGLImageTargetRenderbufferStorage(GLenum target, egl::ImageID image)
{
    Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
    egl::Image *imageObject    = mDisplay->getImage(image);
    ANGLE_CONTEXT_TRY(renderbuffer->setStorageEGLImageTarget(this, imageObject));
}

void Context::framebufferFetchBarrier()
{
    mImplementation->framebufferFetchBarrier();
}

bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) const
{
    return GetQueryParameterInfo(mState, pname, type, numParams);
}

bool Context::getIndexedQueryParameterInfo(GLenum target,
                                           GLenum *type,
                                           unsigned int *numParams) const
{
    return GetIndexedQueryParameterInfo(mState, target, type, numParams);
}

Program *Context::getProgramNoResolveLink(ShaderProgramID handle) const
{
    return mState.mShaderProgramManager->getProgram(handle);
}

Shader *Context::getShaderResolveCompile(ShaderProgramID handle) const
{
    Shader *shader = getShaderNoResolveCompile(handle);
    if (shader)
    {
        shader->resolveCompile(this);
    }
    return shader;
}

Shader *Context::getShaderNoResolveCompile(ShaderProgramID handle) const
{
    return mState.mShaderProgramManager->getShader(handle);
}

const angle::FrontendFeatures &Context::getFrontendFeatures() const
{
    return mDisplay->getFrontendFeatures();
}

bool Context::isRenderbufferGenerated(RenderbufferID renderbuffer) const
{
    return mState.mRenderbufferManager->isHandleGenerated(renderbuffer);
}

bool Context::isFramebufferGenerated(FramebufferID framebuffer) const
{
    return mState.mFramebufferManager->isHandleGenerated(framebuffer);
}

bool Context::isProgramPipelineGenerated(ProgramPipelineID pipeline) const
{
    return mState.mProgramPipelineManager->isHandleGenerated(pipeline);
}

bool Context::usingDisplayTextureShareGroup() const
{
    return mDisplayTextureShareGroup;
}

bool Context::usingDisplaySemaphoreShareGroup() const
{
    return mDisplaySemaphoreShareGroup;
}

GLenum Context::getConvertedRenderbufferFormat(GLenum internalformat) const
{
    if (isWebGL1() && internalformat == GL_DEPTH_STENCIL)
    {
        return GL_DEPTH24_STENCIL8;
    }
    return internalformat;
}

void Context::maxShaderCompilerThreads(GLuint count)
{
    // A count of zero specifies a request for no parallel compiling or linking.  This is handled in
    // getShaderCompileThreadPool.  Otherwise the count itself has no effect as the pool is shared
    // between contexts.
    mState.setMaxShaderCompilerThreads(count);
    mImplementation->setMaxShaderCompilerThreads(count);
}

bool Context::isGLES1() const
{
    return mState.isGLES1();
}

std::shared_ptr<angle::WorkerThreadPool> Context::getShaderCompileThreadPool() const
{
    if (mState.getExtensions().parallelShaderCompileKHR && mState.getMaxShaderCompilerThreads() > 0)
    {
        return mDisplay->getMultiThreadPool();
    }
    return mDisplay->getSingleThreadPool();
}

std::shared_ptr<angle::WorkerThreadPool> Context::getLinkSubTaskThreadPool() const
{
    return getFrontendFeatures().alwaysRunLinkSubJobsThreaded.enabled
               ? getWorkerThreadPool()
               : getShaderCompileThreadPool();
}

std::shared_ptr<angle::WaitableEvent> Context::postCompileLinkTask(
    const std::shared_ptr<angle::Closure> &task,
    angle::JobThreadSafety safety,
    angle::JobResultExpectancy resultExpectancy) const
{
    // If the compile/link job is not thread safe, use the single-thread pool.  Otherwise, the pool
    // that is configured by the application (through GL_KHR_parallel_shader_compile) is used.
    const bool isThreadSafe = safety == angle::JobThreadSafety::Safe;
    std::shared_ptr<angle::WorkerThreadPool> workerPool =
        isThreadSafe ? getShaderCompileThreadPool() : getSingleThreadPool();

    // If the job is thread-safe, but it's still not going to be threaded, then it's performed as an
    // unlocked tail call to allow other threads to proceed.  This is only possible if the results
    // of the call are not immediately needed in the same entry point call.
    if (isThreadSafe && !workerPool->isAsync() &&
        resultExpectancy == angle::JobResultExpectancy::Future &&
        !getShareGroup()->getFrameCaptureShared()->enabled())
    {
        std::shared_ptr<angle::AsyncWaitableEvent> event =
            std::make_shared<angle::AsyncWaitableEvent>();
        auto unlockedTask = [task, event](void *resultOut) {
            ANGLE_TRACE_EVENT0("gpu.angle", "Compile/Link (unlocked)");
            (*task)();
            event->markAsReady();
        };
        egl::Display::GetCurrentThreadUnlockedTailCall()->add(unlockedTask);
        return event;
    }

    // Otherwise, just schedule the task on the pool
    return workerPool->postWorkerTask(task);
}

std::shared_ptr<angle::WorkerThreadPool> Context::getSingleThreadPool() const
{
    return mDisplay->getSingleThreadPool();
}

std::shared_ptr<angle::WorkerThreadPool> Context::getWorkerThreadPool() const
{
    return mDisplay->getMultiThreadPool();
}

void Context::onUniformBlockBindingUpdated(GLuint uniformBlockIndex)
{
    mState.mDirtyBits.set(state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
    mState.mDirtyUniformBlocks.set(uniformBlockIndex);
    mState.mUniformBufferBlocksDirtyTypeMask.set(BufferDirtyType::Binding);
    mStateCache.onUniformBufferStateChange(this);
}

void Context::endTilingImplicit()
{
    if (getMutablePrivateState()->isTiledRendering())
    {
        ANGLE_PERF_WARNING(getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                           "Implicitly ending tiled rendering due to framebuffer state change");
        getMutablePrivateState()->setTiledRendering(false);
    }
}

void Context::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
    switch (index)
    {
        case kVertexArraySubjectIndex:
            switch (message)
            {
                case angle::SubjectMessage::ContentsChanged:
                    mState.setObjectDirty(GL_VERTEX_ARRAY);
                    mPrivateStateCache.onVertexArrayBufferContentsChange();
                    break;
                case angle::SubjectMessage::SubjectMapped:
                case angle::SubjectMessage::SubjectUnmapped:
                case angle::SubjectMessage::BindingChanged:
                    mPrivateStateCache.onVertexArrayBufferStateChange();
                    break;
                default:
                    break;
            }
            break;

        case kReadFramebufferSubjectIndex:
            switch (message)
            {
                case angle::SubjectMessage::DirtyBitsFlagged:
                    mState.setReadFramebufferDirty();
                    break;
                case angle::SubjectMessage::SurfaceChanged:
                    mState.setReadFramebufferBindingDirty();
                    break;
                default:
                    UNREACHABLE();
                    break;
            }
            break;

        case kDrawFramebufferSubjectIndex:
            switch (message)
            {
                case angle::SubjectMessage::DirtyBitsFlagged:
                    mState.setDrawFramebufferDirty();
                    mStateCache.onDrawFramebufferChange(this);
                    break;
                case angle::SubjectMessage::SurfaceChanged:
                    mState.setDrawFramebufferBindingDirty();
                    break;
                default:
                    UNREACHABLE();
                    break;
            }
            break;

        case kProgramSubjectIndex:
            switch (message)
            {
                case angle::SubjectMessage::ProgramUnlinked:
                    mStateCache.onProgramExecutableChange(this);
                    break;
                case angle::SubjectMessage::ProgramRelinked:
                {
                    Program *program = mState.getProgram();
                    ASSERT(program->isLinked());
                    mState.onCurrentExecutableRelink();
                    ANGLE_CONTEXT_TRY(mState.installProgramExecutable(this));
                    mStateCache.onProgramExecutableChange(this);
                    break;
                }
                default:
                    if (angle::IsProgramUniformBlockBindingUpdatedMessage(message))
                    {
                        onUniformBlockBindingUpdated(
                            angle::ProgramUniformBlockBindingUpdatedMessageToIndex(message));
                        break;
                    }
                    // Ignore all the other notifications
                    break;
            }
            break;

        case kProgramPipelineSubjectIndex:
            switch (message)
            {
                case angle::SubjectMessage::ProgramUnlinked:
                    mStateCache.onProgramExecutableChange(this);
                    break;
                case angle::SubjectMessage::ProgramRelinked:
                    mState.onCurrentExecutableRelink();
                    ANGLE_CONTEXT_TRY(mState.installProgramPipelineExecutable(this));
                    mStateCache.onProgramExecutableChange(this);
                    break;
                default:
                    if (angle::IsProgramUniformBlockBindingUpdatedMessage(message))
                    {
                        // Note: if there's a program bound, its executable is used (and not the
                        // PPO's)
                        if (mState.getProgram() == nullptr)
                        {
                            onUniformBlockBindingUpdated(
                                angle::ProgramUniformBlockBindingUpdatedMessageToIndex(message));
                        }
                        break;
                    }
                    UNREACHABLE();
                    break;
            }
            break;

        default:
            if (index < kTextureMaxSubjectIndex)
            {
                if (message != angle::SubjectMessage::ContentsChanged &&
                    message != angle::SubjectMessage::BindingChanged)
                {
                    mState.onActiveTextureStateChange(this, index);
                    mStateCache.onActiveTextureChange(this);
                }
            }
            else if (index < kImageMaxSubjectIndex)
            {
                mState.onImageStateChange(this, index - kImage0SubjectIndex);
                if (message == angle::SubjectMessage::ContentsChanged)
                {
                    mState.mDirtyBits.set(state::DirtyBitType::DIRTY_BIT_IMAGE_BINDINGS);
                }
            }
            else if (index < kUniformBufferMaxSubjectIndex)
            {
                mState.onUniformBufferStateChange(index - kUniformBuffer0SubjectIndex, message);
                mStateCache.onUniformBufferStateChange(this);
            }
            else if (index < kAtomicCounterBufferMaxSubjectIndex)
            {
                mState.onAtomicCounterBufferStateChange(index - kAtomicCounterBuffer0SubjectIndex);
                mStateCache.onAtomicCounterBufferStateChange(this);
            }
            else if (index < kShaderStorageBufferMaxSubjectIndex)
            {
                mState.onShaderStorageBufferStateChange(index - kShaderStorageBuffer0SubjectIndex);
                mStateCache.onShaderStorageBufferStateChange(this);
            }
            else
            {
                ASSERT(index < kSamplerMaxSubjectIndex);
                mState.setSamplerDirty(index - kSampler0SubjectIndex);
                mState.onActiveTextureStateChange(this, index - kSampler0SubjectIndex);
            }
            break;
    }
}

egl::Error Context::setDefaultFramebuffer(egl::Surface *drawSurface, egl::Surface *readSurface)
{
    ASSERT(mCurrentDrawSurface == nullptr);
    ASSERT(mCurrentReadSurface == nullptr);

    mCurrentDrawSurface = drawSurface;
    mCurrentReadSurface = readSurface;

    egl::Error result = egl::NoError();
    if (drawSurface != nullptr)
    {
        result = drawSurface->makeCurrent(this);
    }
    if (drawSurface != readSurface)
    {
        ASSERT(readSurface != nullptr);
        egl::Error readResult = readSurface->makeCurrent(this);
        if (!result.isError())
        {
            result = readResult;
        }
    }
    ANGLE_TRY(result);

    mDefaultFramebuffer->setSurfaces(this, drawSurface, readSurface);

    // Update default framebuffer, the binding of the previous default
    // framebuffer (or lack of) will have a nullptr.
    mState.mFramebufferManager->setDefaultFramebuffer(mDefaultFramebuffer.get());
    if (mState.getDrawFramebuffer() == nullptr)
    {
        bindDrawFramebuffer(mDefaultFramebuffer->id());
    }
    if (mState.getReadFramebuffer() == nullptr)
    {
        bindReadFramebuffer(mDefaultFramebuffer->id());
    }

    return egl::NoError();
}

egl::Error Context::unsetDefaultFramebuffer()
{
    Framebuffer *defaultFramebuffer =
        mState.mFramebufferManager->getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);

    if (defaultFramebuffer)
    {
        // Remove the default framebuffer
        if (defaultFramebuffer == mState.getReadFramebuffer())
        {
            mState.setReadFramebufferBinding(nullptr);
            mReadFramebufferObserverBinding.bind(nullptr);
        }

        if (defaultFramebuffer == mState.getDrawFramebuffer())
        {
            mState.setDrawFramebufferBinding(nullptr);
            mDrawFramebufferObserverBinding.bind(nullptr);
        }

        defaultFramebuffer->unsetSurfaces(this);
        mState.mFramebufferManager->setDefaultFramebuffer(nullptr);
    }

    // Always unset the current surface, even if setIsCurrent fails.
    egl::Surface *drawSurface = mCurrentDrawSurface;
    egl::Surface *readSurface = mCurrentReadSurface;
    mCurrentDrawSurface       = nullptr;
    mCurrentReadSurface       = nullptr;
    if (drawSurface)
    {
        ANGLE_TRY(drawSurface->unMakeCurrent(this));
    }
    if (drawSurface != readSurface)
    {
        ASSERT(readSurface != nullptr);
        ANGLE_TRY(readSurface->unMakeCurrent(this));
    }

    return egl::NoError();
}

void Context::onPreSwap()
{
    // Ignore non-window (side-context / aux-pbuffer) swaps for frame boundaries
    const egl::Surface *drawSurface = getCurrentDrawSurface();
    if (drawSurface && drawSurface->getType() != EGL_WINDOW_BIT)
    {
        return;
    }

    // Dump frame capture if enabled.
    getShareGroup()->getFrameCaptureShared()->onEndFrame(this);
}

void Context::getTexImage(TextureTarget target,
                          GLint level,
                          GLenum format,
                          GLenum type,
                          void *pixels)
{
    Texture *texture   = getTextureByTarget(target);
    Buffer *packBuffer = mState.getTargetBuffer(BufferBinding::PixelPack);
    ANGLE_CONTEXT_TRY(texture->getTexImage(this, mState.getPackState(), packBuffer, target, level,
                                           format, type, pixels));
}

void Context::getCompressedTexImage(TextureTarget target, GLint level, void *pixels)
{
    Texture *texture   = getTextureByTarget(target);
    Buffer *packBuffer = mState.getTargetBuffer(BufferBinding::PixelPack);
    ANGLE_CONTEXT_TRY(texture->getCompressedTexImage(this, mState.getPackState(), packBuffer,
                                                     target, level, pixels));
}

void Context::getRenderbufferImage(GLenum target, GLenum format, GLenum type, void *pixels)
{
    Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
    Buffer *packBuffer         = mState.getTargetBuffer(BufferBinding::PixelPack);
    ANGLE_CONTEXT_TRY(renderbuffer->getRenderbufferImage(this, mState.getPackState(), packBuffer,
                                                         format, type, pixels));
}

void Context::setLogicOpEnabledForGLES1(bool enabled)
{
    // Same implementation as ContextPrivateEnable(GL_COLOR_LOGIC_OP), without the GLES1 forwarding.
    getMutablePrivateState()->setLogicOpEnabled(enabled);
    getMutablePrivateStateCache()->onCapChange();
}

egl::Error Context::releaseHighPowerGPU()
{
    return mImplementation->releaseHighPowerGPU(this);
}

egl::Error Context::reacquireHighPowerGPU()
{
    return mImplementation->reacquireHighPowerGPU(this);
}

void Context::onGPUSwitch()
{
    // Re-initialize the renderer string, which just changed, and
    // which must be visible to applications.
    initRendererString();
}

egl::Error Context::acquireExternalContext(egl::Surface *drawAndReadSurface)
{
    mImplementation->acquireExternalContext(this);

    if (drawAndReadSurface != mCurrentDrawSurface || drawAndReadSurface != mCurrentReadSurface)
    {
        ANGLE_TRY(unsetDefaultFramebuffer());
        ANGLE_TRY(setDefaultFramebuffer(drawAndReadSurface, drawAndReadSurface));
    }

    return egl::NoError();
}

egl::Error Context::releaseExternalContext()
{
    mImplementation->releaseExternalContext(this);
    return egl::NoError();
}

bool Context::supportsGeometryOrTesselation() const
{
    return mState.getClientVersion() == ES_3_2 || mState.getExtensions().geometryShaderAny() ||
           mState.getExtensions().tessellationShaderAny();
}

void Context::dirtyAllState()
{
    mState.setAllDirtyBits();
    mState.setAllDirtyObjects();
    getMutableGLES1State()->setAllDirty();
}

void Context::finishImmutable() const
{
    ANGLE_CONTEXT_TRY(mImplementation->finish(this));
}

void Context::beginPerfMonitor(GLuint monitor)
{
    getMutablePrivateState()->setPerfMonitorActive(true);
}

void Context::deletePerfMonitors(GLsizei n, GLuint *monitors) {}

void Context::endPerfMonitor(GLuint monitor)
{
    getMutablePrivateState()->setPerfMonitorActive(false);
}

void Context::genPerfMonitors(GLsizei n, GLuint *monitors)
{
    for (GLsizei monitorIndex = 0; monitorIndex < n; ++monitorIndex)
    {
        monitors[monitorIndex] = static_cast<GLuint>(monitorIndex);
    }
}

void Context::getPerfMonitorCounterData(GLuint monitor,
                                        GLenum pname,
                                        GLsizei dataSize,
                                        GLuint *data,
                                        GLint *bytesWritten)
{
    using namespace angle;
    GLint byteCount = 0;
    switch (pname)
    {
        case GL_PERFMON_RESULT_AVAILABLE_AMD:
        {
            *data = GL_TRUE;
            byteCount += sizeof(GLuint);
            break;
        }
        case GL_PERFMON_RESULT_SIZE_AMD:
        {
            const PerfMonitorCounterGroupsInfo &perfMonitorGroups =
                mImplementation->getPerfMonitorCountersInfo();
            GLuint resultSize = 0;
            for (const PerfMonitorCounterGroupInfo &group : perfMonitorGroups)
            {
                resultSize += sizeof(PerfMonitorTriplet) * group.counters.size();
            }
            *data = resultSize;
            byteCount += sizeof(GLuint);
            break;
        }
        case GL_PERFMON_RESULT_AMD:
        {
            const PerfMonitorCounterGroups &perfMonitorGroups =
                mImplementation->getPerfMonitorCounters();
            PerfMonitorTriplet *resultsOut = reinterpret_cast<PerfMonitorTriplet *>(data);
            GLsizei maxResults             = dataSize / sizeof(PerfMonitorTriplet);
            GLsizei resultCount            = 0;
            for (size_t groupIndex = 0;
                 groupIndex < perfMonitorGroups.size() && resultCount < maxResults; ++groupIndex)
            {
                const PerfMonitorCounterGroup &group = perfMonitorGroups[groupIndex];
                for (size_t counterIndex = 0;
                     counterIndex < group.counters.size() && resultCount < maxResults;
                     ++counterIndex)
                {
                    const PerfMonitorCounter &counter = group.counters[counterIndex];
                    PerfMonitorTriplet &triplet       = resultsOut[resultCount++];
                    triplet.counter                   = static_cast<GLuint>(counterIndex);
                    triplet.group                     = static_cast<GLuint>(groupIndex);
                    triplet.value                     = counter.value;
                }
            }
            byteCount += sizeof(PerfMonitorTriplet) * resultCount;
            break;
        }
        default:
            UNREACHABLE();
    }

    if (bytesWritten)
    {
        *bytesWritten = byteCount;
    }
}

void Context::getPerfMonitorCounterInfo(GLuint group, GLuint counter, GLenum pname, void *data)
{
    using namespace angle;
    const PerfMonitorCounterGroupsInfo &perfMonitorGroups =
        mImplementation->getPerfMonitorCountersInfo();
    ASSERT(group < perfMonitorGroups.size());
    const PerfMonitorCountersInfo &counters = perfMonitorGroups[group].counters;
    ASSERT(counter < counters.size());

    switch (pname)
    {
        case GL_COUNTER_TYPE_AMD:
        {
            GLenum *dataOut = reinterpret_cast<GLenum *>(data);
            *dataOut        = GL_UNSIGNED_INT;
            break;
        }
        case GL_COUNTER_RANGE_AMD:
        {
            GLuint *dataOut = reinterpret_cast<GLuint *>(data);
            dataOut[0]      = 0;
            dataOut[1]      = std::numeric_limits<GLuint>::max();
            break;
        }
        default:
            UNREACHABLE();
    }
}

void Context::getPerfMonitorCounterString(GLuint group,
                                          GLuint counter,
                                          GLsizei bufSize,
                                          GLsizei *length,
                                          GLchar *counterString)
{
    using namespace angle;
    const PerfMonitorCounterGroupsInfo &perfMonitorGroups =
        mImplementation->getPerfMonitorCountersInfo();
    ASSERT(group < perfMonitorGroups.size());
    const PerfMonitorCountersInfo &counters = perfMonitorGroups[group].counters;
    ASSERT(counter < counters.size());
    GetPerfMonitorString(counters[counter].name, bufSize, length, counterString);
}

void Context::getPerfMonitorCounters(GLuint group,
                                     GLint *numCounters,
                                     GLint *maxActiveCounters,
                                     GLsizei counterSize,
                                     GLuint *counters)
{
    using namespace angle;
    const PerfMonitorCounterGroupsInfo &perfMonitorGroups =
        mImplementation->getPerfMonitorCountersInfo();
    ASSERT(group < perfMonitorGroups.size());
    const PerfMonitorCountersInfo &groupCounters = perfMonitorGroups[group].counters;

    if (numCounters)
    {
        *numCounters = static_cast<GLint>(groupCounters.size());
    }

    if (maxActiveCounters)
    {
        *maxActiveCounters = static_cast<GLint>(groupCounters.size());
    }

    if (counters)
    {
        GLsizei maxCounterIndex = std::min(counterSize, static_cast<GLsizei>(groupCounters.size()));
        for (GLsizei counterIndex = 0; counterIndex < maxCounterIndex; ++counterIndex)
        {
            counters[counterIndex] = static_cast<GLuint>(counterIndex);
        }
    }
}

void Context::getPerfMonitorGroupString(GLuint group,
                                        GLsizei bufSize,
                                        GLsizei *length,
                                        GLchar *groupString)
{
    using namespace angle;
    const PerfMonitorCounterGroupsInfo &perfMonitorGroups =
        mImplementation->getPerfMonitorCountersInfo();
    ASSERT(group < perfMonitorGroups.size());
    GetPerfMonitorString(perfMonitorGroups[group].name, bufSize, length, groupString);
}

void Context::getPerfMonitorGroups(GLint *numGroups, GLsizei groupsSize, GLuint *groups)
{
    using namespace angle;
    const PerfMonitorCounterGroupsInfo &perfMonitorGroups =
        mImplementation->getPerfMonitorCountersInfo();

    if (numGroups)
    {
        *numGroups = static_cast<GLint>(perfMonitorGroups.size());
    }

    GLuint maxGroupIndex =
        std::min<GLuint>(groupsSize, static_cast<GLuint>(perfMonitorGroups.size()));
    for (GLuint groupIndex = 0; groupIndex < maxGroupIndex; ++groupIndex)
    {
        groups[groupIndex] = groupIndex;
    }
}

void Context::selectPerfMonitorCounters(GLuint monitor,
                                        GLboolean enable,
                                        GLuint group,
                                        GLint numCounters,
                                        GLuint *counterList)
{}

const angle::PerfMonitorCounterGroupsInfo &Context::getPerfMonitorCounterGroups() const
{
    return mImplementation->getPerfMonitorCountersInfo();
}

void Context::framebufferFoveationConfig(FramebufferID framebufferPacked,
                                         GLuint numLayers,
                                         GLuint focalPointsPerLayer,
                                         GLuint requestedFeatures,
                                         GLuint *providedFeatures)
{
    ASSERT(numLayers <= gl::IMPLEMENTATION_MAX_NUM_LAYERS);
    ASSERT(focalPointsPerLayer <= gl::IMPLEMENTATION_MAX_FOCAL_POINTS);
    ASSERT(providedFeatures);

    Framebuffer *framebuffer = getFramebuffer(framebufferPacked);
    ASSERT(!framebuffer->isFoveationConfigured());

    *providedFeatures = 0;
    // We only support GL_FOVEATION_ENABLE_BIT_QCOM feature, for now.
    // If requestedFeatures == 0 return without configuring the framebuffer.
    if (requestedFeatures != 0)
    {
        framebuffer->configureFoveation();
        *providedFeatures = framebuffer->getSupportedFoveationFeatures();
    }
}

void Context::framebufferFoveationParameters(FramebufferID framebufferPacked,
                                             GLuint layer,
                                             GLuint focalPoint,
                                             GLfloat focalX,
                                             GLfloat focalY,
                                             GLfloat gainX,
                                             GLfloat gainY,
                                             GLfloat foveaArea)
{
    Framebuffer *framebuffer = getFramebuffer(framebufferPacked);
    ASSERT(framebuffer);
    framebuffer->setFocalPoint(layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea);
}

void Context::textureFoveationParameters(TextureID texturePacked,
                                         GLuint layer,
                                         GLuint focalPoint,
                                         GLfloat focalX,
                                         GLfloat focalY,
                                         GLfloat gainX,
                                         GLfloat gainY,
                                         GLfloat foveaArea)
{
    Texture *texture = getTexture(texturePacked);
    ASSERT(texture);
    texture->setFocalPoint(layer, focalPoint, focalX, focalY, gainX, gainY, foveaArea);
}

void Context::endTiling(GLbitfield preserveMask)
{
    ANGLE_CONTEXT_TRY(mImplementation->endTiling(this, preserveMask));
    getMutablePrivateState()->setTiledRendering(false);
}

void Context::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask)
{
    ANGLE_CONTEXT_TRY(syncDirtyObjects(mTilingDirtyObjects, Command::Other));
    ANGLE_CONTEXT_TRY(syncDirtyBits(kTilingDirtyBits, kTilingExtendedDirtyBits, Command::Other));
    ANGLE_CONTEXT_TRY(
        mImplementation->startTiling(this, Rectangle(x, y, width, height), preserveMask));
    getMutablePrivateState()->setTiledRendering(true);
}

void Context::clearTexImage(TextureID texturePacked,
                            GLint level,
                            GLenum format,
                            GLenum type,
                            const void *data)
{
    Texture *texture = getTexture(texturePacked);

    // Sync the texture's state directly. EXT_clear_texture does not require that the texture is
    // bound.
    if (texture->hasAnyDirtyBit())
    {
        ANGLE_CONTEXT_TRY(texture->syncState(this, Command::ClearTexture));
    }

    ANGLE_CONTEXT_TRY(
        texture->clearImage(this, level, format, type, static_cast<const uint8_t *>(data)));
}

void Context::clearTexSubImage(TextureID texturePacked,
                               GLint level,
                               GLint xoffset,
                               GLint yoffset,
                               GLint zoffset,
                               GLsizei width,
                               GLsizei height,
                               GLsizei depth,
                               GLenum format,
                               GLenum type,
                               const void *data)
{
    Texture *texture = getTexture(texturePacked);

    // It is allowed to use extents of 0 as input args. In this case, the function should return
    // with no changes to the texture.
    if (width == 0 || height == 0 || depth == 0)
    {
        return;
    }

    // Sync the texture's state directly. EXT_clear_texture does not require that the texture is
    // bound.
    if (texture->hasAnyDirtyBit())
    {
        ANGLE_CONTEXT_TRY(texture->syncState(this, Command::ClearTexture));
    }

    Box area(xoffset, yoffset, zoffset, width, height, depth);
    ANGLE_CONTEXT_TRY(texture->clearSubImage(this, level, area, format, type,
                                             static_cast<const uint8_t *>(data)));
}

void Context::blobCacheCallbacks(GLSETBLOBPROCANGLE set,
                                 GLGETBLOBPROCANGLE get,
                                 const void *userParam)
{
    mState.getBlobCacheCallbacks() = {set, get, userParam};
}

void Context::texStorageAttribs2D(TextureType targetPacked,
                                  GLsizei levels,
                                  GLenum internalFormat,
                                  GLsizei width,
                                  GLsizei height,
                                  const GLint *attribList)
{
    Extents size(width, height, 1);
    Texture *texture = getTextureByType(targetPacked);
    ANGLE_CONTEXT_TRY(
        texture->setStorageAttribs(this, targetPacked, levels, internalFormat, size, attribList));
}

void Context::texStorageAttribs3D(TextureType targetPacked,
                                  GLsizei levels,
                                  GLenum internalFormat,
                                  GLsizei width,
                                  GLsizei height,
                                  GLsizei depth,
                                  const GLint *attribList)
{
    Extents size(width, height, depth);
    Texture *texture = getTextureByType(targetPacked);
    ANGLE_CONTEXT_TRY(
        texture->setStorageAttribs(this, targetPacked, levels, internalFormat, size, attribList));
}

size_t Context::getMemoryUsage() const
{
    size_t memoryUsage = 0;

    memoryUsage += mState.mBufferManager->getTotalMemorySize();
    memoryUsage += mState.mRenderbufferManager->getTotalMemorySize();
    memoryUsage += mState.mTextureManager->getTotalMemorySize();

    return memoryUsage;
}

void Context::updateActiveAttribsMaskIfNeeded() const
{
    if (!mPrivateStateCache.isCachedActiveAttribMasksValid())
    {
        mStateCache.updateActiveAttribsMask(this);
        mPrivateStateCache.setCachedActiveAttribMasksValid();
    }
}

AttributesMask Context::getActiveBufferedAttribsMask() const
{
    updateActiveAttribsMaskIfNeeded();
    return mStateCache.getActiveBufferedAttribsMask(mPrivateStateCache);
}

AttributesMask Context::getActiveClientAttribsMask() const
{
    updateActiveAttribsMaskIfNeeded();
    return mStateCache.getActiveClientAttribsMask(mPrivateStateCache);
}

AttributesMask Context::getActiveDefaultAttribsMask() const
{
    updateActiveAttribsMaskIfNeeded();
    return mStateCache.getActiveDefaultAttribsMask(mPrivateStateCache);
}

bool Context::hasAnyEnabledClientAttrib() const
{
    updateActiveAttribsMaskIfNeeded();
    return mStateCache.hasAnyEnabledClientAttrib(mPrivateStateCache);
}

bool Context::hasAnyActiveClientAttrib() const
{
    updateActiveAttribsMaskIfNeeded();
    return mStateCache.hasAnyActiveClientAttrib(mPrivateStateCache);
}

GLint64 Context::getNonInstancedVertexElementLimit() const
{
    ASSERT(mBufferAccessValidationEnabled);
    if (!mPrivateStateCache.isCachedVertexElementLimitValid())
    {
        mStateCache.updateVertexElementLimits(this);
        mPrivateStateCache.setCachedVertexElementLimitValid();
    }
    return mStateCache.getNonInstancedVertexElementLimit(mPrivateStateCache);
}

GLint64 Context::getInstancedVertexElementLimit() const
{
    ASSERT(mBufferAccessValidationEnabled);
    if (!mPrivateStateCache.isCachedVertexElementLimitValid())
    {
        mStateCache.updateVertexElementLimits(this);
        mPrivateStateCache.setCachedVertexElementLimitValid();
    }
    return mStateCache.getInstancedVertexElementLimit(mPrivateStateCache);
}

void Context::onActiveTransformFeedbackChange()
{
    mStateCache.onActiveTransformFeedbackChange(this);
    // This can only be called from current context since transform feedback are per context.
    mPrivateStateCache.invalidateCachedBasicDrawElementsError();
}

bool Context::retainIdUntilObjectDestroyed() const
{
    // If BindGeneratesResource is disabled, then we can defer recycling the handle ID until the
    // object has had the `onDestroy` method called, preventing ID reuse bugs.
    //
    // If the context is being destroyed however, we don't want to try to recycle as the handle
    // manager may be gone.
    return !mDestroyedManagers && !mState.isBindGeneratesResourceEnabled();
}

void Context::onBufferDestroy(const Buffer *buffer) const
{
    mState.mBufferManager->recycleHandle(buffer->id());
}

void Context::onTextureDestroy(const Texture *texture) const
{
    mState.mTextureManager->recycleHandle(texture->id());
}

void Context::onRenderbufferDestroy(const Renderbuffer *renderBuffer) const
{
    mState.mRenderbufferManager->recycleHandle(renderBuffer->id());
}

void Context::onSamplerDestroy(const Sampler *sampler) const
{
    mState.mSamplerManager->recycleHandle(sampler->id());
}

void Context::onSyncDestroy(const Sync *sync) const
{
    mState.mSyncManager->recycleHandle(sync->id());
}

void Context::onFramebufferDestroy(const Framebuffer *framebuffer) const
{
    mState.mFramebufferManager->recycleHandle(framebuffer->id());
}

void Context::onProgramPipelineDestroy(const ProgramPipeline *programPipeline) const
{
    mState.mProgramPipelineManager->recycleHandle(programPipeline->id());
}

void Context::invalidateTransformFeedbackCapacities(const Buffer *buffer) const
{
    for (auto pair : UnsafeResourceMapIter(mTransformFeedbackMap))
    {
        TransformFeedback *tf = pair.second;
        if (tf != nullptr && tf->isBufferBound(buffer->id()))
        {
            tf->invalidateVertexCapacity();
        }
    }
}

// ErrorSet implementation.
ErrorSet::ErrorSet(Debug *debug,
                   const angle::FrontendFeatures &frontendFeatures,
                   const egl::AttributeMap &attribs)
    : mDebug(debug),
      mResetStrategy(GetResetStrategy(attribs)),
      mLoseContextOnOutOfMemory(frontendFeatures.loseContextOnOutOfMemory.enabled),
      mLoseContextOnInternalError(frontendFeatures.loseHardenedContextOnBackendError.enabled &&
                                  (GetWebGLContext(attribs) || GetHardenedContext(attribs))),
      mContextLostForced(false),
      mResetStatus(GraphicsResetStatus::NoError),
      mErrorMessageCount(0),
      // Limit the error message spam to a small number when the context is not in debug mode, as
      // some apps make invalid but harmless calls and the spam has a non-trivial cost.
      //
      // Note: mMaxErrorMessages is kept far from max to avoid overflowing mErrorMessageCount in
      // case of multiple contexts simultaneously adding (context loss) errors, hence the division
      // by 2.
      mMaxErrorMessages(
          GetDebug(frontendFeatures, attribs) ? std::numeric_limits<uint32_t>::max() / 2 : 16),
      mSkipValidation(GetNoError(attribs)),
      mContextLost(0),
#if defined(ANGLE_ENABLE_ASSERTS)
      mPushedErrors(0),
#endif
      mHasAnyErrors(0)
{}

ErrorSet::~ErrorSet() = default;

void ErrorSet::handleError(GLenum errorCode,
                           const char *message,
                           const char *file,
                           const char *function,
                           unsigned int line)
{
    if (mLoseContextOnInternalError ||
        (errorCode == GL_OUT_OF_MEMORY && mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT &&
         mLoseContextOnOutOfMemory))
    {
        markContextLost(GraphicsResetStatus::UnknownContextReset);
    }

    std::stringstream errorStream;
    errorStream << "Error: " << gl::FmtHex(errorCode) << ", in " << file << ", " << function << ':'
                << line << ". " << message;

    std::string formattedMessage = errorStream.str();

    // Process the error, but log it with WARN severity so it shows up in logs.
    mDebug->insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, errorCode,
                          GL_DEBUG_SEVERITY_HIGH, std::move(formattedMessage), gl::LOG_WARN);

    pushError(errorCode);
}

void ErrorSet::validationError(angle::EntryPoint entryPoint, GLenum errorCode, const char *message)
{
    bool reportMessage = true;
    bool isLastMessage = false;

#if !defined(ANGLE_ENABLE_ASSERTS) && !defined(ANGLE_ALWAYS_REPORT_VALIDATION_ERRORS)
    // In release mode, don't spam validation errors as they come with a performance cost, affecting
    // applications that make lots of invalid but otherwise harmless calls. Instead, only report the
    // first few messages. This can still be helpful to application developers who can fix the first
    // few errors more easily and get more messages on the next run.
    //
    // The error messages are always reported for Chromium which uses the debug callback to detect
    // errors instead of glGetError().
    reportMessage =
        MessageCounterBelowMaxRepeat(&mErrorMessageCount, mMaxErrorMessages, &isLastMessage);
#endif

    if (reportMessage)
    {
        std::string completeMessage = std::string(GetEntryPointName(entryPoint)) + ": " + message;
        if (isLastMessage)
        {
            completeMessage += " (No more validation messages will be reported)";
        }

        mDebug->insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, errorCode,
                              GL_DEBUG_SEVERITY_HIGH, completeMessage, gl::LOG_INFO);
    }

    pushError(errorCode);
}

void ErrorSet::validationErrorF(angle::EntryPoint entryPoint,
                                GLenum errorCode,
                                const char *format,
                                ...)
{
    va_list vargs;
    va_start(vargs, format);
    constexpr size_t kMessageSize = 256;
    char message[kMessageSize];
    int r = vsnprintf(message, kMessageSize, format, vargs);
    va_end(vargs);

    if (r > 0)
    {
        validationError(entryPoint, errorCode, message);
    }
    else
    {
        validationError(entryPoint, errorCode, format);
    }
}

std::unique_lock<std::mutex> ErrorSet::getLockIfNotAlready()
{
    // Avoid mutex recursion and return the lock only if it is not already locked.  This can happen
    // if device loss is generated while it is being queried.
    if (mMutex.try_lock())
    {
        return std::unique_lock<std::mutex>(mMutex, std::adopt_lock);
    }
    return std::unique_lock<std::mutex>();
}

void ErrorSet::pushError(GLenum errorCode)
{
    ASSERT(errorCode != GL_NO_ERROR);
    {
        std::lock_guard<std::mutex> lock(mMutex);
        mErrors.insert(errorCode);
#if defined(ANGLE_ENABLE_ASSERTS)
        mPushedErrors++;
#endif
        mHasAnyErrors = 1;
    }
}

GLenum ErrorSet::popError()
{
    std::lock_guard<std::mutex> lock(mMutex);

    ASSERT(!empty());
    GLenum error = *mErrors.begin();
    mErrors.erase(mErrors.begin());
    if (mErrors.empty())
    {
        mHasAnyErrors = 0;
    }
    return error;
}

// NOTE: this function should not assume that this context is current!
void ErrorSet::markContextLost(GraphicsResetStatus status)
{
    // This function may be called indirectly through ErrorSet::getGraphicsResetStatus() from the
    // backend, in which case mMutex is already held.
    std::unique_lock<std::mutex> lock = getLockIfNotAlready();

    ASSERT(status != GraphicsResetStatus::NoError);
    if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
    {
        mResetStatus       = status;
        mContextLostForced = true;
    }
    setContextLost();
}

void ErrorSet::setContextLost()
{
    // Always called with the mutex held.
    ASSERT(mMutex.try_lock() == false);

    mContextLost = 1;

    // Stop skipping validation, since many implementation entrypoint assume they can't
    // be called when lost, or with null object arguments, etc.
    mSkipValidation = 0;

    // Make sure we update TLS.
    SetCurrentValidContext(nullptr);
}

GLenum ErrorSet::getGraphicsResetStatus(rx::ContextImpl *contextImpl)
{
    std::lock_guard<std::mutex> lock(mMutex);

    // Even if the application doesn't want to know about resets, we want to know
    // as it will allow us to skip all the calls.
    if (mResetStrategy == GL_NO_RESET_NOTIFICATION_EXT)
    {
        if (!isContextLost() && contextImpl->getResetStatus() != GraphicsResetStatus::NoError)
        {
            setContextLost();
        }

        // EXT_robustness, section 2.6: If the reset notification behavior is
        // NO_RESET_NOTIFICATION_EXT, then the implementation will never deliver notification of
        // reset events, and GetGraphicsResetStatusEXT will always return NO_ERROR.
        return GL_NO_ERROR;
    }

    // The GL_EXT_robustness spec says that if a reset is encountered, a reset
    // status should be returned at least once, and GL_NO_ERROR should be returned
    // once the device has finished resetting.
    if (!isContextLost())
    {
        ASSERT(mResetStatus == GraphicsResetStatus::NoError);
        mResetStatus = contextImpl->getResetStatus();

        if (mResetStatus != GraphicsResetStatus::NoError)
        {
            setContextLost();
        }
    }
    else if (!mContextLostForced && mResetStatus != GraphicsResetStatus::NoError)
    {
        // If markContextLost was used to mark the context lost then
        // assume that is not recoverable, and continue to report the
        // lost reset status for the lifetime of this context.
        mResetStatus = contextImpl->getResetStatus();
    }

    return ToGLenum(mResetStatus);
}

GLenum ErrorSet::getErrorForCapture() const
{
    if (mErrors.empty())
    {
        return GL_NO_ERROR;
    }
    else
    {
        // Return the error without clearing it
        return *mErrors.begin();
    }
}

// StateCache implementation.
StateCache::StateCache()
    : mCachedNonInstancedVertexElementLimit(0),
      mCachedInstancedVertexElementLimit(0),
      mCachedBasicDrawStatesErrorString(kInvalidPointer),
      mCachedBasicDrawStatesErrorCode(GL_NO_ERROR),
      mCachedProgramPipelineError(kInvalidPointer),
      mCachedHasAnyEnabledClientAttrib(false),
      mCachedTransformFeedbackActiveUnpaused(false),
      mCachedCanDraw(false)
{
    mCachedValidDrawModes.fill(false);
}

StateCache::~StateCache() = default;

ANGLE_INLINE void StateCache::updateVertexElementLimits(const Context *context)
{
    if (context->isBufferAccessValidationEnabled())
    {
        updateVertexElementLimitsImpl(context);
    }
}

void StateCache::initialize(Context *context)
{
    updateValidDrawModes(context);
    updateValidBindTextureTypes(context);
    updateValidDrawElementsTypes(context);
    updateBasicDrawStatesError();
    updateCanDraw(context);
}

void StateCache::updateActiveAttribsMask(const Context *context)
{
    bool isGLES1         = context->isGLES1();
    const State &glState = context->getState();

    if (!isGLES1 && !glState.getProgramExecutable())
    {
        mCachedActiveBufferedAttribsMask = AttributesMask();
        mCachedActiveClientAttribsMask   = AttributesMask();
        mCachedActiveDefaultAttribsMask  = AttributesMask();
        return;
    }

    AttributesMask activeAttribs =
        isGLES1 ? glState.gles1().getActiveAttributesMask()
                : glState.getProgramExecutable()->getActiveAttribLocationsMask();

    const VertexArray *vao = glState.getVertexArray();
    ASSERT(vao);

    const AttributesMask &clientAttribs  = vao->getClientAttribsMask();
    const AttributesMask &enabledAttribs = vao->getEnabledAttributesMask();
    const AttributesMask &activeEnabled  = activeAttribs & enabledAttribs;

    mCachedActiveClientAttribsMask   = activeEnabled & clientAttribs;
    mCachedActiveBufferedAttribsMask = activeEnabled & ~clientAttribs;
    mCachedActiveDefaultAttribsMask  = activeAttribs & ~enabledAttribs;
    mCachedHasAnyEnabledClientAttrib = (clientAttribs & enabledAttribs).any();
}

void StateCache::updateVertexElementLimitsImpl(const Context *context)
{
    ASSERT(context->isBufferAccessValidationEnabled());

    const VertexArray *vao = context->getState().getVertexArray();

    mCachedNonInstancedVertexElementLimit = std::numeric_limits<GLint64>::max();
    mCachedInstancedVertexElementLimit    = std::numeric_limits<GLint64>::max();

    // VAO can be null on Context startup. If we make this computation lazier we could ASSERT.
    // If there are no buffered attributes then we should not limit the draw call count.
    if (!vao || !mCachedActiveBufferedAttribsMask.any())
    {
        return;
    }

    const auto &vertexAttribs  = vao->getVertexAttributes();
    const auto &vertexBindings = vao->getVertexBindings();

    for (size_t attributeIndex : mCachedActiveBufferedAttribsMask)
    {
        const VertexAttribute &attrib = vertexAttribs[attributeIndex];

        const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
        ASSERT(context->isGLES1() ||
               context->getState().getProgramExecutable()->isAttribLocationActive(attributeIndex));

        GLint64 limit = attrib.getCachedElementLimit();
        if (binding.getDivisor() > 0)
        {
            // For instanced draw calls, |divisor| times this limit is the limit for instance count
            // (because every |divisor| instances accesses the same attribute)
            angle::CheckedNumeric<GLint64> checkedLimit = limit;
            checkedLimit *= binding.getDivisor();

            mCachedInstancedVertexElementLimit =
                std::min<GLint64>(mCachedInstancedVertexElementLimit,
                                  checkedLimit.ValueOrDefault(VertexAttribute::kIntegerOverflow));
        }
        else
        {
            mCachedNonInstancedVertexElementLimit =
                std::min(mCachedNonInstancedVertexElementLimit, limit);
        }
    }
}

intptr_t StateCache::getBasicDrawStatesErrorImpl(const Context *context,
                                                 const PrivateStateCache *privateStateCache) const
{
    ASSERT(mCachedBasicDrawStatesErrorString == kInvalidPointer ||
           !privateStateCache->isCachedBasicDrawStatesErrorValid());
    ASSERT(mCachedBasicDrawStatesErrorCode == GL_NO_ERROR ||
           !privateStateCache->isCachedBasicDrawStatesErrorValid());

    // Only assign the error code after ValidateDrawStates has completed. ValidateDrawStates calls
    // updateBasicDrawStatesError in some cases and resets the value mid-call.
    GLenum errorCode = GL_NO_ERROR;
    mCachedBasicDrawStatesErrorString =
        reinterpret_cast<intptr_t>(ValidateDrawStates(context, &errorCode));
    mCachedBasicDrawStatesErrorCode = errorCode;

    // Ensure that if an error is set mCachedBasicDrawStatesErrorCode must be GL_NO_ERROR and if no
    // error is set mCachedBasicDrawStatesErrorCode must be an error.
    ASSERT((mCachedBasicDrawStatesErrorString == 0) ==
           (mCachedBasicDrawStatesErrorCode == GL_NO_ERROR));

    privateStateCache->setCachedBasicDrawStatesErrorValid();
    return mCachedBasicDrawStatesErrorString;
}

intptr_t StateCache::getProgramPipelineErrorImpl(const Context *context) const
{
    ASSERT(mCachedProgramPipelineError == kInvalidPointer);
    mCachedProgramPipelineError = reinterpret_cast<intptr_t>(ValidateProgramPipeline(context));
    return mCachedProgramPipelineError;
}

void StateCache::onProgramExecutableChange(Context *context)
{
    updateActiveAttribsMask(context);
    updateVertexElementLimits(context);
    updateBasicDrawStatesError();
    updateProgramPipelineError();
    updateValidDrawModes(context);
    updateActiveShaderStorageBufferIndices(context);
    updateActiveImageUnitIndices(context);
    updateCanDraw(context);
}

void StateCache::onGLES1ClientStateChange(Context *context)
{
    updateActiveAttribsMask(context);
}

void StateCache::onGLES1TextureStateChange(Context *context)
{
    updateActiveAttribsMask(context);
}

void StateCache::onDrawFramebufferChange(Context *context)
{
    updateBasicDrawStatesError();
}

void StateCache::onActiveTextureChange(Context *context)
{
    updateBasicDrawStatesError();
}

void StateCache::onQueryChange(Context *context)
{
    updateBasicDrawStatesError();
}

void StateCache::onActiveTransformFeedbackChange(Context *context)
{
    updateTransformFeedbackActiveUnpaused(context);
    updateBasicDrawStatesError();
    updateValidDrawModes(context);
}

void StateCache::onUniformBufferStateChange(Context *context)
{
    updateBasicDrawStatesError();
}

void StateCache::onAtomicCounterBufferStateChange(Context *context)
{
    updateBasicDrawStatesError();
}

void StateCache::onShaderStorageBufferStateChange(Context *context)
{
    updateBasicDrawStatesError();
}

void StateCache::setValidDrawModes(bool pointsOK,
                                   bool linesOK,
                                   bool trisOK,
                                   bool lineAdjOK,
                                   bool triAdjOK,
                                   bool patchOK)
{
    mCachedValidDrawModes[PrimitiveMode::Points]                 = pointsOK;
    mCachedValidDrawModes[PrimitiveMode::Lines]                  = linesOK;
    mCachedValidDrawModes[PrimitiveMode::LineLoop]               = linesOK;
    mCachedValidDrawModes[PrimitiveMode::LineStrip]              = linesOK;
    mCachedValidDrawModes[PrimitiveMode::Triangles]              = trisOK;
    mCachedValidDrawModes[PrimitiveMode::TriangleStrip]          = trisOK;
    mCachedValidDrawModes[PrimitiveMode::TriangleFan]            = trisOK;
    mCachedValidDrawModes[PrimitiveMode::LinesAdjacency]         = lineAdjOK;
    mCachedValidDrawModes[PrimitiveMode::LineStripAdjacency]     = lineAdjOK;
    mCachedValidDrawModes[PrimitiveMode::TrianglesAdjacency]     = triAdjOK;
    mCachedValidDrawModes[PrimitiveMode::TriangleStripAdjacency] = triAdjOK;
    mCachedValidDrawModes[PrimitiveMode::Patches]                = patchOK;
}

void StateCache::updateValidDrawModes(Context *context)
{
    const State &state = context->getState();

    const ProgramExecutable *programExecutable = context->getState().getProgramExecutable();

    // If tessellation is active primitive mode must be GL_PATCHES.
    if (programExecutable && programExecutable->hasLinkedTessellationShader())
    {
        setValidDrawModes(false, false, false, false, false, true);
        return;
    }

    bool pointsOK  = true;
    bool linesOK   = true;
    bool trisOK    = true;
    bool lineAdjOK = true;
    bool triAdjOK  = true;

    if (mCachedTransformFeedbackActiveUnpaused)
    {
        TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
        mCachedValidDrawModes.fill(false);

        // ES Spec 3.0 validation text:
        // When transform feedback is active and not paused, all geometric primitives generated must
        // match the value of primitiveMode passed to BeginTransformFeedback. The error
        // INVALID_OPERATION is generated by DrawArrays and DrawArraysInstanced if mode is not
        // identical to primitiveMode. The error INVALID_OPERATION is also generated by
        // DrawElements, DrawElementsInstanced, and DrawRangeElements while transform feedback is
        // active and not paused, regardless of mode. Any primitive type may be used while transform
        // feedback is paused.
        if (!context->getExtensions().geometryShaderAny() &&
            !context->getExtensions().tessellationShaderAny() &&
            context->getClientVersion() < ES_3_2)
        {
            mCachedValidDrawModes[curTransformFeedback->getPrimitiveMode()] = true;
            return;
        }

        // From: EXT_geometry_shader
        //
        // Transform Feedback  Allowed render primitive
        // <primitiveMode>     <modes>
        // -------------------+----------------------------------------
        // POINTS             | POINTS
        // LINES              | LINES, LINE_LOOP, LINE_STRIP
        // TRIANGLES          | TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN
        // ------------------------------------------------------------
        // Table 12.1gs: Legal combinations of the transform feedback
        // primitive mode, as passed to BeginTransformFeedback, and the
        // current primitive mode.
        const PrimitiveMode xfbMode = curTransformFeedback->getPrimitiveMode();

        // If a geometry shader is bound, the primitive that interacts with transform feedback is
        // the geometry shader's output primitive type, which is independent from its input. In that
        // case, either all inputs are ok (if the output matches) or none are (if the output
        // doesn't match).
        if (programExecutable && programExecutable->hasLinkedShaderStage(ShaderType::Geometry))
        {
            const PrimitiveMode gsOutMode =
                programExecutable->getGeometryShaderOutputPrimitiveType();

            // Note: the geometry shader output is either points, line_strip or triangle_strip.
            bool matchingModes = false;
            switch (gsOutMode)
            {
                case PrimitiveMode::Points:
                    matchingModes = xfbMode == PrimitiveMode::Points;
                    break;
                case PrimitiveMode::LineStrip:
                    matchingModes = xfbMode == PrimitiveMode::Lines;
                    break;
                case PrimitiveMode::TriangleStrip:
                    matchingModes = xfbMode == PrimitiveMode::Triangles;
                    break;
                default:
                    // Invalid geometry shader output mode
                    ASSERT(false);
            }

            if (!matchingModes)
            {
                // All draw modes are set to false, so every draw will fail.
                return;
            }
        }
        else
        {
            // When geometry shader is not involved, the draw call's primitive mode is expected to
            // match the transform feedback's.
            pointsOK = xfbMode == PrimitiveMode::Points;
            linesOK  = xfbMode == PrimitiveMode::Lines;
            trisOK   = xfbMode == PrimitiveMode::Triangles;
        }
    }

    if (!programExecutable || !programExecutable->hasLinkedShaderStage(ShaderType::Geometry))
    {
        bool adjacencyOK =
            (context->getExtensions().geometryShaderAny() || context->getClientVersion() >= ES_3_2);

        // All draw modes are valid, since drawing without a program does not generate an error and
        // operations requiring a GS will trigger other validation errors.
        // `patchOK = false` due to checking above already enabling it if a TS is present.
        lineAdjOK = lineAdjOK && adjacencyOK;
        triAdjOK  = triAdjOK && adjacencyOK;
    }
    else
    {
        const PrimitiveMode gsMode = programExecutable->getGeometryShaderInputPrimitiveType();
        pointsOK                   = pointsOK && gsMode == PrimitiveMode::Points;
        linesOK                    = linesOK && gsMode == PrimitiveMode::Lines;
        trisOK                     = trisOK && gsMode == PrimitiveMode::Triangles;
        lineAdjOK                  = lineAdjOK && gsMode == PrimitiveMode::LinesAdjacency;
        triAdjOK                   = triAdjOK && gsMode == PrimitiveMode::TrianglesAdjacency;
    }

    setValidDrawModes(pointsOK, linesOK, trisOK, lineAdjOK, triAdjOK, false);
}

void StateCache::updateValidBindTextureTypes(Context *context)
{
    const Extensions &exts = context->getExtensions();
    const bool isGLES3     = context->getClientVersion() >= ES_3_0;
    const bool isGLES31    = context->getClientVersion() >= ES_3_1;
    const bool isGLES32    = context->getClientVersion() >= ES_3_2;

    mCachedValidBindTextureTypes = {{
        {TextureType::_2D, true},
        {TextureType::_2DArray, isGLES3},
        {TextureType::_2DMultisample, isGLES31 || exts.textureMultisampleANGLE},
        {TextureType::_2DMultisampleArray, isGLES32 || exts.textureStorageMultisample2dArrayOES},
        {TextureType::_3D, isGLES3 || exts.texture3DOES},
        {TextureType::External, exts.EGLImageExternalOES || exts.EGLStreamConsumerExternalNV},
        {TextureType::Rectangle, exts.textureRectangleANGLE},
        {TextureType::CubeMap, true},
        {TextureType::CubeMapArray, isGLES32 || exts.textureCubeMapArrayAny()},
        {TextureType::Buffer, isGLES32 || exts.textureBufferAny()},
    }};
}

void StateCache::updateValidDrawElementsTypes(Context *context)
{
    bool supportsUint =
        (context->getClientVersion() >= ES_3_0 || context->getExtensions().elementIndexUintOES);

    mCachedValidDrawElementsTypes = {{
        {DrawElementsType::UnsignedByte, true},
        {DrawElementsType::UnsignedShort, true},
        {DrawElementsType::UnsignedInt, supportsUint},
    }};
}

void StateCache::updateTransformFeedbackActiveUnpaused(Context *context)
{
    TransformFeedback *xfb                 = context->getState().getCurrentTransformFeedback();
    mCachedTransformFeedbackActiveUnpaused = xfb && xfb->isActive() && !xfb->isPaused();
}

void StateCache::updateActiveShaderStorageBufferIndices(Context *context)
{
    mCachedActiveShaderStorageBufferIndices.reset();
    const ProgramExecutable *executable = context->getState().getProgramExecutable();
    if (executable)
    {
        const std::vector<InterfaceBlock> &blocks = executable->getShaderStorageBlocks();
        for (size_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex)
        {
            const GLuint binding = executable->getShaderStorageBlockBinding(blockIndex);
            mCachedActiveShaderStorageBufferIndices.set(binding);
        }
    }
}

void StateCache::updateActiveImageUnitIndices(Context *context)
{
    mCachedActiveImageUnitIndices.reset();
    const ProgramExecutable *executable = context->getState().getProgramExecutable();
    if (executable)
    {
        for (const ImageBinding &imageBinding : executable->getImageBindings())
        {
            for (GLuint binding : imageBinding.boundImageUnits)
            {
                mCachedActiveImageUnitIndices.set(binding);
            }
        }
    }
}

void StateCache::updateCanDraw(Context *context)
{
    // Can draw if:
    //
    // - Is GLES1: GLES1 always creates programs as needed
    // - There is an installed executable with a vertex shader
    // - A program pipeline is to be used: Program pipelines don't have a specific link function, so
    //   the pipeline might just be waiting to be linked at draw time (in which case there won't
    //   necessarily be an executable installed yet).
    mCachedCanDraw =
        context->isGLES1() || (context->getState().getProgramExecutable() &&
                               context->getState().getProgramExecutable()->hasVertexShader());
}

bool StateCache::isCurrentContext(const Context *context,
                                  const PrivateStateCache *privateStateCache) const
{
    // Ensure that the state cache is not queried by any context other than the one that owns it.
    return &context->getStateCache() == this &&
           &context->getPrivateStateCache() == privateStateCache;
}

// PrivateStateCache implementation
PrivateStateCache::PrivateStateCache()
    : mIsCachedBasicDrawStatesErrorValid(true),
      mIsCachedActiveAttribMasksValid(true),
      mIsCachedVertexElementLimitValid(true),
      mCachedBasicDrawElementsError(kInvalidPointer)
{}

PrivateStateCache::~PrivateStateCache() = default;

void PrivateStateCache::initialize(const Context *context)
{
    updateVertexAttribTypesValidation(context);
    mCachedBasicDrawElementsError = kInvalidPointer;
}

void PrivateStateCache::updateVertexAttribTypesValidation(const Context *context)
{
    VertexAttribTypeCase halfFloatValidity = (context->getExtensions().vertexHalfFloatOES)
                                                 ? VertexAttribTypeCase::Valid
                                                 : VertexAttribTypeCase::Invalid;

    VertexAttribTypeCase vertexType1010102Validity = (context->getExtensions().vertexType1010102OES)
                                                         ? VertexAttribTypeCase::ValidSize3or4
                                                         : VertexAttribTypeCase::Invalid;

    if (context->getClientVersion() < ES_3_0)
    {
        mCachedVertexAttribTypesValidation = {{
            {VertexAttribType::Byte, VertexAttribTypeCase::Valid},
            {VertexAttribType::Short, VertexAttribTypeCase::Valid},
            {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid},
            {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid},
            {VertexAttribType::Float, VertexAttribTypeCase::Valid},
            {VertexAttribType::Fixed, VertexAttribTypeCase::Valid},
            {VertexAttribType::HalfFloatOES, halfFloatValidity},
        }};
    }
    else
    {
        mCachedVertexAttribTypesValidation = {{
            {VertexAttribType::Byte, VertexAttribTypeCase::Valid},
            {VertexAttribType::Short, VertexAttribTypeCase::Valid},
            {VertexAttribType::Int, VertexAttribTypeCase::Valid},
            {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid},
            {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid},
            {VertexAttribType::UnsignedInt, VertexAttribTypeCase::Valid},
            {VertexAttribType::Float, VertexAttribTypeCase::Valid},
            {VertexAttribType::HalfFloat, VertexAttribTypeCase::Valid},
            {VertexAttribType::Fixed, VertexAttribTypeCase::Valid},
            {VertexAttribType::Int2101010, VertexAttribTypeCase::ValidSize4Only},
            {VertexAttribType::HalfFloatOES, halfFloatValidity},
            {VertexAttribType::UnsignedInt2101010, VertexAttribTypeCase::ValidSize4Only},
            {VertexAttribType::Int1010102, vertexType1010102Validity},
            {VertexAttribType::UnsignedInt1010102, vertexType1010102Validity},
        }};

        mCachedIntegerVertexAttribTypesValidation = {{
            {VertexAttribType::Byte, VertexAttribTypeCase::Valid},
            {VertexAttribType::Short, VertexAttribTypeCase::Valid},
            {VertexAttribType::Int, VertexAttribTypeCase::Valid},
            {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid},
            {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid},
            {VertexAttribType::UnsignedInt, VertexAttribTypeCase::Valid},
        }};
    }
}
}  // namespace gl
