//
// Copyright 2016 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.
//
// ContextGL:
//   OpenGL-specific functionality associated with a GL Context.
//

#include "libANGLE/renderer/gl/ContextGL.h"
#include "common/unsafe_buffers.h"

#include "libANGLE/Context.h"
#include "libANGLE/Context.inl.h"
#include "libANGLE/PixelLocalStorage.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/CompilerGL.h"
#include "libANGLE/renderer/gl/FenceNVGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/MemoryObjectGL.h"
#include "libANGLE/renderer/gl/ProgramExecutableGL.h"
#include "libANGLE/renderer/gl/ProgramGL.h"
#include "libANGLE/renderer/gl/ProgramPipelineGL.h"
#include "libANGLE/renderer/gl/QueryGL.h"
#include "libANGLE/renderer/gl/RenderbufferGL.h"
#include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/renderer/gl/SamplerGL.h"
#include "libANGLE/renderer/gl/SemaphoreGL.h"
#include "libANGLE/renderer/gl/ShaderGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/SyncGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
#include "libANGLE/renderer/gl/VertexArrayGL.h"

namespace rx
{
namespace
{
GLsizei GetDrawAdjustedInstanceCount(const gl::ProgramExecutable *executable)
{
    const bool usesMultiview = executable->usesMultiview();
    return usesMultiview ? executable->getNumViews() : 0;
}

GLsizei GetInstancedDrawAdjustedInstanceCount(const gl::ProgramExecutable *executable,
                                              GLsizei instanceCount)
{
    GLsizei adjustedInstanceCount = instanceCount;
    if (executable->usesMultiview())
    {
        adjustedInstanceCount *= executable->getNumViews();
    }
    return adjustedInstanceCount;
}
}  // anonymous namespace

ContextGL::PixelBufferGL::PixelBufferGL(const FunctionsGL *functions_)
    : functions(functions_), bufferID(0), size(0), lifetimeCounter(0)
{
    functions->genBuffers(1, &bufferID);
}
ContextGL::PixelBufferGL::~PixelBufferGL()
{
    if (functions && bufferID != 0)
    {
        functions->deleteBuffers(1, &bufferID);
    }
}
ContextGL::PixelBufferGL::PixelBufferGL(PixelBufferGL &&other)
{
    *this = std::move(other);
}
ContextGL::PixelBufferGL &ContextGL::PixelBufferGL::operator=(PixelBufferGL &&other)
{
    if (this != &other)
    {
        if (functions && bufferID != 0)
        {
            functions->deleteBuffers(1, &bufferID);
        }
        functions       = other.functions;
        bufferID        = other.bufferID;
        size            = other.size;
        lifetimeCounter = other.lifetimeCounter;

        other.bufferID = 0;
        other.size     = 0;
    }
    return *this;
}

ContextGL::ContextGL(const gl::State &state,
                     gl::ErrorSet *errorSet,
                     const std::shared_ptr<RendererGL> &renderer,
                     RobustnessVideoMemoryPurgeStatus robustnessVideoMemoryPurgeStatus)
    : ContextImpl(state, errorSet),
      mRenderer(renderer),
      mRobustnessVideoMemoryPurgeStatus(robustnessVideoMemoryPurgeStatus),
      // Maximum 3 cached depth initialization PBOs stored for now; can be changed in the future if
      // needed.
      mDepthInitPBOs(/*max=*/3)
{}

ContextGL::~ContextGL() {}

void ContextGL::onDestroy(const gl::Context *context)
{
    mDepthInitPBOs.Clear();
}

angle::Result ContextGL::initialize(const angle::ImageLoadContext &imageLoadContext)
{
    return angle::Result::Continue;
}

CompilerImpl *ContextGL::createCompiler()
{
    return new CompilerGL(this);
}

ShaderImpl *ContextGL::createShader(const gl::ShaderState &data)
{
    const FunctionsGL *functions = getFunctions();
    GLuint shader                = functions->createShader(ToGLenum(data.getShaderType()));

    return new ShaderGL(data, shader);
}

ProgramImpl *ContextGL::createProgram(const gl::ProgramState &data)
{
    return new ProgramGL(data, getFunctions(), getFeaturesGL(), getStateManager(), mRenderer);
}

ProgramExecutableImpl *ContextGL::createProgramExecutable(const gl::ProgramExecutable *executable)
{
    return new ProgramExecutableGL(executable);
}

FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data)
{
    const FunctionsGL *funcs = getFunctions();

    GLuint fbo = 0;
    if (!data.isDefault())
    {
        funcs->genFramebuffers(1, &fbo);
    }

    return new FramebufferGL(data, fbo, false, funcs, getStateManager());
}

