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

// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
// index data. Implements GL buffer objects and related functionality.
// [OpenGL ES 2.0.24] section 2.9 page 21.

#include "libANGLE/Buffer.h"

#include "libANGLE/Context.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/GLImplFactory.h"

namespace gl
{
namespace
{
constexpr angle::SubjectIndex kImplementationSubjectIndex = 0;
constexpr size_t kInvalidContentsObserverIndex            = std::numeric_limits<size_t>::max();
}  // anonymous namespace

BufferState::BufferState()
    : mLabel(),
      mUsage(BufferUsage::StaticDraw),
      mSize(0),
      mAccessFlags(0),
      mAccess(GL_WRITE_ONLY_OES),
      mMapped(GL_FALSE),
      mMapPointer(nullptr),
      mMapOffset(0),
      mMapLength(0),
      mBindingCount(0),
      mTransformFeedbackIndexedBindingCount(0),
      mTransformFeedbackGenericBindingCount(0),
      mImmutable(GL_FALSE),
      mStorageExtUsageFlags(0),
      mExternal(GL_FALSE)
{}

BufferState::~BufferState() {}

Buffer::Buffer(rx::GLImplFactory *factory, BufferID id)
    : RefCountObject(factory->generateSerial(), id),
      mImpl(factory->createBuffer(mState)),
      mImplObserver(this, kImplementationSubjectIndex)
{
    mImplObserver.bind(mImpl);
}

Buffer::~Buffer()
{
    SafeDelete(mImpl);
}

void Buffer::onDestroy(const Context *context)
{
    // In tests, mImpl might be null.
    if (mImpl)
        mImpl->destroy(context);
}

void Buffer::setLabel(const Context *context, const std::string &label)
{
    mState.mLabel = label;
}

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

angle::Result Buffer::bufferStorageExternal(Context *context,
                                            BufferBinding target,
                                            GLsizeiptr size,
                                            GLeglClientBufferEXT clientBuffer,
                                            GLbitfield flags)
{
    return bufferExternalDataImpl(context, target, clientBuffer, size, flags);
}

angle::Result Buffer::bufferStorage(Context *context,
                                    BufferBinding target,
                                    GLsizeiptr size,
                                    const void *data,
                                    GLbitfield flags)
{
    return bufferDataImpl(context, target, data, size, BufferUsage::InvalidEnum, flags);
}

angle::Result Buffer::bufferData(Context *context,
                                 BufferBinding target,
                                 const void *data,
                                 GLsizeiptr size,
                                 BufferUsage usage)
{
    GLbitfield flags = (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT_EXT);
    return bufferDataImpl(context, target, data, size, usage, flags);
}

angle::Result Buffer::bufferDataImpl(Context *context,
                                     BufferBinding target,
                                     const void *data,
                                     GLsizeiptr size,
                                     BufferUsage usage,
                                     GLbitfield flags)
{
    const void *dataForImpl = data;

    if (mState.isMapped())
    {
        // Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
        // BufferData happens on a mapped buffer:
        //
        //     If any portion of the buffer object is mapped in the current context or any context
        //     current to another thread, it is as though UnmapBuffer (see section 2.10.3) is
        //     executed in each such context prior to deleting the existing data store.
        //
        GLboolean dontCare = GL_FALSE;
        ANGLE_TRY(unmap(context, &dontCare));
    }

    // If we are using robust resource init, make sure the buffer starts cleared.
    // Note: the Context is checked for nullptr because of some testing code.
    // TODO(jmadill): Investigate lazier clearing.
    if (context && context->getState().isRobustResourceInitEnabled() && !data && size > 0)
    {
        angle::MemoryBuffer *scratchBuffer = nullptr;
        ANGLE_CHECK_GL_ALLOC(
            context, context->getZeroFilledBuffer(static_cast<size_t>(size), &scratchBuffer));
        dataForImpl = scratchBuffer->data();
    }

    if (mImpl->setDataWithUsageFlags(context, target, nullptr, dataForImpl, size, usage, flags) ==
        angle::Result::Stop)
    {
        // If setData fails, the buffer contents are undefined. Set a zero size to indicate that.
        mIndexRangeCache.clear();
        mState.mSize = 0;

        // Notify when storage changes.
        onStateChange(angle::SubjectMessage::SubjectChanged);

        return angle::Result::Stop;
    }

    bool wholeBuffer = size == mState.mSize;

    mIndexRangeCache.clear();
    mState.mUsage                = usage;
    mState.mSize                 = size;
    mState.mImmutable            = (usage == BufferUsage::InvalidEnum);
    mState.mStorageExtUsageFlags = flags;

    // Notify when storage changes.
    if (wholeBuffer)
    {
        onContentsChange();
    }
    else
    {
        onStateChange(angle::SubjectMessage::SubjectChanged);
    }

    return angle::Result::Continue;
}

angle::Result Buffer::bufferExternalDataImpl(Context *context,
                                             BufferBinding target,
                                             GLeglClientBufferEXT clientBuffer,
                                             GLsizeiptr size,
                                             GLbitfield flags)
{
    if (mState.isMapped())
    {
        // Per the OpenGL ES 3.0 spec, buffers are implicitly unmapped when a call to
        // BufferData happens on a mapped buffer:
        //
        //     If any portion of the buffer object is mapped in the current context or any context
        //     current to another thread, it is as though UnmapBuffer (see section 2.10.3) is
        //     executed in each such context prior to deleting the existing data store.
        //
        GLboolean dontCare = GL_FALSE;
        ANGLE_TRY(unmap(context, &dontCare));
    }

    if (mImpl->setDataWithUsageFlags(context, target, clientBuffer, nullptr, size,
                                     BufferUsage::InvalidEnum, flags) == angle::Result::Stop)
    {
        // If setData fails, the buffer contents are undefined. Set a zero size to indicate that.
        mIndexRangeCache.clear();
        mState.mSize = 0;

        // Notify when storage changes.
        onStateChange(angle::SubjectMessage::SubjectChanged);

        return angle::Result::Stop;
    }

    mIndexRangeCache.clear();
    mState.mUsage                = BufferUsage::InvalidEnum;
    mState.mSize                 = size;
    mState.mImmutable            = GL_TRUE;
    mState.mStorageExtUsageFlags = flags;
    mState.mExternal             = GL_TRUE;

    // Notify when storage changes.
    onStateChange(angle::SubjectMessage::SubjectChanged);

    return angle::Result::Continue;
}

angle::Result Buffer::bufferSubData(const Context *context,
                                    BufferBinding target,
                                    const void *data,
                                    GLsizeiptr size,
                                    GLintptr offset)
{
    ANGLE_TRY(mImpl->setSubData(context, target, data, size, offset));

    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset),
                                     static_cast<unsigned int>(size));

    // Notify when data changes.
    onContentsChange();

    return angle::Result::Continue;
}

angle::Result Buffer::copyBufferSubData(const Context *context,
                                        Buffer *source,
                                        GLintptr sourceOffset,
                                        GLintptr destOffset,
                                        GLsizeiptr size)
{
    ANGLE_TRY(
        mImpl->copySubData(context, source->getImplementation(), sourceOffset, destOffset, size));

    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset),
                                     static_cast<unsigned int>(size));

    // Notify when data changes.
    onContentsChange();

    return angle::Result::Continue;
}

angle::Result Buffer::map(const Context *context, GLenum access)
{
    ASSERT(!mState.mMapped);

    mState.mMapPointer = nullptr;
    ANGLE_TRY(mImpl->map(context, access, &mState.mMapPointer));

    ASSERT(access == GL_WRITE_ONLY_OES);

    mState.mMapped      = GL_TRUE;
    mState.mMapOffset   = 0;
    mState.mMapLength   = mState.mSize;
    mState.mAccess      = access;
    mState.mAccessFlags = GL_MAP_WRITE_BIT;
    mIndexRangeCache.clear();

    // Notify when state changes.
    onStateChange(angle::SubjectMessage::SubjectMapped);

    return angle::Result::Continue;
}

angle::Result Buffer::mapRange(const Context *context,
                               GLintptr offset,
                               GLsizeiptr length,
                               GLbitfield access)
{
    ASSERT(!mState.mMapped);
    ASSERT(offset + length <= mState.mSize);

    mState.mMapPointer = nullptr;
    ANGLE_TRY(mImpl->mapRange(context, offset, length, access, &mState.mMapPointer));

    mState.mMapped      = GL_TRUE;
    mState.mMapOffset   = static_cast<GLint64>(offset);
    mState.mMapLength   = static_cast<GLint64>(length);
    mState.mAccess      = GL_WRITE_ONLY_OES;
    mState.mAccessFlags = access;

    // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
    // value for GL_BUFFER_ACCESS_OES because it was written against ES2.  Since there is
    // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
    // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.

    if ((access & GL_MAP_WRITE_BIT) > 0)
    {
        mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset),
                                         static_cast<unsigned int>(length));
    }

    // Notify when state changes.
    onStateChange(angle::SubjectMessage::SubjectMapped);

    return angle::Result::Continue;
}

