// // Copyright 2002 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/Context.h" #include "libANGLE/renderer/d3d/ContextD3D.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; } } gl::DrawElementsType IndexBufferInterface::getIndexType() const { return mIndexBuffer->getIndexType(); } unsigned int IndexBufferInterface::getBufferSize() const { return mIndexBuffer->getBufferSize(); } unsigned int IndexBufferInterface::getSerial() const { return mIndexBuffer->getSerial(); } angle::Result IndexBufferInterface::mapBuffer(const gl::Context *context, unsigned int size, void **outMappedMemory, unsigned int *streamOffset) { // Protect against integer overflow bool check = (mWritePosition + size < mWritePosition); ANGLE_CHECK(GetImplAs(context), !check, "Mapping of internal index buffer would cause an integer overflow.", GL_OUT_OF_MEMORY); angle::Result error = mIndexBuffer->mapBuffer(context, mWritePosition, size, outMappedMemory); if (error == angle::Result::Stop) { if (outMappedMemory) { *outMappedMemory = nullptr; } return error; } if (streamOffset) { *streamOffset = mWritePosition; } mWritePosition += size; return angle::Result::Continue; } angle::Result IndexBufferInterface::unmapBuffer(const gl::Context *context) { return mIndexBuffer->unmapBuffer(context); } IndexBuffer *IndexBufferInterface::getIndexBuffer() const { return mIndexBuffer; } unsigned int IndexBufferInterface::getWritePosition() const { return mWritePosition; } void IndexBufferInterface::setWritePosition(unsigned int writePosition) { mWritePosition = writePosition; } angle::Result IndexBufferInterface::discard(const gl::Context *context) { return mIndexBuffer->discard(context); } angle::Result IndexBufferInterface::setBufferSize(const gl::Context *context, unsigned int bufferSize, gl::DrawElementsType indexType) { if (mIndexBuffer->getBufferSize() == 0) { return mIndexBuffer->initialize(context, bufferSize, indexType, mDynamic); } else { return mIndexBuffer->setSize(context, bufferSize, indexType); } } StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory) : IndexBufferInterface(factory, true) {} StreamingIndexBufferInterface::~StreamingIndexBufferInterface() {} angle::Result StreamingIndexBufferInterface::reserveBufferSpace(const gl::Context *context, unsigned int size, gl::DrawElementsType indexType) { unsigned int curBufferSize = getBufferSize(); unsigned int writePos = getWritePosition(); if (size > curBufferSize) { ANGLE_TRY(setBufferSize(context, std::max(size, 2 * curBufferSize), indexType)); setWritePosition(0); } else if (writePos + size > curBufferSize || writePos + size < writePos) { ANGLE_TRY(discard(context)); setWritePosition(0); } return angle::Result::Continue; } StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory) : IndexBufferInterface(factory, false) {} StaticIndexBufferInterface::~StaticIndexBufferInterface() {} angle::Result StaticIndexBufferInterface::reserveBufferSpace(const gl::Context *context, unsigned int size, gl::DrawElementsType indexType) { unsigned int curSize = getBufferSize(); if (curSize == 0) { return setBufferSize(context, size, indexType); } ASSERT(curSize >= size && indexType == getIndexType()); return angle::Result::Continue; } } // namespace rx