TextureImpl *ContextGL::createTexture(const gl::TextureState &state)
{
    const FunctionsGL *functions = getFunctions();
    StateManagerGL *stateManager = getStateManager();

    GLuint texture = 0;
    functions->genTextures(1, &texture);
    stateManager->bindTexture(state.getType(), texture);

    return new TextureGL(state, texture);
}

RenderbufferImpl *ContextGL::createRenderbuffer(const gl::RenderbufferState &state)
{
    const FunctionsGL *functions = getFunctions();
    StateManagerGL *stateManager = getStateManager();

    GLuint renderbuffer = 0;
    functions->genRenderbuffers(1, &renderbuffer);
    stateManager->bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);

    return new RenderbufferGL(state, renderbuffer);
}

BufferImpl *ContextGL::createBuffer(const gl::BufferState &state)
{
    const FunctionsGL *functions = getFunctions();

    GLuint buffer = 0;
    functions->genBuffers(1, &buffer);

    return new BufferGL(state, buffer);
}

VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data,
                                              const gl::VertexArrayBuffers &vertexArrayBuffers)
{
    const FunctionsGL *functions      = getFunctions();
    const angle::FeaturesGL &features = getFeaturesGL();
    StateManagerGL *stateManager      = getStateManager();

    GLuint vaoID           = 0;
    bool vertexArrayOwnsID = false;

    // Use the shared default vertex array when forced to for workarounds
    // (syncAllVertexArraysToDefault) or for the frontend default vertex array so that client data
    // can be used directly
    // Disable on external contexts so that the default VAO is not modified by both ANGLE and the
    // external user.
    if (features.syncAllVertexArraysToDefault.enabled ||
        (features.syncDefaultVertexArraysToDefault.enabled && data.isDefault() &&
         mState.areClientArraysEnabled()))
    {
        vaoID             = stateManager->getDefaultVAO();
        vertexArrayOwnsID = false;
    }
    else
    {
        functions->genVertexArrays(1, &vaoID);
        vertexArrayOwnsID = true;
    }

    VertexArrayStateGL *vaoState = stateManager->getOrCreateVAOState(vaoID);
    return new VertexArrayGL(data, vaoID, vertexArrayOwnsID, vertexArrayBuffers, vaoState);
}

QueryImpl *ContextGL::createQuery(gl::QueryType type)
{
    return new StandardQueryGL(type, getFunctions(), getStateManager());
}

FenceNVImpl *ContextGL::createFenceNV()
{
    const FunctionsGL *functions = getFunctions();
    if (FenceNVGL::Supported(functions))
    {
        return new FenceNVGL(functions);
    }
    else
    {
        ASSERT(FenceNVSyncGL::Supported(functions));
        return new FenceNVSyncGL(functions);
    }
}

SyncImpl *ContextGL::createSync()
{
    return new SyncGL(mRenderer);
}

TransformFeedbackImpl *ContextGL::createTransformFeedback(const gl::TransformFeedbackState &state)
{
    return new TransformFeedbackGL(state, getFunctions(), getStateManager());
}

SamplerImpl *ContextGL::createSampler(const gl::SamplerState &state)
{
    const FunctionsGL *functions = getFunctions();

    GLuint sampler = 0;
    functions->genSamplers(1, &sampler);

    return new SamplerGL(state, sampler);
}

ProgramPipelineImpl *ContextGL::createProgramPipeline(const gl::ProgramPipelineState &data)
{
    return new ProgramPipelineGL(data, getFunctions());
}

MemoryObjectImpl *ContextGL::createMemoryObject()
{
    const FunctionsGL *functions = getFunctions();

    GLuint memoryObject = 0;
    functions->createMemoryObjectsEXT(1, &memoryObject);

    return new MemoryObjectGL(memoryObject);
}

SemaphoreImpl *ContextGL::createSemaphore()
{
    const FunctionsGL *functions = getFunctions();

    GLuint semaphore = 0;
    functions->genSemaphoresEXT(1, &semaphore);

    return new SemaphoreGL(semaphore);
}

angle::Result ContextGL::flush(const gl::Context *context)
{
    return mRenderer->flush();
}

angle::Result ContextGL::finish(const gl::Context *context)
{
    return mRenderer->finish();
}

