diff options
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp | 296 |
1 files changed, 106 insertions, 190 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp index 932524c132..8d455b4bf3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-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. // @@ -10,54 +9,20 @@ #include "libGLESv2/renderer/d3d/IndexDataManager.h" #include "libGLESv2/renderer/d3d/BufferD3D.h" - +#include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/main.h" #include "libGLESv2/formatutils.h" -#include "libGLESv2/renderer/d3d/IndexBuffer.h" namespace rx { -IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer) +static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output) { - mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); - if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) - { - delete mStreamingBufferShort; - mStreamingBufferShort = NULL; - } - - mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); - if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) - { - delete mStreamingBufferInt; - mStreamingBufferInt = NULL; - } - - if (!mStreamingBufferShort) - { - // Make sure both buffers are deleted. - delete mStreamingBufferInt; - mStreamingBufferInt = NULL; - - ERR("Failed to allocate the streaming index buffer(s)."); - } - - mCountingBuffer = NULL; -} - -IndexDataManager::~IndexDataManager() -{ - delete mStreamingBufferShort; - delete mStreamingBufferInt; - delete mCountingBuffer; -} - -static void convertIndices(GLenum type, const void *input, GLsizei count, void *output) -{ - if (type == GL_UNSIGNED_BYTE) + if (sourceType == GL_UNSIGNED_BYTE) { + ASSERT(destinationType == GL_UNSIGNED_SHORT); const GLubyte *in = static_cast<const GLubyte*>(input); GLushort *out = static_cast<GLushort*>(output); @@ -66,55 +31,51 @@ static void convertIndices(GLenum type, const void *input, GLsizei count, void * out[i] = in[i]; } } - else if (type == GL_UNSIGNED_INT) + else if (sourceType == GL_UNSIGNED_INT) { + ASSERT(destinationType == GL_UNSIGNED_INT); memcpy(output, input, count * sizeof(GLuint)); } - else if (type == GL_UNSIGNED_SHORT) + else if (sourceType == GL_UNSIGNED_SHORT) { - memcpy(output, input, count * sizeof(GLushort)); + if (destinationType == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else if (destinationType == GL_UNSIGNED_INT) + { + const GLushort *in = static_cast<const GLushort*>(input); + GLuint *out = static_cast<GLuint*>(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else UNREACHABLE(); } else UNREACHABLE(); } -template <class IndexType> -static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +IndexDataManager::IndexDataManager(Renderer *renderer) + : mRenderer(renderer), + mStreamingBufferShort(NULL), + mStreamingBufferInt(NULL) { - *minIndex = indices[0]; - *maxIndex = indices[0]; - - for (GLsizei i = 0; i < count; i++) - { - if (*minIndex > indices[i]) *minIndex = indices[i]; - if (*maxIndex < indices[i]) *maxIndex = indices[i]; - } } -static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +IndexDataManager::~IndexDataManager() { - 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(); + SafeDelete(mStreamingBufferShort); + SafeDelete(mStreamingBufferInt); } -GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) +gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) { - if (!mStreamingBufferShort) - { - return GL_OUT_OF_MEMORY; - } + const gl::Type &typeInfo = gl::GetTypeInfo(type); GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + unsigned int offset = 0; bool alignedOffset = false; @@ -122,10 +83,6 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer if (buffer != NULL) { - if (reinterpret_cast<uintptr_t>(indices) > std::numeric_limits<unsigned int>::max()) - { - return GL_OUT_OF_MEMORY; - } offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices)); storage = BufferD3D::makeBufferD3D(buffer->getImplementation()); @@ -138,59 +95,56 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer default: UNREACHABLE(); alignedOffset = false; } - unsigned int typeSize = gl::GetTypeBytes(type); - - // check for integer overflows - if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeSize) || - typeSize * static_cast<unsigned int>(count) + offset < offset) - { - return GL_OUT_OF_MEMORY; - } - - if (typeSize * static_cast<unsigned int>(count) + offset > storage->getSize()) - { - return GL_INVALID_OPERATION; - } + ASSERT(typeInfo.bytes * static_cast<unsigned int>(count) + offset <= storage->getSize()); indices = static_cast<const GLubyte*>(storage->getData()) + offset; } - StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; - StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; - IndexBufferInterface *indexBuffer = streamingBuffer; + IndexBufferInterface *indexBuffer = NULL; bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && destinationIndexType == type; unsigned int streamOffset = 0; if (directStorage) { - indexBuffer = streamingBuffer; streamOffset = offset; - if (!storage->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, - &translated->maxIndex, NULL)) + if (!buffer->getIndexRangeCache()->findRange(type, offset, count, NULL, NULL)) { - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - storage->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, offset); + buffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, offset); } } else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) { indexBuffer = staticBuffer; - if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, - &translated->maxIndex, &streamOffset)) + if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, NULL, &streamOffset)) { - streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, streamOffset); + streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes; + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); } } - else + + // Avoid D3D11's primitive restart index value + // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx + if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRenderer->getMajorShaderModel() > 3) { + destinationIndexType = GL_UNSIGNED_INT; + directStorage = false; + indexBuffer = NULL; + } + + const gl::Type &destTypeInfo = gl::GetTypeInfo(destinationIndexType); + + if (!directStorage && !indexBuffer) + { + gl::Error error = getStreamingIndexBuffer(destinationIndexType, &indexBuffer); + if (error.isError()) + { + return error; + } + unsigned int convertCount = count; if (staticBuffer) @@ -198,7 +152,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer if (staticBuffer->getBufferSize() == 0 && alignedOffset) { indexBuffer = staticBuffer; - convertCount = storage->getSize() / gl::GetTypeBytes(type); + convertCount = storage->getSize() / typeInfo.bytes; } else { @@ -207,133 +161,95 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer } } - if (!indexBuffer) - { - ERR("No valid index buffer."); - return GL_INVALID_OPERATION; - } + ASSERT(indexBuffer); - unsigned int indexTypeSize = gl::GetTypeBytes(destinationIndexType); - if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize) + if (convertCount > std::numeric_limits<unsigned int>::max() / destTypeInfo.bytes) { - ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize); - return GL_OUT_OF_MEMORY; + return gl::Error(GL_OUT_OF_MEMORY, "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", + convertCount, destTypeInfo.bytes); } - unsigned int bufferSizeRequired = convertCount * indexTypeSize; - if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type)) + unsigned int bufferSizeRequired = convertCount * destTypeInfo.bytes; + error = indexBuffer->reserveBufferSpace(bufferSizeRequired, type); + if (error.isError()) { - ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired); - return GL_OUT_OF_MEMORY; + return error; } void* output = NULL; - if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset)) + error = indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset); + if (error.isError()) { - ERR("Failed to map index buffer."); - return GL_OUT_OF_MEMORY; + return error; } - convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output); + ConvertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output); - if (!indexBuffer->unmapBuffer()) + error = indexBuffer->unmapBuffer(); + if (error.isError()) { - ERR("Failed to unmap index buffer."); - return GL_OUT_OF_MEMORY; + return error; } - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - if (staticBuffer) { - streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, streamOffset); + streamOffset = (offset / typeInfo.bytes) * destTypeInfo.bytes; + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); } } translated->storage = directStorage ? storage : NULL; - translated->indexBuffer = indexBuffer->getIndexBuffer(); + translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL; translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - translated->startIndex = streamOffset / gl::GetTypeBytes(destinationIndexType); + translated->startIndex = streamOffset / destTypeInfo.bytes; translated->startOffset = streamOffset; + translated->indexType = destinationIndexType; if (storage) { - storage->promoteStaticUsage(count * gl::GetTypeBytes(type)); + storage->promoteStaticUsage(count * typeInfo.bytes); } - return GL_NO_ERROR; + return gl::Error(GL_NO_ERROR); } -StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count) +gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer) { - if (count <= 65536) // 16-bit indices + ASSERT(outBuffer); + if (destinationIndexType == GL_UNSIGNED_INT) { - const unsigned int spaceNeeded = count * sizeof(unsigned short); - - if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + if (!mStreamingBufferInt) { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBufferInterface(mRenderer); - mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); - - void* mappedMemory = NULL; - if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) - { - ERR("Failed to map counting buffer."); - return NULL; - } - - unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory); - for(int i = 0; i < count; i++) + mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); + gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) { - data[i] = i; - } - - if (!mCountingBuffer->unmapBuffer()) - { - ERR("Failed to unmap counting buffer."); - return NULL; + SafeDelete(mStreamingBufferInt); + return error; } } + + *outBuffer = mStreamingBufferInt; + return gl::Error(GL_NO_ERROR); } - else if (mStreamingBufferInt) // 32-bit indices supported + else { - const unsigned int spaceNeeded = count * sizeof(unsigned int); + ASSERT(destinationIndexType == GL_UNSIGNED_SHORT); - if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + if (!mStreamingBufferShort) { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBufferInterface(mRenderer); - mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - - void* mappedMemory = NULL; - if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) + mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); + gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); + if (error.isError()) { - ERR("Failed to map counting buffer."); - return NULL; - } - - unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); - for(int i = 0; i < count; i++) - { - data[i] = i; - } - - if (!mCountingBuffer->unmapBuffer()) - { - ERR("Failed to unmap counting buffer."); - return NULL; + SafeDelete(mStreamingBufferShort); + return error; } } - } - else - { - return NULL; - } - return mCountingBuffer; + *outBuffer = mStreamingBufferShort; + return gl::Error(GL_NO_ERROR); + } } } |