#include "libANGLE/VertexAttribute.h"
namespace gl
{
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));
angle::CheckedNumeric<GLint64> offset = bufferOffset + attribOffset;
if (!offset.IsValid() || offset.ValueOrDie() < 0)
{
mCachedElementLimit = kIntegerOverflow;
return;
}
angle::CheckedNumeric<GLint64> elementLimit = (checkedBufferSize - offset - attribSize);
if (!elementLimit.IsValid())
{
static_assert(kIntegerOverflow < 0, "Unexpected value");
mCachedElementLimit = kIntegerOverflow;
return;
}
mCachedElementLimit = elementLimit.ValueOrDie();
if (mCachedElementLimit < 0)
{
return;
}
if (binding.getStride() == 0)
{
mCachedElementLimit = std::numeric_limits<GLint64>::max();
return;
}
mCachedElementLimit /= binding.getStride();
++mCachedElementLimit;
}
size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding)
{
return attrib.enabled ? binding.getStride() : 16u;
}
GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding)
{
return attrib.relativeOffset + binding.getOffset();
}
size_t ComputeVertexBindingElementCount(GLuint divisor, uint64_t drawCount, size_t instanceCount)
{
if (instanceCount > 0 && divisor > 0)
{
return (instanceCount + divisor - 1u) / divisor;
}
return angle::CheckedNumeric<size_t>(drawCount).ValueOrDie();
}
}