summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp')
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp96
1 files changed, 69 insertions, 27 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
index ec85857264..7ff5171fca 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
@@ -26,12 +26,32 @@ namespace
namespace rx
{
-static int elementsInBuffer(const gl::VertexAttribute &attribute, int size)
+static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size)
{
- int stride = attribute.stride();
+ // Size cannot be larger than a GLsizei
+ if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
+ {
+ size = static_cast<unsigned int>(std::numeric_limits<int>::max());
+ }
+
+ GLsizei stride = attribute.stride();
return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
}
+static int StreamingBufferElementCount(const gl::VertexAttribute &attribute, int vertexDrawCount, int instanceDrawCount)
+{
+ // 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 (instanceDrawCount > 0 && attribute.mDivisor > 0)
+ {
+ return instanceDrawCount / attribute.mDivisor;
+ }
+
+ return vertexDrawCount;
+}
+
VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
{
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
@@ -92,7 +112,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
- if (staticBuffer && staticBuffer->getBufferSize() > 0 && staticBuffer->lookupAttribute(attribs[i]) == -1 &&
+ if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) &&
!directStoragePossible(staticBuffer, attribs[i]))
{
buffer->invalidateStaticData();
@@ -116,12 +136,27 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
if (staticBuffer->getBufferSize() == 0)
{
int totalCount = elementsInBuffer(attribs[i], buffer->size());
- staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0);
+ if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
}
}
else
{
- mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances);
+ int totalCount = StreamingBufferElementCount(attribs[i], count, instances);
+
+ // Undefined behaviour:
+ // We can return INVALID_OPERATION if our vertex attribute does not have enough backing data.
+ if (buffer && elementsInBuffer(attribs[i], buffer->size()) < totalCount)
+ {
+ return GL_INVALID_OPERATION;
+ }
+
+ if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
}
}
}
@@ -149,7 +184,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
bool directStorage = directStoragePossible(vertexBuffer, attribs[i]);
- std::size_t streamOffset = -1;
+ unsigned int streamOffset = 0;
unsigned int outputElementSize = 0;
if (directStorage)
@@ -160,37 +195,40 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
}
else if (staticBuffer)
{
- streamOffset = staticBuffer->lookupAttribute(attribs[i]);
- outputElementSize = staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0);
+ if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
- if (streamOffset == -1)
+ if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset))
{
// Convert the entire buffer
int totalCount = elementsInBuffer(attribs[i], storage->getSize());
int startIndex = attribs[i].mOffset / attribs[i].stride();
- streamOffset = staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0);
+ if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
}
- if (streamOffset != -1)
+ unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize;
+ unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 0) ? start * outputElementSize : 0;
+ if (streamOffset + firstElementOffset + startOffset < streamOffset)
{
- streamOffset += (attribs[i].mOffset / attribs[i].stride()) * outputElementSize;
-
- if (instances == 0 || attribs[i].mDivisor == 0)
- {
- streamOffset += start * outputElementSize;
- }
+ return GL_OUT_OF_MEMORY;
}
+
+ streamOffset += firstElementOffset + startOffset;
}
else
{
- outputElementSize = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0);
- streamOffset = mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances);
- }
-
- if (streamOffset == -1)
- {
- return GL_OUT_OF_MEMORY;
+ int totalCount = StreamingBufferElementCount(attribs[i], count, instances);
+ if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) ||
+ !mStreamingBuffer->storeVertexAttributes(attribs[i], start, totalCount, instances, &streamOffset))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
}
translated[i].storage = directStorage ? storage : NULL;
@@ -217,9 +255,13 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
mCurrentValue[i][3] != attribs[i].mCurrentValue[3])
{
unsigned int requiredSpace = sizeof(float) * 4;
- buffer->reserveRawDataSpace(requiredSpace);
- int streamOffset = buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace);
- if (streamOffset == -1)
+ if (!buffer->reserveRawDataSpace(requiredSpace))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
+
+ unsigned int streamOffset;
+ if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset))
{
return GL_OUT_OF_MEMORY;
}