//
// Copyright 2013 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.
//
// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
//

#include "libANGLE/VertexArray.h"

#include "common/utilities.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/VertexArrayImpl.h"

namespace gl
{
// VertexArrayState implementation.
VertexArrayState::VertexArrayState(VertexArrayID vertexArrayID,
                                   size_t maxAttribs,
                                   size_t maxAttribBindings)
    : mId(vertexArrayID)
{
    ASSERT(maxAttribs <= maxAttribBindings);

    for (size_t i = 0; i < maxAttribs; i++)
    {
        mVertexAttributes.emplace_back(static_cast<GLuint>(i));
        mVertexBindings.emplace_back(static_cast<GLuint>(i));
    }

    // Initially all attributes start as "client" with no buffer bound.
    mClientMemoryAttribsMask.set();
}

VertexArrayState::~VertexArrayState() {}

bool VertexArrayState::hasEnabledNullPointerClientArray() const
{
    return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
}

AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
{
    ASSERT(bindingIndex < mVertexBindings.size());
    return mVertexBindings[bindingIndex].getBoundAttributesMask();
}

// Set an attribute using a new binding.
void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
{
    ASSERT(attribIndex < mVertexAttributes.size() && newBindingIndex < mVertexBindings.size());

    VertexAttribute &attrib = mVertexAttributes[attribIndex];

    // Update the binding-attribute map.
    const GLuint oldBindingIndex = attrib.bindingIndex;
    ASSERT(oldBindingIndex != newBindingIndex);

    VertexBinding &oldBinding = mVertexBindings[oldBindingIndex];
    VertexBinding &newBinding = mVertexBindings[newBindingIndex];

    ASSERT(oldBinding.getBoundAttributesMask().test(attribIndex) &&
           !newBinding.getBoundAttributesMask().test(attribIndex));

    oldBinding.resetBoundAttribute(attribIndex);
    newBinding.setBoundAttribute(attribIndex);

    // Set the attribute using the new binding.
    attrib.bindingIndex = newBindingIndex;

    mEnabledAttributesMask.set(attribIndex, attrib.enabled);
}

bool VertexArrayState::isDefault() const
{
    return mId.value == 0;
}

// VertexArrayPrivate implementation.
VertexArrayPrivate::VertexArrayPrivate(rx::GLImplFactory *factory,
                                       VertexArrayID id,
                                       size_t maxAttribs,
                                       size_t maxAttribBindings)
    : mId(id), mState(mId, maxAttribs, maxAttribBindings), mRobustBufferAccessEnabled(false)
{}

VertexArrayPrivate::~VertexArrayPrivate() {}

void VertexArrayPrivate::setVertexAttribBinding(size_t attribIndex, GLuint newBindingIndex)
{
    ASSERT(attribIndex < getMaxAttribs() && newBindingIndex < getMaxBindings());

    if (mState.mVertexAttributes[attribIndex].bindingIndex == newBindingIndex)
    {
        return;
    }

    mState.setAttribBinding(attribIndex, newBindingIndex);

    if (mRobustBufferAccessEnabled)
    {
        VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
        attrib.updateCachedElementLimit(mState.mVertexBindings[newBindingIndex],
                                        mCachedBufferSize[newBindingIndex]);
    }

    setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);

    // Update client attribs mask.
    mState.mClientMemoryAttribsMask.set(attribIndex, !mBufferBindingMask[newBindingIndex]);

    mCachedMappedArrayBuffers.set(attribIndex, mCachedBufferPropertyMapped.test(newBindingIndex));
    mCachedMutableOrImpersistentArrayBuffers.set(
        attribIndex, mCachedBufferPropertyMutableOrImpersistent.test(newBindingIndex));
    mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mState.mEnabledAttributesMask &
                                      mCachedMutableOrImpersistentArrayBuffers;
}

const VertexAttribute &VertexArrayPrivate::getVertexAttribute(size_t attribIndex) const
{
    ASSERT(attribIndex < getMaxAttribs());
    return mState.mVertexAttributes[attribIndex];
}

