blob: a2ca881d9fe370165429dfed9658ce57eb0c5243 [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
11#include "common/debug.h"
Geoff Lang7c82bc42015-03-09 16:18:08 -040012#include "common/mathutil.h"
Geoff Lang831b1952015-05-05 11:02:27 -040013#include "common/utilities.h"
Geoff Lang6ae6efc2015-03-09 14:42:35 -040014#include "libANGLE/Buffer.h"
Geoff Langba4c4a82015-02-24 12:38:46 -050015#include "libANGLE/angletypes.h"
Geoff Lang7c82bc42015-03-09 16:18:08 -040016#include "libANGLE/formatutils.h"
Geoff Langba4c4a82015-02-24 12:38:46 -050017#include "libANGLE/renderer/gl/BufferGL.h"
18#include "libANGLE/renderer/gl/FunctionsGL.h"
19#include "libANGLE/renderer/gl/StateManagerGL.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050020
21namespace rx
22{
23
Jamie Madill8e344942015-07-09 14:22:07 -040024VertexArrayGL::VertexArrayGL(const gl::VertexArray::Data &data, const FunctionsGL *functions, StateManagerGL *stateManager)
25 : VertexArrayImpl(data),
Geoff Langba4c4a82015-02-24 12:38:46 -050026 mFunctions(functions),
27 mStateManager(stateManager),
28 mVertexArrayID(0),
Geoff Lang2e5b5002015-07-30 17:40:29 +000029 mAppliedElementArrayBuffer(0),
Geoff Lang7c82bc42015-03-09 16:18:08 -040030 mStreamingElementArrayBufferSize(0),
31 mStreamingElementArrayBuffer(0),
32 mStreamingArrayBufferSize(0),
33 mStreamingArrayBuffer(0)
Geoff Langba4c4a82015-02-24 12:38:46 -050034{
35 ASSERT(mFunctions);
36 ASSERT(mStateManager);
37 mFunctions->genVertexArrays(1, &mVertexArrayID);
38
39 // Set the cached vertex attribute array size
40 GLint maxVertexAttribs;
41 mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
42 mAppliedAttributes.resize(maxVertexAttribs);
43}
Geoff Langf9a6f082015-01-22 13:32:49 -050044
45VertexArrayGL::~VertexArrayGL()
Geoff Langba4c4a82015-02-24 12:38:46 -050046{
Geoff Lang1eb708e2015-05-04 14:58:23 -040047 mStateManager->deleteVertexArray(mVertexArrayID);
48 mVertexArrayID = 0;
Geoff Langba4c4a82015-02-24 12:38:46 -050049
Geoff Lang1eb708e2015-05-04 14:58:23 -040050 mStateManager->deleteBuffer(mStreamingElementArrayBuffer);
51 mStreamingElementArrayBufferSize = 0;
52 mStreamingElementArrayBuffer = 0;
Geoff Lang7c82bc42015-03-09 16:18:08 -040053
Geoff Lang1eb708e2015-05-04 14:58:23 -040054 mStateManager->deleteBuffer(mStreamingArrayBuffer);
55 mStreamingArrayBufferSize = 0;
56 mStreamingArrayBuffer = 0;
Geoff Lang7c82bc42015-03-09 16:18:08 -040057
Geoff Langba4c4a82015-02-24 12:38:46 -050058 for (size_t idx = 0; idx < mAppliedAttributes.size(); idx++)
59 {
Jamie Madill8e344942015-07-09 14:22:07 -040060 mAppliedAttributes[idx].buffer.set(nullptr);
Geoff Langba4c4a82015-02-24 12:38:46 -050061 }
62}
Geoff Langf9a6f082015-01-22 13:32:49 -050063
Geoff Lang2e5b5002015-07-30 17:40:29 +000064void VertexArrayGL::setElementArrayBuffer(const gl::Buffer *buffer)
65{
66 // If the buffer is being unbound/deleted, reset the currently applied buffer ID
67 // so that even if a new buffer is generated with the same ID, it will be re-bound.
68 if (buffer == nullptr && mAppliedElementArrayBuffer != mStreamingElementArrayBuffer)
69 {
70 mAppliedElementArrayBuffer = 0;
71 }
72}
73
74void VertexArrayGL::setAttribute(size_t idx, const gl::VertexAttribute &attr)
75{
76}
77
78void VertexArrayGL::setAttributeDivisor(size_t idx, GLuint divisor)
79{
80}
81
82void VertexArrayGL::enableAttribute(size_t idx, bool enabledState)
83{
84}
85
Geoff Langb61e1732015-06-05 11:49:55 -040086gl::Error VertexArrayGL::syncDrawArraysState(const std::vector<GLuint> &activeAttribLocations, GLint first, GLsizei count) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040087{
Geoff Langb61e1732015-06-05 11:49:55 -040088 return syncDrawState(activeAttribLocations, first, count, GL_NONE, nullptr, nullptr);
Geoff Lang7c82bc42015-03-09 16:18:08 -040089}
90
Geoff Langb61e1732015-06-05 11:49:55 -040091gl::Error VertexArrayGL::syncDrawElementsState(const std::vector<GLuint> &activeAttribLocations, GLsizei count,
92 GLenum type, const GLvoid *indices, const GLvoid **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040093{
Geoff Langb61e1732015-06-05 11:49:55 -040094 return syncDrawState(activeAttribLocations, 0, count, type, indices, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -040095}
96
Geoff Langb61e1732015-06-05 11:49:55 -040097gl::Error VertexArrayGL::syncDrawState(const std::vector<GLuint> &activeAttribLocations, GLint first, GLsizei count, GLenum type, const GLvoid *indices, const GLvoid **outIndices) const
Geoff Lang6ae6efc2015-03-09 14:42:35 -040098{
Geoff Lang2e5b5002015-07-30 17:40:29 +000099 mStateManager->bindVertexArray(mVertexArrayID, mAppliedElementArrayBuffer);
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400100
Geoff Lang7c82bc42015-03-09 16:18:08 -0400101 // Check if any attributes need to be streamed, determines if the index range needs to be computed
Geoff Langb61e1732015-06-05 11:49:55 -0400102 bool attributesNeedStreaming = doAttributesNeedStreaming(activeAttribLocations);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400103
104 // Determine if an index buffer needs to be streamed and the range of vertices that need to be copied
Geoff Lang831b1952015-05-05 11:02:27 -0400105 gl::RangeUI indexRange(0, 0);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400106 if (type != GL_NONE)
Geoff Langba4c4a82015-02-24 12:38:46 -0500107 {
Geoff Lang7c82bc42015-03-09 16:18:08 -0400108 gl::Error error = syncIndexData(count, type, indices, attributesNeedStreaming, &indexRange, outIndices);
109 if (error.isError())
110 {
111 return error;
112 }
113 }
114 else
115 {
116 // Not an indexed call, set the range to [first, first + count)
117 indexRange.start = first;
118 indexRange.end = first + count;
Geoff Langba4c4a82015-02-24 12:38:46 -0500119 }
120
Geoff Lang7c82bc42015-03-09 16:18:08 -0400121 // Sync the vertex attribute state and track what data needs to be streamed
122 size_t streamingDataSize = 0;
123 size_t maxAttributeDataSize = 0;
Geoff Langb61e1732015-06-05 11:49:55 -0400124 gl::Error error = syncAttributeState(activeAttribLocations, attributesNeedStreaming, indexRange,
125 &streamingDataSize, &maxAttributeDataSize);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400126 if (error.isError())
Geoff Langba4c4a82015-02-24 12:38:46 -0500127 {
Geoff Lang7c82bc42015-03-09 16:18:08 -0400128 return error;
Geoff Langba4c4a82015-02-24 12:38:46 -0500129 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500130
Geoff Lang7c82bc42015-03-09 16:18:08 -0400131 if (streamingDataSize > 0)
132 {
133 ASSERT(attributesNeedStreaming);
134
Cooper Partinb459fb02015-08-07 16:12:39 -0700135 error = streamAttributes(activeAttribLocations, streamingDataSize, maxAttributeDataSize,
136 indexRange);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400137 if (error.isError())
138 {
139 return error;
140 }
141 }
142
143 return gl::Error(GL_NO_ERROR);
144}
145
Geoff Langb61e1732015-06-05 11:49:55 -0400146bool VertexArrayGL::doAttributesNeedStreaming(const std::vector<GLuint> &activeAttribLocations) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400147{
148 // TODO: if GLES, nothing needs to be streamed
Jamie Madill8e344942015-07-09 14:22:07 -0400149 const auto &attribs = mData.getVertexAttributes();
Geoff Langb61e1732015-06-05 11:49:55 -0400150 for (size_t activeAttrib = 0; activeAttrib < activeAttribLocations.size(); activeAttrib++)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400151 {
Geoff Langb61e1732015-06-05 11:49:55 -0400152 GLuint idx = activeAttribLocations[activeAttrib];
Jamie Madill8e344942015-07-09 14:22:07 -0400153 if (attribs[idx].enabled && attribs[idx].buffer.get() == nullptr)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400154 {
155 return true;
156 }
157 }
158
159 return false;
160}
161
Geoff Langb61e1732015-06-05 11:49:55 -0400162gl::Error VertexArrayGL::syncAttributeState(const std::vector<GLuint> &activeAttribLocations, bool attributesNeedStreaming,
163 const gl::RangeUI &indexRange, size_t *outStreamingDataSize, size_t *outMaxAttributeDataSize) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400164{
165 *outStreamingDataSize = 0;
166 *outMaxAttributeDataSize = 0;
167
Jamie Madill8e344942015-07-09 14:22:07 -0400168 const auto &attribs = mData.getVertexAttributes();
Geoff Langb61e1732015-06-05 11:49:55 -0400169 for (size_t activeAttrib = 0; activeAttrib < activeAttribLocations.size(); activeAttrib++)
Geoff Langba4c4a82015-02-24 12:38:46 -0500170 {
Geoff Langb61e1732015-06-05 11:49:55 -0400171 GLuint idx = activeAttribLocations[activeAttrib];
Jamie Madill8e344942015-07-09 14:22:07 -0400172 const auto &attrib = attribs[idx];
173
Geoff Lang7c82bc42015-03-09 16:18:08 -0400174 // Always sync the enabled and divisor state, they are required for both streaming and buffered
175 // attributes
Jamie Madill8e344942015-07-09 14:22:07 -0400176 if (mAppliedAttributes[idx].enabled != attrib.enabled)
Geoff Langba4c4a82015-02-24 12:38:46 -0500177 {
Jamie Madill8e344942015-07-09 14:22:07 -0400178 if (attrib.enabled)
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400179 {
180 mFunctions->enableVertexAttribArray(idx);
181 }
182 else
183 {
184 mFunctions->disableVertexAttribArray(idx);
185 }
Jamie Madill8e344942015-07-09 14:22:07 -0400186 mAppliedAttributes[idx].enabled = attrib.enabled;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400187 }
Jamie Madill8e344942015-07-09 14:22:07 -0400188 if (mAppliedAttributes[idx].divisor != attrib.divisor)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400189 {
Jamie Madill8e344942015-07-09 14:22:07 -0400190 mFunctions->vertexAttribDivisor(idx, attrib.divisor);
191 mAppliedAttributes[idx].divisor = attrib.divisor;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400192 }
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400193
Jamie Madill8e344942015-07-09 14:22:07 -0400194 if (attribs[idx].enabled && attrib.buffer.get() == nullptr)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400195 {
196 ASSERT(attributesNeedStreaming);
197
198 const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
199
200 // If streaming is going to be required, compute the size of the required buffer
201 // and how much slack space at the beginning of the buffer will be required by determining
202 // the attribute with the largest data size.
Jamie Madill8e344942015-07-09 14:22:07 -0400203 size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400204 *outStreamingDataSize += typeSize * streamedVertexCount;
205 *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
206 }
207 else
208 {
209 // Sync the attribute with no translation
Jamie Madill8e344942015-07-09 14:22:07 -0400210 if (mAppliedAttributes[idx] != attrib)
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400211 {
Jamie Madill8e344942015-07-09 14:22:07 -0400212 const gl::Buffer *arrayBuffer = attrib.buffer.get();
Geoff Lang851cd582015-05-26 16:47:23 -0400213 if (arrayBuffer != nullptr)
214 {
215 const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
216 mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
217 }
218 else
219 {
220 mStateManager->bindBuffer(GL_ARRAY_BUFFER, 0);
221 }
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400222
Jamie Madill8e344942015-07-09 14:22:07 -0400223 if (attrib.pureInteger)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400224 {
Jamie Madill8e344942015-07-09 14:22:07 -0400225 mFunctions->vertexAttribIPointer(idx, attrib.size, attrib.type,
226 attrib.stride, attrib.pointer);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400227 }
228 else
229 {
Jamie Madill8e344942015-07-09 14:22:07 -0400230 mFunctions->vertexAttribPointer(idx, attrib.size, attrib.type,
231 attrib.normalized, attrib.stride,
232 attrib.pointer);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400233 }
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400234
Jamie Madill8e344942015-07-09 14:22:07 -0400235 mAppliedAttributes[idx] = attrib;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400236 }
Geoff Langba4c4a82015-02-24 12:38:46 -0500237 }
Geoff Langba4c4a82015-02-24 12:38:46 -0500238 }
Geoff Lang7c82bc42015-03-09 16:18:08 -0400239
240 return gl::Error(GL_NO_ERROR);
241}
242
243gl::Error VertexArrayGL::syncIndexData(GLsizei count, GLenum type, const GLvoid *indices, bool attributesNeedStreaming,
Geoff Lang831b1952015-05-05 11:02:27 -0400244 gl::RangeUI *outIndexRange, const GLvoid **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400245{
246 ASSERT(outIndices);
247
Jamie Madill8e344942015-07-09 14:22:07 -0400248 gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
249
Geoff Lang7c82bc42015-03-09 16:18:08 -0400250 // Need to check the range of indices if attributes need to be streamed
Jamie Madill8e344942015-07-09 14:22:07 -0400251 if (elementArrayBuffer != nullptr)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400252 {
Geoff Lang2e5b5002015-07-30 17:40:29 +0000253 const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
254 GLuint elementArrayBufferID = bufferGL->getBufferID();
255 if (elementArrayBufferID != mAppliedElementArrayBuffer)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400256 {
Geoff Lang2e5b5002015-07-30 17:40:29 +0000257 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferID);
258 mAppliedElementArrayBuffer = elementArrayBufferID;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400259 }
260
261 // Only compute the index range if the attributes also need to be streamed
262 if (attributesNeedStreaming)
263 {
264 ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
Jamie Madill8e344942015-07-09 14:22:07 -0400265 gl::Error error = mData.getElementArrayBuffer()->getIndexRange(type, static_cast<size_t>(elementArrayBufferOffset), count, outIndexRange);
Geoff Lang520c4ae2015-05-05 13:12:36 -0400266 if (error.isError())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400267 {
Geoff Lang520c4ae2015-05-05 13:12:36 -0400268 return error;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400269 }
270 }
271
272 // Indices serves as an offset into the index buffer in this case, use the same value for the draw call
273 *outIndices = indices;
274 }
275 else
276 {
277 // Need to stream the index buffer
278 // TODO: if GLES, nothing needs to be streamed
279
280 // Only compute the index range if the attributes also need to be streamed
281 if (attributesNeedStreaming)
282 {
Geoff Lang831b1952015-05-05 11:02:27 -0400283 *outIndexRange = gl::ComputeIndexRange(type, indices, count);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400284 }
285
286 // Allocate the streaming element array buffer
287 if (mStreamingElementArrayBuffer == 0)
288 {
289 mFunctions->genBuffers(1, &mStreamingElementArrayBuffer);
290 mStreamingElementArrayBufferSize = 0;
291 }
292
293 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
Geoff Lang2e5b5002015-07-30 17:40:29 +0000294 mAppliedElementArrayBuffer = mStreamingElementArrayBuffer;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400295
296 // Make sure the element array buffer is large enough
297 const gl::Type &indexTypeInfo = gl::GetTypeInfo(type);
298 size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
299 if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
300 {
301 // Copy the indices in while resizing the buffer
302 mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices, GL_DYNAMIC_DRAW);
303 mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
304 }
305 else
306 {
307 // Put the indices at the beginning of the buffer
308 mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize, indices);
309 }
310
311 // Set the index offset for the draw call to zero since the supplied index pointer is to client data
312 *outIndices = nullptr;
313 }
314
315 return gl::Error(GL_NO_ERROR);
316}
317
Geoff Langb61e1732015-06-05 11:49:55 -0400318gl::Error VertexArrayGL::streamAttributes(const std::vector<GLuint> &activeAttribLocations, size_t streamingDataSize,
319 size_t maxAttributeDataSize, const gl::RangeUI &indexRange) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400320{
321 if (mStreamingArrayBuffer == 0)
322 {
323 mFunctions->genBuffers(1, &mStreamingArrayBuffer);
324 mStreamingArrayBufferSize = 0;
325 }
326
327 // If first is greater than zero, a slack space needs to be left at the beginning of the buffer so that
328 // the same 'first' argument can be passed into the draw call.
329 const size_t bufferEmptySpace = maxAttributeDataSize * indexRange.start;
330 const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;
331
332 mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer);
333 if (requiredBufferSize > mStreamingArrayBufferSize)
334 {
335 mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW);
336 mStreamingArrayBufferSize = requiredBufferSize;
337 }
338
339 // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
340 // somehow (such as by a screen change), retry writing the data a few times and return OUT_OF_MEMORY
341 // if that fails.
342 GLboolean unmapResult = GL_FALSE;
343 size_t unmapRetryAttempts = 5;
344 while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
345 {
346 uint8_t *bufferPointer = reinterpret_cast<uint8_t*>(mFunctions->mapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
347 size_t curBufferOffset = bufferEmptySpace;
348
349 const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
350
Jamie Madill8e344942015-07-09 14:22:07 -0400351 const auto &attribs = mData.getVertexAttributes();
Geoff Langb61e1732015-06-05 11:49:55 -0400352 for (size_t activeAttrib = 0; activeAttrib < activeAttribLocations.size(); activeAttrib++)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400353 {
Geoff Langb61e1732015-06-05 11:49:55 -0400354 GLuint idx = activeAttribLocations[activeAttrib];
Jamie Madill8e344942015-07-09 14:22:07 -0400355 const auto &attrib = attribs[idx];
Geoff Lang7c82bc42015-03-09 16:18:08 -0400356
Jamie Madill8e344942015-07-09 14:22:07 -0400357 if (attrib.enabled && attrib.buffer.get() == nullptr)
358 {
359 const size_t sourceStride = ComputeVertexAttributeStride(attrib);
360 const size_t destStride = ComputeVertexAttributeTypeSize(attrib);
361
362 const uint8_t *inputPointer = reinterpret_cast<const uint8_t*>(attrib.pointer);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400363
364 // Pack the data when copying it, user could have supplied a very large stride that would
365 // cause the buffer to be much larger than needed.
366 if (destStride == sourceStride)
367 {
368 // Can copy in one go, the data is packed
369 memcpy(bufferPointer + curBufferOffset,
370 inputPointer + (sourceStride * indexRange.start),
371 destStride * streamedVertexCount);
372 }
373 else
374 {
375 // Copy each vertex individually
376 for (size_t vertexIdx = indexRange.start; vertexIdx <= indexRange.end; vertexIdx++)
377 {
378 memcpy(bufferPointer + curBufferOffset + (destStride * vertexIdx),
379 inputPointer + (sourceStride * vertexIdx),
380 destStride);
381 }
382 }
383
384 // Compute where the 0-index vertex would be.
385 const size_t vertexStartOffset = curBufferOffset - (indexRange.start * destStride);
386
Jamie Madill8e344942015-07-09 14:22:07 -0400387 mFunctions->vertexAttribPointer(idx, attrib.size, attrib.type,
388 attrib.normalized, destStride,
Geoff Lang7c82bc42015-03-09 16:18:08 -0400389 reinterpret_cast<const GLvoid*>(vertexStartOffset));
390
391 curBufferOffset += destStride * streamedVertexCount;
392
393 // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
394 // need to be streamed later, there is no chance that the caching will skip it.
395 mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
396 }
397 }
398
399 unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
400 }
401
402 if (unmapResult != GL_TRUE)
403 {
404 return gl::Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
405 }
406
407 return gl::Error(GL_NO_ERROR);
Geoff Langba4c4a82015-02-24 12:38:46 -0500408}
409
410GLuint VertexArrayGL::getVertexArrayID() const
411{
412 return mVertexArrayID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500413}
414
Geoff Lang294cad92015-05-26 15:11:23 -0400415GLuint VertexArrayGL::getAppliedElementArrayBufferID() const
416{
Geoff Lang2e5b5002015-07-30 17:40:29 +0000417 return mAppliedElementArrayBuffer;
Geoff Lang294cad92015-05-26 15:11:23 -0400418}
419
Geoff Langf9a6f082015-01-22 13:32:49 -0500420}