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

// VertexArrayGL.cpp: Implements the class methods for VertexArrayGL.

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

#include "common/bitset_utils.h"
#include "common/debug.h"
#include "common/mathutil.h"
#include "common/utilities.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Context.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"
#include "libANGLE/renderer/renderer_utils.h"

using namespace gl;

namespace rx
{
namespace
{

GLuint GetNativeBufferID(const gl::Buffer *frontendBuffer)
{
    return frontendBuffer ? GetImplAs<BufferGL>(frontendBuffer)->getBufferID() : 0;
}

bool SameVertexAttribFormat(const VertexAttributeGL &a, const VertexAttribute &b)
{
    return a.format == b.format && a.relativeOffset == b.relativeOffset;
}

bool SameVertexBuffer(const VertexBindingGL &a, const VertexBinding &b, const gl::Buffer *buffer)
{
    return a.stride == b.getStride() && a.offset == static_cast<GLintptr>(b.getOffset()) &&
           a.buffer == GetNativeBufferID(buffer);
}

bool SameIndexBuffer(const VertexArrayStateGL *a, const gl::Buffer *frontendBuffer)
{
    return a->elementArrayBuffer == GetNativeBufferID(frontendBuffer);
}

bool SameAttribPointer(const VertexAttributeGL &a, const VertexAttribute &b)
{
    return a.pointer == b.pointer;
}

bool IsVertexAttribPointerSupported(size_t attribIndex, const VertexAttribute &attrib)
{
    return (attribIndex == attrib.bindingIndex && attrib.relativeOffset == 0);
}

}  // anonymous namespace

VertexArrayGL::VertexArrayGL(const gl::VertexArrayState &state,
                             GLuint id,
                             bool ownsId,
                             const gl::VertexArrayBuffers &vertexArrayBuffers,
                             VertexArrayStateGL *nativeState)
    : VertexArrayImpl(state, vertexArrayBuffers),
      mVertexArrayID(id),
      mOwnsID(ownsId),
      mNativeState(nativeState)
{
    ASSERT(mNativeState);
    mForcedStreamingAttributesFirstOffsets.fill(0);
}

VertexArrayGL::~VertexArrayGL() {}

void VertexArrayGL::destroy(const gl::Context *context)
{
    StateManagerGL *stateManager = GetStateManagerGL(context);

    if (mOwnsID)
    {
        stateManager->deleteVertexArray(mVertexArrayID);
    }
    mVertexArrayID   = 0;
    mNativeState     = nullptr;
    mAppliedNumViews = 1;

    mElementArrayBuffer.set(context, nullptr);
    for (gl::BindingPointer<gl::Buffer> &binding : mArrayBuffers)
    {
        binding.set(context, nullptr);
    }

    stateManager->deleteBuffer(mStreamingElementArrayBuffer);
    mStreamingElementArrayBufferSize = 0;
    mStreamingElementArrayBuffer     = 0;

    stateManager->deleteBuffer(mStreamingArrayBuffer);
    mStreamingArrayBufferSize = 0;
    mStreamingArrayBuffer     = 0;
}

angle::Result VertexArrayGL::syncClientSideData(const gl::Context *context,
                                                const gl::AttributesMask &activeAttributesMask,
                                                GLint first,
                                                GLsizei count,
                                                GLsizei instanceCount) const
{
    return syncDrawState(context, activeAttributesMask, first, count,
                         gl::DrawElementsType::InvalidEnum, nullptr, instanceCount, false, nullptr);
}

angle::Result VertexArrayGL::updateElementArrayBufferBinding(const gl::Context *context) const
{
    gl::Buffer *elementArrayBuffer = getElementArrayBuffer();
    if (!SameIndexBuffer(mNativeState, elementArrayBuffer))
    {
        GLuint elementArrayBufferId =
            elementArrayBuffer ? GetNativeBufferID(elementArrayBuffer) : 0;

        StateManagerGL *stateManager = GetStateManagerGL(context);
        stateManager->bindBuffer(gl::BufferBinding::ElementArray, elementArrayBufferId);
        mElementArrayBuffer.set(context, elementArrayBuffer);
        ASSERT(mNativeState->elementArrayBuffer == elementArrayBufferId);
    }

    return angle::Result::Continue;
}

angle::Result VertexArrayGL::syncDrawState(const gl::Context *context,
                                           const gl::AttributesMask &activeAttributesMask,
                                           GLint first,
                                           GLsizei count,
                                           gl::DrawElementsType type,
                                           const void *indices,
                                           GLsizei instanceCount,
                                           bool primitiveRestartEnabled,
                                           const void **outIndices) const
{
    const FunctionsGL *functions = GetFunctionsGL(context);

    // Check if any attributes need to be streamed, determines if the index range needs to be
    // computed
    gl::AttributesMask needsStreamingAttribs = context->getActiveClientAttribsMask();
    if (nativegl::CanUseClientSideArrays(functions, mVertexArrayID))
    {
        needsStreamingAttribs.reset();
    }

    // Determine if an index buffer needs to be streamed and the range of vertices that need to be
    // copied
    IndexRange indexRange;
    const angle::FeaturesGL &features = GetFeaturesGL(context);
    if (type != gl::DrawElementsType::InvalidEnum)
    {
        ANGLE_TRY(syncIndexData(context, count, type, indices, primitiveRestartEnabled,
                                needsStreamingAttribs.any(), &indexRange, outIndices));
    }
    else
    {
        // Not an indexed call, set the range to [first, first + count - 1]
        indexRange = IndexRange(first, first + count - 1);

        if (features.shiftInstancedArrayDataWithOffset.enabled && first > 0)
        {
            gl::AttributesMask updatedStreamingAttribsMask = needsStreamingAttribs;
            auto candidateAttributesMask =
                mInstancedAttributesMask & mProgramActiveAttribLocationsMask;
            for (auto attribIndex : candidateAttributesMask)
            {

                if (mForcedStreamingAttributesFirstOffsets[attribIndex] != first)
                {
                    updatedStreamingAttribsMask.set(attribIndex);
                    mForcedStreamingAttributesForDrawArraysInstancedMask.set(attribIndex);
                    mForcedStreamingAttributesFirstOffsets[attribIndex] = first;
                }
            }

            // We need to recover attributes whose divisor used to be > 0 but is reset to 0 now if
            // any
            auto forcedStreamingAttributesNeedRecoverMask =
                candidateAttributesMask ^ mForcedStreamingAttributesForDrawArraysInstancedMask;
            if (forcedStreamingAttributesNeedRecoverMask.any())
            {
                ANGLE_TRY(recoverForcedStreamingAttributesForDrawArraysInstanced(
                    context, &forcedStreamingAttributesNeedRecoverMask));
                mForcedStreamingAttributesForDrawArraysInstancedMask = candidateAttributesMask;
            }

            if (updatedStreamingAttribsMask.any())
            {
                ANGLE_TRY(streamAttributes(context, updatedStreamingAttribsMask, instanceCount,
                                           indexRange, true));
            }
            return angle::Result::Continue;
        }
    }

    if (needsStreamingAttribs.any())
    {
        ANGLE_TRY(
            streamAttributes(context, needsStreamingAttribs, instanceCount, indexRange, false));
    }

    return angle::Result::Continue;
}

angle::Result VertexArrayGL::syncIndexData(const gl::Context *context,
                                           GLsizei count,
                                           gl::DrawElementsType type,
                                           const void *indices,
                                           bool primitiveRestartEnabled,
                                           bool attributesNeedStreaming,
                                           IndexRange *outIndexRange,
                                           const void **outIndices) const
{
    ASSERT(outIndices);

    const FunctionsGL *functions = GetFunctionsGL(context);

    gl::Buffer *elementArrayBuffer = getElementArrayBuffer();

    // Need to check the range of indices if attributes need to be streamed
    if (elementArrayBuffer)
    {
        ASSERT(SameIndexBuffer(mNativeState, elementArrayBuffer));
        // Only compute the index range if the attributes also need to be streamed
        if (attributesNeedStreaming)
        {
            ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
            ANGLE_TRY(getElementArrayBuffer()->getIndexRange(
                context, type, elementArrayBufferOffset, count, primitiveRestartEnabled,
                outIndexRange));
        }

        // Indices serves as an offset into the index buffer in this case, use the same value for
        // the draw call
        *outIndices = indices;
    }
    else if (nativegl::CanUseClientSideArrays(functions, mVertexArrayID))
    {
        ASSERT(SameIndexBuffer(mNativeState, nullptr));

        // Use the client index data directly
        *outIndices = indices;
    }
    else
    {
        StateManagerGL *stateManager = GetStateManagerGL(context);

        // Need to stream the index buffer

        // Only compute the index range if the attributes also need to be streamed
        if (attributesNeedStreaming)
        {
            *outIndexRange = ComputeIndexRange(type, indices, count, primitiveRestartEnabled);
        }

        // Allocate the streaming element array buffer
        if (mStreamingElementArrayBuffer == 0)
        {
            ANGLE_GL_TRY(context, functions->genBuffers(1, &mStreamingElementArrayBuffer));
            mStreamingElementArrayBufferSize = 0;
        }

        stateManager->bindVertexArray(mVertexArrayID);

        stateManager->bindBuffer(gl::BufferBinding::ElementArray, mStreamingElementArrayBuffer);
        mElementArrayBuffer.set(context, nullptr);
        ASSERT(mNativeState->elementArrayBuffer == mStreamingElementArrayBuffer);

        // Make sure the element array buffer is large enough
        const GLuint indexTypeBytes        = gl::GetDrawElementsTypeSize(type);
        size_t requiredStreamingBufferSize = indexTypeBytes * count;
        if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
        {
            // Copy the indices in while resizing the buffer
            ANGLE_GL_TRY_ALWAYS_CHECK(
                context, functions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize,
                                               indices, GL_DYNAMIC_DRAW));
            mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
        }
        else
        {
            // Put the indices at the beginning of the buffer
            ANGLE_GL_TRY(context, functions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0,
                                                           requiredStreamingBufferSize, indices));
        }