const VertexBinding &VertexArrayPrivate::getVertexBinding(size_t bindingIndex) const
{
    ASSERT(bindingIndex < getMaxBindings());
    return mState.mVertexBindings[bindingIndex];
}

void VertexArrayPrivate::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
{
    mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
    mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
}

ANGLE_INLINE void VertexArrayPrivate::clearDirtyAttribBit(size_t attribIndex,
                                                          DirtyAttribBitType dirtyAttribBit)
{
    mDirtyAttribBits[attribIndex].set(dirtyAttribBit, false);
    if (mDirtyAttribBits[attribIndex].any())
    {
        return;
    }
    mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex, false);
}

ANGLE_INLINE void VertexArrayPrivate::setDirtyBindingBit(size_t bindingIndex,
                                                         DirtyBindingBitType dirtyBindingBit)
{
    mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
    mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
}

ANGLE_INLINE void VertexArrayPrivate::updateCachedElementLimit(const VertexBinding &binding,
                                                               GLint64 bufferSize)
{
    ASSERT(mRobustBufferAccessEnabled);
    for (size_t boundAttribute : binding.getBoundAttributesMask())
    {
        mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(binding, bufferSize);
    }
}

ANGLE_INLINE void VertexArrayPrivate::updateCachedArrayBuffersMasks(
    bool isMapped,
    bool isImmutable,
    bool isPersistent,
    const AttributesMask &boundAttributesMask)
{
    if (isMapped)
    {
        mCachedMappedArrayBuffers |= boundAttributesMask;
    }
    else
    {
        mCachedMappedArrayBuffers &= ~boundAttributesMask;
    }

    if (!isImmutable || !isPersistent)
    {
        mCachedMutableOrImpersistentArrayBuffers |= boundAttributesMask;
    }
    else
    {
        mCachedMutableOrImpersistentArrayBuffers &= ~boundAttributesMask;
    }

    mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mState.mEnabledAttributesMask &
                                      mCachedMutableOrImpersistentArrayBuffers;
}

void VertexArrayPrivate::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
{
    ASSERT(bindingIndex < getMaxBindings());

    VertexBinding &binding = mState.mVertexBindings[bindingIndex];

    if (binding.getDivisor() == divisor)
    {
        return;
    }

    binding.setDivisor(divisor);
    setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
}

bool VertexArrayPrivate::setVertexAttribFormatImpl(VertexAttribute *attrib,
                                                   GLint size,
                                                   VertexAttribType type,
                                                   bool normalized,
                                                   bool pureInteger,
                                                   GLuint relativeOffset)
{
    angle::FormatID formatID = GetVertexFormatID(type, normalized, size, pureInteger);

    if (formatID != attrib->format->id || attrib->relativeOffset != relativeOffset)
    {
        attrib->relativeOffset = relativeOffset;
        attrib->format         = &angle::Format::Get(formatID);
        return true;
    }

    return false;
}

void VertexArrayPrivate::setVertexAttribFormat(size_t attribIndex,
                                               GLint size,
                                               VertexAttribType type,
                                               bool normalized,
                                               bool pureInteger,
                                               GLuint relativeOffset)
{
    VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];

    ComponentType componentType = GetVertexAttributeComponentType(pureInteger, type);
    SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask);

    if (setVertexAttribFormatImpl(&attrib, size, type, normalized, pureInteger, relativeOffset))
    {
        setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
    }

    if (mRobustBufferAccessEnabled)
    {
        attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex],
                                        mCachedBufferSize[attrib.bindingIndex]);
    }
}

void VertexArrayPrivate::setVertexAttribDivisor(size_t attribIndex, GLuint divisor)
{
    ASSERT(attribIndex < getMaxAttribs());

    setVertexAttribBinding(attribIndex, static_cast<GLuint>(attribIndex));
    setVertexBindingDivisor(attribIndex, divisor);
}