ANGLE_INLINE angle::Result ContextGL::setDrawArraysState(const gl::Context *context,
                                                         GLint first,
                                                         GLsizei count,
                                                         GLsizei instanceCount)
{
    const angle::FeaturesGL &features = getFeaturesGL();
    if (context->hasAnyActiveClientAttrib() ||
        (features.shiftInstancedArrayDataWithOffset.enabled && first > 0))
    {
        const gl::State &glState                = context->getState();
        const gl::ProgramExecutable *executable = getState().getProgramExecutable();
        const gl::VertexArray *vao              = glState.getVertexArray();
        const VertexArrayGL *vaoGL              = GetImplAs<VertexArrayGL>(vao);

        ANGLE_TRY(vaoGL->syncClientSideData(context, executable->getActiveAttribLocationsMask(),
                                            first, count, instanceCount));

        validateState(StateTypes{StateType::GlobalState, StateType::VAOState});
    }
    else if (features.shiftInstancedArrayDataWithOffset.enabled && first == 0)
    {
        // There could be previous draw call that has modified the attributes
        // Instead of forcefully streaming attributes, we just rebind the original ones
        const gl::State &glState   = context->getState();
        const gl::VertexArray *vao = glState.getVertexArray();
        const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
        ANGLE_TRY(vaoGL->recoverForcedStreamingAttributesForDrawArraysInstanced(context));
    }

    if (features.setPrimitiveRestartFixedIndexForDrawArrays.enabled)
    {
        StateManagerGL *stateManager           = getStateManager();
        constexpr GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndexFromType<GLuint>();
        ANGLE_TRY(stateManager->setPrimitiveRestartIndex(context, primitiveRestartIndex));
    }

    return angle::Result::Continue;
}

ANGLE_INLINE angle::Result ContextGL::setDrawElementsState(const gl::Context *context,
                                                           GLsizei count,
                                                           gl::DrawElementsType type,
                                                           const void *indices,
                                                           GLsizei instanceCount,
                                                           const void **outIndices)
{
    const gl::State &glState                = context->getState();
    const gl::ProgramExecutable *executable = getState().getProgramExecutable();
    const gl::VertexArray *vao              = glState.getVertexArray();

    const angle::FeaturesGL &features = getFeaturesGL();
    if (features.shiftInstancedArrayDataWithOffset.enabled)
    {
        // There might be instanced arrays that are forced streaming for drawArraysInstanced
        // They cannot be ELEMENT_ARRAY_BUFFER
        const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
        ANGLE_TRY(vaoGL->recoverForcedStreamingAttributesForDrawArraysInstanced(context));
    }

    if (context->hasAnyActiveClientAttrib() || vao->getElementArrayBuffer() == nullptr)
    {
        const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
        ANGLE_TRY(vaoGL->syncDrawElementsState(context, executable->getActiveAttribLocationsMask(),
                                               count, type, indices, instanceCount,
                                               glState.isPrimitiveRestartEnabled(), outIndices));
    }
    else
    {
        *outIndices = indices;
    }

    if (glState.isPrimitiveRestartEnabled() && features.emulatePrimitiveRestartFixedIndex.enabled)
    {
        StateManagerGL *stateManager = getStateManager();

        GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndex(type);
        ANGLE_TRY(stateManager->setPrimitiveRestartIndex(context, primitiveRestartIndex));
    }

    validateState(StateTypes{StateType::GlobalState, StateType::VAOState});

    return angle::Result::Continue;
}