        // Set the index offset for the draw call to zero since the supplied index pointer is to
        // client data
        *outIndices = nullptr;
    }

    return angle::Result::Continue;
}

void VertexArrayGL::computeStreamingAttributeSizes(
    const gl::AttributesMask &attribsToStream,
    GLsizei instanceCount,
    const gl::IndexRange &indexRange,
    size_t *outStreamingDataSize,
    size_t *outMaxAttributeDataSize,
    bool applyExtraOffsetWorkaroundForInstancedAttributes) const
{
    *outStreamingDataSize    = 0;
    *outMaxAttributeDataSize = 0;

    ASSERT(attribsToStream.any());

    const auto &attribs  = mState.getVertexAttributes();
    const auto &bindings = mState.getVertexBindings();

    for (auto idx : attribsToStream)
    {
        const auto &attrib  = attribs[idx];
        const auto &binding = bindings[attrib.bindingIndex];

        // If streaming is going to be required, compute the size of the required buffer
        // and how much slack space at the beginning of the buffer will be required by determining
        // the attribute with the largest data size.
        size_t typeSize        = ComputeVertexAttributeTypeSize(attrib);
        GLuint adjustedDivisor =
            GetMultiviewAdjustedDivisor(mAppliedNumViews, binding.getDivisor());
        size_t streamedVertexCount = ComputeVertexBindingElementCount(
            adjustedDivisor, indexRange.vertexCount(), std::max(instanceCount, 1), 0);
        if (applyExtraOffsetWorkaroundForInstancedAttributes && adjustedDivisor > 0)
        {
            streamedVertexCount =
                (instanceCount + indexRange.start() + adjustedDivisor - 1u) / adjustedDivisor;
        }
        *outStreamingDataSize += typeSize * streamedVertexCount;
        *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
    }
}