void VertexArrayPrivate::enableAttribute(size_t attribIndex, bool enabledState)
{
    ASSERT(attribIndex < getMaxAttribs());

    VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];

    if (mState.mEnabledAttributesMask.test(attribIndex) == enabledState)
    {
        return;
    }

    attrib.enabled = enabledState;

    // Update state cache
    mState.mEnabledAttributesMask.set(attribIndex, enabledState);
    bool enableChanged = (mState.mEnabledAttributesMask.test(attribIndex) !=
                          mState.mLastSyncedEnabledAttributesMask.test(attribIndex));

    if (enableChanged)
    {
        setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
    }
    else
    {
        clearDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
    }

    mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mState.mEnabledAttributesMask &
                                      mCachedMutableOrImpersistentArrayBuffers;
}

bool VertexArrayPrivate::hasTransformFeedbackBindingConflict(const Context *context) const
{
    // Fast check first.
    if (!mCachedBufferPropertyTransformFeedbackConflict.any())
    {
        return false;
    }

    const AttributesMask &activeAttribues = context->getActiveBufferedAttribsMask();

    // Slow check. We must ensure that the conflicting attributes are enabled/active.
    for (size_t attribIndex : activeAttribues)
    {
        const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
        if (mCachedBufferPropertyTransformFeedbackConflict[attrib.bindingIndex])
        {
            return true;
        }
    }

    return false;
}

// VertexArray implementation.
VertexArray::VertexArray(rx::GLImplFactory *factory,
                         VertexArrayID id,
                         size_t maxAttribs,
                         size_t maxAttribBindings)
    : VertexArrayPrivate(factory, id, maxAttribs, maxAttribBindings),
      mVertexArray(factory->createVertexArray(mState, mVertexArrayBuffers))
{}

void VertexArray::onDestroy(const Context *context)
{
    bool isBound = context->isCurrentVertexArray(this);

    for (size_t bindingIndex : mBufferBindingMask)
    {
        Buffer *buffer = mVertexArrayBuffers[bindingIndex].get();
        ASSERT(buffer != nullptr);
        if (isBound)
        {
            buffer->onNonTFBindingChanged(-1);
            buffer->removeVertexArrayBinding(context, bindingIndex);
        }
        mVertexArrayBuffers[bindingIndex].set(context, nullptr);
    }

    mBufferBindingMask.reset();
    mVertexArray->destroy(context);
    SafeDelete(mVertexArray);
    delete this;
}

VertexArray::~VertexArray()
{
    ASSERT(!mVertexArray);
}

angle::Result VertexArray::setLabel(const Context *context, const std::string &label)
{
    mState.mLabel = label;

    if (mVertexArray)
    {
        return mVertexArray->onLabelUpdate(context);
    }
    return angle::Result::Continue;
}

const std::string &VertexArray::getLabel() const
{
    return mState.getLabel();
}

bool VertexArray::detachBuffer(const Context *context, BufferID bufferID)
{
    bool isBound           = context->isCurrentVertexArray(this);
    bool anyBufferDetached = false;

    for (size_t bindingIndex : mBufferBindingMask)
    {
        Buffer *buffer = mVertexArrayBuffers[bindingIndex].get();
        ASSERT(buffer != nullptr);
        if (buffer->id() == bufferID)
        {
            if (isBound)
            {
                buffer->onNonTFBindingChanged(-1);
            }

            buffer->removeVertexArrayBinding(context, bindingIndex);
            mVertexArrayBuffers[bindingIndex].set(context, nullptr);
            mBufferBindingMask.reset(bindingIndex);

            if (bindingIndex == kElementArrayBufferIndex)
            {
                mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
            }
            else
            {
                VertexBinding &binding = mState.mVertexBindings[bindingIndex];
                if (context->getClientVersion() >= ES_3_1 && !mState.isDefault())
                {
                    setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
                }
                else
                {
                    static_assert(MAX_VERTEX_ATTRIB_BINDINGS < 8 * sizeof(uint32_t),
                                  "Not enough bits in bindingIndex");
                    // The redundant uint32_t cast here is required to avoid a warning on MSVC.
                    ASSERT(binding.getBoundAttributesMask() ==
                           AttributesMask(static_cast<uint32_t>(1 << bindingIndex)));
                    setDirtyAttribBit(bindingIndex, DIRTY_ATTRIB_POINTER);
                }

                for (size_t attribIndex : binding.getBoundAttributesMask())
                {
                    VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
                    attrib.pointer          = nullptr;
                }

                mState.mClientMemoryAttribsMask |= binding.getBoundAttributesMask();
            }

            anyBufferDetached = true;
        }
    }

    return anyBufferDetached;
}

ANGLE_INLINE void VertexArray::updateCachedMappedArrayBuffersBinding(size_t bindingIndex)
{
    const VertexBinding &binding = mState.mVertexBindings[bindingIndex];
    const Buffer *buffer         = mVertexArrayBuffers[bindingIndex].get();
    ASSERT(mBufferBindingMask.test(bindingIndex));
    ASSERT(buffer != nullptr);

    bool isMapped     = buffer->isMapped() == GL_TRUE;
    bool isImmutable  = buffer->isImmutable() == GL_TRUE;
    bool isPersistent = (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;

    mCachedBufferPropertyMapped.set(bindingIndex, isMapped);
    mCachedBufferPropertyMutableOrImpersistent.set(bindingIndex, !isImmutable || !isPersistent);

    return updateCachedArrayBuffersMasks(isMapped, isImmutable, isPersistent,
                                         binding.getBoundAttributesMask());
}

void VertexArray::bindElementBuffer(const Context *context, Buffer *boundBuffer)
{
    Buffer *oldBuffer = getElementArrayBuffer();

    if (oldBuffer)
    {
        oldBuffer->removeVertexArrayBinding(context, kElementArrayBufferIndex);
        if (context->isWebGL())
        {
            oldBuffer->onNonTFBindingChanged(-1);
        }
        oldBuffer->release(context);
        mBufferBindingMask.reset(kElementArrayBufferIndex);
    }

    mVertexArrayBuffers[kElementArrayBufferIndex].assign(boundBuffer);

    if (boundBuffer)
    {
        boundBuffer->addVertexArrayBinding(context, kElementArrayBufferIndex);
        if (context->isWebGL())
        {
            boundBuffer->onNonTFBindingChanged(1);
        }
        boundBuffer->addRef();
        mBufferBindingMask.set(kElementArrayBufferIndex);
    }

    mDirtyBits.set(VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
    mIndexRangeInlineCache = {};
}

ANGLE_INLINE VertexArray::DirtyBindingBits VertexArray::bindVertexBufferImpl(const Context *context,
                                                                             size_t bindingIndex,
                                                                             Buffer *boundBuffer,
                                                                             GLintptr offset,
                                                                             GLsizei stride)
{
    ASSERT(bindingIndex < getMaxBindings());
    ASSERT(context->isCurrentVertexArray(this));

    VertexBinding *binding = &mState.mVertexBindings[bindingIndex];

    Buffer *oldBuffer = mVertexArrayBuffers[bindingIndex].get();

    DirtyBindingBits dirtyBindingBits;
    dirtyBindingBits.set(DIRTY_BINDING_BUFFER, oldBuffer != boundBuffer);
    dirtyBindingBits.set(DIRTY_BINDING_STRIDE, static_cast<GLuint>(stride) != binding->getStride());
    dirtyBindingBits.set(DIRTY_BINDING_OFFSET, offset != binding->getOffset());
    if (mRobustBufferAccessEnabled)
    {
        GLint64 bufferSize = boundBuffer ? boundBuffer->getSize() : 0;
        dirtyBindingBits.set(DIRTY_BINDING_SIZE, bufferSize != mCachedBufferSize[bindingIndex]);
        mCachedBufferSize[bindingIndex] = bufferSize;
    }

    if (dirtyBindingBits.none())
    {
        return dirtyBindingBits;
    }

    if (boundBuffer != oldBuffer)
    {
        // Several nullptr checks are combined here for optimization purposes.
        if (oldBuffer)
        {
            oldBuffer->onNonTFBindingChanged(-1);
            oldBuffer->removeVertexArrayBinding(context, bindingIndex);
            oldBuffer->release(context);
            mBufferBindingMask.reset(bindingIndex);
        }

        mVertexArrayBuffers[bindingIndex].assign(boundBuffer);

        // Update client memory attribute pointers. Affects all bound attributes.
        if (boundBuffer)
        {
            boundBuffer->addRef();
            boundBuffer->onNonTFBindingChanged(1);
            boundBuffer->addVertexArrayBinding(context, bindingIndex);
            if (context->isWebGL())
            {
                mCachedBufferPropertyTransformFeedbackConflict.set(
                    bindingIndex, boundBuffer->hasWebGLXFBBindingConflict(true));
            }
            mBufferBindingMask.set(bindingIndex);
            mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
            updateCachedMappedArrayBuffersBinding(bindingIndex);
        }
        else
        {
            if (context->isWebGL())
            {
                mCachedBufferPropertyTransformFeedbackConflict.set(bindingIndex, false);
            }
            mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
            mCachedBufferPropertyMapped.set(bindingIndex, false);
            mCachedBufferPropertyMutableOrImpersistent.set(bindingIndex, false);
            updateCachedArrayBuffersMasks(false, false, false, binding->getBoundAttributesMask());
        }
    }

    binding->setOffset(offset);
    binding->setStride(stride);

    if (mRobustBufferAccessEnabled)
    {
        updateCachedElementLimit(*binding, mCachedBufferSize[bindingIndex]);
    }

    return dirtyBindingBits;
}

void VertexArray::bindVertexBuffer(const Context *context,
                                   size_t bindingIndex,
                                   Buffer *boundBuffer,
                                   GLintptr offset,
                                   GLsizei stride)
{
    const VertexArray::DirtyBindingBits dirtyBindingBits =
        bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);

    if (!dirtyBindingBits.test(DIRTY_BINDING_BUFFER) && context->isSharedContext() &&
        boundBuffer != nullptr)
    {
        ASSERT(boundBuffer == mVertexArrayBuffers[bindingIndex].get());
        VertexArrayBufferBindingMask bindingMask = boundBuffer->getVertexArrayBinding(context);
        ASSERT(!bindingMask.none());
        onSharedBufferBind(context, boundBuffer, bindingMask);
    }

    if (dirtyBindingBits.any())
    {
        mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
        mDirtyBindingBits[bindingIndex] |= dirtyBindingBits;
    }
}

ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context,
                                                          ComponentType componentType,
                                                          bool pureInteger,
                                                          size_t attribIndex,
                                                          Buffer *boundBuffer,
                                                          GLint size,
                                                          VertexAttribType type,
                                                          bool normalized,
                                                          GLsizei stride,
                                                          const void *pointer,
                                                          bool *isVertexAttribDirtyOut)
{
    ASSERT(isVertexAttribDirtyOut);
    ASSERT(attribIndex < getMaxAttribs());

    VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];

    SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask);

    bool attribDirty = setVertexAttribFormatImpl(&attrib, size, type, normalized, pureInteger, 0);

    if (attrib.bindingIndex != attribIndex)
    {
        setVertexAttribBinding(attribIndex, static_cast<GLuint>(attribIndex));
    }

    GLsizei effectiveStride =
        stride == 0 ? static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)) : stride;

    if (attrib.vertexAttribArrayStride != static_cast<GLuint>(stride))
    {
        attribDirty = true;
    }
    attrib.vertexAttribArrayStride = stride;

    // If we switch from an array buffer to a client pointer(or vice-versa), we set the whole
    // attribute dirty. This notifies the Vulkan back-end to update all its caches.
    Buffer *oldBuffer = mVertexArrayBuffers[attrib.bindingIndex].get();
    if ((boundBuffer == nullptr) != (oldBuffer == nullptr))
    {
        attribDirty = true;
    }

    // If using client arrays and the pointer changes, set the attribute as dirty
    if (boundBuffer == nullptr && attrib.pointer != pointer)
    {
        attribDirty = true;
    }

    // Change of attrib.pointer is not part of attribDirty. Pointer is actually the buffer offset
    // which is handled within bindVertexBufferImpl and reflected in bufferDirty.
    attrib.pointer  = pointer;
    GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
    const VertexArray::DirtyBindingBits dirtyBindingBits =
        bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);

    if (attribDirty)
    {
        setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
        *isVertexAttribDirtyOut = true;
    }
    else if (dirtyBindingBits.any())
    {
        setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER_BUFFER);
        *isVertexAttribDirtyOut = true;
    }

    mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
                                                   boundBuffer == nullptr && pointer == nullptr);
}

