1 #include "precompiled.h"
2 //
3 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 //
7
8 // VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface
9 // class with derivations, classes that perform graphics API agnostic vertex buffer operations.
10
11 #include "libGLESv2/renderer/VertexBuffer.h"
12 #include "libGLESv2/renderer/Renderer.h"
13 #include "libGLESv2/Context.h"
14
15 namespace rx
16 {
17
18 unsigned int VertexBuffer::mNextSerial = 1;
19
VertexBuffer()20 VertexBuffer::VertexBuffer()
21 {
22 updateSerial();
23 }
24
~VertexBuffer()25 VertexBuffer::~VertexBuffer()
26 {
27 }
28
updateSerial()29 void VertexBuffer::updateSerial()
30 {
31 mSerial = mNextSerial++;
32 }
33
getSerial() const34 unsigned int VertexBuffer::getSerial() const
35 {
36 return mSerial;
37 }
38
VertexBufferInterface(rx::Renderer * renderer,bool dynamic)39 VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer)
40 {
41 mDynamic = dynamic;
42 mWritePosition = 0;
43 mReservedSpace = 0;
44
45 mVertexBuffer = renderer->createVertexBuffer();
46 }
47
~VertexBufferInterface()48 VertexBufferInterface::~VertexBufferInterface()
49 {
50 delete mVertexBuffer;
51 }
52
getSerial() const53 unsigned int VertexBufferInterface::getSerial() const
54 {
55 return mVertexBuffer->getSerial();
56 }
57
getBufferSize() const58 unsigned int VertexBufferInterface::getBufferSize() const
59 {
60 return mVertexBuffer->getBufferSize();
61 }
62
setBufferSize(unsigned int size)63 bool VertexBufferInterface::setBufferSize(unsigned int size)
64 {
65 if (mVertexBuffer->getBufferSize() == 0)
66 {
67 return mVertexBuffer->initialize(size, mDynamic);
68 }
69 else
70 {
71 return mVertexBuffer->setBufferSize(size);
72 }
73 }
74
getWritePosition() const75 unsigned int VertexBufferInterface::getWritePosition() const
76 {
77 return mWritePosition;
78 }
79
setWritePosition(unsigned int writePosition)80 void VertexBufferInterface::setWritePosition(unsigned int writePosition)
81 {
82 mWritePosition = writePosition;
83 }
84
discard()85 bool VertexBufferInterface::discard()
86 {
87 return mVertexBuffer->discard();
88 }
89
storeVertexAttributes(const gl::VertexAttribute & attrib,GLint start,GLsizei count,GLsizei instances,unsigned int * outStreamOffset)90 bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
91 unsigned int *outStreamOffset)
92 {
93 unsigned int spaceRequired;
94 if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired))
95 {
96 return false;
97 }
98
99 if (mWritePosition + spaceRequired < mWritePosition)
100 {
101 return false;
102 }
103
104 if (!reserveSpace(mReservedSpace))
105 {
106 return false;
107 }
108 mReservedSpace = 0;
109
110 if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition))
111 {
112 return false;
113 }
114
115 if (outStreamOffset)
116 {
117 *outStreamOffset = mWritePosition;
118 }
119
120 mWritePosition += spaceRequired;
121
122 return true;
123 }
124
storeRawData(const void * data,unsigned int size,unsigned int * outStreamOffset)125 bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset)
126 {
127 if (mWritePosition + size < mWritePosition)
128 {
129 return false;
130 }
131
132 if (!reserveSpace(mReservedSpace))
133 {
134 return false;
135 }
136 mReservedSpace = 0;
137
138 if (!mVertexBuffer->storeRawData(data, size, mWritePosition))
139 {
140 return false;
141 }
142
143 if (outStreamOffset)
144 {
145 *outStreamOffset = mWritePosition;
146 }
147
148 mWritePosition += size;
149
150 return true;
151 }
152
reserveVertexSpace(const gl::VertexAttribute & attribute,GLsizei count,GLsizei instances)153 bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances)
154 {
155 unsigned int requiredSpace;
156 if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace))
157 {
158 return false;
159 }
160
161 // Protect against integer overflow
162 if (mReservedSpace + requiredSpace < mReservedSpace)
163 {
164 return false;
165 }
166
167 mReservedSpace += requiredSpace;
168 return true;
169 }
170
reserveRawDataSpace(unsigned int size)171 bool VertexBufferInterface::reserveRawDataSpace(unsigned int size)
172 {
173 // Protect against integer overflow
174 if (mReservedSpace + size < mReservedSpace)
175 {
176 return false;
177 }
178
179 mReservedSpace += size;
180 return true;
181 }
182
getVertexBuffer() const183 VertexBuffer* VertexBufferInterface::getVertexBuffer() const
184 {
185 return mVertexBuffer;
186 }
187
188
StreamingVertexBufferInterface(rx::Renderer * renderer,std::size_t initialSize)189 StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
190 {
191 setBufferSize(initialSize);
192 }
193
~StreamingVertexBufferInterface()194 StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
195 {
196 }
197
reserveSpace(unsigned int size)198 bool StreamingVertexBufferInterface::reserveSpace(unsigned int size)
199 {
200 bool result = true;
201 unsigned int curBufferSize = getBufferSize();
202 if (size > curBufferSize)
203 {
204 result = setBufferSize(std::max(size, 3 * curBufferSize / 2));
205 setWritePosition(0);
206 }
207 else if (getWritePosition() + size > curBufferSize)
208 {
209 if (!discard())
210 {
211 return false;
212 }
213 setWritePosition(0);
214 }
215
216 return result;
217 }
218
StaticVertexBufferInterface(rx::Renderer * renderer)219 StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false)
220 {
221 }
222
~StaticVertexBufferInterface()223 StaticVertexBufferInterface::~StaticVertexBufferInterface()
224 {
225 }
226
lookupAttribute(const gl::VertexAttribute & attribute,unsigned int * outStreamOffset)227 bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset)
228 {
229 for (unsigned int element = 0; element < mCache.size(); element++)
230 {
231 if (mCache[element].type == attribute.mType &&
232 mCache[element].size == attribute.mSize &&
233 mCache[element].stride == attribute.stride() &&
234 mCache[element].normalized == attribute.mNormalized)
235 {
236 if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
237 {
238 if (outStreamOffset)
239 {
240 *outStreamOffset = mCache[element].streamOffset;
241 }
242 return true;
243 }
244 }
245 }
246
247 return false;
248 }
249
reserveSpace(unsigned int size)250 bool StaticVertexBufferInterface::reserveSpace(unsigned int size)
251 {
252 unsigned int curSize = getBufferSize();
253 if (curSize == 0)
254 {
255 setBufferSize(size);
256 return true;
257 }
258 else if (curSize >= size)
259 {
260 return true;
261 }
262 else
263 {
264 UNREACHABLE(); // Static vertex buffers can't be resized
265 return false;
266 }
267 }
268
storeVertexAttributes(const gl::VertexAttribute & attrib,GLint start,GLsizei count,GLsizei instances,unsigned int * outStreamOffset)269 bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
270 unsigned int *outStreamOffset)
271 {
272 unsigned int streamOffset;
273 if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset))
274 {
275 int attributeOffset = attrib.mOffset % attrib.stride();
276 VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset };
277 mCache.push_back(element);
278
279 if (outStreamOffset)
280 {
281 *outStreamOffset = streamOffset;
282 }
283
284 return true;
285 }
286 else
287 {
288 return false;
289 }
290 }
291
292 }
293