angle::Result VertexArrayGL::streamAttributes(
    const gl::Context *context,
    const gl::AttributesMask &attribsToStream,
    GLsizei instanceCount,
    const gl::IndexRange &indexRange,
    bool applyExtraOffsetWorkaroundForInstancedAttributes) const
{
    const FunctionsGL *functions = GetFunctionsGL(context);
    StateManagerGL *stateManager = GetStateManagerGL(context);

    // Sync the vertex attribute state and track what data needs to be streamed
    size_t streamingDataSize    = 0;
    size_t maxAttributeDataSize = 0;

    computeStreamingAttributeSizes(attribsToStream, instanceCount, indexRange, &streamingDataSize,
                                   &maxAttributeDataSize,
                                   applyExtraOffsetWorkaroundForInstancedAttributes);

    if (streamingDataSize == 0)
    {
        return angle::Result::Continue;
    }

    if (mStreamingArrayBuffer == 0)
    {
        ANGLE_GL_TRY(context, functions->genBuffers(1, &mStreamingArrayBuffer));
        mStreamingArrayBufferSize = 0;
    }

    // If first is greater than zero, a slack space needs to be left at the beginning of the buffer
    // for each attribute so that the same 'first' argument can be passed into the draw call.
    const size_t bufferEmptySpace =
        attribsToStream.count() * maxAttributeDataSize * indexRange.start();
    const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;

    stateManager->bindBuffer(gl::BufferBinding::Array, mStreamingArrayBuffer);
    if (requiredBufferSize > mStreamingArrayBufferSize)
    {
        ANGLE_GL_TRY_ALWAYS_CHECK(
            context,
            functions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW));
        mStreamingArrayBufferSize = requiredBufferSize;
    }

    stateManager->bindVertexArray(mVertexArrayID);

    // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
    // somehow (such as by a screen change), retry writing the data a few times and return
    // OUT_OF_MEMORY if that fails.
    GLboolean unmapResult     = GL_FALSE;
    size_t unmapRetryAttempts = 5;
    while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
    {
        uint8_t *bufferPointer = MapBufferRangeWithFallback(functions, GL_ARRAY_BUFFER, 0,
                                                            requiredBufferSize, GL_MAP_WRITE_BIT);
        size_t curBufferOffset = maxAttributeDataSize * indexRange.start();

        const auto &attribs  = mState.getVertexAttributes();
        const auto &bindings = mState.getVertexBindings();

        for (auto idx : attribsToStream)
        {
            const auto &attrib = attribs[idx];
            ASSERT(IsVertexAttribPointerSupported(idx, attrib));

            const auto &binding = bindings[attrib.bindingIndex];

            GLuint adjustedDivisor =
                GetMultiviewAdjustedDivisor(mAppliedNumViews, binding.getDivisor());
            // streamedVertexCount is only going to be modified by
            // shiftInstancedArrayDataWithOffset workaround, otherwise it's const
            size_t streamedVertexCount = ComputeVertexBindingElementCount(
                adjustedDivisor, indexRange.vertexCount(), std::max(instanceCount, 1), 0);
            const size_t originalStreamedVertexCount = streamedVertexCount;

            const size_t sourceStride = ComputeVertexAttributeStride(attrib, binding);
            const size_t destStride   = ComputeVertexAttributeTypeSize(attrib);

            // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
            // a non-instanced draw call
            const size_t firstIndex =
                (adjustedDivisor == 0 || applyExtraOffsetWorkaroundForInstancedAttributes)
                    ? indexRange.start()
                    : 0;

            // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state.
            // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt
            const uint8_t *inputPointer = static_cast<const uint8_t *>(attrib.pointer);
            // store batchMemcpySize since streamedVertexCount could be changed by workaround
            const size_t batchMemcpySize = destStride * streamedVertexCount;

            size_t batchMemcpyInputOffset                    = sourceStride * firstIndex;
            bool needsUnmapAndRebindStreamingAttributeBuffer = false;
            size_t firstIndexForSeparateCopy                 = firstIndex;

            if (applyExtraOffsetWorkaroundForInstancedAttributes && adjustedDivisor > 0)
            {
                streamedVertexCount =
                    (instanceCount + indexRange.start() + adjustedDivisor - 1u) / adjustedDivisor;

                const size_t copySize =
                    sourceStride *
                    originalStreamedVertexCount;  // the real data in the buffer we are streaming

                const gl::Buffer *bindingBufferPointer = getVertexArrayBuffer(attrib.bindingIndex);
                if (!bindingBufferPointer)
                {
                    if (!inputPointer)
                    {
                        continue;
                    }
                    inputPointer = static_cast<const uint8_t *>(attrib.pointer);
                }
                else
                {
                    needsUnmapAndRebindStreamingAttributeBuffer = true;
                    const auto buffer = GetImplAs<BufferGL>(bindingBufferPointer);
                    stateManager->bindBuffer(gl::BufferBinding::Array, buffer->getBufferID());
                    // The workaround is only for latest Mac Intel so glMapBufferRange should be
                    // supported
                    ASSERT(CanMapBufferForRead(functions));
                    // Validate if there is OOB access of the input buffer.
                    angle::CheckedNumeric<GLint64> inputRequiredSize;
                    inputRequiredSize = copySize;
                    inputRequiredSize += binding.getOffset();
                    ANGLE_CHECK(GetImplAs<ContextGL>(context),
                                inputRequiredSize.IsValid() && inputRequiredSize.ValueOrDie() <=
                                                                   bindingBufferPointer->getSize(),
                                "Failed to map buffer range of the attribute buffer.",
                                GL_OUT_OF_MEMORY);
                    uint8_t *inputBufferPointer = MapBufferRangeWithFallback(
                        functions, GL_ARRAY_BUFFER, binding.getOffset(), copySize, GL_MAP_READ_BIT);
                    ASSERT(inputBufferPointer);
                    inputPointer = inputBufferPointer;
                }

                batchMemcpyInputOffset    = 0;
                firstIndexForSeparateCopy = 0;
            }

            // Pack the data when copying it, user could have supplied a very large stride that
            // would cause the buffer to be much larger than needed.
            if (destStride == sourceStride)
            {
                // Can copy in one go, the data is packed
                ANGLE_UNSAFE_TODO(memcpy(bufferPointer + curBufferOffset,
                                         inputPointer + batchMemcpyInputOffset, batchMemcpySize));
            }
            else
            {
                for (size_t vertexIdx = 0; vertexIdx < originalStreamedVertexCount; vertexIdx++)
                {
                    uint8_t *out      = ANGLE_UNSAFE_TODO(bufferPointer + curBufferOffset +
                                                          (destStride * vertexIdx));
                    const uint8_t *in = ANGLE_UNSAFE_TODO(
                        inputPointer + sourceStride * (vertexIdx + firstIndexForSeparateCopy));
                    ANGLE_UNSAFE_TODO(memcpy(out, in, destStride));
                }
            }

            if (needsUnmapAndRebindStreamingAttributeBuffer)
            {
                ANGLE_GL_TRY(context, functions->unmapBuffer(GL_ARRAY_BUFFER));
                stateManager->bindBuffer(gl::BufferBinding::Array, mStreamingArrayBuffer);
            }

            // Compute where the 0-index vertex would be.
            const size_t vertexStartOffset = curBufferOffset - (firstIndex * destStride);

            ANGLE_TRY(callVertexAttribPointer(context, static_cast<GLuint>(idx), attrib,
                                              static_cast<GLsizei>(destStride),
                                              static_cast<uintptr_t>(vertexStartOffset)));

            // Update the state to track the streamed attribute
            mNativeState->attributes[idx].format = attrib.format;

            mNativeState->attributes[idx].relativeOffset = 0;
            mNativeState->attributes[idx].bindingIndex   = static_cast<GLuint>(idx);

            mNativeState->bindings[idx].stride = static_cast<GLsizei>(destStride);
            mNativeState->bindings[idx].offset = static_cast<uintptr_t>(vertexStartOffset);
            mArrayBuffers[idx].set(context, nullptr);
            mNativeState->bindings[idx].buffer = mStreamingArrayBuffer;

            // There's maxAttributeDataSize * indexRange.start() of empty space allocated for each
            // streaming attributes
            curBufferOffset +=
                destStride * streamedVertexCount + maxAttributeDataSize * indexRange.start();
        }

        unmapResult = ANGLE_GL_TRY(context, functions->unmapBuffer(GL_ARRAY_BUFFER));
    }

    ANGLE_CHECK(GetImplAs<ContextGL>(context), unmapResult == GL_TRUE,
                "Failed to unmap the client data streaming buffer.", GL_OUT_OF_MEMORY);
    return angle::Result::Continue;
}