void VertexArray::setVertexAttribPointer(const Context *context,
                                         size_t attribIndex,
                                         Buffer *boundBuffer,
                                         GLint size,
                                         VertexAttribType type,
                                         bool normalized,
                                         GLsizei stride,
                                         const void *pointer,
                                         bool *isVertexAttribDirtyOut)
{
    setVertexAttribPointerImpl(context, ComponentType::Float, false, attribIndex, boundBuffer, size,
                               type, normalized, stride, pointer, isVertexAttribDirtyOut);
}

void VertexArray::setVertexAttribIPointer(const Context *context,
                                          size_t attribIndex,
                                          Buffer *boundBuffer,
                                          GLint size,
                                          VertexAttribType type,
                                          GLsizei stride,
                                          const void *pointer,
                                          bool *isVertexAttribDirtyOut)
{
    ComponentType componentType = GetVertexAttributeComponentType(true, type);
    setVertexAttribPointerImpl(context, componentType, true, attribIndex, boundBuffer, size, type,
                               false, stride, pointer, isVertexAttribDirtyOut);
}

angle::Result VertexArray::syncState(const Context *context)
{
    if (mDirtyBits.any())
    {
        mDirtyBitsGuard = mDirtyBits;
        ANGLE_TRY(
            mVertexArray->syncState(context, mDirtyBits, &mDirtyAttribBits, &mDirtyBindingBits));
        mDirtyBits.reset();
        mDirtyBitsGuard.reset();

        // The dirty bits should be reset in the back-end. To simplify ASSERTs only check attrib 0.
        ASSERT(mDirtyAttribBits[0].none());
        ASSERT(mDirtyBindingBits[0].none());
        mState.mLastSyncedEnabledAttributesMask = mState.mEnabledAttributesMask;
    }
    return angle::Result::Continue;
}