angle::Result Buffer::unmap(const Context *context, GLboolean *result)
{
    ASSERT(mState.mMapped);

    *result = GL_FALSE;
    ANGLE_TRY(mImpl->unmap(context, result));

    mState.mMapped      = GL_FALSE;
    mState.mMapPointer  = nullptr;
    mState.mMapOffset   = 0;
    mState.mMapLength   = 0;
    mState.mAccess      = GL_WRITE_ONLY_OES;
    mState.mAccessFlags = 0;

    // Notify when data changes.
    onStateChange(angle::SubjectMessage::SubjectUnmapped);

    return angle::Result::Continue;
}

void Buffer::onDataChanged()
{
    mIndexRangeCache.clear();

    // Notify when data changes.
    onContentsChange();

    mImpl->onDataChanged();
}

angle::Result Buffer::getIndexRange(const gl::Context *context,
                                    DrawElementsType type,
                                    size_t offset,
                                    size_t count,
                                    bool primitiveRestartEnabled,
                                    IndexRange *outRange) const
{
    if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
    {
        return angle::Result::Continue;
    }

    ANGLE_TRY(
        mImpl->getIndexRange(context, type, offset, count, primitiveRestartEnabled, outRange));

    mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);

    return angle::Result::Continue;
}

GLint64 Buffer::getMemorySize() const
{
    GLint64 implSize = mImpl->getMemorySize();
    return implSize > 0 ? implSize : mState.mSize;
}

bool Buffer::isDoubleBoundForTransformFeedback() const
{
    return mState.mTransformFeedbackIndexedBindingCount > 1;
}

void Buffer::onTFBindingChanged(const Context *context, bool bound, bool indexed)
{
    ASSERT(bound || mState.mBindingCount > 0);
    mState.mBindingCount += bound ? 1 : -1;
    if (indexed)
    {
        ASSERT(bound || mState.mTransformFeedbackIndexedBindingCount > 0);
        mState.mTransformFeedbackIndexedBindingCount += bound ? 1 : -1;

        onStateChange(angle::SubjectMessage::BindingChanged);
    }
    else
    {
        mState.mTransformFeedbackGenericBindingCount += bound ? 1 : -1;
    }
}

angle::Result Buffer::getSubData(const gl::Context *context,
                                 GLintptr offset,
                                 GLsizeiptr size,
                                 void *outData)
{
    return mImpl->getSubData(context, offset, size, outData);
}

void Buffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
    if (message == angle::SubjectMessage::BufferVkStorageChanged)
    {
        return;
    }

    // Pass it along!
    ASSERT(index == kImplementationSubjectIndex);
    ASSERT(message == angle::SubjectMessage::SubjectChanged ||
           message == angle::SubjectMessage::InternalMemoryAllocationChanged);
    onStateChange(message);
}

size_t Buffer::getContentsObserverIndex(VertexArray *vertexArray, uint32_t bufferIndex) const
{
    for (size_t observerIndex = 0; observerIndex < mContentsObservers.size(); ++observerIndex)
    {
        const ContentsObserver &observer = mContentsObservers[observerIndex];
        if (observer.vertexArray == vertexArray && observer.bufferIndex == bufferIndex)
        {
            return observerIndex;
        }
    }

    return kInvalidContentsObserverIndex;
}

void Buffer::addContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex)
{
    if (getContentsObserverIndex(vertexArray, bufferIndex) == kInvalidContentsObserverIndex)
    {
        mContentsObservers.push_back({vertexArray, bufferIndex});
    }
}

void Buffer::removeContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex)
{
    size_t foundObserver = getContentsObserverIndex(vertexArray, bufferIndex);
    if (foundObserver != kInvalidContentsObserverIndex)
    {
        size_t lastObserverIndex = mContentsObservers.size() - 1;
        if (foundObserver != lastObserverIndex)
        {
            mContentsObservers[foundObserver] = mContentsObservers[lastObserverIndex];
        }
        mContentsObservers.pop_back();
    }
}

void Buffer::onContentsChange()
{
    for (const ContentsObserver &observer : mContentsObservers)
    {
        observer.vertexArray->onBufferContentsChange(observer.bufferIndex);
    }
}
}  // namespace gl