angle::Result VertexArrayGL::recoverForcedStreamingAttributesForDrawArraysInstanced(
    const gl::Context *context) const
{
    return recoverForcedStreamingAttributesForDrawArraysInstanced(
        context, &mForcedStreamingAttributesForDrawArraysInstancedMask);
}

angle::Result VertexArrayGL::recoverForcedStreamingAttributesForDrawArraysInstanced(
    const gl::Context *context,
    gl::AttributesMask *attributeMask) const
{
    if (attributeMask->none())
    {
        return angle::Result::Continue;
    }

    StateManagerGL *stateManager = GetStateManagerGL(context);

    stateManager->bindVertexArray(mVertexArrayID);

    const auto &attribs  = mState.getVertexAttributes();
    const auto &bindings = mState.getVertexBindings();
    for (auto idx : *attributeMask)
    {
        const auto &attrib = attribs[idx];
        ASSERT(IsVertexAttribPointerSupported(idx, attrib));

        const auto &binding = bindings[attrib.bindingIndex];
        gl::Buffer *buffer       = getVertexArrayBuffer(attrib.bindingIndex);
        const BufferGL *bufferGL = GetImplAs<BufferGL>(buffer);
        stateManager->bindBuffer(gl::BufferBinding::Array, bufferGL->getBufferID());

        ANGLE_TRY(callVertexAttribPointer(context, static_cast<GLuint>(idx), attrib,
                                          static_cast<GLsizei>(binding.getStride()),
                                          binding.getOffset()));

        // Restore the state to track their original buffers
        mNativeState->attributes[idx].format = attrib.format;

        mNativeState->attributes[idx].relativeOffset = 0;
        mNativeState->attributes[idx].bindingIndex   = static_cast<GLuint>(attrib.bindingIndex);

        mNativeState->bindings[idx].stride = binding.getStride();
        mNativeState->bindings[idx].offset = binding.getOffset();
        mArrayBuffers[idx].set(context, buffer);
        mNativeState->bindings[idx].buffer = bufferGL->getBufferID();
    }

    attributeMask->reset();
    mForcedStreamingAttributesFirstOffsets.fill(0);

    return angle::Result::Continue;
}

GLuint VertexArrayGL::getVertexArrayID() const
{
    return mVertexArrayID;
}

angle::Result VertexArrayGL::updateAttribEnabled(const gl::Context *context, size_t attribIndex)
{
    const bool enabled = mState.getVertexAttribute(attribIndex).enabled &&
                         mProgramActiveAttribLocationsMask.test(attribIndex);
    if (mNativeState->attributes[attribIndex].enabled == enabled)
    {
        return angle::Result::Continue;
    }

    const FunctionsGL *functions = GetFunctionsGL(context);

    if (enabled)
    {
        ANGLE_GL_TRY(context, functions->enableVertexAttribArray(static_cast<GLuint>(attribIndex)));
    }
    else
    {
        ANGLE_GL_TRY(context,
                     functions->disableVertexAttribArray(static_cast<GLuint>(attribIndex)));
    }

    mNativeState->attributes[attribIndex].enabled = enabled;
    return angle::Result::Continue;
}

angle::Result VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attribIndex)
{
    const angle::FeaturesGL &features = GetFeaturesGL(context);
    const FunctionsGL *functions      = GetFunctionsGL(context);

    const VertexAttribute &attrib = mState.getVertexAttribute(attribIndex);

    // According to SPEC, VertexAttribPointer should update the binding indexed attribIndex instead
    // of the binding indexed attrib.bindingIndex (unless attribIndex == attrib.bindingIndex).
    const VertexBinding &binding = mState.getVertexBinding(attribIndex);

    const bool canUseClientArrays = nativegl::CanUseClientSideArrays(functions, mVertexArrayID);

    // Early return when the vertex attribute isn't using a buffer object:
    // - If we need to stream, defer the attribPointer to the draw call.
    // - Skip the attribute that is disabled and uses a client memory pointer.
    // - Skip the attribute whose buffer is detached by BindVertexBuffer. Since it cannot have a
    //   client memory pointer either, it must be disabled and shouldn't affect the draw.
    gl::Buffer *arrayBuffer = getVertexArrayBuffer(attribIndex);
    if (arrayBuffer == nullptr && !canUseClientArrays)
    {
        // Mark the applied binding isn't using a buffer by setting its buffer to nullptr so that if
        // it starts to use a buffer later, there is no chance that the caching will skip it.

        mArrayBuffers[attribIndex].set(context, nullptr);
        mNativeState->bindings[attribIndex].offset = 0;
        mNativeState->bindings[attribIndex].buffer = 0;
        return angle::Result::Continue;
    }

    // We do not need to compare attrib.pointer because when we use a different client memory
    // pointer, we don't need to update mAttributesNeedStreaming by binding.buffer and we won't
    // update attribPointer in this function.
    if (SameVertexAttribFormat(mNativeState->attributes[attribIndex], attrib) &&
        (mNativeState->attributes[attribIndex].bindingIndex == attrib.bindingIndex) &&
        SameVertexBuffer(mNativeState->bindings[attribIndex], binding, arrayBuffer) &&
        (!canUseClientArrays || SameAttribPointer(mNativeState->attributes[attribIndex], attrib)))
    {
        return angle::Result::Continue;
    }

    StateManagerGL *stateManager = GetStateManagerGL(context);
    GLuint bufferId              = 0;
    if (arrayBuffer != nullptr)
    {
        // When ANGLE uses non-zero VAO, we cannot use a client memory pointer on it:
        // [OpenGL ES 3.0.2] Section 2.8 page 24:
        // An INVALID_OPERATION error is generated when a non-zero vertex array object is bound,
        // zero is bound to the ARRAY_BUFFER buffer object binding point, and the pointer argument
        // is not NULL.

        BufferGL *bufferGL = GetImplAs<BufferGL>(arrayBuffer);
        bufferId           = bufferGL->getBufferID();
        stateManager->bindBuffer(gl::BufferBinding::Array, bufferId);
        if (features.ensureNonEmptyBufferIsBoundForDraw.enabled && bufferGL->getBufferSize() == 0)
        {
            BufferFeedback feedback;
            constexpr uint32_t data = 0;
            ANGLE_TRY(bufferGL->setData(context, gl::BufferBinding::Array, &data, sizeof(data),
                                        gl::BufferUsage::StaticDraw, &feedback,
                                        gl::ZeroFillRequired::No));
            ASSERT(bufferGL->getBufferSize() > 0);
        }
        ANGLE_TRY(callVertexAttribPointer(context, static_cast<GLuint>(attribIndex), attrib,
                                          binding.getStride(), binding.getOffset()));
    }
    else
    {
        ASSERT(canUseClientArrays);
        stateManager->bindBuffer(gl::BufferBinding::Array, 0);
        ANGLE_TRY(callVertexAttribPointer(context, static_cast<GLuint>(attribIndex), attrib,
                                          binding.getStride(),
                                          reinterpret_cast<uintptr_t>(attrib.pointer)));
    }

    mNativeState->attributes[attribIndex].format = attrib.format;

    // After VertexAttribPointer, attrib.relativeOffset is set to 0 and attrib.bindingIndex is set
    // to attribIndex in driver. If attrib.relativeOffset != 0 or attrib.bindingIndex !=
    // attribIndex, they should be set in updateAttribFormat and updateAttribBinding. The cache
    // should be consistent with driver so that we won't miss anything.
    mNativeState->attributes[attribIndex].pointer        = attrib.pointer;
    mNativeState->attributes[attribIndex].relativeOffset = 0;
    mNativeState->attributes[attribIndex].bindingIndex   = static_cast<GLuint>(attribIndex);

    mNativeState->bindings[attribIndex].stride = binding.getStride();
    mNativeState->bindings[attribIndex].offset = binding.getOffset();
    mArrayBuffers[attribIndex].set(context, arrayBuffer);
    mNativeState->bindings[attribIndex].buffer = bufferId;

    return angle::Result::Continue;
}

