blob: 708566370be731078f9b0f63ce1c0ead2f9980c9 [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
hendrikwbb7740c2015-10-20 15:30:53 -070053 GLint maxVertexAttribs = 0;
Geoff Langba4c4a82015-02-24 12:38:46 -050054 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 Lang3edfe032015-09-04 16:38:24 -040083 return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount, false,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040084 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,
Geoff Lang3edfe032015-09-04 16:38:24 -040092 bool primitiveRestartEnabled,
Jamie Madill0b9e9032015-08-17 11:51:52 +000093 const GLvoid **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040094{
Geoff Lang3edfe032015-09-04 16:38:24 -040095 return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount,
96 primitiveRestartEnabled, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -040097}
98
Jamie Madill0b9e9032015-08-17 11:51:52 +000099gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
100 GLint first,
101 GLsizei count,
102 GLenum type,
103 const GLvoid *indices,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400104 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400105 bool primitiveRestartEnabled,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000106 const GLvoid **outIndices) const
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400107{
Jamie Madill77a90c22015-08-11 16:33:17 -0400108 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400109
Geoff Lang7c82bc42015-03-09 16:18:08 -0400110 // Check if any attributes need to be streamed, determines if the index range needs to be computed
Jamie Madill0b9e9032015-08-17 11:51:52 +0000111 bool attributesNeedStreaming = mAttributesNeedStreaming.any();
Geoff Lang7c82bc42015-03-09 16:18:08 -0400112
113 // Determine if an index buffer needs to be streamed and the range of vertices that need to be copied
Geoff Lang3edfe032015-09-04 16:38:24 -0400114 IndexRange indexRange;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400115 if (type != GL_NONE)
Geoff Langba4c4a82015-02-24 12:38:46 -0500116 {
Geoff Lang3edfe032015-09-04 16:38:24 -0400117 Error error = syncIndexData(count, type, indices, primitiveRestartEnabled,
118 attributesNeedStreaming, &indexRange, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400119 if (error.isError())
120 {
121 return error;
122 }
123 }
124 else
125 {
Corentin Wallez2c34a4b2015-08-25 16:26:02 -0400126 // Not an indexed call, set the range to [first, first + count - 1]
Geoff Lang7c82bc42015-03-09 16:18:08 -0400127 indexRange.start = first;
Corentin Wallez2c34a4b2015-08-25 16:26:02 -0400128 indexRange.end = first + count - 1;
Geoff Langba4c4a82015-02-24 12:38:46 -0500129 }
130
Jamie Madill0b9e9032015-08-17 11:51:52 +0000131 if (attributesNeedStreaming)
Geoff Langba4c4a82015-02-24 12:38:46 -0500132 {
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400133 Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400134 if (error.isError())
135 {
136 return error;
137 }
138 }
139
Jamie Madill0b9e9032015-08-17 11:51:52 +0000140 return Error(GL_NO_ERROR);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400141}
142
Jamie Madill0b9e9032015-08-17 11:51:52 +0000143Error VertexArrayGL::syncIndexData(GLsizei count,
144 GLenum type,
145 const GLvoid *indices,
Geoff Lang3edfe032015-09-04 16:38:24 -0400146 bool primitiveRestartEnabled,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000147 bool attributesNeedStreaming,
Geoff Lang3edfe032015-09-04 16:38:24 -0400148 IndexRange *outIndexRange,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000149 const GLvoid **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400150{
151 ASSERT(outIndices);
152
Jamie Madill8e344942015-07-09 14:22:07 -0400153 gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
154
Geoff Lang7c82bc42015-03-09 16:18:08 -0400155 // Need to check the range of indices if attributes need to be streamed
Jamie Madill8e344942015-07-09 14:22:07 -0400156 if (elementArrayBuffer != nullptr)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400157 {
Jamie Madill77a90c22015-08-11 16:33:17 -0400158 if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400159 {
Jamie Madill77a90c22015-08-11 16:33:17 -0400160 const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
161 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
162 mAppliedElementArrayBuffer.set(elementArrayBuffer);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400163 }
164
165 // Only compute the index range if the attributes also need to be streamed
166 if (attributesNeedStreaming)
167 {
168 ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000169 Error error = mData.getElementArrayBuffer()->getIndexRange(
Geoff Lang3edfe032015-09-04 16:38:24 -0400170 type, elementArrayBufferOffset, count, primitiveRestartEnabled, outIndexRange);
Geoff Lang520c4ae2015-05-05 13:12:36 -0400171 if (error.isError())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400172 {
Geoff Lang520c4ae2015-05-05 13:12:36 -0400173 return error;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400174 }
175 }
176
177 // Indices serves as an offset into the index buffer in this case, use the same value for the draw call
178 *outIndices = indices;
179 }
180 else
181 {
182 // Need to stream the index buffer
183 // TODO: if GLES, nothing needs to be streamed
184
185 // Only compute the index range if the attributes also need to be streamed
186 if (attributesNeedStreaming)
187 {
Geoff Lang3edfe032015-09-04 16:38:24 -0400188 *outIndexRange = ComputeIndexRange(type, indices, count, primitiveRestartEnabled);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400189 }
190
191 // Allocate the streaming element array buffer
192 if (mStreamingElementArrayBuffer == 0)
193 {
194 mFunctions->genBuffers(1, &mStreamingElementArrayBuffer);
195 mStreamingElementArrayBufferSize = 0;
196 }
197
198 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
Jamie Madill77a90c22015-08-11 16:33:17 -0400199 mAppliedElementArrayBuffer.set(nullptr);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400200
201 // Make sure the element array buffer is large enough
Jamie Madill0b9e9032015-08-17 11:51:52 +0000202 const Type &indexTypeInfo = GetTypeInfo(type);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400203 size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
204 if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
205 {
206 // Copy the indices in while resizing the buffer
207 mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices, GL_DYNAMIC_DRAW);
208 mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
209 }
210 else
211 {
212 // Put the indices at the beginning of the buffer
213 mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize, indices);
214 }
215
216 // Set the index offset for the draw call to zero since the supplied index pointer is to client data
217 *outIndices = nullptr;
218 }
219
Jamie Madill0b9e9032015-08-17 11:51:52 +0000220 return Error(GL_NO_ERROR);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400221}
222
Jamie Madill0b9e9032015-08-17 11:51:52 +0000223void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400224 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400225 const gl::IndexRange &indexRange,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000226 size_t *outStreamingDataSize,
227 size_t *outMaxAttributeDataSize) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400228{
Jamie Madill0b9e9032015-08-17 11:51:52 +0000229 *outStreamingDataSize = 0;
230 *outMaxAttributeDataSize = 0;
231
232 ASSERT(mAttributesNeedStreaming.any());
233
234 const auto &attribs = mData.getVertexAttributes();
235 for (unsigned int idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
236 {
237 const auto &attrib = attribs[idx];
238 ASSERT(AttributeNeedsStreaming(attrib));
239
Jamie Madill0b9e9032015-08-17 11:51:52 +0000240 // If streaming is going to be required, compute the size of the required buffer
241 // and how much slack space at the beginning of the buffer will be required by determining
242 // the attribute with the largest data size.
243 size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
Geoff Lang3edfe032015-09-04 16:38:24 -0400244 *outStreamingDataSize += typeSize * ComputeVertexAttributeElementCount(
245 attrib, indexRange.vertexCount(), instanceCount);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000246 *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
247 }
248}
249
250gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400251 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400252 const gl::IndexRange &indexRange) const
Jamie Madill0b9e9032015-08-17 11:51:52 +0000253{
254 // Sync the vertex attribute state and track what data needs to be streamed
255 size_t streamingDataSize = 0;
256 size_t maxAttributeDataSize = 0;
257
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400258 computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange,
259 &streamingDataSize, &maxAttributeDataSize);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000260
261 if (streamingDataSize == 0)
262 {
263 return gl::Error(GL_NO_ERROR);
264 }
265
Geoff Lang7c82bc42015-03-09 16:18:08 -0400266 if (mStreamingArrayBuffer == 0)
267 {
268 mFunctions->genBuffers(1, &mStreamingArrayBuffer);
269 mStreamingArrayBufferSize = 0;
270 }
271
272 // If first is greater than zero, a slack space needs to be left at the beginning of the buffer so that
273 // the same 'first' argument can be passed into the draw call.
274 const size_t bufferEmptySpace = maxAttributeDataSize * indexRange.start;
275 const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;
276
277 mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer);
278 if (requiredBufferSize > mStreamingArrayBufferSize)
279 {
280 mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW);
281 mStreamingArrayBufferSize = requiredBufferSize;
282 }
283
284 // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
285 // somehow (such as by a screen change), retry writing the data a few times and return OUT_OF_MEMORY
286 // if that fails.
287 GLboolean unmapResult = GL_FALSE;
288 size_t unmapRetryAttempts = 5;
289 while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
290 {
291 uint8_t *bufferPointer = reinterpret_cast<uint8_t*>(mFunctions->mapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
292 size_t curBufferOffset = bufferEmptySpace;
293
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 =
Geoff Lang3edfe032015-09-04 16:38:24 -0400302 ComputeVertexAttributeElementCount(attrib, indexRange.vertexCount(), instanceCount);
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400303
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