summaryrefslogtreecommitdiffstats
path: root/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp')
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp383
1 files changed, 252 insertions, 131 deletions
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp
index d573579..f79d606 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/geometry/IndexDataManager.cpp
@@ -13,7 +13,7 @@
#include "libGLESv2/Buffer.h"
#include "libGLESv2/mathutil.h"
-#include "libGLESv2/geometry/backend.h"
+#include "libGLESv2/main.h"
namespace
{
@@ -23,239 +23,360 @@ namespace
namespace gl
{
-IndexDataManager::IndexDataManager(Context *context, BufferBackEnd *backend)
- : mContext(context), mBackend(backend), mIntIndicesSupported(backend->supportIntIndices())
+IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device)
{
- mCountingBuffer = NULL;
- mCountingBufferSize = 0;
+ mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
- mLineLoopBuffer = NULL;
-
- mStreamBufferShort = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
-
- if (mIntIndicesSupported)
+ if (context->supports32bitIndices())
{
- mStreamBufferInt = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
}
else
{
- mStreamBufferInt = NULL;
+ mStreamingBufferInt = NULL;
}
}
IndexDataManager::~IndexDataManager()
{
- delete mStreamBufferShort;
- delete mStreamBufferInt;
- delete mCountingBuffer;
- delete mLineLoopBuffer;
+ delete mStreamingBufferShort;
+ delete mStreamingBufferInt;
}
-namespace
+void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
{
+ if (type == GL_UNSIGNED_BYTE)
+ {
+ const GLubyte *in = static_cast<const GLubyte*>(input);
+ GLushort *out = static_cast<GLushort*>(output);
+
+ for (GLsizei i = 0; i < count; i++)
+ {
+ out[i] = in[i];
+ }
+ }
+ else if (type == GL_UNSIGNED_INT)
+ {
+ memcpy(output, input, count * sizeof(GLuint));
+ }
+ else if (type == GL_UNSIGNED_SHORT)
+ {
+ memcpy(output, input, count * sizeof(GLushort));
+ }
+ else UNREACHABLE();
+}
-template <class InputIndexType, class OutputIndexType>
-void copyIndices(const InputIndexType *in, GLsizei count, OutputIndexType *out, GLuint *minIndex, GLuint *maxIndex)
+template <class IndexType>
+void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
{
- InputIndexType first = *in;
- GLuint minIndexSoFar = first;
- GLuint maxIndexSoFar = first;
+ *minIndex = indices[0];
+ *maxIndex = indices[0];
for (GLsizei i = 0; i < count; i++)
{
- if (minIndexSoFar > *in) minIndexSoFar = *in;
- if (maxIndexSoFar < *in) maxIndexSoFar = *in;
-
- *out++ = *in++;
+ if (*minIndex > indices[i]) *minIndex = indices[i];
+ if (*maxIndex < indices[i]) *maxIndex = indices[i];
}
-
- // It might be a line loop, so copy the loop index.
- *out = first;
-
- *minIndex = minIndexSoFar;
- *maxIndex = maxIndexSoFar;
}
+void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
+{
+ if (type == GL_UNSIGNED_BYTE)
+ {
+ computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
+ }
+ else if (type == GL_UNSIGNED_INT)
+ {
+ computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
+ }
+ else if (type == GL_UNSIGNED_SHORT)
+ {
+ computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
+ }
+ else UNREACHABLE();
}
-GLenum IndexDataManager::preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated)
+GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated)
{
- ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT);
- ASSERT(count > 0);
+ D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ bool alignedOffset = false;
- if (arrayElementBuffer != NULL)
+ if (buffer != NULL)
{
- GLsizei offset = reinterpret_cast<GLsizei>(indices);
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break;
+ case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
+ case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break;
+ default: UNREACHABLE(); alignedOffset = false;
+ }
- if (typeSize(type) * count + offset > static_cast<std::size_t>(arrayElementBuffer->size()))
+ if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
{
return GL_INVALID_OPERATION;
}
- indices = static_cast<const GLubyte*>(arrayElementBuffer->data()) + offset;
+ indices = static_cast<const GLubyte*>(buffer->data()) + offset;
}
- translated->count = count;
-
- std::size_t requiredSpace = spaceRequired(type, count);
-
- TranslatedIndexBuffer *streamIb = prepareIndexBuffer(type, requiredSpace);
+ StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
- size_t offset;
- void *output = streamIb->map(requiredSpace, &offset);
+ StaticIndexBuffer *staticBuffer = buffer ? buffer->getIndexBuffer() : NULL;
+ IndexBuffer *indexBuffer = streamingBuffer;
+ UINT streamOffset = 0;
- translated->buffer = streamIb;
- translated->offset = offset;
- translated->indexSize = indexSize(type);
-
- if (type == GL_UNSIGNED_BYTE)
+ if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
{
- const GLubyte *in = static_cast<const GLubyte*>(indices);
- GLushort *out = static_cast<GLushort*>(output);
+ indexBuffer = staticBuffer;
+ streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
- copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex);
+ if (streamOffset == -1)
+ {
+ streamOffset = (offset / typeSize(type)) * indexSize(format);
+ computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+ staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+ }
}
- else if (type == GL_UNSIGNED_INT)
+ else
{
- const GLuint *in = static_cast<const GLuint*>(indices);
+ int convertCount = count;
- if (mIntIndicesSupported)
+ if (staticBuffer)
{
- GLuint *out = static_cast<GLuint*>(output);
+ if (staticBuffer->size() == 0 && alignedOffset)
+ {
+ indexBuffer = staticBuffer;
+ convertCount = buffer->size() / typeSize(type);
+ }
+ else
+ {
+ buffer->invalidateStaticData();
+ staticBuffer = NULL;
+ }
+ }
- copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex);
+ void *output = NULL;
+
+ if (indexBuffer)
+ {
+ indexBuffer->reserveSpace(convertCount * indexSize(format), type);
+ output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
}
- else
+
+ if (output == NULL)
{
- // When 32-bit indices are unsupported, fake them by truncating to 16-bit.
+ ERR("Failed to map index buffer.");
+ return GL_OUT_OF_MEMORY;
+ }
- GLushort *out = static_cast<GLushort*>(output);
+ convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
+ indexBuffer->unmap();
- copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex);
- }
- }
- else
- {
- const GLushort *in = static_cast<const GLushort*>(indices);
- GLushort *out = static_cast<GLushort*>(output);
+ computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
- copyIndices(in, count, out, &translated->minIndex, &translated->maxIndex);
+ if (staticBuffer)
+ {
+ streamOffset = (offset / typeSize(type)) * indexSize(format);
+ staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+ }
}
- streamIb->unmap();
+ translated->indexBuffer = indexBuffer->getBuffer();
+ translated->startIndex = streamOffset / indexSize(format);
return GL_NO_ERROR;
}
-std::size_t IndexDataManager::indexSize(GLenum type) const
+std::size_t IndexDataManager::indexSize(D3DFORMAT format) const
{
- return (type == GL_UNSIGNED_INT && mIntIndicesSupported) ? sizeof(GLuint) : sizeof(GLushort);
+ return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short);
}
std::size_t IndexDataManager::typeSize(GLenum type) const
{
switch (type)
{
- case GL_UNSIGNED_INT: return sizeof(GLuint);
+ case GL_UNSIGNED_INT: return sizeof(GLuint);
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
- default: UNREACHABLE();
- case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
+ case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
+ default: UNREACHABLE(); return sizeof(GLushort);
}
}
-std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count) const
+IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL)
{
- return (count + 1) * indexSize(type); // +1 because we always leave an extra for line loops
+ if (size > 0)
+ {
+ D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+ HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL);
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating an index buffer of size %lu.", size);
+ }
+ }
}
-TranslatedIndexBuffer *IndexDataManager::prepareIndexBuffer(GLenum type, std::size_t requiredSpace)
+IndexBuffer::~IndexBuffer()
{
- bool use32 = (type == GL_UNSIGNED_INT && mIntIndicesSupported);
+ if (mIndexBuffer)
+ {
+ mIndexBuffer->Release();
+ }
+}
- TranslatedIndexBuffer *streamIb = use32 ? mStreamBufferInt : mStreamBufferShort;
+IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const
+{
+ return mIndexBuffer;
+}
- if (requiredSpace > streamIb->size())
+void IndexBuffer::unmap()
+{
+ if (mIndexBuffer)
{
- std::size_t newSize = std::max(requiredSpace, 2 * streamIb->size());
+ mIndexBuffer->Unlock();
+ }
+}
- TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize, use32 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT);
+StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format)
+{
+ mWritePosition = 0;
+}
- delete streamIb;
+StreamingIndexBuffer::~StreamingIndexBuffer()
+{
+}
- streamIb = newStreamBuffer;
+void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset)
+{
+ void *mapPtr = NULL;
- if (use32)
- {
- mStreamBufferInt = streamIb;
- }
- else
+ if (mIndexBuffer)
+ {
+ HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
+
+ if (FAILED(result))
{
- mStreamBufferShort = streamIb;
+ ERR(" Lock failed with error 0x%08x", result);
+ return NULL;
}
- }
- streamIb->reserveSpace(requiredSpace);
+ *offset = mWritePosition;
+ mWritePosition += requiredSpace;
+ }
- return streamIb;
+ return mapPtr;
}
-GLenum IndexDataManager::preRenderValidateUnindexed(GLenum mode, GLsizei count, TranslatedIndexData *indexInfo)
+void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
{
- if (count >= 65535) return GL_OUT_OF_MEMORY;
-
- if (mode == GL_LINE_LOOP)
+ if (requiredSpace > mBufferSize)
{
- // For line loops, create a single-use buffer that runs 0 - count-1, 0.
- delete mLineLoopBuffer;
- mLineLoopBuffer = mBackend->createIndexBuffer((count+1) * sizeof(unsigned short), GL_UNSIGNED_SHORT);
-
- unsigned short *indices = static_cast<unsigned short *>(mLineLoopBuffer->map());
-
- for (int i = 0; i < count; i++)
+ if (mIndexBuffer)
{
- indices[i] = i;
+ mIndexBuffer->Release();
+ mIndexBuffer = NULL;
}
- indices[count] = 0;
+ mBufferSize = std::max(requiredSpace, 2 * mBufferSize);
- mLineLoopBuffer->unmap();
+ D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+ HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+ }
- indexInfo->buffer = mLineLoopBuffer;
- indexInfo->count = count + 1;
- indexInfo->maxIndex = count - 1;
+ mWritePosition = 0;
}
- else if (mCountingBufferSize < count)
+ else if (mWritePosition + requiredSpace > mBufferSize) // Recycle
{
- mCountingBufferSize = std::max(static_cast<GLsizei>(ceilPow2(count)), mCountingBufferSize*2);
+ void *dummy;
+ mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ mIndexBuffer->Unlock();
- delete mCountingBuffer;
- mCountingBuffer = mBackend->createIndexBuffer(count * sizeof(unsigned short), GL_UNSIGNED_SHORT);
+ mWritePosition = 0;
+ }
+}
- unsigned short *indices = static_cast<unsigned short *>(mCountingBuffer->map());
+StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN)
+{
+ mCacheType = GL_NONE;
+}
- for (int i = 0; i < count; i++)
+StaticIndexBuffer::~StaticIndexBuffer()
+{
+}
+
+void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset)
+{
+ void *mapPtr = NULL;
+
+ if (mIndexBuffer)
+ {
+ HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
+
+ if (FAILED(result))
{
- indices[i] = i;
+ ERR(" Lock failed with error 0x%08x", result);
+ return NULL;
}
- mCountingBuffer->unmap();
+ *offset = 0;
+ }
+
+ return mapPtr;
+}
+
+void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
+{
+ if (!mIndexBuffer && mBufferSize == 0)
+ {
+ D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY);
+ HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+ }
- indexInfo->buffer = mCountingBuffer;
- indexInfo->count = count;
- indexInfo->maxIndex = count - 1;
+ mBufferSize = requiredSpace;
+ mCacheType = type;
}
- else
+ else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
{
- indexInfo->buffer = mCountingBuffer;
- indexInfo->count = count;
- indexInfo->maxIndex = count - 1;
+ // Already allocated
}
+ else UNREACHABLE(); // Static index buffers can't be resized
+}
- indexInfo->indexSize = sizeof(unsigned short);
- indexInfo->minIndex = 0;
- indexInfo->offset = 0;
+bool StaticIndexBuffer::lookupType(GLenum type)
+{
+ return mCacheType == type;
+}
- return GL_NO_ERROR;
+UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
+{
+ for (unsigned int range = 0; range < mCache.size(); range++)
+ {
+ if (mCache[range].offset == offset && mCache[range].count == count)
+ {
+ *minIndex = mCache[range].minIndex;
+ *maxIndex = mCache[range].maxIndex;
+
+ return mCache[range].streamOffset;
+ }
+ }
+
+ return -1;
+}
+
+void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset)
+{
+ IndexRange indexRange = {offset, count, minIndex, maxIndex, streamOffset};
+ mCache.push_back(indexRange);
}
}