angle::Result VertexArrayGL::callVertexAttribPointer(const gl::Context *context,
                                                     GLuint attribIndex,
                                                     const VertexAttribute &attrib,
                                                     GLsizei stride,
                                                     uintptr_t offset) const
{
    const FunctionsGL *functions = GetFunctionsGL(context);
    const GLvoid *pointer        = reinterpret_cast<const GLvoid *>(offset);
    const angle::Format &format  = *attrib.format;
    if (format.isPureInt())
    {
        ASSERT(!format.isNorm());
        ANGLE_GL_TRY(context, functions->vertexAttribIPointer(attribIndex, format.channelCount,
                                                              gl::ToGLenum(format.vertexAttribType),
                                                              stride, pointer));
    }
    else
    {
        ANGLE_GL_TRY(context, functions->vertexAttribPointer(attribIndex, format.channelCount,
                                                             gl::ToGLenum(format.vertexAttribType),
                                                             format.isNorm(), stride, pointer));
    }

    return angle::Result::Continue;
}

bool VertexArrayGL::supportVertexAttribBinding(const gl::Context *context) const
{
    const FunctionsGL *functions = GetFunctionsGL(context);
    ASSERT(functions);
    // Vertex attrib bindings are not supported on the default VAO so if we're syncing to the
    // default VAO due to the feature, disable bindings.
    return (functions->vertexAttribBinding != nullptr) && mVertexArrayID != 0;
}

