blob: e87097540a7b47147cff55a134e24acc35b6c0e6 [file] [log] [blame]
//
// Copyright (c) 2002-2012 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.
//
// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
// class with derivations, classes that perform graphics API agnostic index buffer operations.
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace rx
{
unsigned int IndexBuffer::mNextSerial = 1;
IndexBuffer::IndexBuffer()
{
updateSerial();
}
IndexBuffer::~IndexBuffer()
{
}
unsigned int IndexBuffer::getSerial() const
{
return mSerial;
}
void IndexBuffer::updateSerial()
{
mSerial = mNextSerial++;
}
IndexBufferInterface::IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
{
mIndexBuffer = factory->createIndexBuffer();
mDynamic = dynamic;
mWritePosition = 0;
}
IndexBufferInterface::~IndexBufferInterface()
{
if (mIndexBuffer)
{
delete mIndexBuffer;
}
}
GLenum IndexBufferInterface::getIndexType() const
{
return mIndexBuffer->getIndexType();
}
unsigned int IndexBufferInterface::getBufferSize() const
{
return mIndexBuffer->getBufferSize();
}
unsigned int IndexBufferInterface::getSerial() const
{
return mIndexBuffer->getSerial();
}
gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMemory, unsigned int *streamOffset)
{
// Protect against integer overflow
if (mWritePosition + size < mWritePosition)
{
return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow.");
}
gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory);
if (error.isError())
{
if (outMappedMemory)
{
*outMappedMemory = nullptr;
}
return error;
}
if (streamOffset)
{
*streamOffset = mWritePosition;
}
mWritePosition += size;
return gl::NoError();
}
gl::Error IndexBufferInterface::unmapBuffer()
{
return mIndexBuffer->unmapBuffer();
}
IndexBuffer * IndexBufferInterface::getIndexBuffer() const
{
return mIndexBuffer;
}
unsigned int IndexBufferInterface::getWritePosition() const
{
return mWritePosition;
}
void IndexBufferInterface::setWritePosition(unsigned int writePosition)
{
mWritePosition = writePosition;
}
gl::Error IndexBufferInterface::discard()
{
return mIndexBuffer->discard();
}
gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
{
if (mIndexBuffer->getBufferSize() == 0)
{
return mIndexBuffer->initialize(bufferSize, indexType, mDynamic);
}
else
{
return mIndexBuffer->setSize(bufferSize, indexType);
}
}
StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory)
: IndexBufferInterface(factory, true)
{
}
StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
{
}
gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
{
unsigned int curBufferSize = getBufferSize();
unsigned int writePos = getWritePosition();
if (size > curBufferSize)
{
gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
if (error.isError())
{
return error;
}
setWritePosition(0);
}
else if (writePos + size > curBufferSize || writePos + size < writePos)
{
gl::Error error = discard();
if (error.isError())
{
return error;
}
setWritePosition(0);
}
return gl::NoError();
}
StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory)
: IndexBufferInterface(factory, false)
{
}
StaticIndexBufferInterface::~StaticIndexBufferInterface()
{
}
gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
{
unsigned int curSize = getBufferSize();
if (curSize == 0)
{
return setBufferSize(size, indexType);
}
else if (curSize >= size && indexType == getIndexType())
{
return gl::NoError();
}
else
{
UNREACHABLE();
return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized");
}
}
}