blob: 555279ef12cc2b05b64efd15dc4bf4cd62330d9f [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
Geoff Lang6b10ddb2015-09-02 15:55:10 -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
Geoff Lang2b835a62015-09-10 15:58:44 -0400333 if (attrib.pureInteger)
334 {
335 ASSERT(!attrib.normalized);
336 mFunctions->vertexAttribIPointer(
337 idx, attrib.size, attrib.type, static_cast<GLsizei>(destStride),
338 reinterpret_cast<const GLvoid *>(vertexStartOffset));
339 }
340 else
341 {
342 mFunctions->vertexAttribPointer(
343 idx, attrib.size, attrib.type, attrib.normalized,
344 static_cast<GLsizei>(destStride),
345 reinterpret_cast<const GLvoid *>(vertexStartOffset));
346 }
Jamie Madill0b9e9032015-08-17 11:51:52 +0000347
348 curBufferOffset += destStride * streamedVertexCount;
349
350 // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
351 // need to be streamed later, there is no chance that the caching will skip it.
352 mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400353 }
354
355 unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
356 }
357
358 if (unmapResult != GL_TRUE)
359 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000360 return Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
Geoff Lang7c82bc42015-03-09 16:18:08 -0400361 }
362
Jamie Madill0b9e9032015-08-17 11:51:52 +0000363 return Error(GL_NO_ERROR);
Geoff Langba4c4a82015-02-24 12:38:46 -0500364}
365
366GLuint VertexArrayGL::getVertexArrayID() const
367{
368 return mVertexArrayID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500369}
370
Geoff Lang294cad92015-05-26 15:11:23 -0400371GLuint VertexArrayGL::getAppliedElementArrayBufferID() const
372{
Jamie Madill77a90c22015-08-11 16:33:17 -0400373 if (mAppliedElementArrayBuffer.get() == nullptr)
374 {
375 return mStreamingElementArrayBuffer;
376 }
377
378 return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
Geoff Lang294cad92015-05-26 15:11:23 -0400379}
380
Jamie Madill0b9e9032015-08-17 11:51:52 +0000381void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
382{
383 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
384 mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib));
Geoff Langf9a6f082015-01-22 13:32:49 -0500385}
Jamie Madill0b9e9032015-08-17 11:51:52 +0000386
387void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
388{
389 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
390 if (mAppliedAttributes[attribIndex].enabled == attrib.enabled)
391 {
392 return;
393 }
394
395 updateNeedsStreaming(attribIndex);
396
397 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
398 if (attrib.enabled)
399 {
400 mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
401 }
402 else
403 {
404 mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
405 }
406 mAppliedAttributes[attribIndex].enabled = attrib.enabled;
407}
408
409void VertexArrayGL::updateAttribPointer(size_t attribIndex)
410{
411 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
412 if (mAppliedAttributes[attribIndex] == attrib)
413 {
414 return;
415 }
416
417 updateNeedsStreaming(attribIndex);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000418
419 // If we need to stream, defer the attribPointer to the draw call.
420 if (mAttributesNeedStreaming[attribIndex])
421 {
422 return;
423 }
424
425 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
426 const Buffer *arrayBuffer = attrib.buffer.get();
427 if (arrayBuffer != nullptr)
428 {
429 const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
430 mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
431 }
432 else
433 {
434 mStateManager->bindBuffer(GL_ARRAY_BUFFER, 0);
435 }
Geoff Lang3caa6522015-08-27 14:38:52 -0400436 mAppliedAttributes[attribIndex].buffer = attrib.buffer;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000437
438 if (attrib.pureInteger)
439 {
440 mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
441 attrib.stride, attrib.pointer);
442 }
443 else
444 {
445 mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
446 attrib.normalized, attrib.stride, attrib.pointer);
447 }
Geoff Lang3caa6522015-08-27 14:38:52 -0400448 mAppliedAttributes[attribIndex].size = attrib.size;
449 mAppliedAttributes[attribIndex].type = attrib.type;
450 mAppliedAttributes[attribIndex].normalized = attrib.normalized;
451 mAppliedAttributes[attribIndex].pureInteger = attrib.pureInteger;
452 mAppliedAttributes[attribIndex].stride = attrib.stride;
453 mAppliedAttributes[attribIndex].pointer = attrib.pointer;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000454}
455
456void VertexArrayGL::syncState(const VertexArray::DirtyBits &dirtyBits)
457{
458 for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits))
459 {
460 if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
461 {
462 // TODO(jmadill): Element array buffer bindings
463 }
464 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
465 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
466 {
467 size_t attribIndex =
468 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED;
469 updateAttribEnabled(attribIndex);
470 }
471 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
472 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
473 {
474 size_t attribIndex =
475 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_POINTER;
476 updateAttribPointer(attribIndex);
477 }
478 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR &&
479 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR)
480 {
481 size_t attribIndex =
482 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR;
483 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
484
485 if (mAppliedAttributes[attribIndex].divisor != attrib.divisor)
486 {
487 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
488 mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), attrib.divisor);
489 mAppliedAttributes[attribIndex].divisor = attrib.divisor;
490 }
491 }
492 else
493 UNREACHABLE();
494 }
495}
496
497} // rx