angle::Result VertexArrayGL::updateAttribFormat(const gl::Context *context, size_t attribIndex)
{
    ASSERT(supportVertexAttribBinding(context));

    const VertexAttribute &attrib = mState.getVertexAttribute(attribIndex);
    if (SameVertexAttribFormat(mNativeState->attributes[attribIndex], attrib))
    {
        return angle::Result::Continue;
    }

    const FunctionsGL *functions = GetFunctionsGL(context);

    const angle::Format &format = *attrib.format;
    if (format.isPureInt())
    {
        ASSERT(!format.isNorm());
        ANGLE_GL_TRY(context, functions->vertexAttribIFormat(
                                  static_cast<GLuint>(attribIndex), format.channelCount,
                                  gl::ToGLenum(format.vertexAttribType), attrib.relativeOffset));
    }
    else
    {
        ANGLE_GL_TRY(context, functions->vertexAttribFormat(
                                  static_cast<GLuint>(attribIndex), format.channelCount,
                                  gl::ToGLenum(format.vertexAttribType), format.isNorm(),
                                  attrib.relativeOffset));
    }

    mNativeState->attributes[attribIndex].format         = attrib.format;
    mNativeState->attributes[attribIndex].relativeOffset = attrib.relativeOffset;
    return angle::Result::Continue;
}

angle::Result VertexArrayGL::updateAttribBinding(const gl::Context *context, size_t attribIndex)
{
    ASSERT(supportVertexAttribBinding(context));

    GLuint bindingIndex = mState.getVertexAttribute(attribIndex).bindingIndex;
    if (mNativeState->attributes[attribIndex].bindingIndex == bindingIndex)
    {
        return angle::Result::Continue;
    }

    const FunctionsGL *functions = GetFunctionsGL(context);
    ANGLE_GL_TRY(context,
                 functions->vertexAttribBinding(static_cast<GLuint>(attribIndex), bindingIndex));

    mNativeState->attributes[attribIndex].bindingIndex = bindingIndex;

    return angle::Result::Continue;
}

angle::Result VertexArrayGL::updateBindingBuffer(const gl::Context *context, size_t bindingIndex)
{
    ASSERT(supportVertexAttribBinding(context));

    const VertexBinding &binding = mState.getVertexBinding(bindingIndex);
    gl::Buffer *arrayBuffer      = getVertexArrayBuffer(bindingIndex);
    if (SameVertexBuffer(mNativeState->bindings[bindingIndex], binding, arrayBuffer))
    {
        return angle::Result::Continue;
    }

    GLuint bufferId         = GetNativeBufferID(arrayBuffer);

    const FunctionsGL *functions = GetFunctionsGL(context);
    ANGLE_GL_TRY(context, functions->bindVertexBuffer(static_cast<GLuint>(bindingIndex), bufferId,
                                                      binding.getOffset(), binding.getStride()));

    mNativeState->bindings[bindingIndex].stride = binding.getStride();
    mNativeState->bindings[bindingIndex].offset = binding.getOffset();
    mArrayBuffers[bindingIndex].set(context, arrayBuffer);
    mNativeState->bindings[bindingIndex].buffer = bufferId;

    return angle::Result::Continue;
}

angle::Result VertexArrayGL::updateBindingDivisor(const gl::Context *context, size_t bindingIndex)
{
    GLuint adjustedDivisor = GetMultiviewAdjustedDivisor(
        mAppliedNumViews, mState.getVertexBinding(bindingIndex).getDivisor());
    if (mNativeState->bindings[bindingIndex].divisor == adjustedDivisor)
    {
        return angle::Result::Continue;
    }

    const FunctionsGL *functions = GetFunctionsGL(context);
    if (supportVertexAttribBinding(context))
    {
        ANGLE_GL_TRY(context, functions->vertexBindingDivisor(static_cast<GLuint>(bindingIndex),
                                                              adjustedDivisor));
    }
    else
    {
        // We can only use VertexAttribDivisor on platforms that don't support Vertex Attrib
        // Binding.
        ANGLE_GL_TRY(context, functions->vertexAttribDivisor(static_cast<GLuint>(bindingIndex),
                                                             adjustedDivisor));
    }

    if (adjustedDivisor > 0)
    {
        mInstancedAttributesMask.set(bindingIndex);
    }
    else if (mInstancedAttributesMask.test(bindingIndex))
    {
        // divisor is reset to 0
        mInstancedAttributesMask.reset(bindingIndex);
    }

    mNativeState->bindings[bindingIndex].divisor = adjustedDivisor;

    return angle::Result::Continue;
}

angle::Result VertexArrayGL::syncDirtyAttrib(
    const gl::Context *context,
    size_t attribIndex,
    const gl::VertexArray::DirtyAttribBits &dirtyAttribBits)
{
    ASSERT(dirtyAttribBits.any());

    for (size_t dirtyBit : dirtyAttribBits)
    {
        switch (dirtyBit)
        {
            case VertexArray::DIRTY_ATTRIB_ENABLED:
                ANGLE_TRY(updateAttribEnabled(context, attribIndex));
                break;

            case VertexArray::DIRTY_ATTRIB_POINTER_BUFFER:
            case VertexArray::DIRTY_ATTRIB_POINTER:
                ANGLE_TRY(updateAttribPointer(context, attribIndex));
                break;

            case VertexArray::DIRTY_ATTRIB_FORMAT:
                ASSERT(supportVertexAttribBinding(context));
                ANGLE_TRY(updateAttribFormat(context, attribIndex));
                break;

            case VertexArray::DIRTY_ATTRIB_BINDING:
                ASSERT(supportVertexAttribBinding(context));
                ANGLE_TRY(updateAttribBinding(context, attribIndex));
                break;

            default:
                UNREACHABLE();
                break;
        }
    }
    return angle::Result::Continue;
}

