//
// Copyright 2014 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 classes for mananging GLES 3.1 Vertex Array Objects.
//

#include "libANGLE/VertexAttribute.h"
#include "common/mathutil.h"

namespace gl
{

// [OpenGL ES 3.1] (November 3, 2016) Section 20 Page 361
// Table 20.2: Vertex Array Object State
VertexBinding::VertexBinding() : VertexBinding(0) {}

VertexBinding::VertexBinding(GLuint boundAttribute) : mStride(16u), mDivisor(0), mOffset(0)
{
    mBoundAttributesMask.set(boundAttribute);
}

VertexBinding::VertexBinding(VertexBinding &&binding)
{
    *this = std::move(binding);
}

VertexBinding::~VertexBinding() {}

VertexBinding &VertexBinding::operator=(VertexBinding &&binding)
{
    if (this != &binding)
    {
        mStride              = binding.mStride;
        mDivisor             = binding.mDivisor;
        mOffset              = binding.mOffset;
        mBoundAttributesMask = binding.mBoundAttributesMask;
    }
    return *this;
}

VertexAttribute::VertexAttribute(GLuint bindingIndex)
    : enabled(false),
      format(&angle::Format::Get(angle::FormatID::R32G32B32A32_FLOAT)),
      pointer(nullptr),
      relativeOffset(0),
      vertexAttribArrayStride(0),
      bindingIndex(bindingIndex),
      mCachedElementLimit(0)
{}

VertexAttribute::VertexAttribute(VertexAttribute &&attrib)
    : enabled(attrib.enabled),
      format(attrib.format),
      pointer(attrib.pointer),
      relativeOffset(attrib.relativeOffset),
      vertexAttribArrayStride(attrib.vertexAttribArrayStride),
      bindingIndex(attrib.bindingIndex),
      mCachedElementLimit(attrib.mCachedElementLimit)
{}

VertexAttribute &VertexAttribute::operator=(VertexAttribute &&attrib)
{
    if (this != &attrib)
    {
        enabled                 = attrib.enabled;
        format                  = attrib.format;
        pointer                 = attrib.pointer;
        relativeOffset          = attrib.relativeOffset;
        vertexAttribArrayStride = attrib.vertexAttribArrayStride;
        bindingIndex            = attrib.bindingIndex;
        mCachedElementLimit     = attrib.mCachedElementLimit;
    }
    return *this;
}

void VertexAttribute::updateCachedElementLimit(const VertexBinding &binding, GLint64 bufferSize)
{
    if (bufferSize == 0)
    {
        mCachedElementLimit = 0;
        return;
    }

    angle::CheckedNumeric<GLint64> bufferOffset(binding.getOffset());
    angle::CheckedNumeric<GLint64> checkedBufferSize(bufferSize);
    angle::CheckedNumeric<GLint64> attribOffset(relativeOffset);
    angle::CheckedNumeric<GLint64> attribSize(ComputeVertexAttributeTypeSize(*this));

    // Disallow referencing data before the start of the buffer with negative offsets
    angle::CheckedNumeric<GLint64> offset = bufferOffset + attribOffset;
    if (!offset.IsValid() || offset.ValueOrDie() < 0)
    {
        mCachedElementLimit = kIntegerOverflow;
        return;
    }

    // The element limit is (exclusive) end of the accessible range for the vertex.  For example, if
    // N attributes can be accessed, the following calculates N.
    //
    // (buffer.size - buffer.offset - attrib.relativeOffset - attrib.size) / binding.stride + 1
    angle::CheckedNumeric<GLint64> elementLimit = (checkedBufferSize - offset - attribSize);

    // Use the special integer overflow value if there was a math error.
    if (!elementLimit.IsValid())
    {
        static_assert(kIntegerOverflow < 0, "Unexpected value");
        mCachedElementLimit = kIntegerOverflow;
        return;
    }

    mCachedElementLimit = elementLimit.ValueOrDie();
    if (mCachedElementLimit < 0)
    {
        return;
    }

    if (binding.getStride() == 0)
    {
        // Special case for a zero stride. If we can fit one vertex we can fit infinite vertices.
        mCachedElementLimit = std::numeric_limits<GLint64>::max();
        return;
    }

    mCachedElementLimit /= binding.getStride();
    ++mCachedElementLimit;
}

size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding)
{
    // In ES 3.1, VertexAttribPointer will store the type size in the binding stride.
    // Hence, rendering always uses the binding's stride.
    return attrib.enabled ? binding.getStride() : 16u;
}

// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
uintptr_t ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding)
{
    return attrib.relativeOffset + binding.getOffset();
}

size_t ComputeVertexBindingElementCount(GLuint divisor,
                                        uint64_t drawCount,
                                        size_t instanceCount,
                                        uint64_t baseInstance)
{
    // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
    //
    // A vertex attribute with a positive divisor loads one instanced vertex for every set of
    // non-instanced vertices, and the instanced vertex index advances once every "mDivisor"
    // instances.
    if (instanceCount > 0 && divisor > 0)
    {
        // When instanceDrawCount is not a multiple of divisor, the division must round up.
        // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced
        // vertices.
        angle::CheckedNumeric<size_t> checkedElementCount = baseInstance;
        checkedElementCount += static_cast<size_t>(rx::UnsignedCeilDivide64(
            static_cast<uint64_t>(instanceCount), static_cast<uint64_t>(divisor)));
        return checkedElementCount.ValueOrDie();
    }

    // Ensure that drawCount can always fit into a size_t. This should also be validated by
    // maxElementIndex.
    return angle::CheckedNumeric<size_t>(drawCount).ValueOrDie();
}

std::ostream &operator<<(std::ostream &os, const VertexAttribCurrentValueData &data)
{
    auto printTypedData = [](std::ostream &os, auto data) {
        os << "x = " << data[0] << ", y = " << data[1] << ", z = " << data[2]
           << ", w = " << data[3];
    };

    switch (data.Type)
    {
        case gl::VertexAttribType::Float:
            os << "Type = Float, ";
            printTypedData(os, data.Values.FloatValues);
            break;
        case gl::VertexAttribType::Int:
            os << "Type = Int, ";
            printTypedData(os, data.Values.IntValues);
            break;

        case gl::VertexAttribType::UnsignedInt:
            os << "Type = UnsignedInt, ";
            printTypedData(os, data.Values.UnsignedIntValues);
            break;
        default:
            UNREACHABLE();
    }
    return os;
}

}  // namespace gl
