summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp')
-rw-r--r--gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp b/gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp
new file mode 100644
index 0000000000..f525addbba
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp
@@ -0,0 +1,170 @@
+//
+// 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"
+
+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;
+ std::swap(binding.mBuffer, mBuffer);
+ }
+ return *this;
+}
+
+void VertexBinding::onContainerBindingChanged(const Context *context, int incr) const
+{
+ if (mBuffer.get())
+ mBuffer->onNonTFBindingChanged(incr);
+}
+
+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)
+{
+ Buffer *buffer = binding.getBuffer().get();
+ if (!buffer)
+ {
+ mCachedElementLimit = 0;
+ return;
+ }
+
+ angle::CheckedNumeric<GLint64> bufferSize(buffer->getSize());
+ angle::CheckedNumeric<GLint64> bufferOffset(binding.getOffset());
+ angle::CheckedNumeric<GLint64> attribOffset(relativeOffset);
+ angle::CheckedNumeric<GLint64> attribSize(ComputeVertexAttributeTypeSize(*this));
+
+ // (buffer.size - buffer.offset - attrib.relativeOffset - attrib.size) / binding.stride
+ angle::CheckedNumeric<GLint64> elementLimit =
+ (bufferSize - bufferOffset - attribOffset - 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;
+ }
+
+ angle::CheckedNumeric<GLint64> bindingStride(binding.getStride());
+ elementLimit /= bindingStride;
+
+ if (binding.getDivisor() > 0)
+ {
+ // For instanced draws, the element count is floor(instanceCount - 1) / binding.divisor.
+ angle::CheckedNumeric<GLint64> bindingDivisor(binding.getDivisor());
+ elementLimit *= bindingDivisor;
+
+ // We account for the floor() part rounding by adding a rounding constant.
+ elementLimit += bindingDivisor - 1;
+ }
+
+ mCachedElementLimit = elementLimit.ValueOrDefault(kIntegerOverflow);
+}
+
+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.
+GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding)
+{
+ return attrib.relativeOffset + binding.getOffset();
+}
+
+size_t ComputeVertexBindingElementCount(GLuint divisor, size_t drawCount, size_t instanceCount)
+{
+ // 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 attrib.divisor, the division must round up.
+ // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced
+ // vertices.
+ return (instanceCount + divisor - 1u) / divisor;
+ }
+
+ return drawCount;
+}
+
+} // namespace gl