angle::Result VertexArrayGL::syncDirtyBinding(
    const gl::Context *context,
    size_t bindingIndex,
    const gl::VertexArray::DirtyBindingBits &dirtyBindingBits)
{
    // Dependent state changes in buffers can trigger updates with no dirty bits set.

    for (auto iter = dirtyBindingBits.begin(), endIter = dirtyBindingBits.end(); iter != endIter;
         ++iter)
    {
        size_t dirtyBit = *iter;
        switch (dirtyBit)
        {
            case VertexArray::DIRTY_BINDING_BUFFER:
            case VertexArray::DIRTY_BINDING_STRIDE:
            case VertexArray::DIRTY_BINDING_OFFSET:
                ASSERT(supportVertexAttribBinding(context));
                ANGLE_TRY(updateBindingBuffer(context, bindingIndex));
                // Clear these bits to avoid repeated processing
                iter.resetLaterBits(gl::VertexArray::DirtyBindingBits{
                    VertexArray::DIRTY_BINDING_BUFFER, VertexArray::DIRTY_BINDING_STRIDE,
                    VertexArray::DIRTY_BINDING_OFFSET});
                break;

            case VertexArray::DIRTY_BINDING_DIVISOR:
                ANGLE_TRY(updateBindingDivisor(context, bindingIndex));
                break;

            case VertexArray::DIRTY_BINDING_SIZE:
                break;

            default:
                UNREACHABLE();
                break;
        }
    }
    return angle::Result::Continue;
}

#define ANGLE_DIRTY_ATTRIB_FUNC(INDEX)                                    \
    case VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:                         \
        ANGLE_TRY(syncDirtyAttrib(context, INDEX, (*attribBits)[INDEX])); \
        (*attribBits)[INDEX].reset();                                     \
        break;

#define ANGLE_DIRTY_BINDING_FUNC(INDEX)                                     \
    case VertexArray::DIRTY_BIT_BINDING_0 + INDEX:                          \
        ANGLE_TRY(syncDirtyBinding(context, INDEX, (*bindingBits)[INDEX])); \
        (*bindingBits)[INDEX].reset();                                      \
        break;

#define ANGLE_DIRTY_BUFFER_DATA_FUNC(INDEX)            \
    case VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
        break;

angle::Result VertexArrayGL::syncState(const gl::Context *context,
                                       const gl::VertexArray::DirtyBits &dirtyBits,
                                       gl::VertexArray::DirtyAttribBitsArray *attribBits,
                                       gl::VertexArray::DirtyBindingBitsArray *bindingBits)
{
    StateManagerGL *stateManager = GetStateManagerGL(context);
    stateManager->bindVertexArray(mVertexArrayID);

    for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter)
    {
        size_t dirtyBit = *iter;
        switch (dirtyBit)
        {
            case VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
                ANGLE_TRY(updateElementArrayBufferBinding(context));
                break;

            case VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
                break;

                ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_ATTRIB_FUNC)
                ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_BINDING_FUNC)
                ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_BUFFER_DATA_FUNC)

            default:
                UNREACHABLE();
                break;
        }
    }

    return angle::Result::Continue;
}

angle::Result VertexArrayGL::applyNumViewsToDivisor(const gl::Context *context, int numViews)
{
    if (numViews != mAppliedNumViews)
    {
        StateManagerGL *stateManager = GetStateManagerGL(context);
        stateManager->bindVertexArray(mVertexArrayID);
        mAppliedNumViews = numViews;
        for (size_t index = 0u; index < mNativeState->bindings.size(); ++index)
        {
            ANGLE_TRY(updateBindingDivisor(context, index));
        }
    }

    return angle::Result::Continue;
}

angle::Result VertexArrayGL::applyActiveAttribLocationsMask(const gl::Context *context,
                                                            const gl::AttributesMask &activeMask)
{
    gl::AttributesMask updateMask = mProgramActiveAttribLocationsMask ^ activeMask;
    if (!updateMask.any())
    {
        return angle::Result::Continue;
    }

    ASSERT(mVertexArrayID == GetStateManagerGL(context)->getVertexArrayID());
    mProgramActiveAttribLocationsMask = activeMask;

    for (size_t attribIndex : updateMask)
    {
        ANGLE_TRY(updateAttribEnabled(context, attribIndex));
    }

    return angle::Result::Continue;
}

void VertexArrayGL::validateState(const FunctionsGL *functions) const
{
    VertexArrayStateGL queriedState(mNativeState->attributes.size(), mNativeState->bindings.size());
    QueryVertexArrayStateGL(functions, &queriedState);

    if (*mNativeState != queriedState)
    {
        std::ostringstream msg;
        msg << "Queried state does not match tracked state!" << std::endl;
        msg << "Tracked state:" << std::endl << *mNativeState << std::endl << std::endl;
        msg << "Queried state:" << std::endl << queriedState << std::endl;
        FATAL() << msg.str();
    }
}

}  // namespace rx
