1 //
2 // Copyright (c) 2002-2012 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 #include "libANGLE/renderer/d3d/RendererD3D.h"
12
13 namespace rx
14 {
15
16 unsigned int IndexBuffer::mNextSerial = 1;
17
IndexBuffer()18 IndexBuffer::IndexBuffer()
19 {
20 updateSerial();
21 }
22
~IndexBuffer()23 IndexBuffer::~IndexBuffer()
24 {
25 }
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
37
IndexBufferInterface(BufferFactoryD3D * factory,bool dynamic)38 IndexBufferInterface::IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
39 {
40 mIndexBuffer = factory->createIndexBuffer();
41
42 mDynamic = dynamic;
43 mWritePosition = 0;
44 }
45
~IndexBufferInterface()46 IndexBufferInterface::~IndexBufferInterface()
47 {
48 if (mIndexBuffer)
49 {
50 delete mIndexBuffer;
51 }
52 }
53
getIndexType() const54 GLenum IndexBufferInterface::getIndexType() const
55 {
56 return mIndexBuffer->getIndexType();
57 }
58
getBufferSize() const59 unsigned int IndexBufferInterface::getBufferSize() const
60 {
61 return mIndexBuffer->getBufferSize();
62 }
63
getSerial() const64 unsigned int IndexBufferInterface::getSerial() const
65 {
66 return mIndexBuffer->getSerial();
67 }
68
mapBuffer(unsigned int size,void ** outMappedMemory,unsigned int * streamOffset)69 gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMemory, unsigned int *streamOffset)
70 {
71 // Protect against integer overflow
72 if (mWritePosition + size < mWritePosition)
73 {
74 return gl::OutOfMemory()
75 << "Mapping of internal index buffer would cause an integer overflow.";
76 }
77
78 gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory);
79 if (error.isError())
80 {
81 if (outMappedMemory)
82 {
83 *outMappedMemory = nullptr;
84 }
85 return error;
86 }
87
88 if (streamOffset)
89 {
90 *streamOffset = mWritePosition;
91 }
92
93 mWritePosition += size;
94 return gl::NoError();
95 }
96
unmapBuffer()97 gl::Error IndexBufferInterface::unmapBuffer()
98 {
99 return mIndexBuffer->unmapBuffer();
100 }
101
getIndexBuffer() const102 IndexBuffer * IndexBufferInterface::getIndexBuffer() const
103 {
104 return mIndexBuffer;
105 }
106
getWritePosition() const107 unsigned int IndexBufferInterface::getWritePosition() const
108 {
109 return mWritePosition;
110 }
111
setWritePosition(unsigned int writePosition)112 void IndexBufferInterface::setWritePosition(unsigned int writePosition)
113 {
114 mWritePosition = writePosition;
115 }
116
discard()117 gl::Error IndexBufferInterface::discard()
118 {
119 return mIndexBuffer->discard();
120 }
121
setBufferSize(unsigned int bufferSize,GLenum indexType)122 gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
123 {
124 if (mIndexBuffer->getBufferSize() == 0)
125 {
126 return mIndexBuffer->initialize(bufferSize, indexType, mDynamic);
127 }
128 else
129 {
130 return mIndexBuffer->setSize(bufferSize, indexType);
131 }
132 }
133
StreamingIndexBufferInterface(BufferFactoryD3D * factory)134 StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory)
135 : IndexBufferInterface(factory, true)
136 {
137 }
138
~StreamingIndexBufferInterface()139 StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
140 {
141 }
142
reserveBufferSpace(unsigned int size,GLenum indexType)143 gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
144 {
145 unsigned int curBufferSize = getBufferSize();
146 unsigned int writePos = getWritePosition();
147 if (size > curBufferSize)
148 {
149 ANGLE_TRY(setBufferSize(std::max(size, 2 * curBufferSize), indexType));
150 setWritePosition(0);
151 }
152 else if (writePos + size > curBufferSize || writePos + size < writePos)
153 {
154 ANGLE_TRY(discard());
155 setWritePosition(0);
156 }
157
158 return gl::NoError();
159 }
160
161
StaticIndexBufferInterface(BufferFactoryD3D * factory)162 StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory)
163 : IndexBufferInterface(factory, false)
164 {
165 }
166
~StaticIndexBufferInterface()167 StaticIndexBufferInterface::~StaticIndexBufferInterface()
168 {
169 }
170
reserveBufferSpace(unsigned int size,GLenum indexType)171 gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
172 {
173 unsigned int curSize = getBufferSize();
174 if (curSize == 0)
175 {
176 return setBufferSize(size, indexType);
177 }
178 else if (curSize >= size && indexType == getIndexType())
179 {
180 return gl::NoError();
181 }
182 else
183 {
184 UNREACHABLE();
185 return gl::InternalError() << "Internal static index buffers can't be resized";
186 }
187 }
188
189 } // namespace rx
190