1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface 8 // class with derivations, classes that perform graphics API agnostic index buffer operations. 9 10 #include "libANGLE/renderer/d3d/IndexBuffer.h" 11 12 #include "libANGLE/Context.h" 13 #include "libANGLE/renderer/d3d/ContextD3D.h" 14 15 namespace rx 16 { 17 18 unsigned int IndexBuffer::mNextSerial = 1; 19 IndexBuffer()20 IndexBuffer::IndexBuffer() 21 { 22 updateSerial(); 23 } 24 ~IndexBuffer()25 IndexBuffer::~IndexBuffer() {} 26 getSerial() const27 unsigned int IndexBuffer::getSerial() const 28 { 29 return mSerial; 30 } 31 updateSerial()32 void IndexBuffer::updateSerial() 33 { 34 mSerial = mNextSerial++; 35 } 36 IndexBufferInterface(BufferFactoryD3D * factory,bool dynamic)37 IndexBufferInterface::IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic) 38 { 39 mIndexBuffer = factory->createIndexBuffer(); 40 41 mDynamic = dynamic; 42 mWritePosition = 0; 43 } 44 ~IndexBufferInterface()45 IndexBufferInterface::~IndexBufferInterface() 46 { 47 if (mIndexBuffer) 48 { 49 delete mIndexBuffer; 50 } 51 } 52 getIndexType() const53 gl::DrawElementsType IndexBufferInterface::getIndexType() const 54 { 55 return mIndexBuffer->getIndexType(); 56 } 57 getBufferSize() const58 unsigned int IndexBufferInterface::getBufferSize() const 59 { 60 return mIndexBuffer->getBufferSize(); 61 } 62 getSerial() const63 unsigned int IndexBufferInterface::getSerial() const 64 { 65 return mIndexBuffer->getSerial(); 66 } 67 mapBuffer(const gl::Context * context,unsigned int size,void ** outMappedMemory,unsigned int * streamOffset)68 angle::Result IndexBufferInterface::mapBuffer(const gl::Context *context, 69 unsigned int size, 70 void **outMappedMemory, 71 unsigned int *streamOffset) 72 { 73 // Protect against integer overflow 74 bool check = (mWritePosition + size < mWritePosition); 75 ANGLE_CHECK(GetImplAs<ContextD3D>(context), !check, 76 "Mapping of internal index buffer would cause an integer overflow.", 77 GL_OUT_OF_MEMORY); 78 79 angle::Result error = mIndexBuffer->mapBuffer(context, mWritePosition, size, outMappedMemory); 80 if (error == angle::Result::Stop) 81 { 82 if (outMappedMemory) 83 { 84 *outMappedMemory = nullptr; 85 } 86 return error; 87 } 88 89 if (streamOffset) 90 { 91 *streamOffset = mWritePosition; 92 } 93 94 mWritePosition += size; 95 return angle::Result::Continue; 96 } 97 unmapBuffer(const gl::Context * context)98 angle::Result IndexBufferInterface::unmapBuffer(const gl::Context *context) 99 { 100 return mIndexBuffer->unmapBuffer(context); 101 } 102 getIndexBuffer() const103 IndexBuffer *IndexBufferInterface::getIndexBuffer() const 104 { 105 return mIndexBuffer; 106 } 107 getWritePosition() const108 unsigned int IndexBufferInterface::getWritePosition() const 109 { 110 return mWritePosition; 111 } 112 setWritePosition(unsigned int writePosition)113 void IndexBufferInterface::setWritePosition(unsigned int writePosition) 114 { 115 mWritePosition = writePosition; 116 } 117 discard(const gl::Context * context)118 angle::Result IndexBufferInterface::discard(const gl::Context *context) 119 { 120 return mIndexBuffer->discard(context); 121 } 122 setBufferSize(const gl::Context * context,unsigned int bufferSize,gl::DrawElementsType indexType)123 angle::Result IndexBufferInterface::setBufferSize(const gl::Context *context, 124 unsigned int bufferSize, 125 gl::DrawElementsType indexType) 126 { 127 if (mIndexBuffer->getBufferSize() == 0) 128 { 129 return mIndexBuffer->initialize(context, bufferSize, indexType, mDynamic); 130 } 131 else 132 { 133 return mIndexBuffer->setSize(context, bufferSize, indexType); 134 } 135 } 136 StreamingIndexBufferInterface(BufferFactoryD3D * factory)137 StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory) 138 : IndexBufferInterface(factory, true) 139 {} 140 ~StreamingIndexBufferInterface()141 StreamingIndexBufferInterface::~StreamingIndexBufferInterface() {} 142 reserveBufferSpace(const gl::Context * context,unsigned int size,gl::DrawElementsType indexType)143 angle::Result StreamingIndexBufferInterface::reserveBufferSpace(const gl::Context *context, 144 unsigned int size, 145 gl::DrawElementsType indexType) 146 { 147 unsigned int curBufferSize = getBufferSize(); 148 unsigned int writePos = getWritePosition(); 149 if (size > curBufferSize) 150 { 151 ANGLE_TRY(setBufferSize(context, std::max(size, 2 * curBufferSize), indexType)); 152 setWritePosition(0); 153 } 154 else if (writePos + size > curBufferSize || writePos + size < writePos) 155 { 156 ANGLE_TRY(discard(context)); 157 setWritePosition(0); 158 } 159 160 return angle::Result::Continue; 161 } 162 StaticIndexBufferInterface(BufferFactoryD3D * factory)163 StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory) 164 : IndexBufferInterface(factory, false) 165 {} 166 ~StaticIndexBufferInterface()167 StaticIndexBufferInterface::~StaticIndexBufferInterface() {} 168 reserveBufferSpace(const gl::Context * context,unsigned int size,gl::DrawElementsType indexType)169 angle::Result StaticIndexBufferInterface::reserveBufferSpace(const gl::Context *context, 170 unsigned int size, 171 gl::DrawElementsType indexType) 172 { 173 unsigned int curSize = getBufferSize(); 174 if (curSize == 0) 175 { 176 return setBufferSize(context, size, indexType); 177 } 178 179 ASSERT(curSize >= size && indexType == getIndexType()); 180 return angle::Result::Continue; 181 } 182 183 } // namespace rx 184