// // 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 = NULL; } return error; } if (streamOffset) { *streamOffset = mWritePosition; } mWritePosition += size; return gl::Error(GL_NO_ERROR); } 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::Error(GL_NO_ERROR); } 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::Error(GL_NO_ERROR); } else { UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized"); } } }