blob: 2ef2eabc1aa73a534b5080d2be874b13611d2f39 [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 Madillad637282018-07-31 11:22:14 -040020 : mLabel(), mVertexBindings()
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));
Jamie Madillad637282018-07-31 11:22:14 -040027 mVertexBindings.emplace_back(static_cast<GLuint>(i));
Jiawei-Shao2597fb62016-12-09 16:38:02 +080028 }
Jamie Madilldc358af2018-07-31 11:22:13 -040029
30 // Initially all attributes start as "client" with no buffer bound.
31 mClientMemoryAttribsMask.set();
Jamie Madill8e344942015-07-09 14:22:07 -040032}
33
Jamie Madill3f572682016-04-26 13:41:36 -040034VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040035{
Jamie Madill8e344942015-07-09 14:22:07 -040036}
37
Jamie Madill51af38b2018-04-15 08:50:56 -040038bool VertexArrayState::hasEnabledNullPointerClientArray() const
39{
40 return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
41}
42
Jamie Madillad637282018-07-31 11:22:14 -040043AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080044{
45 ASSERT(bindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
Jamie Madillad637282018-07-31 11:22:14 -040046 return mVertexBindings[bindingIndex].getBoundAttributesMask();
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080047}
48
49// Set an attribute using a new binding.
50void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
51{
52 ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
53
54 // Update the binding-attribute map.
55 const GLuint oldBindingIndex = mVertexAttributes[attribIndex].bindingIndex;
56 ASSERT(oldBindingIndex != newBindingIndex);
57
Jamie Madillad637282018-07-31 11:22:14 -040058 ASSERT(mVertexBindings[oldBindingIndex].getBoundAttributesMask().test(attribIndex) &&
59 !mVertexBindings[newBindingIndex].getBoundAttributesMask().test(attribIndex));
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080060
Jamie Madillad637282018-07-31 11:22:14 -040061 mVertexBindings[oldBindingIndex].resetBoundAttribute(attribIndex);
62 mVertexBindings[newBindingIndex].setBoundAttribute(attribIndex);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080063
64 // Set the attribute using the new binding.
65 mVertexAttributes[attribIndex].bindingIndex = newBindingIndex;
66}
67
Jamie Madillbcef3222018-04-13 15:19:11 -040068// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080069VertexArray::VertexArray(rx::GLImplFactory *factory,
70 GLuint id,
71 size_t maxAttribs,
72 size_t maxAttribBindings)
73 : mId(id),
74 mState(maxAttribs, maxAttribBindings),
Jamie Madill09463932018-04-04 05:26:59 -040075 mVertexArray(factory->createVertexArray(mState)),
76 mElementArrayBufferObserverBinding(this, maxAttribBindings)
Jamie Madill8e344942015-07-09 14:22:07 -040077{
Jamie Madill09463932018-04-04 05:26:59 -040078 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
79 {
80 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
81 }
Jamie Madill004a6f92013-07-10 15:13:38 -040082}
83
Jamie Madill4928b7c2017-06-20 12:57:39 -040084void VertexArray::onDestroy(const Context *context)
85{
James Darpiniane8a93c62018-01-04 18:02:24 -080086 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -040087 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -040088 {
James Darpiniane8a93c62018-01-04 18:02:24 -080089 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -040090 }
James Darpiniane8a93c62018-01-04 18:02:24 -080091 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -070092 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray,
93 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -040094 mState.mElementArrayBuffer.set(context, nullptr);
95 mVertexArray->destroy(context);
96 SafeDelete(mVertexArray);
97 delete this;
98}
99
Jamie Madill004a6f92013-07-10 15:13:38 -0400100VertexArray::~VertexArray()
101{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400102 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -0400103}
104
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400105GLuint VertexArray::id() const
106{
107 return mId;
108}
109
Geoff Lang70d0f492015-12-10 17:45:46 -0500110void VertexArray::setLabel(const std::string &label)
111{
Jamie Madill3f572682016-04-26 13:41:36 -0400112 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500113}
114
115const std::string &VertexArray::getLabel() const
116{
Jamie Madill3f572682016-04-26 13:41:36 -0400117 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500118}
119
Jamie Madill4928b7c2017-06-20 12:57:39 -0400120void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400121{
James Darpiniane8a93c62018-01-04 18:02:24 -0800122 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800123 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -0400124 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300125 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400126 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800127 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400128 }
129 }
130
Jamie Madill3f572682016-04-26 13:41:36 -0400131 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400132 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800133 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700134 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::Array,
135 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400136 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400137 }
138}
139
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800140const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400141{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800142 ASSERT(attribIndex < getMaxAttribs());
143 return mState.mVertexAttributes[attribIndex];
144}
145
146const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
147{
148 ASSERT(bindingIndex < getMaxBindings());
149 return mState.mVertexBindings[bindingIndex];
150}
151
Shaodde78e82017-05-22 14:13:27 +0800152size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800153{
154 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
155 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800156 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400157 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
158}
159
160void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
161{
162 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
163 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
164}
165
166void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
167{
168 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
169 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800170}
171
Shaodde78e82017-05-22 14:13:27 +0800172void VertexArray::bindVertexBufferImpl(const Context *context,
173 size_t bindingIndex,
174 Buffer *boundBuffer,
175 GLintptr offset,
176 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800177{
178 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800179 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800180
181 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
182
James Darpiniane8a93c62018-01-04 18:02:24 -0800183 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300184 binding->setOffset(offset);
185 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400186
187 updateObserverBinding(bindingIndex);
Jamie Madill02c9c042018-04-17 13:43:48 -0400188 updateCachedBufferBindingSize(bindingIndex);
Jamie Madill7267aa62018-04-17 15:28:21 -0400189 updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
Jamie Madilldc358af2018-07-31 11:22:13 -0400190
191 // Update client memory attribute pointers. Affects all bound attributes.
192 if (boundBuffer)
193 {
Jamie Madillad637282018-07-31 11:22:14 -0400194 mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400195 }
196 else
197 {
Jamie Madillad637282018-07-31 11:22:14 -0400198 mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400199 }
Shaodde78e82017-05-22 14:13:27 +0800200}
201
202void VertexArray::bindVertexBuffer(const Context *context,
203 size_t bindingIndex,
204 Buffer *boundBuffer,
205 GLintptr offset,
206 GLsizei stride)
207{
208 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400209 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800210}
211
Shaodde78e82017-05-22 14:13:27 +0800212void VertexArray::setVertexAttribBinding(const Context *context,
213 size_t attribIndex,
214 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800215{
216 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
217
Shaodde78e82017-05-22 14:13:27 +0800218 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
219 {
220 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
221 ASSERT(context->getClientVersion() >= ES_3_1);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +0800222
223 mState.setAttribBinding(attribIndex, bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800224
Jamie Madille858cb12018-03-27 09:44:32 -0400225 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Jamie Madilldc358af2018-07-31 11:22:13 -0400226
227 // Update client attribs mask.
228 bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
229 mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
Shaodde78e82017-05-22 14:13:27 +0800230 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800231}
232
233void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
234{
235 ASSERT(bindingIndex < getMaxBindings());
236
Martin Radevdd5f27e2017-06-07 10:17:09 +0300237 mState.mVertexBindings[bindingIndex].setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400238 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800239}
240
Shaodde78e82017-05-22 14:13:27 +0800241void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
242 GLint size,
243 GLenum type,
244 bool normalized,
245 bool pureInteger,
246 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800247{
248 ASSERT(attribIndex < getMaxAttribs());
249
250 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
251
252 attrib->size = size;
253 attrib->type = type;
254 attrib->normalized = normalized;
255 attrib->pureInteger = pureInteger;
256 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800257 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Jamie Madill02c9c042018-04-17 13:43:48 -0400258 attrib->updateCachedSizePlusRelativeOffset();
Shaodde78e82017-05-22 14:13:27 +0800259}
260
261void VertexArray::setVertexAttribFormat(size_t attribIndex,
262 GLint size,
263 GLenum type,
264 bool normalized,
265 bool pureInteger,
266 GLuint relativeOffset)
267{
268 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400269 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madill57a89722013-07-02 11:57:03 -0400270}
271
Shaodde78e82017-05-22 14:13:27 +0800272void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400273{
Shaodde78e82017-05-22 14:13:27 +0800274 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800275
Shaodde78e82017-05-22 14:13:27 +0800276 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
277 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400278}
279
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800280void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400281{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800282 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800283
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800284 mState.mVertexAttributes[attribIndex].enabled = enabledState;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800285 mState.mVertexAttributesTypeMask.setIndex(
286 GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800287
Jamie Madille858cb12018-03-27 09:44:32 -0400288 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400289
290 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500291 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madill57a89722013-07-02 11:57:03 -0400292}
293
Shaodde78e82017-05-22 14:13:27 +0800294void VertexArray::setVertexAttribPointer(const Context *context,
295 size_t attribIndex,
296 gl::Buffer *boundBuffer,
297 GLint size,
298 GLenum type,
299 bool normalized,
300 bool pureInteger,
301 GLsizei stride,
302 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400303{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800304 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400305
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800306 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400307
Shaodde78e82017-05-22 14:13:27 +0800308 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
309 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800310
311 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800312
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800313 GLsizei effectiveStride =
314 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
315 attrib.pointer = pointer;
316 attrib.vertexAttribArrayStride = stride;
317
Shaodde78e82017-05-22 14:13:27 +0800318 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800319
Jamie Madille858cb12018-03-27 09:44:32 -0400320 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400321
Jamie Madill51af38b2018-04-15 08:50:56 -0400322 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
323 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700324}
325
Jamie Madill4928b7c2017-06-20 12:57:39 -0400326void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700327{
James Darpiniane8a93c62018-01-04 18:02:24 -0800328 bool isBound = context->isCurrentVertexArray(this);
329 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700330 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray,
331 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400332 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800333 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700334 mState.mElementArrayBuffer->onBindingChanged(context, true, BufferBinding::ElementArray,
335 false);
Jamie Madill09463932018-04-04 05:26:59 -0400336 mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000337 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
338}
339
Frank Henigman0af5b862018-03-27 20:19:33 -0400340gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000341{
342 if (mDirtyBits.any())
343 {
Jamie Madill09463932018-04-04 05:26:59 -0400344 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400345 ANGLE_TRY(
346 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000347 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400348 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400349
350 // This is a bit of an implementation hack - but since we know the implementation
351 // details of the dirty bit class it should always have the same effect as iterating
352 // individual attribs. We could also look into schemes where iterating the dirty
353 // bit set also resets it as you pass through it.
354 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
355 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000356 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400357 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400358}
359
Jamie Madill7267aa62018-04-17 15:28:21 -0400360void VertexArray::onBindingChanged(const Context *context, bool bound)
James Darpiniane8a93c62018-01-04 18:02:24 -0800361{
362 if (mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700363 mState.mElementArrayBuffer->onBindingChanged(context, bound, BufferBinding::ElementArray,
364 false);
James Darpiniane8a93c62018-01-04 18:02:24 -0800365 for (auto &binding : mState.mVertexBindings)
366 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400367 binding.onContainerBindingChanged(context, bound);
James Darpiniane8a93c62018-01-04 18:02:24 -0800368 }
369}
370
Jamie Madill09463932018-04-04 05:26:59 -0400371VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
372 angle::SubjectIndex index) const
373{
374 if (index == mArrayBufferObserverBindings.size())
375 {
376 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
377 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
378 }
379 else
380 {
381 // Note: this currently just gets the top-level dirty bit.
382 ASSERT(index < mArrayBufferObserverBindings.size());
383 return static_cast<DirtyBitType>(
384 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
385 }
386}
387
388void VertexArray::onSubjectStateChange(const gl::Context *context,
389 angle::SubjectIndex index,
390 angle::SubjectMessage message)
391{
Jamie Madill7267aa62018-04-17 15:28:21 -0400392 switch (message)
393 {
394 case angle::SubjectMessage::CONTENTS_CHANGED:
395 setDependentDirtyBit(context, true, index);
396 break;
397
398 case angle::SubjectMessage::STORAGE_CHANGED:
399 setDependentDirtyBit(context, false, index);
400 if (index < mArrayBufferObserverBindings.size())
401 {
402 updateCachedBufferBindingSize(index);
403 }
404 break;
405
406 case angle::SubjectMessage::BINDING_CHANGED:
407 if (index < mArrayBufferObserverBindings.size())
408 {
409 const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
410 updateCachedTransformFeedbackBindingValidation(index, buffer);
411 }
412 break;
413
414 default:
415 UNREACHABLE();
416 break;
417 }
418}
419
420void VertexArray::setDependentDirtyBit(const gl::Context *context,
421 bool contentsChanged,
422 angle::SubjectIndex index)
423{
Jamie Madill09463932018-04-04 05:26:59 -0400424 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
425 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
426 mDirtyBits.set(dirtyBit);
427 context->getGLState().setVertexArrayDirty(this);
428}
429
430void VertexArray::updateObserverBinding(size_t bindingIndex)
431{
432 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
433 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
434 : nullptr);
435}
436
Jamie Madill02c9c042018-04-17 13:43:48 -0400437void VertexArray::updateCachedVertexAttributeSize(size_t attribIndex)
438{
439 mState.mVertexAttributes[attribIndex].updateCachedSizePlusRelativeOffset();
440}
441
442void VertexArray::updateCachedBufferBindingSize(size_t bindingIndex)
443{
444 mState.mVertexBindings[bindingIndex].updateCachedBufferSizeMinusOffset();
445}
446
Jamie Madill7267aa62018-04-17 15:28:21 -0400447void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
448 const Buffer *buffer)
449{
450 const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
451 mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
452}
453
Jamie Madillac43aaa2018-07-31 11:22:13 -0400454bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
Jamie Madill7267aa62018-04-17 15:28:21 -0400455{
456 // Fast check first.
457 if (!mCachedTransformFeedbackConflictedBindingsMask.any())
458 {
459 return false;
460 }
461
Jamie Madillac43aaa2018-07-31 11:22:13 -0400462 const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
463
Jamie Madill7267aa62018-04-17 15:28:21 -0400464 // Slow check. We must ensure that the conflicting attributes are enabled/active.
465 for (size_t attribIndex : activeAttribues)
466 {
467 const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
468 if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
469 {
470 return true;
471 }
472 }
473
474 return false;
475}
476
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800477} // namespace gl