bool VertexArray::bufferMaskBitsPointToTheSameBuffer(
    VertexArrayBufferBindingMask bufferBindingMask) const
{
    const Buffer *buffer = nullptr;
    for (size_t bindingIndex : bufferBindingMask)
    {
        if (buffer == nullptr)
        {
            buffer = mVertexArrayBuffers[bindingIndex].get();
        }
        else if (buffer != mVertexArrayBuffers[bindingIndex].get())
        {
            return false;
        }
    }
    return true;
}

void VertexArray::updateBindingSizeIfChanged(const size_t bindingIndex, const GLint64 bufferSize)
{
    ASSERT(mRobustBufferAccessEnabled);
    if (mCachedBufferSize[bindingIndex] != bufferSize)
    {
        setDirtyBindingBit(bindingIndex, DIRTY_BINDING_SIZE);
        mCachedBufferSize[bindingIndex] = bufferSize;
    }
}

// This becomes current vertex array on the context
void VertexArray::onBind(const Context *context)
{
    VertexArrayBufferBindingMask bufferBindingMask = mBufferBindingMask;

    if (bufferBindingMask[kElementArrayBufferIndex])
    {
        Buffer *bufferGL = getElementArrayBuffer();
        ASSERT(bufferGL != nullptr);
        bufferGL->addVertexArrayBinding(context, kElementArrayBufferIndex);
        bufferBindingMask.reset(kElementArrayBufferIndex);
    }
    else
    {
        ASSERT(getElementArrayBuffer() == nullptr);
    }

    // This vertex array becoming current. Some of the bindings we may have removed from buffer's
    // observer list. We need to add it back to the buffer's observer list and update dirty bits
    // that we may have missed while we were not observing.
    for (size_t bindingIndex : bufferBindingMask)
    {
        Buffer *bufferGL = mVertexArrayBuffers[bindingIndex].get();
        ASSERT(bufferGL != nullptr);
        ASSERT(bindingIndex != kElementArrayBufferIndex);
        bufferGL->addVertexArrayBinding(context, bindingIndex);
        updateCachedMappedArrayBuffersBinding(bindingIndex);
    }

    if (mRobustBufferAccessEnabled)
    {
        for (size_t bindingIndex : bufferBindingMask)
        {
            Buffer *bufferGL                = mVertexArrayBuffers[bindingIndex].get();
            updateBindingSizeIfChanged(bindingIndex, bufferGL->getSize());
            updateCachedElementLimit(mState.mVertexBindings[bindingIndex],
                                     mCachedBufferSize[bindingIndex]);
        }
    }

    if (context->isWebGL())
    {
        for (size_t bindingIndex : bufferBindingMask)
        {
            bool hasConflict = mVertexArrayBuffers[bindingIndex]->hasWebGLXFBBindingConflict(true);
            mCachedBufferPropertyTransformFeedbackConflict.set(bindingIndex, hasConflict);
        }
    }

    // Buffers may have changed while vertex array was not current, we need to check buffer's
    // internal storage and set proper dirty bits if buffer has changed since last syncState.
    mDirtyBits |= mVertexArray->checkBufferForDirtyBits(context, mBufferBindingMask);

    // Always reset mIndexRangeInlineCache since we lost buffer observation while unbind
    mIndexRangeInlineCache = {};

    onStateChange(angle::SubjectMessage::ContentsChanged);
}

