blob: 776b641c8336ea0bb55b2932e3cc248275a69c70 [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"
Geoff Langb2ebb5e2016-06-08 18:17:55 +000020#include "libANGLE/renderer/gl/renderergl_utils.h"
Geoff Langba4c4a82015-02-24 12:38:46 -050021#include "libANGLE/renderer/gl/StateManagerGL.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050022
Jamie Madill0b9e9032015-08-17 11:51:52 +000023using namespace gl;
24
Geoff Langf9a6f082015-01-22 13:32:49 -050025namespace rx
26{
Jamie Madill0b9e9032015-08-17 11:51:52 +000027namespace
28{
29bool AttributeNeedsStreaming(const VertexAttribute &attribute)
30{
31 return (attribute.enabled && attribute.buffer.get() == nullptr);
32}
Geoff Langf9a6f082015-01-22 13:32:49 -050033
Jamie Madill0b9e9032015-08-17 11:51:52 +000034} // anonymous namespace
35
Jamie Madill3f572682016-04-26 13:41:36 -040036VertexArrayGL::VertexArrayGL(const VertexArrayState &state,
Jamie Madill77a90c22015-08-11 16:33:17 -040037 const FunctionsGL *functions,
38 StateManagerGL *stateManager)
Jamie Madill3f572682016-04-26 13:41:36 -040039 : VertexArrayImpl(state),
Geoff Langba4c4a82015-02-24 12:38:46 -050040 mFunctions(functions),
41 mStateManager(stateManager),
42 mVertexArrayID(0),
Jamie Madill77a90c22015-08-11 16:33:17 -040043 mAppliedElementArrayBuffer(),
Geoff Lang7c82bc42015-03-09 16:18:08 -040044 mStreamingElementArrayBufferSize(0),
45 mStreamingElementArrayBuffer(0),
46 mStreamingArrayBufferSize(0),
47 mStreamingArrayBuffer(0)
Geoff Langba4c4a82015-02-24 12:38:46 -050048{
49 ASSERT(mFunctions);
50 ASSERT(mStateManager);
51 mFunctions->genVertexArrays(1, &mVertexArrayID);
52
53 // Set the cached vertex attribute array size
hendrikwbb7740c2015-10-20 15:30:53 -070054 GLint maxVertexAttribs = 0;
Geoff Langba4c4a82015-02-24 12:38:46 -050055 mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
56 mAppliedAttributes.resize(maxVertexAttribs);
57}
Geoff Langf9a6f082015-01-22 13:32:49 -050058
59VertexArrayGL::~VertexArrayGL()
Geoff Langba4c4a82015-02-24 12:38:46 -050060{
Geoff Lang1eb708e2015-05-04 14:58:23 -040061 mStateManager->deleteVertexArray(mVertexArrayID);
62 mVertexArrayID = 0;
Geoff Langba4c4a82015-02-24 12:38:46 -050063
Geoff Lang1eb708e2015-05-04 14:58:23 -040064 mStateManager->deleteBuffer(mStreamingElementArrayBuffer);
65 mStreamingElementArrayBufferSize = 0;
66 mStreamingElementArrayBuffer = 0;
Geoff Lang7c82bc42015-03-09 16:18:08 -040067
Geoff Lang1eb708e2015-05-04 14:58:23 -040068 mStateManager->deleteBuffer(mStreamingArrayBuffer);
69 mStreamingArrayBufferSize = 0;
70 mStreamingArrayBuffer = 0;
Geoff Lang7c82bc42015-03-09 16:18:08 -040071
Jamie Madill77a90c22015-08-11 16:33:17 -040072 mAppliedElementArrayBuffer.set(nullptr);
Geoff Langba4c4a82015-02-24 12:38:46 -050073 for (size_t idx = 0; idx < mAppliedAttributes.size(); idx++)
74 {
Jamie Madill8e344942015-07-09 14:22:07 -040075 mAppliedAttributes[idx].buffer.set(nullptr);
Geoff Langba4c4a82015-02-24 12:38:46 -050076 }
77}
Geoff Langf9a6f082015-01-22 13:32:49 -050078
Jamie Madill0b9e9032015-08-17 11:51:52 +000079gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
80 GLint first,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040081 GLsizei count,
82 GLsizei instanceCount) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040083{
Geoff Lang3edfe032015-09-04 16:38:24 -040084 return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount, false,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040085 nullptr);
Geoff Lang7c82bc42015-03-09 16:18:08 -040086}
87
Jamie Madill0b9e9032015-08-17 11:51:52 +000088gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
89 GLsizei count,
90 GLenum type,
91 const GLvoid *indices,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040092 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -040093 bool primitiveRestartEnabled,
Jamie Madill0b9e9032015-08-17 11:51:52 +000094 const GLvoid **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040095{
Geoff Lang3edfe032015-09-04 16:38:24 -040096 return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount,
97 primitiveRestartEnabled, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -040098}
99
Jiajia Qind9671222016-11-29 16:30:31 +0800100gl::Error VertexArrayGL::syncElementArrayState() const
101{
102 gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
103 ASSERT(elementArrayBuffer);
104 if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
105 {
106 const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
107 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
108 mAppliedElementArrayBuffer.set(elementArrayBuffer);
109 }
110
111 return gl::NoError();
112}
113
Jamie Madill0b9e9032015-08-17 11:51:52 +0000114gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
115 GLint first,
116 GLsizei count,
117 GLenum type,
118 const GLvoid *indices,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400119 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400120 bool primitiveRestartEnabled,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000121 const GLvoid **outIndices) const
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400122{
Jamie Madill77a90c22015-08-11 16:33:17 -0400123 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400124
Geoff Lang7c82bc42015-03-09 16:18:08 -0400125 // Check if any attributes need to be streamed, determines if the index range needs to be computed
Jamie Madill0b9e9032015-08-17 11:51:52 +0000126 bool attributesNeedStreaming = mAttributesNeedStreaming.any();
Geoff Lang7c82bc42015-03-09 16:18:08 -0400127
128 // 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 -0400129 IndexRange indexRange;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400130 if (type != GL_NONE)
Geoff Langba4c4a82015-02-24 12:38:46 -0500131 {
Geoff Lang3edfe032015-09-04 16:38:24 -0400132 Error error = syncIndexData(count, type, indices, primitiveRestartEnabled,
133 attributesNeedStreaming, &indexRange, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400134 if (error.isError())
135 {
136 return error;
137 }
138 }
139 else
140 {
Corentin Wallez2c34a4b2015-08-25 16:26:02 -0400141 // Not an indexed call, set the range to [first, first + count - 1]
Geoff Lang7c82bc42015-03-09 16:18:08 -0400142 indexRange.start = first;
Corentin Wallez2c34a4b2015-08-25 16:26:02 -0400143 indexRange.end = first + count - 1;
Geoff Langba4c4a82015-02-24 12:38:46 -0500144 }
145
Jamie Madill0b9e9032015-08-17 11:51:52 +0000146 if (attributesNeedStreaming)
Geoff Langba4c4a82015-02-24 12:38:46 -0500147 {
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400148 Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400149 if (error.isError())
150 {
151 return error;
152 }
153 }
154
He Yunchaoacd18982017-01-04 10:46:42 +0800155 return NoError();
Geoff Lang7c82bc42015-03-09 16:18:08 -0400156}
157
Jiajia Qind9671222016-11-29 16:30:31 +0800158gl::Error VertexArrayGL::syncIndexData(GLsizei count,
159 GLenum type,
160 const GLvoid *indices,
161 bool primitiveRestartEnabled,
162 bool attributesNeedStreaming,
163 IndexRange *outIndexRange,
164 const GLvoid **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400165{
166 ASSERT(outIndices);
167
Jamie Madill8e344942015-07-09 14:22:07 -0400168 gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
169
Geoff Lang7c82bc42015-03-09 16:18:08 -0400170 // Need to check the range of indices if attributes need to be streamed
Jamie Madill8e344942015-07-09 14:22:07 -0400171 if (elementArrayBuffer != nullptr)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400172 {
Jamie Madill77a90c22015-08-11 16:33:17 -0400173 if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400174 {
Jamie Madill77a90c22015-08-11 16:33:17 -0400175 const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
176 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
177 mAppliedElementArrayBuffer.set(elementArrayBuffer);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400178 }
179
180 // Only compute the index range if the attributes also need to be streamed
181 if (attributesNeedStreaming)
182 {
183 ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000184 Error error = mData.getElementArrayBuffer()->getIndexRange(
Geoff Lang3edfe032015-09-04 16:38:24 -0400185 type, elementArrayBufferOffset, count, primitiveRestartEnabled, outIndexRange);
Geoff Lang520c4ae2015-05-05 13:12:36 -0400186 if (error.isError())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400187 {
Geoff Lang520c4ae2015-05-05 13:12:36 -0400188 return error;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400189 }
190 }
191
192 // Indices serves as an offset into the index buffer in this case, use the same value for the draw call
193 *outIndices = indices;
194 }
195 else
196 {
197 // Need to stream the index buffer
198 // TODO: if GLES, nothing needs to be streamed
199
200 // Only compute the index range if the attributes also need to be streamed
201 if (attributesNeedStreaming)
202 {
Geoff Lang3edfe032015-09-04 16:38:24 -0400203 *outIndexRange = ComputeIndexRange(type, indices, count, primitiveRestartEnabled);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400204 }
205
206 // Allocate the streaming element array buffer
207 if (mStreamingElementArrayBuffer == 0)
208 {
209 mFunctions->genBuffers(1, &mStreamingElementArrayBuffer);
210 mStreamingElementArrayBufferSize = 0;
211 }
212
213 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
Jamie Madill77a90c22015-08-11 16:33:17 -0400214 mAppliedElementArrayBuffer.set(nullptr);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400215
216 // Make sure the element array buffer is large enough
Jamie Madill0b9e9032015-08-17 11:51:52 +0000217 const Type &indexTypeInfo = GetTypeInfo(type);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400218 size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
219 if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
220 {
221 // Copy the indices in while resizing the buffer
222 mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices, GL_DYNAMIC_DRAW);
223 mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
224 }
225 else
226 {
227 // Put the indices at the beginning of the buffer
228 mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize, indices);
229 }
230
231 // Set the index offset for the draw call to zero since the supplied index pointer is to client data
232 *outIndices = nullptr;
233 }
234
He Yunchaoacd18982017-01-04 10:46:42 +0800235 return NoError();
Geoff Lang7c82bc42015-03-09 16:18:08 -0400236}
237
Jamie Madill0b9e9032015-08-17 11:51:52 +0000238void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400239 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400240 const gl::IndexRange &indexRange,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000241 size_t *outStreamingDataSize,
242 size_t *outMaxAttributeDataSize) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400243{
Jamie Madill0b9e9032015-08-17 11:51:52 +0000244 *outStreamingDataSize = 0;
245 *outMaxAttributeDataSize = 0;
246
247 ASSERT(mAttributesNeedStreaming.any());
248
249 const auto &attribs = mData.getVertexAttributes();
Corentin Wallezca311dd2015-12-07 15:07:48 -0500250 for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
Jamie Madill0b9e9032015-08-17 11:51:52 +0000251 {
252 const auto &attrib = attribs[idx];
253 ASSERT(AttributeNeedsStreaming(attrib));
254
Jamie Madill0b9e9032015-08-17 11:51:52 +0000255 // If streaming is going to be required, compute the size of the required buffer
256 // and how much slack space at the beginning of the buffer will be required by determining
257 // the attribute with the largest data size.
258 size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
Geoff Lang3edfe032015-09-04 16:38:24 -0400259 *outStreamingDataSize += typeSize * ComputeVertexAttributeElementCount(
260 attrib, indexRange.vertexCount(), instanceCount);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000261 *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
262 }
263}
264
265gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400266 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400267 const gl::IndexRange &indexRange) const
Jamie Madill0b9e9032015-08-17 11:51:52 +0000268{
269 // Sync the vertex attribute state and track what data needs to be streamed
270 size_t streamingDataSize = 0;
271 size_t maxAttributeDataSize = 0;
272
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400273 computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange,
274 &streamingDataSize, &maxAttributeDataSize);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000275
276 if (streamingDataSize == 0)
277 {
He Yunchaoacd18982017-01-04 10:46:42 +0800278 return gl::NoError();
Jamie Madill0b9e9032015-08-17 11:51:52 +0000279 }
280
Geoff Lang7c82bc42015-03-09 16:18:08 -0400281 if (mStreamingArrayBuffer == 0)
282 {
283 mFunctions->genBuffers(1, &mStreamingArrayBuffer);
284 mStreamingArrayBufferSize = 0;
285 }
286
287 // If first is greater than zero, a slack space needs to be left at the beginning of the buffer so that
288 // the same 'first' argument can be passed into the draw call.
289 const size_t bufferEmptySpace = maxAttributeDataSize * indexRange.start;
290 const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;
291
292 mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer);
293 if (requiredBufferSize > mStreamingArrayBufferSize)
294 {
295 mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW);
296 mStreamingArrayBufferSize = requiredBufferSize;
297 }
298
299 // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
300 // somehow (such as by a screen change), retry writing the data a few times and return OUT_OF_MEMORY
301 // if that fails.
302 GLboolean unmapResult = GL_FALSE;
303 size_t unmapRetryAttempts = 5;
304 while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
305 {
Geoff Langb2ebb5e2016-06-08 18:17:55 +0000306 uint8_t *bufferPointer = MapBufferRangeWithFallback(mFunctions, GL_ARRAY_BUFFER, 0,
307 requiredBufferSize, GL_MAP_WRITE_BIT);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400308 size_t curBufferOffset = bufferEmptySpace;
309
Jamie Madill8e344942015-07-09 14:22:07 -0400310 const auto &attribs = mData.getVertexAttributes();
Corentin Wallezca311dd2015-12-07 15:07:48 -0500311 for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
Geoff Lang7c82bc42015-03-09 16:18:08 -0400312 {
Jamie Madill8e344942015-07-09 14:22:07 -0400313 const auto &attrib = attribs[idx];
Jamie Madill0b9e9032015-08-17 11:51:52 +0000314 ASSERT(AttributeNeedsStreaming(attrib));
Geoff Lang7c82bc42015-03-09 16:18:08 -0400315
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400316 const size_t streamedVertexCount =
Geoff Lang3edfe032015-09-04 16:38:24 -0400317 ComputeVertexAttributeElementCount(attrib, indexRange.vertexCount(), instanceCount);
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400318
Jamie Madill0b9e9032015-08-17 11:51:52 +0000319 const size_t sourceStride = ComputeVertexAttributeStride(attrib);
320 const size_t destStride = ComputeVertexAttributeTypeSize(attrib);
321
Geoff Lang38a24a92017-02-15 13:53:06 -0500322 // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
323 // a non-instanced draw call
324 const size_t firstIndex = attrib.divisor == 0 ? indexRange.start : 0;
325
Jamie Madill0b9e9032015-08-17 11:51:52 +0000326 const uint8_t *inputPointer = reinterpret_cast<const uint8_t *>(attrib.pointer);
327
328 // Pack the data when copying it, user could have supplied a very large stride that
329 // would cause the buffer to be much larger than needed.
330 if (destStride == sourceStride)
Jamie Madill8e344942015-07-09 14:22:07 -0400331 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000332 // Can copy in one go, the data is packed
Geoff Lang38a24a92017-02-15 13:53:06 -0500333 memcpy(bufferPointer + curBufferOffset, inputPointer + (sourceStride * firstIndex),
Jamie Madill0b9e9032015-08-17 11:51:52 +0000334 destStride * streamedVertexCount);
Jamie Madill6d51c702015-08-14 10:38:10 -0400335 }
Jamie Madill0b9e9032015-08-17 11:51:52 +0000336 else
337 {
338 // Copy each vertex individually
Geoff Lang6b10ddb2015-09-02 15:55:10 -0400339 for (size_t vertexIdx = 0; vertexIdx < streamedVertexCount; vertexIdx++)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000340 {
Corentin Wallez4d5362d2015-08-25 11:25:14 -0400341 uint8_t *out = bufferPointer + curBufferOffset + (destStride * vertexIdx);
Geoff Lang38a24a92017-02-15 13:53:06 -0500342 const uint8_t *in = inputPointer + sourceStride * (vertexIdx + firstIndex);
Corentin Wallez4d5362d2015-08-25 11:25:14 -0400343 memcpy(out, in, destStride);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000344 }
345 }
346
347 // Compute where the 0-index vertex would be.
Geoff Lang38a24a92017-02-15 13:53:06 -0500348 const size_t vertexStartOffset = curBufferOffset - (firstIndex * destStride);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000349
Geoff Lang2b835a62015-09-10 15:58:44 -0400350 if (attrib.pureInteger)
351 {
352 ASSERT(!attrib.normalized);
353 mFunctions->vertexAttribIPointer(
Corentin Wallezca311dd2015-12-07 15:07:48 -0500354 static_cast<GLuint>(idx), attrib.size, attrib.type,
355 static_cast<GLsizei>(destStride),
Geoff Lang2b835a62015-09-10 15:58:44 -0400356 reinterpret_cast<const GLvoid *>(vertexStartOffset));
357 }
358 else
359 {
360 mFunctions->vertexAttribPointer(
Corentin Wallezca311dd2015-12-07 15:07:48 -0500361 static_cast<GLuint>(idx), attrib.size, attrib.type, attrib.normalized,
Geoff Lang2b835a62015-09-10 15:58:44 -0400362 static_cast<GLsizei>(destStride),
363 reinterpret_cast<const GLvoid *>(vertexStartOffset));
364 }
Jamie Madill0b9e9032015-08-17 11:51:52 +0000365
366 curBufferOffset += destStride * streamedVertexCount;
367
368 // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
369 // need to be streamed later, there is no chance that the caching will skip it.
370 mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400371 }
372
373 unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
374 }
375
376 if (unmapResult != GL_TRUE)
377 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000378 return Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
Geoff Lang7c82bc42015-03-09 16:18:08 -0400379 }
380
He Yunchaoacd18982017-01-04 10:46:42 +0800381 return NoError();
Geoff Langba4c4a82015-02-24 12:38:46 -0500382}
383
384GLuint VertexArrayGL::getVertexArrayID() const
385{
386 return mVertexArrayID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500387}
388
Geoff Lang294cad92015-05-26 15:11:23 -0400389GLuint VertexArrayGL::getAppliedElementArrayBufferID() const
390{
Jamie Madill77a90c22015-08-11 16:33:17 -0400391 if (mAppliedElementArrayBuffer.get() == nullptr)
392 {
393 return mStreamingElementArrayBuffer;
394 }
395
396 return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
Geoff Lang294cad92015-05-26 15:11:23 -0400397}
398
Jamie Madill0b9e9032015-08-17 11:51:52 +0000399void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
400{
401 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
402 mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib));
Geoff Langf9a6f082015-01-22 13:32:49 -0500403}
Jamie Madill0b9e9032015-08-17 11:51:52 +0000404
405void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
406{
407 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
408 if (mAppliedAttributes[attribIndex].enabled == attrib.enabled)
409 {
410 return;
411 }
412
413 updateNeedsStreaming(attribIndex);
414
415 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
416 if (attrib.enabled)
417 {
418 mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
419 }
420 else
421 {
422 mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
423 }
424 mAppliedAttributes[attribIndex].enabled = attrib.enabled;
425}
426
427void VertexArrayGL::updateAttribPointer(size_t attribIndex)
428{
429 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
430 if (mAppliedAttributes[attribIndex] == attrib)
431 {
432 return;
433 }
434
435 updateNeedsStreaming(attribIndex);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000436
437 // If we need to stream, defer the attribPointer to the draw call.
438 if (mAttributesNeedStreaming[attribIndex])
439 {
440 return;
441 }
442
443 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
444 const Buffer *arrayBuffer = attrib.buffer.get();
445 if (arrayBuffer != nullptr)
446 {
447 const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
448 mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
449 }
450 else
451 {
452 mStateManager->bindBuffer(GL_ARRAY_BUFFER, 0);
453 }
Geoff Lang3caa6522015-08-27 14:38:52 -0400454 mAppliedAttributes[attribIndex].buffer = attrib.buffer;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000455
456 if (attrib.pureInteger)
457 {
458 mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
459 attrib.stride, attrib.pointer);
460 }
461 else
462 {
463 mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
464 attrib.normalized, attrib.stride, attrib.pointer);
465 }
Geoff Lang3caa6522015-08-27 14:38:52 -0400466 mAppliedAttributes[attribIndex].size = attrib.size;
467 mAppliedAttributes[attribIndex].type = attrib.type;
468 mAppliedAttributes[attribIndex].normalized = attrib.normalized;
469 mAppliedAttributes[attribIndex].pureInteger = attrib.pureInteger;
470 mAppliedAttributes[attribIndex].stride = attrib.stride;
471 mAppliedAttributes[attribIndex].pointer = attrib.pointer;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000472}
473
474void VertexArrayGL::syncState(const VertexArray::DirtyBits &dirtyBits)
475{
476 for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits))
477 {
478 if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
479 {
480 // TODO(jmadill): Element array buffer bindings
481 }
482 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
483 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
484 {
485 size_t attribIndex =
486 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED;
487 updateAttribEnabled(attribIndex);
488 }
489 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
490 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
491 {
492 size_t attribIndex =
493 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_POINTER;
494 updateAttribPointer(attribIndex);
495 }
496 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR &&
497 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR)
498 {
499 size_t attribIndex =
500 static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR;
501 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
502
503 if (mAppliedAttributes[attribIndex].divisor != attrib.divisor)
504 {
505 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
506 mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), attrib.divisor);
507 mAppliedAttributes[attribIndex].divisor = attrib.divisor;
508 }
509 }
510 else
511 UNREACHABLE();
512 }
513}
514
515} // rx