angle::Result ContextGL::drawArrays(const gl::Context *context,
                                    gl::PrimitiveMode mode,
                                    GLint first,
                                    GLsizei count)
{
    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
    const GLsizei instanceCount             = GetDrawAdjustedInstanceCount(executable);

    validateState(StateTypes{StateType::GlobalState});

    ANGLE_TRY(setDrawArraysState(context, first, count, instanceCount));
    if (!executable->usesMultiview())
    {
        ANGLE_GL_TRY(context, getFunctions()->drawArrays(ToGLenum(mode), first, count));
    }
    else
    {
        ANGLE_GL_TRY(context, getFunctions()->drawArraysInstanced(ToGLenum(mode), first, count,
                                                                  instanceCount));
    }
    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawArraysInstanced(const gl::Context *context,
                                             gl::PrimitiveMode mode,
                                             GLint first,
                                             GLsizei count,
                                             GLsizei instanceCount)
{
    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
    const GLsizei adjustedInstanceCount =
        GetInstancedDrawAdjustedInstanceCount(executable, instanceCount);

    ANGLE_TRY(setDrawArraysState(context, first, count, adjustedInstanceCount));
    ANGLE_GL_TRY(context, getFunctions()->drawArraysInstanced(ToGLenum(mode), first, count,
                                                              adjustedInstanceCount));
    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

gl::AttributesMask ContextGL::updateAttributesForBaseInstance(GLuint baseInstance)
{
    const gl::ProgramExecutable *executable = getState().getProgramExecutable();
    gl::AttributesMask attribToUpdateMask;

    if (baseInstance != 0)
    {
        const FunctionsGL *functions = getFunctions();
        const auto &attribs          = mState.getVertexArray()->getVertexAttributes();
        const auto &bindings         = mState.getVertexArray()->getVertexBindings();
        for (GLuint attribIndex = 0; attribIndex < attribs.size(); attribIndex++)
        {
            const gl::VertexAttribute &attrib = attribs[attribIndex];
            const gl::VertexBinding &binding  = bindings[attrib.bindingIndex];
            if (executable->isAttribLocationActive(attribIndex) && binding.getDivisor() != 0)
            {
                attribToUpdateMask.set(attribIndex);
                const char *p             = static_cast<const char *>(attrib.pointer);
                const size_t sourceStride = gl::ComputeVertexAttributeStride(attrib, binding);
                const void *newPointer    = ANGLE_UNSAFE_TODO(p + sourceStride * baseInstance);
                const BufferGL *buffer    = GetImplAs<BufferGL>(
                    mState.getVertexArray()->getVertexArrayBuffer(attrib.bindingIndex));
                // We often stream data from scratch buffers when client side data is being used
                // and that information is in VertexArrayGL.
                // Assert that the buffer is non-null because this case isn't handled.
                ASSERT(buffer);
                getStateManager()->bindBuffer(gl::BufferBinding::Array, buffer->getBufferID());
                if (attrib.format->isPureInt())
                {
                    functions->vertexAttribIPointer(attribIndex, attrib.format->channelCount,
                                                    gl::ToGLenum(attrib.format->vertexAttribType),
                                                    attrib.vertexAttribArrayStride, newPointer);
                }
                else
                {
                    functions->vertexAttribPointer(attribIndex, attrib.format->channelCount,
                                                   gl::ToGLenum(attrib.format->vertexAttribType),
                                                   attrib.format->isNorm(),
                                                   attrib.vertexAttribArrayStride, newPointer);
                }
            }
        }
    }

    return attribToUpdateMask;
}

void ContextGL::resetUpdatedAttributes(gl::AttributesMask attribMask)
{
    const FunctionsGL *functions = getFunctions();
    for (size_t attribIndex : attribMask)
    {
        const gl::VertexAttribute &attrib =
            mState.getVertexArray()->getVertexAttributes()[attribIndex];
        const gl::Buffer *buffer =
            mState.getVertexArray()->getVertexArrayBuffer(attrib.bindingIndex);
        getStateManager()->bindBuffer(gl::BufferBinding::Array,
                                      GetImplAs<BufferGL>(buffer)->getBufferID());
        if (attrib.format->isPureInt())
        {
            functions->vertexAttribIPointer(static_cast<GLuint>(attribIndex),
                                            attrib.format->channelCount,
                                            gl::ToGLenum(attrib.format->vertexAttribType),
                                            attrib.vertexAttribArrayStride, attrib.pointer);
        }
        else
        {
            functions->vertexAttribPointer(
                static_cast<GLuint>(attribIndex), attrib.format->channelCount,
                gl::ToGLenum(attrib.format->vertexAttribType), attrib.format->isNorm(),
                attrib.vertexAttribArrayStride, attrib.pointer);
        }
    }
}

angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *context,
                                                         gl::PrimitiveMode mode,
                                                         GLint first,
                                                         GLsizei count,
                                                         GLsizei instanceCount,
                                                         GLuint baseInstance)
{
    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
    const GLsizei adjustedInstanceCount =
        GetInstancedDrawAdjustedInstanceCount(executable, instanceCount);

    ANGLE_TRY(setDrawArraysState(context, first, count, adjustedInstanceCount));

    const FunctionsGL *functions = getFunctions();

    if (functions->drawArraysInstancedBaseInstance)
    {
        // GL 4.2+ or GL_EXT_base_instance
        ANGLE_GL_TRY(context,
                     functions->drawArraysInstancedBaseInstance(
                         ToGLenum(mode), first, count, adjustedInstanceCount, baseInstance));
    }
    else
    {
        // GL 3.3+ or GLES 3.2+
        // TODO(http://anglebug.com/42262554): This is a temporary solution by setting and resetting
        // pointer offset calling vertexAttribPointer Will refactor stateCache and pass baseInstance
        // to setDrawArraysState to set pointer offset

        gl::AttributesMask attribToResetMask = updateAttributesForBaseInstance(baseInstance);

        ANGLE_GL_TRY(context, functions->drawArraysInstanced(ToGLenum(mode), first, count,
                                                             adjustedInstanceCount));

        resetUpdatedAttributes(attribToResetMask);
    }

    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawElements(const gl::Context *context,
                                      gl::PrimitiveMode mode,
                                      GLsizei count,
                                      gl::DrawElementsType type,
                                      const void *indices)
{
    const gl::State &glState                = context->getState();
    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
    const GLsizei instanceCount             = GetDrawAdjustedInstanceCount(executable);
    const void *drawIndexPtr                = nullptr;

    validateState(StateTypes{StateType::GlobalState});

    ANGLE_TRY(setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPtr));
    if (!executable->usesMultiview())
    {
        ANGLE_GL_TRY(context, getFunctions()->drawElements(ToGLenum(mode), count, ToGLenum(type),
                                                           drawIndexPtr));
    }
    else
    {
        ANGLE_GL_TRY(context,
                     getFunctions()->drawElementsInstanced(ToGLenum(mode), count, ToGLenum(type),
                                                           drawIndexPtr, instanceCount));
    }
    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawElementsBaseVertex(const gl::Context *context,
                                                gl::PrimitiveMode mode,
                                                GLsizei count,
                                                gl::DrawElementsType type,
                                                const void *indices,
                                                GLint baseVertex)
{
    const gl::State &glState                = context->getState();
    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
    const GLsizei instanceCount             = GetDrawAdjustedInstanceCount(executable);
    const void *drawIndexPtr                = nullptr;

    validateState(StateTypes{StateType::GlobalState});

    ANGLE_TRY(setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPtr));
    if (!executable->usesMultiview())
    {
        ANGLE_GL_TRY(context, getFunctions()->drawElementsBaseVertex(
                                  ToGLenum(mode), count, ToGLenum(type), drawIndexPtr, baseVertex));
    }
    else
    {
        ANGLE_GL_TRY(context, getFunctions()->drawElementsInstancedBaseVertex(
                                  ToGLenum(mode), count, ToGLenum(type), drawIndexPtr,
                                  instanceCount, baseVertex));
    }
    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawElementsInstanced(const gl::Context *context,
                                               gl::PrimitiveMode mode,
                                               GLsizei count,
                                               gl::DrawElementsType type,
                                               const void *indices,
                                               GLsizei instances)
{
    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
    const GLsizei adjustedInstanceCount =
        GetInstancedDrawAdjustedInstanceCount(executable, instances);
    const void *drawIndexPointer = nullptr;

    ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
                                   &drawIndexPointer));
    ANGLE_GL_TRY(context,
                 getFunctions()->drawElementsInstanced(ToGLenum(mode), count, ToGLenum(type),
                                                       drawIndexPointer, adjustedInstanceCount));
    return angle::Result::Continue;
}

