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