// This becomes non-current vertex array on the context
void VertexArray::onUnbind(const Context *context)
{
    // This vertex array becoming non-current. For performance reason, we remove it from the
    // buffers' observer list so that the cost of buffer sending signal to observers will not be too
    // expensive.
    for (size_t bindingIndex : mBufferBindingMask)
    {
        Buffer *bufferGL = mVertexArrayBuffers[bindingIndex].get();
        ASSERT(bufferGL != nullptr);
        bufferGL->removeVertexArrayBinding(context, bindingIndex);
    }
}

void VertexArray::onBindingChanged(const Context *context, int incr)
{
    // When vertex array gets unbound, we remove it from bound buffers' observer list so that when
    // buffer changes, it wont has to loop over all these non-current vertex arrays and set dirty
    // bit on them. To compensate for that, when we bind a vertex array, we have to check against
    // each bound buffers and see if they have changed and needs to update vertex array's dirty bits
    // accordingly
    ASSERT(incr == 1 || incr == -1);
    if (incr < 0)
    {
        onUnbind(context);
    }
    else
    {
        onBind(context);
    }

    if (context->isWebGL())
    {
        for (size_t bindingIndex : mBufferBindingMask)
        {
            ASSERT(mVertexArrayBuffers[bindingIndex].get());
            mVertexArrayBuffers[bindingIndex]->onNonTFBindingChanged(incr);
        }
    }
}

void VertexArray::setDependentDirtyBits(bool contentsChanged,
                                        VertexArrayBufferBindingMask bufferBindingMask)
{
    DirtyBits dirtyBits(contentsChanged ? (bufferBindingMask.bits() << DIRTY_BIT_BUFFER_DATA_0)
                                        : (bufferBindingMask.bits() << DIRTY_BIT_BINDING_0));
    ASSERT(!mDirtyBitsGuard.valid() || (mDirtyBitsGuard.value() & dirtyBits) == dirtyBits);
    mDirtyBits |= dirtyBits;

    if (bufferBindingMask.test(kElementArrayBufferIndex))
    {
        mIndexRangeInlineCache = {};
    }

    onStateChange(angle::SubjectMessage::ContentsChanged);
}