angle::Result ContextGL::drawElementsInstancedBaseVertex(const gl::Context *context,
                                                         gl::PrimitiveMode mode,
                                                         GLsizei count,
                                                         gl::DrawElementsType type,
                                                         const void *indices,
                                                         GLsizei instances,
                                                         GLint baseVertex)
{
    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
    const GLsizei adjustedInstanceCount =
        GetInstancedDrawAdjustedInstanceCount(executable, instances);
    const void *drawIndexPointer = nullptr;

    ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
                                   &drawIndexPointer));
    ANGLE_GL_TRY(context, getFunctions()->drawElementsInstancedBaseVertex(
                              ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
                              adjustedInstanceCount, baseVertex));
    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
                                                                     gl::PrimitiveMode mode,
                                                                     GLsizei count,
                                                                     gl::DrawElementsType type,
                                                                     const void *indices,
                                                                     GLsizei instances,
                                                                     GLint baseVertex,
                                                                     GLuint baseInstance)
{
    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
    const GLsizei adjustedInstanceCount =
        GetInstancedDrawAdjustedInstanceCount(executable, instances);
    const void *drawIndexPointer = nullptr;

    ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
                                   &drawIndexPointer));

    const FunctionsGL *functions = getFunctions();

    if (functions->drawElementsInstancedBaseVertexBaseInstance)
    {
        // GL 4.2+ or GL_EXT_base_instance
        ANGLE_GL_TRY(context, functions->drawElementsInstancedBaseVertexBaseInstance(
                                  ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
                                  adjustedInstanceCount, baseVertex, baseInstance));
    }
    else
    {
        // GL 3.3+ or GLES 3.2+
        // TODO(http://anglebug.com/42262554): same as above
        gl::AttributesMask attribToResetMask = updateAttributesForBaseInstance(baseInstance);

        ANGLE_GL_TRY(context, functions->drawElementsInstancedBaseVertex(
                                  ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
                                  adjustedInstanceCount, baseVertex));

        resetUpdatedAttributes(attribToResetMask);
    }

    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawRangeElements(const gl::Context *context,
                                           gl::PrimitiveMode mode,
                                           GLuint start,
                                           GLuint end,
                                           GLsizei count,
                                           gl::DrawElementsType type,
                                           const void *indices)
{
    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
    const GLsizei instanceCount             = GetDrawAdjustedInstanceCount(executable);
    const void *drawIndexPointer            = nullptr;

    ANGLE_TRY(
        setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPointer));
    if (!executable->usesMultiview())
    {
        ANGLE_GL_TRY(context, getFunctions()->drawRangeElements(ToGLenum(mode), start, end, count,
                                                                ToGLenum(type), drawIndexPointer));
    }
    else
    {
        ANGLE_GL_TRY(context,
                     getFunctions()->drawElementsInstanced(ToGLenum(mode), count, ToGLenum(type),
                                                           drawIndexPointer, instanceCount));
    }
    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawRangeElementsBaseVertex(const gl::Context *context,
                                                     gl::PrimitiveMode mode,
                                                     GLuint start,
                                                     GLuint end,
                                                     GLsizei count,
                                                     gl::DrawElementsType type,
                                                     const void *indices,
                                                     GLint baseVertex)
{
    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
    const GLsizei instanceCount             = GetDrawAdjustedInstanceCount(executable);
    const void *drawIndexPointer            = nullptr;

    ANGLE_TRY(
        setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPointer));
    if (!executable->usesMultiview())
    {
        ANGLE_GL_TRY(context, getFunctions()->drawRangeElementsBaseVertex(
                                  ToGLenum(mode), start, end, count, ToGLenum(type),
                                  drawIndexPointer, baseVertex));
    }
    else
    {
        ANGLE_GL_TRY(context, getFunctions()->drawElementsInstancedBaseVertex(
                                  ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
                                  instanceCount, baseVertex));
    }
    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawArraysIndirect(const gl::Context *context,
                                            gl::PrimitiveMode mode,
                                            const void *indirect)
{
    ANGLE_GL_TRY(context, getFunctions()->drawArraysIndirect(ToGLenum(mode), indirect));
    mRenderer->markWorkSubmitted();

    return angle::Result::Continue;
}

