blob: 1166ae2d3f4e53233c525a81459fb843deb4c474 [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 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// VertexArrayGL.cpp: Implements the class methods for VertexArrayGL.
8
9#include "libANGLE/renderer/gl/VertexArrayGL.h"
10
Jamie Madill0b9e9032015-08-17 11:51:52 +000011#include "common/BitSetIterator.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050012#include "common/debug.h"
Geoff Lang7c82bc42015-03-09 16:18:08 -040013#include "common/mathutil.h"
Geoff Lang831b1952015-05-05 11:02:27 -040014#include "common/utilities.h"
Geoff Lang6ae6efc2015-03-09 14:42:35 -040015#include "libANGLE/Buffer.h"
Geoff Langba4c4a82015-02-24 12:38:46 -050016#include "libANGLE/angletypes.h"
Geoff Lang7c82bc42015-03-09 16:18:08 -040017#include "libANGLE/formatutils.h"
Geoff Langba4c4a82015-02-24 12:38:46 -050018#include "libANGLE/renderer/gl/BufferGL.h"
19#include "libANGLE/renderer/gl/FunctionsGL.h"
20#include "libANGLE/renderer/gl/StateManagerGL.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050021
Jamie Madill0b9e9032015-08-17 11:51:52 +000022using namespace gl;
23
Geoff Langf9a6f082015-01-22 13:32:49 -050024namespace rx
25{
Jamie Madill0b9e9032015-08-17 11:51:52 +000026namespace
27{
28bool AttributeNeedsStreaming(const VertexAttribute &attribute)
29{
30 return (attribute.enabled && attribute.buffer.get() == nullptr);
31}
Geoff Langf9a6f082015-01-22 13:32:49 -050032
Jamie Madill0b9e9032015-08-17 11:51:52 +000033} // anonymous namespace
34
35VertexArrayGL::VertexArrayGL(const VertexArray::Data &data,
Jamie Madill77a90c22015-08-11 16:33:17 -040036 const FunctionsGL *functions,
37 StateManagerGL *stateManager)
Jamie Madill8e344942015-07-09 14:22:07 -040038 : VertexArrayImpl(data),
Geoff Langba4c4a82015-02-24 12:38:46 -050039 mFunctions(functions),
40 mStateManager(stateManager),
41 mVertexArrayID(0),
Jamie Madill77a90c22015-08-11 16:33:17 -040042 mAppliedElementArrayBuffer(),
Geoff Lang7c82bc42015-03-09 16:18:08 -040043 mStreamingElementArrayBufferSize(0),
44 mStreamingElementArrayBuffer(0),
45 mStreamingArrayBufferSize(0),
46 mStreamingArrayBuffer(0)
Geoff Langba4c4a82015-02-24 12:38:46 -050047{
48 ASSERT(mFunctions);
49 ASSERT(mStateManager);
50 mFunctions->genVertexArrays(1, &mVertexArrayID);
51
52 // Set the cached vertex attribute array size
53 GLint maxVertexAttribs;
54 mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
55 mAppliedAttributes.resize(maxVertexAttribs);
56}
Geoff Langf9a6f082015-01-22 13:32:49 -050057
58VertexArrayGL::~VertexArrayGL()
Geoff Langba4c4a82015-02-24 12:38:46 -050059{
Geoff Lang1eb708e2015-05-04 14:58:23 -040060 mStateManager->deleteVertexArray(mVertexArrayID);
61 mVertexArrayID = 0;
Geoff Langba4c4a82015-02-24 12:38:46 -050062
Geoff Lang1eb708e2015-05-04 14:58:23 -040063 mStateManager->deleteBuffer(mStreamingElementArrayBuffer);
64 mStreamingElementArrayBufferSize = 0;
65 mStreamingElementArrayBuffer = 0;
Geoff Lang7c82bc42015-03-09 16:18:08 -040066
Geoff Lang1eb708e2015-05-04 14:58:23 -040067 mStateManager->deleteBuffer(mStreamingArrayBuffer);
68 mStreamingArrayBufferSize = 0;
69 mStreamingArrayBuffer = 0;
Geoff Lang7c82bc42015-03-09 16:18:08 -040070
Jamie Madill77a90c22015-08-11 16:33:17 -040071 mAppliedElementArrayBuffer.set(nullptr);
Geoff Langba4c4a82015-02-24 12:38:46 -050072 for (size_t idx = 0; idx < mAppliedAttributes.size(); idx++)
73 {
Jamie Madill8e344942015-07-09 14:22:07 -040074 mAppliedAttributes[idx].buffer.set(nullptr);
Geoff Langba4c4a82015-02-24 12:38:46 -050075 }
76}
Geoff Langf9a6f082015-01-22 13:32:49 -050077
Jamie Madill0b9e9032015-08-17 11:51:52 +000078gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
79 GLint first,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040080 GLsizei count,
81 GLsizei instanceCount) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040082{
Geoff Lang3cf12ce2015-08-27 14:40:48 -040083 return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount,
84 nullptr);
Geoff Lang7c82bc42015-03-09 16:18:08 -040085}
86
Jamie Madill0b9e9032015-08-17 11:51:52 +000087gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
88 GLsizei count,
89 GLenum type,
90 const GLvoid *indices,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040091 GLsizei instanceCount,
Jamie Madill0b9e9032015-08-17 11:51:52 +000092 const GLvoid **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040093{
Geoff Lang3cf12ce2015-08-27 14:40:48 -040094 return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -040095}
96
Jamie Madill0b9e9032015-08-17 11:51:52 +000097gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
98 GLint first,
99 GLsizei count,
100 GLenum type,
101 const GLvoid *indices,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400102 GLsizei instanceCount,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000103 const GLvoid **outIndices) const
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400104{
Jamie Madill77a90c22015-08-11 16:33:17 -0400105 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400106
Geoff Lang7c82bc42015-03-09 16:18:08 -0400107 // Check if any attributes need to be streamed, determines if the index range needs to be computed
Jamie Madill0b9e9032015-08-17 11:51:52 +0000108 bool attributesNeedStreaming = mAttributesNeedStreaming.any();
Geoff Lang7c82bc42015-03-09 16:18:08 -0400109
110 // Determine if an index buffer needs to be streamed and the range of vertices that need to be copied
Jamie Madill0b9e9032015-08-17 11:51:52 +0000111 RangeUI indexRange(0, 0);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400112 if (type != GL_NONE)
Geoff Langba4c4a82015-02-24 12:38:46 -0500113 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000114 Error error =
115 syncIndexData(count, type, indices, attributesNeedStreaming, &indexRange, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400116 if (error.isError())
117 {
118 return error;
119 }
120 }
121 else
122 {
Corentin Wallez2c34a4b2015-08-25 16:26:02 -0400123 // Not an indexed call, set the range to [first, first + count - 1]
Geoff Lang7c82bc42015-03-09 16:18:08 -0400124 indexRange.start = first;
Corentin Wallez2c34a4b2015-08-25 16:26:02 -0400125 indexRange.end = first + count - 1;
Geoff Langba4c4a82015-02-24 12:38:46 -0500126 }
127
Jamie Madill0b9e9032015-08-17 11:51:52 +0000128 if (attributesNeedStreaming)
Geoff Langba4c4a82015-02-24 12:38:46 -0500129 {
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400130 Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400131 if (error.isError())
132 {
133 return error;
134 }
135 }
136
Jamie Madill0b9e9032015-08-17 11:51:52 +0000137 return Error(GL_NO_ERROR);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400138}
139
Jamie Madill0b9e9032015-08-17 11:51:52 +0000140Error VertexArrayGL::syncIndexData(GLsizei count,
141 GLenum type,
142 const GLvoid *indices,
143 bool attributesNeedStreaming,
144 RangeUI *outIndexRange,
145 const GLvoid **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400146{
147 ASSERT(outIndices);
148
Jamie Madill8e344942015-07-09 14:22:07 -0400149 gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
150
Geoff Lang7c82bc42015-03-09 16:18:08 -0400151 // Need to check the range of indices if attributes need to be streamed
Jamie Madill8e344942015-07-09 14:22:07 -0400152 if (elementArrayBuffer != nullptr)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400153 {
Jamie Madill77a90c22015-08-11 16:33:17 -0400154 if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400155 {
Jamie Madill77a90c22015-08-11 16:33:17 -0400156 const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
157 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
158 mAppliedElementArrayBuffer.set(elementArrayBuffer);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400159 }
160
161 // Only compute the index range if the attributes also need to be streamed
162 if (attributesNeedStreaming)
163 {
164 ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000165 Error error = mData.getElementArrayBuffer()->getIndexRange(
166 type, static_cast<size_t>(elementArrayBufferOffset), count, outIndexRange);
Geoff Lang520c4ae2015-05-05 13:12:36 -0400167 if (error.isError())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400168 {
Geoff Lang520c4ae2015-05-05 13:12:36 -0400169 return error;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400170 }
171 }
172
173 // Indices serves as an offset into the index buffer in this case, use the same value for the draw call
174 *outIndices = indices;
175 }
176 else
177 {
178 // Need to stream the index buffer
179 // TODO: if GLES, nothing needs to be streamed
180
181 // Only compute the index range if the attributes also need to be streamed
182 if (attributesNeedStreaming)
183 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000184 *outIndexRange = ComputeIndexRange(type, indices, count);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400185 }
186
187 // Allocate the streaming element array buffer
188 if (mStreamingElementArrayBuffer == 0)
189 {
190 mFunctions->genBuffers(1, &mStreamingElementArrayBuffer);
191 mStreamingElementArrayBufferSize = 0;
192 }
193
194 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
Jamie Madill77a90c22015-08-11 16:33:17 -0400195 mAppliedElementArrayBuffer.set(nullptr);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400196
197 // Make sure the element array buffer is large enough
Jamie Madill0b9e9032015-08-17 11:51:52 +0000198 const Type &indexTypeInfo = GetTypeInfo(type);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400199 size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
200 if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
201 {
202 // Copy the indices in while resizing the buffer
203 mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices, GL_DYNAMIC_DRAW);
204 mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
205 }
206 else
207 {
208 // Put the indices at the beginning of the buffer
209 mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize, indices);
210 }
211
212 // Set the index offset for the draw call to zero since the supplied index pointer is to client data
213 *outIndices = nullptr;
214 }
215
Jamie Madill0b9e9032015-08-17 11:51:52 +0000216 return Error(GL_NO_ERROR);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400217}
218
Jamie Madill0b9e9032015-08-17 11:51:52 +0000219void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400220 GLsizei instanceCount,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000221 const gl::RangeUI &indexRange,
222 size_t *outStreamingDataSize,
223 size_t *outMaxAttributeDataSize) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400224{
Jamie Madill0b9e9032015-08-17 11:51:52 +0000225 *outStreamingDataSize = 0;
226 *outMaxAttributeDataSize = 0;
227
228 ASSERT(mAttributesNeedStreaming.any());
229
230 const auto &attribs = mData.getVertexAttributes();
231 for (unsigned int idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
232 {
233 const auto &attrib = attribs[idx];
234 ASSERT(AttributeNeedsStreaming(attrib));
235
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400236 const size_t vertexCount = indexRange.end - indexRange.start + 1;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000237
238 // If streaming is going to be required, compute the size of the required buffer
239 // and how much slack space at the beginning of the buffer will be required by determining
240 // the attribute with the largest data size.
241 size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400242 *outStreamingDataSize +=
243 typeSize * ComputeVertexAttributeElementCount(attrib, vertexCount, instanceCount);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000244 *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
245 }
246}
247
248gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400249 GLsizei instanceCount,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000250 const gl::RangeUI &indexRange) const
251{
252 // Sync the vertex attribute state and track what data needs to be streamed
253 size_t streamingDataSize = 0;
254 size_t maxAttributeDataSize = 0;
255
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400256 computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange,
257 &streamingDataSize, &maxAttributeDataSize);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000258
259 if (streamingDataSize == 0)
260 {
261 return gl::Error(GL_NO_ERROR);
262 }
263
Geoff Lang7c82bc42015-03-09 16:18:08 -0400264 if (mStreamingArrayBuffer == 0)
265 {
266 mFunctions->genBuffers(1, &mStreamingArrayBuffer);
267 mStreamingArrayBufferSize = 0;
268 }
269
270 // If first is greater than zero, a slack space needs to be left at the beginning of the buffer so that
271 // the same 'first' argument can be passed into the draw call.
272 const size_t bufferEmptySpace = maxAttributeDataSize * indexRange.start;
273 const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;
274
275 mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer);
276 if (requiredBufferSize > mStreamingArrayBufferSize)
277 {
278 mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW);
279 mStreamingArrayBufferSize = requiredBufferSize;
280 }
281
282 // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
283 // somehow (such as by a screen change), retry writing the data a few times and return OUT_OF_MEMORY
284 // if that fails.
285 GLboolean unmapResult = GL_FALSE;
286 size_t unmapRetryAttempts = 5;
287 while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
288 {
289 uint8_t *bufferPointer = reinterpret_cast<uint8_t*>(mFunctions->mapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
290 size_t curBufferOffset = bufferEmptySpace;
291
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400292 const size_t vertexCount = indexRange.end - indexRange.start + 1;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400293
Jamie Madill8e344942015-07-09 14:22:07 -0400294 const auto &attribs = mData.getVertexAttributes();
Jamie Madill0b9e9032015-08-17 11:51:52 +0000295 for (unsigned int idx :
296 angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
Geoff Lang7c82bc42015-03-09 16:18:08 -0400297 {
Jamie Madill8e344942015-07-09 14:22:07 -0400298 const auto &attrib = attribs[idx];
Jamie Madill0b9e9032015-08-17 11:51:52 +0000299 ASSERT(AttributeNeedsStreaming(attrib));
Geoff Lang7c82bc42015-03-09 16:18:08 -0400300
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400301 const size_t streamedVertexCount =
302 ComputeVertexAttributeElementCount(attrib, vertexCount, instanceCount);
303
Jamie Madill0b9e9032015-08-17 11:51:52 +0000304 const size_t sourceStride = ComputeVertexAttributeStride(attrib);
305 const size_t destStride = ComputeVertexAttributeTypeSize(attrib);
306
307 const uint8_t *inputPointer = reinterpret_cast<const uint8_t *>(attrib.pointer);
308
309 // Pack the data when copying it, user could have supplied a very large stride that
310 // would cause the buffer to be much larger than needed.
311 if (destStride == sourceStride)
Jamie Madill8e344942015-07-09 14:22:07 -0400312 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000313 // Can copy in one go, the data is packed
314 memcpy(bufferPointer + curBufferOffset,
315 inputPointer + (sourceStride * indexRange.start),
316 destStride * streamedVertexCount);
Jamie Madill6d51c702015-08-14 10:38:10 -0400317 }
Jamie Madill0b9e9032015-08-17 11:51:52 +0000318 else
319 {
320 // Copy each vertex individually
Corentin Wallez4d5362d2015-08-25 11:25:14 -0400321 for (size_t vertexIdx = 0; vertexIdx <= streamedVertexCount; vertexIdx++)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000322 {
Corentin Wallez4d5362d2015-08-25 11:25:14 -0400323 uint8_t *out = bufferPointer + curBufferOffset + (destStride * vertexIdx);
324 const uint8_t *in =
325 inputPointer + sourceStride * (vertexIdx + indexRange.start);
326 memcpy(out, in, destStride);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000327 }
328 }
329
330 // Compute where the 0-index vertex would be.
331 const size_t vertexStartOffset = curBufferOffset - (indexRange.start * destStride);
332
333 mFunctions->vertexAttribPointer(idx, attrib.size, attrib.type, attrib.normalized,
334 static_cast<GLsizei>(destStride),
335 reinterpret_cast<const GLvoid *>(vertexStartOffset));
336
337 curBufferOffset += destStride * streamedVertexCount;
338
339 // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
340 // need to be streamed later, there is no chance that the caching will skip it.
341 mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400342 }
343
344 unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
345 }
346
347 if (unmapResult != GL_TRUE)
348 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000349 return Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
Geoff Lang7c82bc42015-03-09 16:18:08 -0400350 }
351
Jamie Madill0b9e9032015-08-17 11:51:52 +0000352 return Error(GL_NO_ERROR);
Geoff Langba4c4a82015-02-24 12:38:46 -0500353}
354
355GLuint VertexArrayGL::getVertexArrayID() const
356{
357 return mVertexArrayID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500358}
359
Geoff Lang294cad92015-05-26 15:11:23 -0400360GLuint VertexArrayGL::getAppliedElementArrayBufferID() const
361{
Jamie Madill77a90c22015-08-11 16:33:17 -0400362 if (mAppliedElementArrayBuffer.get() == nullptr)
363 {
364 return mStreamingElementArrayBuffer;
365 }
366
367 return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
Geoff Lang294cad92015-05-26 15:11:23 -0400368}
369
Jamie Madill0b9e9032015-08-17 11:51:52 +0000370void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
371{
372 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
373 mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib));
Geoff Langf9a6f082015-01-22 13:32:49 -0500374}
Jamie Madill0b9e9032015-08-17 11:51:52 +0000375
376void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
377{
378 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
379 if (mAppliedAttributes[attribIndex].enabled == attrib.enabled)
380 {
381 return;
382 }
383
384 updateNeedsStreaming(attribIndex);
385
386 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
387 if (attrib.enabled)
388 {
389 mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
390 }
391 else
392 {
393 mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
394 }
395 mAppliedAttributes[attribIndex].enabled = attrib.enabled;
396}
397
398void VertexArrayGL::updateAttribPointer(size_t attribIndex)
399{
400 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
401 if (mAppliedAttributes[attribIndex] == attrib)
402 {
403 return;
404 }
405
406 updateNeedsStreaming(attribIndex);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000407
408 // If we need to stream, defer the attribPointer to the draw call.
409 if (mAttributesNeedStreaming[attribIndex])
410 {
411 return;
412 }
413
414 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
415 const Buffer *arrayBuffer = attrib.buffer.get();
416 if (arrayBuffer != nullptr)
417 {
418 const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
419 mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
420 }
421 else
422 {
423 mStateManager->bindBuffer(GL_ARRAY_BUFFER, 0);
424 }
Geoff Lang3caa6522015-08-27 14:38:52 -0400425 mAppliedAttributes[attribIndex].buffer = attrib.buffer;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000426
427 if (attrib.pureInteger)
428 {
429 mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
430 attrib.stride, attrib.pointer);
431 }
432 else
433 {
434 mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
435 attrib.normalized, attrib.stride, attrib.pointer);
436 }
Geoff Lang3caa6522015-08-27 14:38:52 -0400437 mAppliedAttributes[attribIndex].size = attrib.size;
438 mAppliedAttributes[attribIndex].type = attrib.type;
439 mAppliedAttributes[attribIndex].normalized = attrib.normalized;
440 mAppliedAttributes[attribIndex].pureInteger = attrib.pureInteger;
441 mAppliedAttributes[attribIndex].stride = attrib.stride;
442 mAppliedAttributes[attribIndex].pointer = attrib.pointer;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000443}
444
445void VertexArrayGL::syncState(const VertexArray::DirtyBits &dirtyBits)
446{
447 for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits))
448 {
449 if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
450 {
451 // TODO(jmadill): Element array buffer bindings
452 }
453 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
454 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
455 {
456 size_t attribIndex =
457 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED;
458 updateAttribEnabled(attribIndex);
459 }
460 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
461 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
462 {
463 size_t attribIndex =
464 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_POINTER;
465 updateAttribPointer(attribIndex);
466 }
467 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR &&
468 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR)
469 {
470 size_t attribIndex =
471 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR;
472 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
473
474 if (mAppliedAttributes[attribIndex].divisor != attrib.divisor)
475 {
476 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
477 mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), attrib.divisor);
478 mAppliedAttributes[attribIndex].divisor = attrib.divisor;
479 }
480 }
481 else
482 UNREACHABLE();
483 }
484}
485
486} // rx