blob: 2cd9b49c608d5ffe52d5497e14f68bced5b7edcb [file] [log] [blame]
Jamie Madill57a89722013-07-02 11:57:03 -04001//
2// Copyright (c) 2013 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// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
7//
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/VertexArray.h"
10#include "libANGLE/Buffer.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040011#include "libANGLE/Context.h"
Jamie Madill09463932018-04-04 05:26:59 -040012#include "libANGLE/renderer/BufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040013#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/renderer/VertexArrayImpl.h"
Jamie Madill57a89722013-07-02 11:57:03 -040015
16namespace gl
17{
Jamie Madillbcef3222018-04-13 15:19:11 -040018// VertexArrayState implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080019VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
Jamie Madilld078c682018-01-02 11:50:24 -050020 : mLabel(), mVertexBindings(maxAttribBindings)
Jamie Madill57a89722013-07-02 11:57:03 -040021{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080022 ASSERT(maxAttribs <= maxAttribBindings);
23
24 for (size_t i = 0; i < maxAttribs; i++)
25 {
26 mVertexAttributes.emplace_back(static_cast<GLuint>(i));
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080027 mBindingToAttributeMasks[i].set(i);
Jiawei-Shao2597fb62016-12-09 16:38:02 +080028 }
Jamie Madill8e344942015-07-09 14:22:07 -040029}
30
Jamie Madill3f572682016-04-26 13:41:36 -040031VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040032{
Jamie Madill8e344942015-07-09 14:22:07 -040033}
34
Jamie Madillbcef3222018-04-13 15:19:11 -040035gl::AttributesMask VertexArrayState::getEnabledClientMemoryAttribsMask() const
36{
37 return (mClientMemoryAttribsMask & mEnabledAttributesMask);
38}
39
Jamie Madill51af38b2018-04-15 08:50:56 -040040bool VertexArrayState::hasEnabledNullPointerClientArray() const
41{
42 return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
43}
44
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080045AttributesMask VertexArrayState::getBindingToAttributeMasks(GLuint bindingIndex) const
46{
47 ASSERT(bindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
48 return mBindingToAttributeMasks[bindingIndex];
49}
50
51// Set an attribute using a new binding.
52void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
53{
54 ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
55
56 // Update the binding-attribute map.
57 const GLuint oldBindingIndex = mVertexAttributes[attribIndex].bindingIndex;
58 ASSERT(oldBindingIndex != newBindingIndex);
59
60 ASSERT(mBindingToAttributeMasks[oldBindingIndex].test(attribIndex) &&
61 !mBindingToAttributeMasks[newBindingIndex].test(attribIndex));
62
63 mBindingToAttributeMasks[oldBindingIndex].reset(attribIndex);
64 mBindingToAttributeMasks[newBindingIndex].set(attribIndex);
65
66 // Set the attribute using the new binding.
67 mVertexAttributes[attribIndex].bindingIndex = newBindingIndex;
68}
69
Jamie Madillbcef3222018-04-13 15:19:11 -040070// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080071VertexArray::VertexArray(rx::GLImplFactory *factory,
72 GLuint id,
73 size_t maxAttribs,
74 size_t maxAttribBindings)
75 : mId(id),
76 mState(maxAttribs, maxAttribBindings),
Jamie Madill09463932018-04-04 05:26:59 -040077 mVertexArray(factory->createVertexArray(mState)),
78 mElementArrayBufferObserverBinding(this, maxAttribBindings)
Jamie Madill8e344942015-07-09 14:22:07 -040079{
Jamie Madill09463932018-04-04 05:26:59 -040080 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
81 {
82 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
83 }
Jamie Madill004a6f92013-07-10 15:13:38 -040084}
85
Jamie Madill4928b7c2017-06-20 12:57:39 -040086void VertexArray::onDestroy(const Context *context)
87{
James Darpiniane8a93c62018-01-04 18:02:24 -080088 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -040089 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -040090 {
James Darpiniane8a93c62018-01-04 18:02:24 -080091 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -040092 }
James Darpiniane8a93c62018-01-04 18:02:24 -080093 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -070094 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray,
95 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -040096 mState.mElementArrayBuffer.set(context, nullptr);
97 mVertexArray->destroy(context);
98 SafeDelete(mVertexArray);
99 delete this;
100}
101
Jamie Madill004a6f92013-07-10 15:13:38 -0400102VertexArray::~VertexArray()
103{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400104 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -0400105}
106
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400107GLuint VertexArray::id() const
108{
109 return mId;
110}
111
Geoff Lang70d0f492015-12-10 17:45:46 -0500112void VertexArray::setLabel(const std::string &label)
113{
Jamie Madill3f572682016-04-26 13:41:36 -0400114 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500115}
116
117const std::string &VertexArray::getLabel() const
118{
Jamie Madill3f572682016-04-26 13:41:36 -0400119 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500120}
121
Jamie Madill4928b7c2017-06-20 12:57:39 -0400122void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400123{
James Darpiniane8a93c62018-01-04 18:02:24 -0800124 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800125 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -0400126 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300127 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400128 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800129 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400130 }
131 }
132
Jamie Madill3f572682016-04-26 13:41:36 -0400133 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400134 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800135 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700136 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::Array,
137 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400138 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400139 }
140}
141
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800142const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400143{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800144 ASSERT(attribIndex < getMaxAttribs());
145 return mState.mVertexAttributes[attribIndex];
146}
147
148const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
149{
150 ASSERT(bindingIndex < getMaxBindings());
151 return mState.mVertexBindings[bindingIndex];
152}
153
Shaodde78e82017-05-22 14:13:27 +0800154size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800155{
156 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
157 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800158 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400159 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
160}
161
162void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
163{
164 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
165 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
166}
167
168void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
169{
170 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
171 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800172}
173
Shaodde78e82017-05-22 14:13:27 +0800174void VertexArray::bindVertexBufferImpl(const Context *context,
175 size_t bindingIndex,
176 Buffer *boundBuffer,
177 GLintptr offset,
178 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800179{
180 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800181 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800182
183 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
184
James Darpiniane8a93c62018-01-04 18:02:24 -0800185 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300186 binding->setOffset(offset);
187 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400188
189 updateObserverBinding(bindingIndex);
Jamie Madill02c9c042018-04-17 13:43:48 -0400190 updateCachedBufferBindingSize(bindingIndex);
Jamie Madill7267aa62018-04-17 15:28:21 -0400191 updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
Shaodde78e82017-05-22 14:13:27 +0800192}
193
194void VertexArray::bindVertexBuffer(const Context *context,
195 size_t bindingIndex,
196 Buffer *boundBuffer,
197 GLintptr offset,
198 GLsizei stride)
199{
200 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400201 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800202}
203
Shaodde78e82017-05-22 14:13:27 +0800204void VertexArray::setVertexAttribBinding(const Context *context,
205 size_t attribIndex,
206 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800207{
208 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
209
Shaodde78e82017-05-22 14:13:27 +0800210 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
211 {
212 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
213 ASSERT(context->getClientVersion() >= ES_3_1);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +0800214
215 mState.setAttribBinding(attribIndex, bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800216
Jamie Madille858cb12018-03-27 09:44:32 -0400217 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Shaodde78e82017-05-22 14:13:27 +0800218 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800219}
220
221void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
222{
223 ASSERT(bindingIndex < getMaxBindings());
224
Martin Radevdd5f27e2017-06-07 10:17:09 +0300225 mState.mVertexBindings[bindingIndex].setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400226 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800227}
228
Shaodde78e82017-05-22 14:13:27 +0800229void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
230 GLint size,
231 GLenum type,
232 bool normalized,
233 bool pureInteger,
234 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800235{
236 ASSERT(attribIndex < getMaxAttribs());
237
238 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
239
240 attrib->size = size;
241 attrib->type = type;
242 attrib->normalized = normalized;
243 attrib->pureInteger = pureInteger;
244 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800245 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Jamie Madill02c9c042018-04-17 13:43:48 -0400246 attrib->updateCachedSizePlusRelativeOffset();
Shaodde78e82017-05-22 14:13:27 +0800247}
248
249void VertexArray::setVertexAttribFormat(size_t attribIndex,
250 GLint size,
251 GLenum type,
252 bool normalized,
253 bool pureInteger,
254 GLuint relativeOffset)
255{
256 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400257 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madill57a89722013-07-02 11:57:03 -0400258}
259
Shaodde78e82017-05-22 14:13:27 +0800260void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400261{
Shaodde78e82017-05-22 14:13:27 +0800262 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800263
Shaodde78e82017-05-22 14:13:27 +0800264 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
265 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400266}
267
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800268void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400269{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800270 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800271
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800272 mState.mVertexAttributes[attribIndex].enabled = enabledState;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800273 mState.mVertexAttributesTypeMask.setIndex(
274 GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800275
Jamie Madille858cb12018-03-27 09:44:32 -0400276 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400277
278 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500279 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madill57a89722013-07-02 11:57:03 -0400280}
281
Shaodde78e82017-05-22 14:13:27 +0800282void VertexArray::setVertexAttribPointer(const Context *context,
283 size_t attribIndex,
284 gl::Buffer *boundBuffer,
285 GLint size,
286 GLenum type,
287 bool normalized,
288 bool pureInteger,
289 GLsizei stride,
290 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400291{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800292 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400293
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800294 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400295
Shaodde78e82017-05-22 14:13:27 +0800296 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
297 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800298
299 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800300
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800301 GLsizei effectiveStride =
302 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
303 attrib.pointer = pointer;
304 attrib.vertexAttribArrayStride = stride;
305
Shaodde78e82017-05-22 14:13:27 +0800306 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800307
Jamie Madille858cb12018-03-27 09:44:32 -0400308 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400309
310 mState.mClientMemoryAttribsMask.set(attribIndex, boundBuffer == nullptr);
Jamie Madill51af38b2018-04-15 08:50:56 -0400311 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
312 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700313}
314
Jamie Madill4928b7c2017-06-20 12:57:39 -0400315void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700316{
James Darpiniane8a93c62018-01-04 18:02:24 -0800317 bool isBound = context->isCurrentVertexArray(this);
318 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700319 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray,
320 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400321 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800322 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700323 mState.mElementArrayBuffer->onBindingChanged(context, true, BufferBinding::ElementArray,
324 false);
Jamie Madill09463932018-04-04 05:26:59 -0400325 mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000326 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
327}
328
Frank Henigman0af5b862018-03-27 20:19:33 -0400329gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000330{
331 if (mDirtyBits.any())
332 {
Jamie Madill09463932018-04-04 05:26:59 -0400333 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400334 ANGLE_TRY(
335 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000336 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400337 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400338
339 // This is a bit of an implementation hack - but since we know the implementation
340 // details of the dirty bit class it should always have the same effect as iterating
341 // individual attribs. We could also look into schemes where iterating the dirty
342 // bit set also resets it as you pass through it.
343 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
344 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000345 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400346 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400347}
348
Jamie Madill7267aa62018-04-17 15:28:21 -0400349void VertexArray::onBindingChanged(const Context *context, bool bound)
James Darpiniane8a93c62018-01-04 18:02:24 -0800350{
351 if (mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700352 mState.mElementArrayBuffer->onBindingChanged(context, bound, BufferBinding::ElementArray,
353 false);
James Darpiniane8a93c62018-01-04 18:02:24 -0800354 for (auto &binding : mState.mVertexBindings)
355 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400356 binding.onContainerBindingChanged(context, bound);
James Darpiniane8a93c62018-01-04 18:02:24 -0800357 }
358}
359
Jamie Madill09463932018-04-04 05:26:59 -0400360VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
361 angle::SubjectIndex index) const
362{
363 if (index == mArrayBufferObserverBindings.size())
364 {
365 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
366 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
367 }
368 else
369 {
370 // Note: this currently just gets the top-level dirty bit.
371 ASSERT(index < mArrayBufferObserverBindings.size());
372 return static_cast<DirtyBitType>(
373 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
374 }
375}
376
377void VertexArray::onSubjectStateChange(const gl::Context *context,
378 angle::SubjectIndex index,
379 angle::SubjectMessage message)
380{
Jamie Madill7267aa62018-04-17 15:28:21 -0400381 switch (message)
382 {
383 case angle::SubjectMessage::CONTENTS_CHANGED:
384 setDependentDirtyBit(context, true, index);
385 break;
386
387 case angle::SubjectMessage::STORAGE_CHANGED:
388 setDependentDirtyBit(context, false, index);
389 if (index < mArrayBufferObserverBindings.size())
390 {
391 updateCachedBufferBindingSize(index);
392 }
393 break;
394
395 case angle::SubjectMessage::BINDING_CHANGED:
396 if (index < mArrayBufferObserverBindings.size())
397 {
398 const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
399 updateCachedTransformFeedbackBindingValidation(index, buffer);
400 }
401 break;
402
403 default:
404 UNREACHABLE();
405 break;
406 }
407}
408
409void VertexArray::setDependentDirtyBit(const gl::Context *context,
410 bool contentsChanged,
411 angle::SubjectIndex index)
412{
Jamie Madill09463932018-04-04 05:26:59 -0400413 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
414 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
415 mDirtyBits.set(dirtyBit);
416 context->getGLState().setVertexArrayDirty(this);
417}
418
419void VertexArray::updateObserverBinding(size_t bindingIndex)
420{
421 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
422 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
423 : nullptr);
424}
425
Jamie Madill02c9c042018-04-17 13:43:48 -0400426void VertexArray::updateCachedVertexAttributeSize(size_t attribIndex)
427{
428 mState.mVertexAttributes[attribIndex].updateCachedSizePlusRelativeOffset();
429}
430
431void VertexArray::updateCachedBufferBindingSize(size_t bindingIndex)
432{
433 mState.mVertexBindings[bindingIndex].updateCachedBufferSizeMinusOffset();
434}
435
Jamie Madill7267aa62018-04-17 15:28:21 -0400436void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
437 const Buffer *buffer)
438{
439 const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
440 mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
441}
442
443bool VertexArray::hasTransformFeedbackBindingConflict(const AttributesMask &activeAttribues) const
444{
445 // Fast check first.
446 if (!mCachedTransformFeedbackConflictedBindingsMask.any())
447 {
448 return false;
449 }
450
451 // Slow check. We must ensure that the conflicting attributes are enabled/active.
452 for (size_t attribIndex : activeAttribues)
453 {
454 const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
455 if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
456 {
457 return true;
458 }
459 }
460
461 return false;
462}
463
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800464} // namespace gl