angle::Result ContextGL::drawElementsIndirect(const gl::Context *context,
                                              gl::PrimitiveMode mode,
                                              gl::DrawElementsType type,
                                              const void *indirect)
{
    ANGLE_GL_TRY(context,
                 getFunctions()->drawElementsIndirect(ToGLenum(mode), ToGLenum(type), indirect));
    return angle::Result::Continue;
}

angle::Result ContextGL::multiDrawArrays(const gl::Context *context,
                                         gl::PrimitiveMode mode,
                                         const GLint *firsts,
                                         const GLsizei *counts,
                                         GLsizei drawcount)
{
    mRenderer->markWorkSubmitted();

    return rx::MultiDrawArraysGeneral(this, context, mode, firsts, counts, drawcount);
}

angle::Result ContextGL::multiDrawArraysInstanced(const gl::Context *context,
                                                  gl::PrimitiveMode mode,
                                                  const GLint *firsts,
                                                  const GLsizei *counts,
                                                  const GLsizei *instanceCounts,
                                                  GLsizei drawcount)
{
    mRenderer->markWorkSubmitted();

    return rx::MultiDrawArraysInstancedGeneral(this, context, mode, firsts, counts, instanceCounts,
                                               drawcount);
}

angle::Result ContextGL::multiDrawArraysIndirect(const gl::Context *context,
                                                 gl::PrimitiveMode mode,
                                                 const void *indirect,
                                                 GLsizei drawcount,
                                                 GLsizei stride)
{
    mRenderer->markWorkSubmitted();

    return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride);
}

angle::Result ContextGL::multiDrawElements(const gl::Context *context,
                                           gl::PrimitiveMode mode,
                                           const GLsizei *counts,
                                           gl::DrawElementsType type,
                                           const GLvoid *const *indices,
                                           GLsizei drawcount)
{
    mRenderer->markWorkSubmitted();

    return rx::MultiDrawElementsGeneral(this, context, mode, counts, type, indices, drawcount);
}

angle::Result ContextGL::multiDrawElementsInstanced(const gl::Context *context,
                                                    gl::PrimitiveMode mode,
                                                    const GLsizei *counts,
                                                    gl::DrawElementsType type,
                                                    const GLvoid *const *indices,
                                                    const GLsizei *instanceCounts,
                                                    GLsizei drawcount)
{
    mRenderer->markWorkSubmitted();

    return rx::MultiDrawElementsInstancedGeneral(this, context, mode, counts, type, indices,
                                                 instanceCounts, drawcount);
}

angle::Result ContextGL::multiDrawElementsIndirect(const gl::Context *context,
                                                   gl::PrimitiveMode mode,
                                                   gl::DrawElementsType type,
                                                   const void *indirect,
                                                   GLsizei drawcount,
                                                   GLsizei stride)
{
    mRenderer->markWorkSubmitted();

    return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount,
                                                stride);
}

