Integrated new IndexBuffer into IndexDataManager and Renderer9.

TRAC #22237 Author: Geoff Lang Signed-off-by: Shannon Woods Signed-off-by: Nicolas Capens Signed-off-by: Daniel Koch git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1607 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 0b6d7741
......@@ -70,7 +70,7 @@ void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
memcpy(mContents + offset, data, size);
if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0))
if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
{
invalidateStaticData();
}
......
......@@ -9,8 +9,6 @@
#include "libGLESv2/renderer/IndexBuffer.h"
#include "libGLESv2/renderer/Renderer9.h"
namespace rx
{
......@@ -36,172 +34,143 @@ void IndexBuffer::updateSerial()
}
unsigned int IndexBufferInterface::mCurrentSerial = 1;
IndexBufferInterface::IndexBufferInterface(rx::Renderer9 *renderer, UINT size, D3DFORMAT format) : mRenderer(renderer), mBufferSize(size), mIndexBuffer(NULL)
IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer)
{
if (size > 0)
{
// D3D9_REPLACE
HRESULT result = mRenderer->createIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, &mIndexBuffer);
mSerial = issueSerial();
mIndexBuffer = renderer->createIndexBuffer();
if (FAILED(result))
{
ERR("Out of memory allocating an index buffer of size %lu.", size);
}
}
mDynamic = dynamic;
mWritePosition = 0;
}
IndexBufferInterface::~IndexBufferInterface()
{
if (mIndexBuffer)
{
mIndexBuffer->Release();
delete mIndexBuffer;
}
}
IDirect3DIndexBuffer9 *IndexBufferInterface::getBuffer() const
GLenum IndexBufferInterface::getIndexType() const
{
return mIndexBuffer;
return mIndexBuffer->getIndexType();
}
unsigned int IndexBufferInterface::getSerial() const
unsigned int IndexBufferInterface::getBufferSize() const
{
return mSerial;
return mIndexBuffer->getBufferSize();
}
unsigned int IndexBufferInterface::issueSerial()
unsigned int IndexBufferInterface::getSerial() const
{
return mCurrentSerial++;
return mIndexBuffer->getSerial();
}
void IndexBufferInterface::unmap()
int IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory)
{
if (mIndexBuffer)
if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
{
mIndexBuffer->Unlock();
*outMappedMemory = NULL;
return -1;
}
int oldWritePos = static_cast<int>(mWritePosition);
mWritePosition += size;
return oldWritePos;
}
StreamingIndexBufferInterface::StreamingIndexBufferInterface(rx::Renderer9 *renderer, UINT initialSize, D3DFORMAT format) : IndexBufferInterface(renderer, initialSize, format)
bool IndexBufferInterface::unmapBuffer()
{
mWritePosition = 0;
return mIndexBuffer->unmapBuffer();
}
StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
IndexBuffer * IndexBufferInterface::getIndexBuffer() const
{
return mIndexBuffer;
}
void *StreamingIndexBufferInterface::map(UINT requiredSpace, UINT *offset)
unsigned int IndexBufferInterface::getWritePosition() const
{
void *mapPtr = NULL;
if (mIndexBuffer)
{
HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
if (FAILED(result))
{
ERR(" Lock failed with error 0x%08x", result);
return NULL;
}
return mWritePosition;
}
*offset = mWritePosition;
mWritePosition += requiredSpace;
}
void IndexBufferInterface::setWritePosition(unsigned int writePosition)
{
mWritePosition = writePosition;
}
return mapPtr;
bool IndexBufferInterface::discard()
{
return mIndexBuffer->discard();
}
void StreamingIndexBufferInterface::reserveSpace(UINT requiredSpace, GLenum type)
bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
{
if (requiredSpace > mBufferSize)
if (mIndexBuffer->getBufferSize() == 0)
{
if (mIndexBuffer)
{
mIndexBuffer->Release();
mIndexBuffer = NULL;
}
mBufferSize = std::max(requiredSpace, 2 * mBufferSize);
// D3D9_REPLACE
HRESULT result = mRenderer->createIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, &mIndexBuffer);
mSerial = issueSerial();
if (FAILED(result))
{
ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
}
mWritePosition = 0;
return mIndexBuffer->initialize(bufferSize, indexType, mDynamic);
}
else if (mWritePosition + requiredSpace > mBufferSize) // Recycle
else
{
void *dummy;
mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
mIndexBuffer->Unlock();
mWritePosition = 0;
return mIndexBuffer->setSize(bufferSize, indexType);
}
}
StaticIndexBufferInterface::StaticIndexBufferInterface(rx::Renderer9 *renderer) : IndexBufferInterface(renderer, 0, D3DFMT_UNKNOWN)
StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true)
{
mCacheType = GL_NONE;
}
StaticIndexBufferInterface::~StaticIndexBufferInterface()
StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
{
}
void *StaticIndexBufferInterface::map(UINT requiredSpace, UINT *offset)
bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
{
void *mapPtr = NULL;
if (mIndexBuffer)
bool result = true;
unsigned int curBufferSize = getBufferSize();
if (size > curBufferSize)
{
HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
if (FAILED(result))
result = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
setWritePosition(0);
}
else if (getWritePosition() + size > curBufferSize)
{
if (!discard())
{
ERR(" Lock failed with error 0x%08x", result);
return NULL;
return false;
}
*offset = 0;
setWritePosition(0);
}
return mapPtr;
return result;
}
void StaticIndexBufferInterface::reserveSpace(UINT requiredSpace, GLenum type)
StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false)
{
if (!mIndexBuffer && mBufferSize == 0)
{
// D3D9_REPLACE
HRESULT result = mRenderer->createIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, &mIndexBuffer);
mSerial = issueSerial();
}
if (FAILED(result))
{
ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
}
StaticIndexBufferInterface::~StaticIndexBufferInterface()
{
}
mBufferSize = requiredSpace;
mCacheType = type;
bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
{
unsigned int curSize = getBufferSize();
if (curSize == 0)
{
return setBufferSize(size, indexType);
}
else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
else if (curSize >= size && indexType == getIndexType())
{
// Already allocated
return true;
}
else
{
ERR("Static index buffers can't be resized");
UNREACHABLE();
return false;
}
else UNREACHABLE(); // Static index buffers can't be resized
}
bool StaticIndexBufferInterface::lookupType(GLenum type)
{
return mCacheType == type;
}
UINT StaticIndexBufferInterface::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
......
......@@ -10,9 +10,6 @@
#ifndef LIBGLESV2_RENDERER_INDEXBUFFER_H_
#define LIBGLESV2_RENDERER_INDEXBUFFER_H_
#include <vector>
#include <cstddef>
#define GL_APICALL
#include <GLES2/gl2.h>
......@@ -22,8 +19,6 @@
namespace rx
{
class Renderer9;
class IndexBuffer
{
public:
......@@ -56,60 +51,61 @@ class IndexBuffer
class IndexBufferInterface
{
public:
IndexBufferInterface(rx::Renderer9 *renderer, UINT size, D3DFORMAT format);
IndexBufferInterface(Renderer *renderer, bool dynamic);
virtual ~IndexBufferInterface();
UINT size() const { return mBufferSize; }
virtual void *map(UINT requiredSpace, UINT *offset) = 0;
void unmap();
virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0;
virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
GLenum getIndexType() const;
unsigned int getBufferSize() const;
IDirect3DIndexBuffer9 *getBuffer() const;
unsigned int getSerial() const;
int mapBuffer(unsigned int size, void** outMappedMemory);
bool unmapBuffer();
IndexBuffer *getIndexBuffer() const;
protected:
rx::Renderer9 *const mRenderer; // D3D9_REPLACE
unsigned int getWritePosition() const;
void setWritePosition(unsigned int writePosition);
IDirect3DIndexBuffer9 *mIndexBuffer;
UINT mBufferSize;
bool discard();
unsigned int mSerial;
static unsigned int issueSerial();
static unsigned int mCurrentSerial;
bool setBufferSize(unsigned int bufferSize, GLenum indexType);
private:
DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface);
rx::Renderer *const mRenderer;
IndexBuffer* mIndexBuffer;
unsigned int mWritePosition;
bool mDynamic;
};
class StreamingIndexBufferInterface : public IndexBufferInterface
{
public:
StreamingIndexBufferInterface(rx::Renderer9 *renderer, UINT initialSize, D3DFORMAT format);
StreamingIndexBufferInterface(Renderer *renderer);
~StreamingIndexBufferInterface();
virtual void *map(UINT requiredSpace, UINT *offset);
virtual void reserveSpace(UINT requiredSpace, GLenum type);
private:
UINT mWritePosition;
virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
};
class StaticIndexBufferInterface : public IndexBufferInterface
{
public:
explicit StaticIndexBufferInterface(rx::Renderer9 *renderer);
explicit StaticIndexBufferInterface(Renderer *renderer);
~StaticIndexBufferInterface();
virtual void *map(UINT requiredSpace, UINT *offset);
virtual void reserveSpace(UINT requiredSpace, GLenum type);
virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
bool lookupType(GLenum type);
UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex); // Returns the offset into the index buffer, or -1 if not found
void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset);
private:
GLenum mCacheType;
struct IndexRange
{
intptr_t offset;
......
......@@ -18,28 +18,28 @@
namespace rx
{
IndexDataManager::IndexDataManager(rx::Renderer9 *renderer) : mRenderer(renderer)
IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer)
{
mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
if (renderer->get32BitIndexSupport())
mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer);
if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
{
mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
if (!mStreamingBufferInt)
{
// Don't leave it in a half-initialized state
delete mStreamingBufferShort;
mStreamingBufferShort = NULL;
}
delete mStreamingBufferShort;
mStreamingBufferShort = NULL;
}
else
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).");
}
......@@ -53,7 +53,18 @@ IndexDataManager::~IndexDataManager()
delete mCountingBuffer;
}
void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
static unsigned int indexTypeSize(GLenum type)
{
switch (type)
{
case GL_UNSIGNED_INT: return sizeof(GLuint);
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
default: UNREACHABLE(); return sizeof(GLushort);
}
}
static void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
{
if (type == GL_UNSIGNED_BYTE)
{
......@@ -77,7 +88,7 @@ void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
}
template <class IndexType>
void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
{
*minIndex = indices[0];
*maxIndex = indices[0];
......@@ -89,7 +100,7 @@ void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLu
}
}
void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
{
if (type == GL_UNSIGNED_BYTE)
{
......@@ -106,14 +117,14 @@ void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *min
else UNREACHABLE();
}
GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **d3dIndexBuffer, unsigned int *serial)
GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
{
if (!mStreamingBufferShort)
{
return GL_OUT_OF_MEMORY;
}
D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
intptr_t offset = reinterpret_cast<intptr_t>(indices);
bool alignedOffset = false;
......@@ -127,7 +138,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
default: UNREACHABLE(); alignedOffset = false;
}
if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
if (indexTypeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
{
return GL_INVALID_OPERATION;
}
......@@ -141,14 +152,14 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
IndexBufferInterface *indexBuffer = streamingBuffer;
UINT streamOffset = 0;
if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
if (staticBuffer && staticBuffer->getIndexType() == type && alignedOffset)
{
indexBuffer = staticBuffer;
streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
if (streamOffset == -1)
{
streamOffset = (offset / typeSize(type)) * indexSize(format);
streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
}
......@@ -159,10 +170,10 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
if (staticBuffer)
{
if (staticBuffer->size() == 0 && alignedOffset)
if (staticBuffer->getBufferSize() == 0 && alignedOffset)
{
indexBuffer = staticBuffer;
convertCount = buffer->size() / typeSize(type);
convertCount = buffer->size() / indexTypeSize(type);
}
else
{
......@@ -171,83 +182,81 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
}
}
void *output = NULL;
if (indexBuffer)
if (!indexBuffer)
{
indexBuffer->reserveSpace(convertCount * indexSize(format), type);
output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
ERR("No valid index buffer.");
return GL_INVALID_OPERATION;
}
if (output == NULL)
unsigned int bufferSizeRequired = convertCount * indexTypeSize(destinationIndexType);
indexBuffer->reserveBufferSpace(bufferSizeRequired, type);
void* output = NULL;
streamOffset = indexBuffer->mapBuffer(bufferSizeRequired, &output);
if (streamOffset == -1 || output == NULL)
{
ERR("Failed to map index buffer.");
return GL_OUT_OF_MEMORY;
}
convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
indexBuffer->unmap();
if (!indexBuffer->unmapBuffer())
{
ERR("Failed to unmap index buffer.");
return GL_OUT_OF_MEMORY;
}
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
if (staticBuffer)
{
streamOffset = (offset / typeSize(type)) * indexSize(format);
streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
}
}
*d3dIndexBuffer = indexBuffer->getBuffer();
*serial = indexBuffer->getSerial();
translated->startIndex = streamOffset / indexSize(format);
translated->indexBuffer = indexBuffer->getIndexBuffer();
translated->serial = indexBuffer->getSerial();
translated->startIndex = streamOffset / indexTypeSize(destinationIndexType);
if (buffer)
{
buffer->promoteStaticUsage(count * typeSize(type));
buffer->promoteStaticUsage(count * indexTypeSize(type));
}
return GL_NO_ERROR;
}
std::size_t IndexDataManager::indexSize(D3DFORMAT format) const
{
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_SHORT: return sizeof(GLushort);
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
default: UNREACHABLE(); return sizeof(GLushort);
}
}
StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
{
if (count <= 65536) // 16-bit indices
{
const unsigned int spaceNeeded = count * sizeof(unsigned short);
if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
{
delete mCountingBuffer;
mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
UINT offset;
unsigned short *data = static_cast<unsigned short*>(mCountingBuffer->map(spaceNeeded, &offset));
void* mappedMemory = NULL;
if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
{
ERR("Failed to map counting buffer.");
return NULL;
}
if (data)
unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
for(int i = 0; i < count; i++)
{
for(int i = 0; i < count; i++)
{
data[i] = i;
}
data[i] = i;
}
mCountingBuffer->unmap();
if (!mCountingBuffer->unmapBuffer())
{
ERR("Failed to unmap counting buffer.");
return NULL;
}
}
}
......@@ -255,27 +264,36 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
{
const unsigned int spaceNeeded = count * sizeof(unsigned int);
if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
{
delete mCountingBuffer;
mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
UINT offset;
unsigned int *data = static_cast<unsigned int*>(mCountingBuffer->map(spaceNeeded, &offset));
void* mappedMemory = NULL;
if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
{
ERR("Failed to map counting buffer.");
return NULL;
}
if (data)
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
for(int i = 0; i < count; i++)
{
for(int i = 0; i < count; i++)
{
data[i] = i;
}
data[i] = i;
}
mCountingBuffer->unmap();
if (!mCountingBuffer->unmapBuffer())
{
ERR("Failed to unmap counting buffer.");
return NULL;
}
}
}
else return NULL;
else
{
return NULL;
}
return mCountingBuffer;
}
......
......@@ -32,24 +32,24 @@ struct TranslatedIndexData
UINT minIndex;
UINT maxIndex;
UINT startIndex;
IndexBuffer *indexBuffer;
unsigned int serial;
};
class IndexDataManager
{
public:
IndexDataManager(rx::Renderer9 *renderer);
explicit IndexDataManager(Renderer *renderer);
virtual ~IndexDataManager();
GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **indexBuffer, unsigned int *serial);
GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
StaticIndexBufferInterface *getCountingIndices(GLsizei count);
private:
DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
std::size_t typeSize(GLenum type) const;
std::size_t indexSize(D3DFORMAT format) const;
rx::Renderer9 *const mRenderer; // D3D9_REPLACE
Renderer *const mRenderer;
StreamingIndexBufferInterface *mStreamingBufferShort;
StreamingIndexBufferInterface *mStreamingBufferInt;
......
......@@ -1200,16 +1200,16 @@ GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::Vertex
// Applies the indices and element array bindings to the Direct3D 9 device
GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
{
IDirect3DIndexBuffer9 *indexBuffer;
unsigned int serial;
GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, &indexBuffer, &serial);
GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
if (err == GL_NO_ERROR)
{
if (serial != mAppliedIBSerial)
if (indexInfo->serial != mAppliedIBSerial)
{
mDevice->SetIndices(indexBuffer);
mAppliedIBSerial = serial;
IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
mDevice->SetIndices(indexBuffer->getBuffer());
mAppliedIBSerial = indexInfo->serial;
}
}
......@@ -1231,7 +1231,9 @@ void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
{
if (mAppliedIBSerial != countingIB->getSerial())
{
mDevice->SetIndices(countingIB->getBuffer());
IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
mDevice->SetIndices(indexBuffer->getBuffer());
mAppliedIBSerial = countingIB->getSerial();
}
......@@ -1281,138 +1283,161 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
UINT startIndex = 0;
bool succeeded = false;
if (get32BitIndexSupport())
{
const int spaceNeeded = (count + 1) * sizeof(unsigned int);
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
mLineLoopIB = new StreamingIndexBufferInterface(this);
if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
{
delete mLineLoopIB;
mLineLoopIB = NULL;
ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
}
if (mLineLoopIB)
const int spaceNeeded = (count + 1) * sizeof(unsigned int);
if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
{
mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
UINT offset = 0;
unsigned int *data = static_cast<unsigned int*>(mLineLoopIB->map(spaceNeeded, &offset));
startIndex = offset / 4;
if (data)
{
switch (type)
{
case GL_NONE: // Non-indexed draw
for (int i = 0; i < count; i++)
{
data[i] = i;
}
data[count] = 0;
break;
case GL_UNSIGNED_BYTE:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLubyte*>(indices)[i];
}
data[count] = static_cast<const GLubyte*>(indices)[0];
break;
case GL_UNSIGNED_SHORT:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLushort*>(indices)[i];
}
data[count] = static_cast<const GLushort*>(indices)[0];
break;
case GL_UNSIGNED_INT:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLuint*>(indices)[i];
}
data[count] = static_cast<const GLuint*>(indices)[0];
break;
default: UNREACHABLE();
}
void* mappedMemory = NULL;
int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
if (offset == -1 || mappedMemory == NULL)
{
ERR("Could not map index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
startIndex = static_cast<UINT>(offset) / 4;
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
mLineLoopIB->unmap();
succeeded = true;
switch (type)
{
case GL_NONE: // Non-indexed draw
for (int i = 0; i < count; i++)
{
data[i] = i;
}
data[count] = 0;
break;
case GL_UNSIGNED_BYTE:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLubyte*>(indices)[i];
}
data[count] = static_cast<const GLubyte*>(indices)[0];
break;
case GL_UNSIGNED_SHORT:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLushort*>(indices)[i];
}
data[count] = static_cast<const GLushort*>(indices)[0];
break;
case GL_UNSIGNED_INT:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLuint*>(indices)[i];
}
data[count] = static_cast<const GLuint*>(indices)[0];
break;
default: UNREACHABLE();
}
if (!mLineLoopIB->unmapBuffer())
{
ERR("Could not unmap index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
}
else
{
const int spaceNeeded = (count + 1) * sizeof(unsigned short);
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
mLineLoopIB = new StreamingIndexBufferInterface(this);
if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
{
delete mLineLoopIB;
mLineLoopIB = NULL;
ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
}
if (mLineLoopIB)
const int spaceNeeded = (count + 1) * sizeof(unsigned short);
if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
{
mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
UINT offset = 0;
unsigned short *data = static_cast<unsigned short*>(mLineLoopIB->map(spaceNeeded, &offset));
startIndex = offset / 2;
if (data)
{
switch (type)
{
case GL_NONE: // Non-indexed draw
for (int i = 0; i < count; i++)
{
data[i] = i;
}
data[count] = 0;
break;
case GL_UNSIGNED_BYTE:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLubyte*>(indices)[i];
}
data[count] = static_cast<const GLubyte*>(indices)[0];
break;
case GL_UNSIGNED_SHORT:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLushort*>(indices)[i];
}
data[count] = static_cast<const GLushort*>(indices)[0];
break;
case GL_UNSIGNED_INT:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLuint*>(indices)[i];
}
data[count] = static_cast<const GLuint*>(indices)[0];
break;
default: UNREACHABLE();
}
void* mappedMemory = NULL;
int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
if (offset == -1 || mappedMemory == NULL)
{
ERR("Could not map index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
startIndex = static_cast<UINT>(offset) / 2;
unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
mLineLoopIB->unmap();
succeeded = true;
switch (type)
{
case GL_NONE: // Non-indexed draw
for (int i = 0; i < count; i++)
{
data[i] = i;
}
data[count] = 0;
break;
case GL_UNSIGNED_BYTE:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLubyte*>(indices)[i];
}
data[count] = static_cast<const GLubyte*>(indices)[0];
break;
case GL_UNSIGNED_SHORT:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLushort*>(indices)[i];
}
data[count] = static_cast<const GLushort*>(indices)[0];
break;
case GL_UNSIGNED_INT:
for (int i = 0; i < count; i++)
{
data[i] = static_cast<const GLuint*>(indices)[i];
}
data[count] = static_cast<const GLuint*>(indices)[0];
break;
default: UNREACHABLE();
}
}
if (succeeded)
{
if (mAppliedIBSerial != mLineLoopIB->getSerial())
if (!mLineLoopIB->unmapBuffer())
{
mDevice->SetIndices(mLineLoopIB->getBuffer());
mAppliedIBSerial = mLineLoopIB->getSerial();
ERR("Could not unmap index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
}
mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
}
else
if (mAppliedIBSerial != mLineLoopIB->getSerial())
{
ERR("Could not create a looping index buffer for GL_LINE_LOOP.");
return error(GL_OUT_OF_MEMORY);
IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer());
mDevice->SetIndices(indexBuffer->getBuffer());
mAppliedIBSerial = mLineLoopIB->getSerial();
}
mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
}
void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment