|
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 |
|
20 VertexBuffer::VertexBuffer() |
|
21 { |
|
22 updateSerial(); |
|
23 } |
|
24 |
|
25 VertexBuffer::~VertexBuffer() |
|
26 { |
|
27 } |
|
28 |
|
29 void VertexBuffer::updateSerial() |
|
30 { |
|
31 mSerial = mNextSerial++; |
|
32 } |
|
33 |
|
34 unsigned int VertexBuffer::getSerial() const |
|
35 { |
|
36 return mSerial; |
|
37 } |
|
38 |
|
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 |
|
48 VertexBufferInterface::~VertexBufferInterface() |
|
49 { |
|
50 delete mVertexBuffer; |
|
51 } |
|
52 |
|
53 unsigned int VertexBufferInterface::getSerial() const |
|
54 { |
|
55 return mVertexBuffer->getSerial(); |
|
56 } |
|
57 |
|
58 unsigned int VertexBufferInterface::getBufferSize() const |
|
59 { |
|
60 return mVertexBuffer->getBufferSize(); |
|
61 } |
|
62 |
|
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 |
|
75 unsigned int VertexBufferInterface::getWritePosition() const |
|
76 { |
|
77 return mWritePosition; |
|
78 } |
|
79 |
|
80 void VertexBufferInterface::setWritePosition(unsigned int writePosition) |
|
81 { |
|
82 mWritePosition = writePosition; |
|
83 } |
|
84 |
|
85 bool VertexBufferInterface::discard() |
|
86 { |
|
87 return mVertexBuffer->discard(); |
|
88 } |
|
89 |
|
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 |
|
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 |
|
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 |
|
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 |
|
183 VertexBuffer* VertexBufferInterface::getVertexBuffer() const |
|
184 { |
|
185 return mVertexBuffer; |
|
186 } |
|
187 |
|
188 |
|
189 StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) |
|
190 { |
|
191 setBufferSize(initialSize); |
|
192 } |
|
193 |
|
194 StreamingVertexBufferInterface::~StreamingVertexBufferInterface() |
|
195 { |
|
196 } |
|
197 |
|
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 |
|
219 StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) |
|
220 { |
|
221 } |
|
222 |
|
223 StaticVertexBufferInterface::~StaticVertexBufferInterface() |
|
224 { |
|
225 } |
|
226 |
|
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 |
|
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 |
|
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 } |