angle::Result ContextGL::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
                                                              gl::PrimitiveMode mode,
                                                              const GLint *firsts,
                                                              const GLsizei *counts,
                                                              const GLsizei *instanceCounts,
                                                              const GLuint *baseInstances,
                                                              GLsizei drawcount)
{
    mRenderer->markWorkSubmitted();

    return rx::MultiDrawArraysInstancedBaseInstanceGeneral(
        this, context, mode, firsts, counts, instanceCounts, baseInstances, drawcount);
}

angle::Result ContextGL::multiDrawElementsInstancedBaseVertexBaseInstance(
    const gl::Context *context,
    gl::PrimitiveMode mode,
    const GLsizei *counts,
    gl::DrawElementsType type,
    const GLvoid *const *indices,
    const GLsizei *instanceCounts,
    const GLint *baseVertices,
    const GLuint *baseInstances,
    GLsizei drawcount)
{
    mRenderer->markWorkSubmitted();

    return rx::MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(
        this, context, mode, counts, type, indices, instanceCounts, baseVertices, baseInstances,
        drawcount);
}

gl::GraphicsResetStatus ContextGL::getResetStatus()
{
    gl::GraphicsResetStatus resetStatus = mRenderer->getResetStatus();
    if (resetStatus == gl::GraphicsResetStatus::PurgedContextResetNV)
    {
        if (mRobustnessVideoMemoryPurgeStatus == RobustnessVideoMemoryPurgeStatus::NOT_REQUESTED)
        {
            resetStatus = gl::GraphicsResetStatus::UnknownContextReset;
        }
    }
    return resetStatus;
}

angle::Result ContextGL::insertEventMarker(GLsizei length, const char *marker)
{
    mRenderer->insertEventMarker(length, marker);
    return angle::Result::Continue;
}

angle::Result ContextGL::pushGroupMarker(GLsizei length, const char *marker)
{
    mRenderer->pushGroupMarker(length, marker);
    return angle::Result::Continue;
}

angle::Result ContextGL::popGroupMarker()
{
    mRenderer->popGroupMarker();
    return angle::Result::Continue;
}

angle::Result ContextGL::pushDebugGroup(const gl::Context *context,
                                        GLenum source,
                                        GLuint id,
                                        const std::string &message)
{
    mRenderer->pushDebugGroup(source, id, message);
    return angle::Result::Continue;
}

angle::Result ContextGL::popDebugGroup(const gl::Context *context)
{
    mRenderer->popDebugGroup();
    return angle::Result::Continue;
}

angle::Result ContextGL::syncState(const gl::Context *context,
                                   const gl::state::DirtyBits dirtyBits,
                                   const gl::state::DirtyBits bitMask,
                                   const gl::state::ExtendedDirtyBits extendedDirtyBits,
                                   const gl::state::ExtendedDirtyBits extendedBitMask,
                                   gl::Command command)
{
    return mRenderer->getStateManager()->syncState(context, dirtyBits, bitMask, extendedDirtyBits,
                                                   extendedBitMask);
}

GLint ContextGL::getGPUDisjoint()
{
    return mRenderer->getGPUDisjoint();
}

GLint64 ContextGL::getTimestamp()
{
    return mRenderer->getTimestamp();
}

angle::Result ContextGL::onMakeCurrent(const gl::Context *context)
{
    // Queries need to be paused/resumed on context switches
    return mRenderer->getStateManager()->onMakeCurrent(context);
}

angle::Result ContextGL::onUnMakeCurrent(const gl::Context *context)
{
    ANGLE_TRY(flush(context));
    if (getFeaturesGL().unbindFBOBeforeSwitchingContext.enabled)
    {
        mRenderer->getStateManager()->bindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    tickGC();
    return ContextImpl::onUnMakeCurrent(context);
}

gl::Caps ContextGL::getNativeCaps() const
{
    return mRenderer->getNativeCaps();
}

const gl::TextureCapsMap &ContextGL::getNativeTextureCaps() const
{
    return mRenderer->getNativeTextureCaps();
}

const gl::Extensions &ContextGL::getNativeExtensions() const
{
    return mRenderer->getNativeExtensions();
}

const gl::Limitations &ContextGL::getNativeLimitations() const
{
    return mRenderer->getNativeLimitations();
}

const ShPixelLocalStorageOptions &ContextGL::getNativePixelLocalStorageOptions() const
{
    return mRenderer->getNativePixelLocalStorageOptions();
}

StateManagerGL *ContextGL::getStateManager()
{
    return mRenderer->getStateManager();
}

const angle::FeaturesGL &ContextGL::getFeaturesGL() const
{
    return mRenderer->getFeatures();
}

BlitGL *ContextGL::getBlitter() const
{
    return mRenderer->getBlitter();
}

ClearMultiviewGL *ContextGL::getMultiviewClearer() const
{
    return mRenderer->getMultiviewClearer();
}

angle::Result ContextGL::dispatchCompute(const gl::Context *context,
                                         GLuint numGroupsX,
                                         GLuint numGroupsY,
                                         GLuint numGroupsZ)
{
    return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
}

angle::Result ContextGL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
    return mRenderer->dispatchComputeIndirect(context, indirect);
}