void VertexArray::onSharedBufferBind(const Context *context,
                                     const Buffer *buffer,
                                     VertexArrayBufferBindingMask bufferBindingMask)
{
    bufferBindingMask &= mBufferBindingMask;
    ASSERT(bufferBindingMask.any());

    // vertexBufferBindingMask is bufferBindingMask without elementBuffer.
    VertexArrayBufferBindingMask vertexBufferBindingMask = bufferBindingMask;
    vertexBufferBindingMask.reset(kElementArrayBufferIndex);

    for (size_t bindingIndex : vertexBufferBindingMask)
    {
        updateCachedMappedArrayBuffersBinding(bindingIndex);
    }

    if (mRobustBufferAccessEnabled)
    {
        for (size_t bindingIndex : vertexBufferBindingMask)
        {
            ASSERT(buffer == mVertexArrayBuffers[bindingIndex].get());
            updateBindingSizeIfChanged(bindingIndex, buffer->getSize());
            updateCachedElementLimit(mState.mVertexBindings[bindingIndex],
                                     mCachedBufferSize[bindingIndex]);
        }
    }

    if (context->isWebGL())
    {
        if (buffer->hasWebGLXFBBindingConflict(true))
        {
            mCachedBufferPropertyTransformFeedbackConflict |= vertexBufferBindingMask;
        }
        else
        {
            mCachedBufferPropertyTransformFeedbackConflict &= ~vertexBufferBindingMask;
        }
    }

    // Set proper dirty bits on VertexArray
    mDirtyBits |= mVertexArray->checkBufferForDirtyBits(context, bufferBindingMask);

    // mIndexRangeInlineCache is no longer invalid
    mIndexRangeInlineCache = {};
}

void VertexArray::onBufferChanged(const Context *context,
                                  const Buffer *buffer,
                                  angle::SubjectMessage message,
                                  VertexArrayBufferBindingMask vertexArrayBufferBindingMask)
{
    VertexArrayBufferBindingMask bufferBindingMask =
        vertexArrayBufferBindingMask & mBufferBindingMask;
    ASSERT(buffer);
    ASSERT(bufferBindingMask.any());
    ASSERT(bufferMaskBitsPointToTheSameBuffer(bufferBindingMask));

    switch (message)
    {
        case angle::SubjectMessage::SubjectChanged:
            if (mRobustBufferAccessEnabled)
            {
                VertexArrayBufferBindingMask VertexBufferBindingMask = bufferBindingMask;
                VertexBufferBindingMask.reset(kElementArrayBufferIndex);
                for (size_t bindingIndex : VertexBufferBindingMask)
                {
                    updateBindingSizeIfChanged(bindingIndex, buffer->getSize());
                    updateCachedElementLimit(mState.mVertexBindings[bindingIndex],
                                             mCachedBufferSize[bindingIndex]);
                }
            }
            // This has to be called after updateCachedElementLimit due to
            // mCachedElementLimit dependency
            setDependentDirtyBits(false, bufferBindingMask);
            break;

        case angle::SubjectMessage::BindingChanged:
            if (context->isWebGL())
            {
                bufferBindingMask.reset(kElementArrayBufferIndex);

                bool hasConflict = buffer->hasWebGLXFBBindingConflict(true);
                if (hasConflict)
                {
                    mCachedBufferPropertyTransformFeedbackConflict |= bufferBindingMask;
                }
                else
                {
                    mCachedBufferPropertyTransformFeedbackConflict &= ~bufferBindingMask;
                }
            }
            break;

        case angle::SubjectMessage::SubjectMapped:
            bufferBindingMask.reset(kElementArrayBufferIndex);
            for (size_t bindingIndex : bufferBindingMask)
            {
                updateCachedMappedArrayBuffersBinding(bindingIndex);
            }
            onStateChange(angle::SubjectMessage::SubjectMapped);
            break;

        case angle::SubjectMessage::SubjectUnmapped:
        {
            VertexArrayBufferBindingMask VertexBufferBindingMask = bufferBindingMask;
            VertexBufferBindingMask.reset(kElementArrayBufferIndex);
            for (size_t bindingIndex : VertexBufferBindingMask)
            {
                updateCachedMappedArrayBuffersBinding(bindingIndex);
            }
            setDependentDirtyBits(true, bufferBindingMask);
            onStateChange(angle::SubjectMessage::SubjectUnmapped);
        }
        break;

        case angle::SubjectMessage::InternalMemoryAllocationChanged:
            setDependentDirtyBits(false, bufferBindingMask);
            break;

        case angle::SubjectMessage::ContentsChanged:
        {
            VertexArrayBufferBindingMask bufferContentObserverBindingMask =
                vertexArrayBufferBindingMask & mVertexArray->getContentObserversBindingMask();
            if (bufferContentObserverBindingMask.any())
            {
                setDependentDirtyBits(true, bufferBindingMask);
            }
        }
        break;

        default:
            UNREACHABLE();
            break;
    }
}
}  // namespace gl
