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