angle::Result ContextGL::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{
    return mRenderer->memoryBarrier(barriers);
}
angle::Result ContextGL::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
{
    return mRenderer->memoryBarrierByRegion(barriers);
}

void ContextGL::framebufferFetchBarrier()
{
    mRenderer->framebufferFetchBarrier();
}

angle::Result ContextGL::startTiling(const gl::Context *context,
                                     const gl::Rectangle &area,
                                     GLbitfield preserveMask)
{
    const FunctionsGL *functions = getFunctions();
    ANGLE_GL_TRY(context,
                 functions->startTilingQCOM(area.x, area.y, area.width, area.height, preserveMask));
    return angle::Result::Continue;
}

angle::Result ContextGL::endTiling(const gl::Context *context, GLbitfield preserveMask)
{
    const FunctionsGL *functions = getFunctions();
    ANGLE_GL_TRY(context, functions->endTilingQCOM(preserveMask));
    return angle::Result::Continue;
}

void ContextGL::setMaxShaderCompilerThreads(GLuint count)
{
    mRenderer->setMaxShaderCompilerThreads(count);
}

void ContextGL::validateState(StateTypes statesToValidate)
{
    if (getFeaturesGL().validateState.enabled)
    {
        if (statesToValidate[StateType::GlobalState])
        {
            StateManagerGL *stateManager = mRenderer->getStateManager();
            stateManager->validateState();
        }

        if (statesToValidate[StateType::VAOState])
        {
            VertexArrayGL *vao = GetImplAs<VertexArrayGL>(mState.getVertexArray());
            vao->validateState(getFunctions());
        }
    }
}

void ContextGL::setNeedsFlushBeforeDeleteTextures()
{
    mRenderer->setNeedsFlushBeforeDeleteTextures();
}

void ContextGL::flushIfNecessaryBeforeDeleteTextures()
{
    mRenderer->flushIfNecessaryBeforeDeleteTextures();
}

void ContextGL::markWorkSubmitted()
{
    mRenderer->markWorkSubmitted();
}

bool ContextGL::hasNativeParallelCompile()
{
    return mRenderer->hasNativeParallelCompile();
}

angle::Result ContextGL::getDepthInitPBO(const gl::Context *context,
                                         size_t requestedSize,
                                         GLenum type,
                                         GLuint *pboIdOut)
{
    const FunctionsGL *functions = mRenderer->getFunctions();
    StateManagerGL *stateManager = mRenderer->getStateManager();

    auto iter = mDepthInitPBOs.Get(type);
    if (iter == mDepthInitPBOs.end())
    {
        iter = mDepthInitPBOs.Put(type, PixelBufferGL(functions));
    }

    PixelBufferGL &pbo = iter->second;

    // We only reset the counter if the requested size is equal to or larger than the cached PBO's
    // size. If the app keeps asking for smaller buffers, do not reset the counter. This allows the
    // oversized PBO to be garbage-collected gradually and eventually re-allocated at the correct
    // smaller size.
    if (requestedSize >= pbo.size)
    {
        pbo.lifetimeCounter = 100;
    }

    if (requestedSize > pbo.size)
    {
        stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, pbo.bufferID);

        functions->bufferData(GL_PIXEL_UNPACK_BUFFER, requestedSize, nullptr, GL_STATIC_DRAW);
        GLubyte *mapPointer = static_cast<GLubyte *>(
            functions->mapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, requestedSize,
                                      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
        if (mapPointer)
        {
            ANGLE_UNSAFE_TODO(FillDepthOneMemory(type, {mapPointer, requestedSize}));
            functions->unmapBuffer(GL_PIXEL_UNPACK_BUFFER);
        }
        pbo.size = requestedSize;
    }

    *pboIdOut = pbo.bufferID;
    return angle::Result::Continue;
}

void ContextGL::tickGC()
{
    for (auto iter = mDepthInitPBOs.begin(); iter != mDepthInitPBOs.end();)
    {
        PixelBufferGL &pbo = iter->second;
        if (pbo.lifetimeCounter > 0)
        {
            --pbo.lifetimeCounter;
            if (pbo.lifetimeCounter == 0)
            {
                iter = mDepthInitPBOs.Erase(iter);
                continue;
            }
        }
        ++iter;
    }
}

}  // namespace rx
