1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // Implementation of the state class for mananging GLES 3 Vertex Array Objects.
7*8975f5c5SAndroid Build Coastguard Worker //
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/VertexArray.h"
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Buffer.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/BufferImpl.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/GLImplFactory.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/VertexArrayImpl.h"
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker namespace gl
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker namespace
21*8975f5c5SAndroid Build Coastguard Worker {
IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex)22*8975f5c5SAndroid Build Coastguard Worker bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex)
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker return (subjectIndex == kElementArrayBufferIndex);
25*8975f5c5SAndroid Build Coastguard Worker }
26*8975f5c5SAndroid Build Coastguard Worker } // namespace
27*8975f5c5SAndroid Build Coastguard Worker
28*8975f5c5SAndroid Build Coastguard Worker // VertexArrayState implementation.
VertexArrayState(VertexArray * vertexArray,size_t maxAttribs,size_t maxAttribBindings)29*8975f5c5SAndroid Build Coastguard Worker VertexArrayState::VertexArrayState(VertexArray *vertexArray,
30*8975f5c5SAndroid Build Coastguard Worker size_t maxAttribs,
31*8975f5c5SAndroid Build Coastguard Worker size_t maxAttribBindings)
32*8975f5c5SAndroid Build Coastguard Worker : mId(vertexArray->id()), mElementArrayBuffer(vertexArray, kElementArrayBufferIndex)
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker ASSERT(maxAttribs <= maxAttribBindings);
35*8975f5c5SAndroid Build Coastguard Worker
36*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < maxAttribs; i++)
37*8975f5c5SAndroid Build Coastguard Worker {
38*8975f5c5SAndroid Build Coastguard Worker mVertexAttributes.emplace_back(static_cast<GLuint>(i));
39*8975f5c5SAndroid Build Coastguard Worker mVertexBindings.emplace_back(static_cast<GLuint>(i));
40*8975f5c5SAndroid Build Coastguard Worker }
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker // Initially all attributes start as "client" with no buffer bound.
43*8975f5c5SAndroid Build Coastguard Worker mClientMemoryAttribsMask.set();
44*8975f5c5SAndroid Build Coastguard Worker }
45*8975f5c5SAndroid Build Coastguard Worker
~VertexArrayState()46*8975f5c5SAndroid Build Coastguard Worker VertexArrayState::~VertexArrayState() {}
47*8975f5c5SAndroid Build Coastguard Worker
hasEnabledNullPointerClientArray() const48*8975f5c5SAndroid Build Coastguard Worker bool VertexArrayState::hasEnabledNullPointerClientArray() const
49*8975f5c5SAndroid Build Coastguard Worker {
50*8975f5c5SAndroid Build Coastguard Worker return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
51*8975f5c5SAndroid Build Coastguard Worker }
52*8975f5c5SAndroid Build Coastguard Worker
getBindingToAttributesMask(GLuint bindingIndex) const53*8975f5c5SAndroid Build Coastguard Worker AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
54*8975f5c5SAndroid Build Coastguard Worker {
55*8975f5c5SAndroid Build Coastguard Worker ASSERT(bindingIndex < mVertexBindings.size());
56*8975f5c5SAndroid Build Coastguard Worker return mVertexBindings[bindingIndex].getBoundAttributesMask();
57*8975f5c5SAndroid Build Coastguard Worker }
58*8975f5c5SAndroid Build Coastguard Worker
59*8975f5c5SAndroid Build Coastguard Worker // Set an attribute using a new binding.
setAttribBinding(const Context * context,size_t attribIndex,GLuint newBindingIndex)60*8975f5c5SAndroid Build Coastguard Worker void VertexArrayState::setAttribBinding(const Context *context,
61*8975f5c5SAndroid Build Coastguard Worker size_t attribIndex,
62*8975f5c5SAndroid Build Coastguard Worker GLuint newBindingIndex)
63*8975f5c5SAndroid Build Coastguard Worker {
64*8975f5c5SAndroid Build Coastguard Worker ASSERT(attribIndex < mVertexAttributes.size() && newBindingIndex < mVertexBindings.size());
65*8975f5c5SAndroid Build Coastguard Worker
66*8975f5c5SAndroid Build Coastguard Worker VertexAttribute &attrib = mVertexAttributes[attribIndex];
67*8975f5c5SAndroid Build Coastguard Worker
68*8975f5c5SAndroid Build Coastguard Worker // Update the binding-attribute map.
69*8975f5c5SAndroid Build Coastguard Worker const GLuint oldBindingIndex = attrib.bindingIndex;
70*8975f5c5SAndroid Build Coastguard Worker ASSERT(oldBindingIndex != newBindingIndex);
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker VertexBinding &oldBinding = mVertexBindings[oldBindingIndex];
73*8975f5c5SAndroid Build Coastguard Worker VertexBinding &newBinding = mVertexBindings[newBindingIndex];
74*8975f5c5SAndroid Build Coastguard Worker
75*8975f5c5SAndroid Build Coastguard Worker ASSERT(oldBinding.getBoundAttributesMask().test(attribIndex) &&
76*8975f5c5SAndroid Build Coastguard Worker !newBinding.getBoundAttributesMask().test(attribIndex));
77*8975f5c5SAndroid Build Coastguard Worker
78*8975f5c5SAndroid Build Coastguard Worker oldBinding.resetBoundAttribute(attribIndex);
79*8975f5c5SAndroid Build Coastguard Worker newBinding.setBoundAttribute(attribIndex);
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker // Set the attribute using the new binding.
82*8975f5c5SAndroid Build Coastguard Worker attrib.bindingIndex = newBindingIndex;
83*8975f5c5SAndroid Build Coastguard Worker
84*8975f5c5SAndroid Build Coastguard Worker if (context->isBufferAccessValidationEnabled())
85*8975f5c5SAndroid Build Coastguard Worker {
86*8975f5c5SAndroid Build Coastguard Worker attrib.updateCachedElementLimit(newBinding);
87*8975f5c5SAndroid Build Coastguard Worker }
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard Worker bool isMapped = newBinding.getBuffer().get() && newBinding.getBuffer()->isMapped();
90*8975f5c5SAndroid Build Coastguard Worker mCachedMappedArrayBuffers.set(attribIndex, isMapped);
91*8975f5c5SAndroid Build Coastguard Worker mEnabledAttributesMask.set(attribIndex, attrib.enabled);
92*8975f5c5SAndroid Build Coastguard Worker updateCachedMutableOrNonPersistentArrayBuffers(attribIndex);
93*8975f5c5SAndroid Build Coastguard Worker mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mEnabledAttributesMask &
94*8975f5c5SAndroid Build Coastguard Worker mCachedMutableOrImpersistentArrayBuffers;
95*8975f5c5SAndroid Build Coastguard Worker }
96*8975f5c5SAndroid Build Coastguard Worker
updateCachedMutableOrNonPersistentArrayBuffers(size_t index)97*8975f5c5SAndroid Build Coastguard Worker void VertexArrayState::updateCachedMutableOrNonPersistentArrayBuffers(size_t index)
98*8975f5c5SAndroid Build Coastguard Worker {
99*8975f5c5SAndroid Build Coastguard Worker const VertexBinding &vertexBinding = mVertexBindings[index];
100*8975f5c5SAndroid Build Coastguard Worker const BindingPointer<Buffer> &buffer = vertexBinding.getBuffer();
101*8975f5c5SAndroid Build Coastguard Worker bool isMutableOrImpersistentArrayBuffer =
102*8975f5c5SAndroid Build Coastguard Worker buffer.get() &&
103*8975f5c5SAndroid Build Coastguard Worker (!buffer->isImmutable() || (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0);
104*8975f5c5SAndroid Build Coastguard Worker mCachedMutableOrImpersistentArrayBuffers.set(index, isMutableOrImpersistentArrayBuffer);
105*8975f5c5SAndroid Build Coastguard Worker }
106*8975f5c5SAndroid Build Coastguard Worker
isDefault() const107*8975f5c5SAndroid Build Coastguard Worker bool VertexArrayState::isDefault() const
108*8975f5c5SAndroid Build Coastguard Worker {
109*8975f5c5SAndroid Build Coastguard Worker return mId.value == 0;
110*8975f5c5SAndroid Build Coastguard Worker }
111*8975f5c5SAndroid Build Coastguard Worker
112*8975f5c5SAndroid Build Coastguard Worker // VertexArray implementation.
VertexArray(rx::GLImplFactory * factory,VertexArrayID id,size_t maxAttribs,size_t maxAttribBindings)113*8975f5c5SAndroid Build Coastguard Worker VertexArray::VertexArray(rx::GLImplFactory *factory,
114*8975f5c5SAndroid Build Coastguard Worker VertexArrayID id,
115*8975f5c5SAndroid Build Coastguard Worker size_t maxAttribs,
116*8975f5c5SAndroid Build Coastguard Worker size_t maxAttribBindings)
117*8975f5c5SAndroid Build Coastguard Worker : mId(id),
118*8975f5c5SAndroid Build Coastguard Worker mState(this, maxAttribs, maxAttribBindings),
119*8975f5c5SAndroid Build Coastguard Worker mVertexArray(factory->createVertexArray(mState)),
120*8975f5c5SAndroid Build Coastguard Worker mBufferAccessValidationEnabled(false),
121*8975f5c5SAndroid Build Coastguard Worker mContentsObservers(this)
122*8975f5c5SAndroid Build Coastguard Worker {
123*8975f5c5SAndroid Build Coastguard Worker for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker mArrayBufferObserverBindings.emplace_back(this, attribIndex);
126*8975f5c5SAndroid Build Coastguard Worker }
127*8975f5c5SAndroid Build Coastguard Worker
128*8975f5c5SAndroid Build Coastguard Worker mVertexArray->setContentsObservers(&mContentsObservers);
129*8975f5c5SAndroid Build Coastguard Worker }
130*8975f5c5SAndroid Build Coastguard Worker
onDestroy(const Context * context)131*8975f5c5SAndroid Build Coastguard Worker void VertexArray::onDestroy(const Context *context)
132*8975f5c5SAndroid Build Coastguard Worker {
133*8975f5c5SAndroid Build Coastguard Worker bool isBound = context->isCurrentVertexArray(this);
134*8975f5c5SAndroid Build Coastguard Worker for (size_t bindingIndex : mState.mBufferBindingMask)
135*8975f5c5SAndroid Build Coastguard Worker {
136*8975f5c5SAndroid Build Coastguard Worker VertexBinding &binding = mState.mVertexBindings[bindingIndex];
137*8975f5c5SAndroid Build Coastguard Worker Buffer *buffer = binding.getBuffer().get();
138*8975f5c5SAndroid Build Coastguard Worker ASSERT(buffer != nullptr);
139*8975f5c5SAndroid Build Coastguard Worker if (isBound)
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker buffer->onNonTFBindingChanged(-1);
142*8975f5c5SAndroid Build Coastguard Worker }
143*8975f5c5SAndroid Build Coastguard Worker else
144*8975f5c5SAndroid Build Coastguard Worker {
145*8975f5c5SAndroid Build Coastguard Worker // un-assigning to avoid assertion, since it was already removed from buffer's observer
146*8975f5c5SAndroid Build Coastguard Worker // list.
147*8975f5c5SAndroid Build Coastguard Worker mArrayBufferObserverBindings[bindingIndex].assignSubject(nullptr);
148*8975f5c5SAndroid Build Coastguard Worker }
149*8975f5c5SAndroid Build Coastguard Worker // Note: the non-contents observer is unbound in the ObserverBinding destructor.
150*8975f5c5SAndroid Build Coastguard Worker buffer->removeContentsObserver(this, static_cast<uint32_t>(bindingIndex));
151*8975f5c5SAndroid Build Coastguard Worker binding.setBuffer(context, nullptr);
152*8975f5c5SAndroid Build Coastguard Worker }
153*8975f5c5SAndroid Build Coastguard Worker mState.mBufferBindingMask.reset();
154*8975f5c5SAndroid Build Coastguard Worker
155*8975f5c5SAndroid Build Coastguard Worker if (mState.mElementArrayBuffer.get())
156*8975f5c5SAndroid Build Coastguard Worker {
157*8975f5c5SAndroid Build Coastguard Worker if (isBound)
158*8975f5c5SAndroid Build Coastguard Worker {
159*8975f5c5SAndroid Build Coastguard Worker mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
160*8975f5c5SAndroid Build Coastguard Worker }
161*8975f5c5SAndroid Build Coastguard Worker mState.mElementArrayBuffer->removeContentsObserver(this, kElementArrayBufferIndex);
162*8975f5c5SAndroid Build Coastguard Worker }
163*8975f5c5SAndroid Build Coastguard Worker mState.mElementArrayBuffer.bind(context, nullptr);
164*8975f5c5SAndroid Build Coastguard Worker
165*8975f5c5SAndroid Build Coastguard Worker mVertexArray->destroy(context);
166*8975f5c5SAndroid Build Coastguard Worker SafeDelete(mVertexArray);
167*8975f5c5SAndroid Build Coastguard Worker delete this;
168*8975f5c5SAndroid Build Coastguard Worker }
169*8975f5c5SAndroid Build Coastguard Worker
~VertexArray()170*8975f5c5SAndroid Build Coastguard Worker VertexArray::~VertexArray()
171*8975f5c5SAndroid Build Coastguard Worker {
172*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mVertexArray);
173*8975f5c5SAndroid Build Coastguard Worker }
174*8975f5c5SAndroid Build Coastguard Worker
setLabel(const Context * context,const std::string & label)175*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexArray::setLabel(const Context *context, const std::string &label)
176*8975f5c5SAndroid Build Coastguard Worker {
177*8975f5c5SAndroid Build Coastguard Worker mState.mLabel = label;
178*8975f5c5SAndroid Build Coastguard Worker
179*8975f5c5SAndroid Build Coastguard Worker if (mVertexArray)
180*8975f5c5SAndroid Build Coastguard Worker {
181*8975f5c5SAndroid Build Coastguard Worker return mVertexArray->onLabelUpdate(context);
182*8975f5c5SAndroid Build Coastguard Worker }
183*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
184*8975f5c5SAndroid Build Coastguard Worker }
185*8975f5c5SAndroid Build Coastguard Worker
getLabel() const186*8975f5c5SAndroid Build Coastguard Worker const std::string &VertexArray::getLabel() const
187*8975f5c5SAndroid Build Coastguard Worker {
188*8975f5c5SAndroid Build Coastguard Worker return mState.mLabel;
189*8975f5c5SAndroid Build Coastguard Worker }
190*8975f5c5SAndroid Build Coastguard Worker
detachBuffer(const Context * context,BufferID bufferID)191*8975f5c5SAndroid Build Coastguard Worker bool VertexArray::detachBuffer(const Context *context, BufferID bufferID)
192*8975f5c5SAndroid Build Coastguard Worker {
193*8975f5c5SAndroid Build Coastguard Worker bool isBound = context->isCurrentVertexArray(this);
194*8975f5c5SAndroid Build Coastguard Worker bool anyBufferDetached = false;
195*8975f5c5SAndroid Build Coastguard Worker for (size_t bindingIndex : mState.mBufferBindingMask)
196*8975f5c5SAndroid Build Coastguard Worker {
197*8975f5c5SAndroid Build Coastguard Worker VertexBinding &binding = mState.mVertexBindings[bindingIndex];
198*8975f5c5SAndroid Build Coastguard Worker const BindingPointer<Buffer> &bufferBinding = binding.getBuffer();
199*8975f5c5SAndroid Build Coastguard Worker if (bufferBinding.id() == bufferID)
200*8975f5c5SAndroid Build Coastguard Worker {
201*8975f5c5SAndroid Build Coastguard Worker if (isBound)
202*8975f5c5SAndroid Build Coastguard Worker {
203*8975f5c5SAndroid Build Coastguard Worker if (bufferBinding.get())
204*8975f5c5SAndroid Build Coastguard Worker bufferBinding->onNonTFBindingChanged(-1);
205*8975f5c5SAndroid Build Coastguard Worker }
206*8975f5c5SAndroid Build Coastguard Worker bufferBinding->removeContentsObserver(this, static_cast<uint32_t>(bindingIndex));
207*8975f5c5SAndroid Build Coastguard Worker binding.setBuffer(context, nullptr);
208*8975f5c5SAndroid Build Coastguard Worker mArrayBufferObserverBindings[bindingIndex].reset();
209*8975f5c5SAndroid Build Coastguard Worker mState.mBufferBindingMask.reset(bindingIndex);
210*8975f5c5SAndroid Build Coastguard Worker
211*8975f5c5SAndroid Build Coastguard Worker if (context->getClientVersion() >= ES_3_1 && !mState.isDefault())
212*8975f5c5SAndroid Build Coastguard Worker {
213*8975f5c5SAndroid Build Coastguard Worker setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
214*8975f5c5SAndroid Build Coastguard Worker }
215*8975f5c5SAndroid Build Coastguard Worker else
216*8975f5c5SAndroid Build Coastguard Worker {
217*8975f5c5SAndroid Build Coastguard Worker static_assert(MAX_VERTEX_ATTRIB_BINDINGS < 8 * sizeof(uint32_t),
218*8975f5c5SAndroid Build Coastguard Worker "Not enough bits in bindingIndex");
219*8975f5c5SAndroid Build Coastguard Worker // The redundant uint32_t cast here is required to avoid a warning on MSVC.
220*8975f5c5SAndroid Build Coastguard Worker ASSERT(binding.getBoundAttributesMask() ==
221*8975f5c5SAndroid Build Coastguard Worker AttributesMask(static_cast<uint32_t>(1 << bindingIndex)));
222*8975f5c5SAndroid Build Coastguard Worker setDirtyAttribBit(bindingIndex, DIRTY_ATTRIB_POINTER);
223*8975f5c5SAndroid Build Coastguard Worker }
224*8975f5c5SAndroid Build Coastguard Worker
225*8975f5c5SAndroid Build Coastguard Worker anyBufferDetached = true;
226*8975f5c5SAndroid Build Coastguard Worker mState.mClientMemoryAttribsMask |= binding.getBoundAttributesMask();
227*8975f5c5SAndroid Build Coastguard Worker }
228*8975f5c5SAndroid Build Coastguard Worker }
229*8975f5c5SAndroid Build Coastguard Worker
230*8975f5c5SAndroid Build Coastguard Worker if (mState.mElementArrayBuffer.get() && mState.mElementArrayBuffer->id() == bufferID)
231*8975f5c5SAndroid Build Coastguard Worker {
232*8975f5c5SAndroid Build Coastguard Worker if (isBound && mState.mElementArrayBuffer.get())
233*8975f5c5SAndroid Build Coastguard Worker mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
234*8975f5c5SAndroid Build Coastguard Worker mState.mElementArrayBuffer->removeContentsObserver(this, kElementArrayBufferIndex);
235*8975f5c5SAndroid Build Coastguard Worker mState.mElementArrayBuffer.bind(context, nullptr);
236*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
237*8975f5c5SAndroid Build Coastguard Worker anyBufferDetached = true;
238*8975f5c5SAndroid Build Coastguard Worker }
239*8975f5c5SAndroid Build Coastguard Worker
240*8975f5c5SAndroid Build Coastguard Worker return anyBufferDetached;
241*8975f5c5SAndroid Build Coastguard Worker }
242*8975f5c5SAndroid Build Coastguard Worker
getVertexAttribute(size_t attribIndex) const243*8975f5c5SAndroid Build Coastguard Worker const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
244*8975f5c5SAndroid Build Coastguard Worker {
245*8975f5c5SAndroid Build Coastguard Worker ASSERT(attribIndex < getMaxAttribs());
246*8975f5c5SAndroid Build Coastguard Worker return mState.mVertexAttributes[attribIndex];
247*8975f5c5SAndroid Build Coastguard Worker }
248*8975f5c5SAndroid Build Coastguard Worker
getVertexBinding(size_t bindingIndex) const249*8975f5c5SAndroid Build Coastguard Worker const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
250*8975f5c5SAndroid Build Coastguard Worker {
251*8975f5c5SAndroid Build Coastguard Worker ASSERT(bindingIndex < getMaxBindings());
252*8975f5c5SAndroid Build Coastguard Worker return mState.mVertexBindings[bindingIndex];
253*8975f5c5SAndroid Build Coastguard Worker }
254*8975f5c5SAndroid Build Coastguard Worker
GetVertexIndexFromDirtyBit(size_t dirtyBit)255*8975f5c5SAndroid Build Coastguard Worker size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
256*8975f5c5SAndroid Build Coastguard Worker {
257*8975f5c5SAndroid Build Coastguard Worker static_assert(MAX_VERTEX_ATTRIBS == MAX_VERTEX_ATTRIB_BINDINGS,
258*8975f5c5SAndroid Build Coastguard Worker "The stride of vertex attributes should equal to that of vertex bindings.");
259*8975f5c5SAndroid Build Coastguard Worker ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
260*8975f5c5SAndroid Build Coastguard Worker return (dirtyBit - DIRTY_BIT_ATTRIB_0) % MAX_VERTEX_ATTRIBS;
261*8975f5c5SAndroid Build Coastguard Worker }
262*8975f5c5SAndroid Build Coastguard Worker
setDirtyAttribBit(size_t attribIndex,DirtyAttribBitType dirtyAttribBit)263*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void VertexArray::setDirtyAttribBit(size_t attribIndex,
264*8975f5c5SAndroid Build Coastguard Worker DirtyAttribBitType dirtyAttribBit)
265*8975f5c5SAndroid Build Coastguard Worker {
266*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
267*8975f5c5SAndroid Build Coastguard Worker mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
268*8975f5c5SAndroid Build Coastguard Worker }
269*8975f5c5SAndroid Build Coastguard Worker
clearDirtyAttribBit(size_t attribIndex,DirtyAttribBitType dirtyAttribBit)270*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void VertexArray::clearDirtyAttribBit(size_t attribIndex,
271*8975f5c5SAndroid Build Coastguard Worker DirtyAttribBitType dirtyAttribBit)
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker mDirtyAttribBits[attribIndex].set(dirtyAttribBit, false);
274*8975f5c5SAndroid Build Coastguard Worker if (mDirtyAttribBits[attribIndex].any())
275*8975f5c5SAndroid Build Coastguard Worker {
276*8975f5c5SAndroid Build Coastguard Worker return;
277*8975f5c5SAndroid Build Coastguard Worker }
278*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex, false);
279*8975f5c5SAndroid Build Coastguard Worker }
280*8975f5c5SAndroid Build Coastguard Worker
setDirtyBindingBit(size_t bindingIndex,DirtyBindingBitType dirtyBindingBit)281*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void VertexArray::setDirtyBindingBit(size_t bindingIndex,
282*8975f5c5SAndroid Build Coastguard Worker DirtyBindingBitType dirtyBindingBit)
283*8975f5c5SAndroid Build Coastguard Worker {
284*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
285*8975f5c5SAndroid Build Coastguard Worker mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
286*8975f5c5SAndroid Build Coastguard Worker }
287*8975f5c5SAndroid Build Coastguard Worker
updateCachedBufferBindingSize(VertexBinding * binding)288*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
289*8975f5c5SAndroid Build Coastguard Worker {
290*8975f5c5SAndroid Build Coastguard Worker if (!mBufferAccessValidationEnabled)
291*8975f5c5SAndroid Build Coastguard Worker return;
292*8975f5c5SAndroid Build Coastguard Worker
293*8975f5c5SAndroid Build Coastguard Worker for (size_t boundAttribute : binding->getBoundAttributesMask())
294*8975f5c5SAndroid Build Coastguard Worker {
295*8975f5c5SAndroid Build Coastguard Worker mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
296*8975f5c5SAndroid Build Coastguard Worker }
297*8975f5c5SAndroid Build Coastguard Worker }
298*8975f5c5SAndroid Build Coastguard Worker
updateCachedArrayBuffersMasks(bool isMapped,bool isImmutable,bool isPersistent,const AttributesMask & boundAttributesMask)299*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void VertexArray::updateCachedArrayBuffersMasks(
300*8975f5c5SAndroid Build Coastguard Worker bool isMapped,
301*8975f5c5SAndroid Build Coastguard Worker bool isImmutable,
302*8975f5c5SAndroid Build Coastguard Worker bool isPersistent,
303*8975f5c5SAndroid Build Coastguard Worker const AttributesMask &boundAttributesMask)
304*8975f5c5SAndroid Build Coastguard Worker {
305*8975f5c5SAndroid Build Coastguard Worker if (isMapped)
306*8975f5c5SAndroid Build Coastguard Worker {
307*8975f5c5SAndroid Build Coastguard Worker mState.mCachedMappedArrayBuffers |= boundAttributesMask;
308*8975f5c5SAndroid Build Coastguard Worker }
309*8975f5c5SAndroid Build Coastguard Worker else
310*8975f5c5SAndroid Build Coastguard Worker {
311*8975f5c5SAndroid Build Coastguard Worker mState.mCachedMappedArrayBuffers &= ~boundAttributesMask;
312*8975f5c5SAndroid Build Coastguard Worker }
313*8975f5c5SAndroid Build Coastguard Worker
314*8975f5c5SAndroid Build Coastguard Worker if (!isImmutable || !isPersistent)
315*8975f5c5SAndroid Build Coastguard Worker {
316*8975f5c5SAndroid Build Coastguard Worker mState.mCachedMutableOrImpersistentArrayBuffers |= boundAttributesMask;
317*8975f5c5SAndroid Build Coastguard Worker }
318*8975f5c5SAndroid Build Coastguard Worker else
319*8975f5c5SAndroid Build Coastguard Worker {
320*8975f5c5SAndroid Build Coastguard Worker mState.mCachedMutableOrImpersistentArrayBuffers &= ~boundAttributesMask;
321*8975f5c5SAndroid Build Coastguard Worker }
322*8975f5c5SAndroid Build Coastguard Worker
323*8975f5c5SAndroid Build Coastguard Worker mState.mCachedInvalidMappedArrayBuffer = mState.mCachedMappedArrayBuffers &
324*8975f5c5SAndroid Build Coastguard Worker mState.mEnabledAttributesMask &
325*8975f5c5SAndroid Build Coastguard Worker mState.mCachedMutableOrImpersistentArrayBuffers;
326*8975f5c5SAndroid Build Coastguard Worker }
327*8975f5c5SAndroid Build Coastguard Worker
updateCachedMappedArrayBuffersBinding(const VertexBinding & binding)328*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void VertexArray::updateCachedMappedArrayBuffersBinding(const VertexBinding &binding)
329*8975f5c5SAndroid Build Coastguard Worker {
330*8975f5c5SAndroid Build Coastguard Worker const Buffer *buffer = binding.getBuffer().get();
331*8975f5c5SAndroid Build Coastguard Worker bool isMapped = buffer && buffer->isMapped();
332*8975f5c5SAndroid Build Coastguard Worker bool isImmutable = buffer && buffer->isImmutable();
333*8975f5c5SAndroid Build Coastguard Worker bool isPersistent = buffer && (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
334*8975f5c5SAndroid Build Coastguard Worker return updateCachedArrayBuffersMasks(isMapped, isImmutable, isPersistent,
335*8975f5c5SAndroid Build Coastguard Worker binding.getBoundAttributesMask());
336*8975f5c5SAndroid Build Coastguard Worker }
337*8975f5c5SAndroid Build Coastguard Worker
updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,const Buffer * buffer)338*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
339*8975f5c5SAndroid Build Coastguard Worker const Buffer *buffer)
340*8975f5c5SAndroid Build Coastguard Worker {
341*8975f5c5SAndroid Build Coastguard Worker const bool hasConflict = buffer && buffer->hasWebGLXFBBindingConflict(true);
342*8975f5c5SAndroid Build Coastguard Worker mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
343*8975f5c5SAndroid Build Coastguard Worker }
344*8975f5c5SAndroid Build Coastguard Worker
bindVertexBufferImpl(const Context * context,size_t bindingIndex,Buffer * boundBuffer,GLintptr offset,GLsizei stride)345*8975f5c5SAndroid Build Coastguard Worker VertexArray::DirtyBindingBits VertexArray::bindVertexBufferImpl(const Context *context,
346*8975f5c5SAndroid Build Coastguard Worker size_t bindingIndex,
347*8975f5c5SAndroid Build Coastguard Worker Buffer *boundBuffer,
348*8975f5c5SAndroid Build Coastguard Worker GLintptr offset,
349*8975f5c5SAndroid Build Coastguard Worker GLsizei stride)
350*8975f5c5SAndroid Build Coastguard Worker {
351*8975f5c5SAndroid Build Coastguard Worker ASSERT(bindingIndex < getMaxBindings());
352*8975f5c5SAndroid Build Coastguard Worker ASSERT(context->isCurrentVertexArray(this));
353*8975f5c5SAndroid Build Coastguard Worker
354*8975f5c5SAndroid Build Coastguard Worker VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
355*8975f5c5SAndroid Build Coastguard Worker
356*8975f5c5SAndroid Build Coastguard Worker Buffer *oldBuffer = binding->getBuffer().get();
357*8975f5c5SAndroid Build Coastguard Worker
358*8975f5c5SAndroid Build Coastguard Worker DirtyBindingBits dirtyBindingBits;
359*8975f5c5SAndroid Build Coastguard Worker dirtyBindingBits.set(DIRTY_BINDING_BUFFER, oldBuffer != boundBuffer);
360*8975f5c5SAndroid Build Coastguard Worker dirtyBindingBits.set(DIRTY_BINDING_STRIDE, static_cast<GLuint>(stride) != binding->getStride());
361*8975f5c5SAndroid Build Coastguard Worker dirtyBindingBits.set(DIRTY_BINDING_OFFSET, offset != binding->getOffset());
362*8975f5c5SAndroid Build Coastguard Worker
363*8975f5c5SAndroid Build Coastguard Worker if (dirtyBindingBits.none())
364*8975f5c5SAndroid Build Coastguard Worker {
365*8975f5c5SAndroid Build Coastguard Worker return dirtyBindingBits;
366*8975f5c5SAndroid Build Coastguard Worker }
367*8975f5c5SAndroid Build Coastguard Worker
368*8975f5c5SAndroid Build Coastguard Worker if (boundBuffer != oldBuffer)
369*8975f5c5SAndroid Build Coastguard Worker {
370*8975f5c5SAndroid Build Coastguard Worker angle::ObserverBinding *observer = &mArrayBufferObserverBindings[bindingIndex];
371*8975f5c5SAndroid Build Coastguard Worker observer->assignSubject(boundBuffer);
372*8975f5c5SAndroid Build Coastguard Worker
373*8975f5c5SAndroid Build Coastguard Worker // Several nullptr checks are combined here for optimization purposes.
374*8975f5c5SAndroid Build Coastguard Worker if (oldBuffer)
375*8975f5c5SAndroid Build Coastguard Worker {
376*8975f5c5SAndroid Build Coastguard Worker oldBuffer->onNonTFBindingChanged(-1);
377*8975f5c5SAndroid Build Coastguard Worker oldBuffer->removeObserver(observer);
378*8975f5c5SAndroid Build Coastguard Worker oldBuffer->removeContentsObserver(this, static_cast<uint32_t>(bindingIndex));
379*8975f5c5SAndroid Build Coastguard Worker oldBuffer->release(context);
380*8975f5c5SAndroid Build Coastguard Worker mState.mBufferBindingMask.reset(bindingIndex);
381*8975f5c5SAndroid Build Coastguard Worker }
382*8975f5c5SAndroid Build Coastguard Worker
383*8975f5c5SAndroid Build Coastguard Worker binding->assignBuffer(boundBuffer);
384*8975f5c5SAndroid Build Coastguard Worker
385*8975f5c5SAndroid Build Coastguard Worker // Update client memory attribute pointers. Affects all bound attributes.
386*8975f5c5SAndroid Build Coastguard Worker if (boundBuffer)
387*8975f5c5SAndroid Build Coastguard Worker {
388*8975f5c5SAndroid Build Coastguard Worker boundBuffer->addRef();
389*8975f5c5SAndroid Build Coastguard Worker boundBuffer->onNonTFBindingChanged(1);
390*8975f5c5SAndroid Build Coastguard Worker boundBuffer->addObserver(observer);
391*8975f5c5SAndroid Build Coastguard Worker if (context->isWebGL())
392*8975f5c5SAndroid Build Coastguard Worker {
393*8975f5c5SAndroid Build Coastguard Worker mCachedTransformFeedbackConflictedBindingsMask.set(
394*8975f5c5SAndroid Build Coastguard Worker bindingIndex, boundBuffer->hasWebGLXFBBindingConflict(true));
395*8975f5c5SAndroid Build Coastguard Worker }
396*8975f5c5SAndroid Build Coastguard Worker mState.mBufferBindingMask.set(bindingIndex);
397*8975f5c5SAndroid Build Coastguard Worker mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
398*8975f5c5SAndroid Build Coastguard Worker
399*8975f5c5SAndroid Build Coastguard Worker bool isMapped = boundBuffer->isMapped() == GL_TRUE;
400*8975f5c5SAndroid Build Coastguard Worker bool isImmutable = boundBuffer->isImmutable() == GL_TRUE;
401*8975f5c5SAndroid Build Coastguard Worker bool isPersistent = (boundBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
402*8975f5c5SAndroid Build Coastguard Worker updateCachedArrayBuffersMasks(isMapped, isImmutable, isPersistent,
403*8975f5c5SAndroid Build Coastguard Worker binding->getBoundAttributesMask());
404*8975f5c5SAndroid Build Coastguard Worker }
405*8975f5c5SAndroid Build Coastguard Worker else
406*8975f5c5SAndroid Build Coastguard Worker {
407*8975f5c5SAndroid Build Coastguard Worker if (context->isWebGL())
408*8975f5c5SAndroid Build Coastguard Worker {
409*8975f5c5SAndroid Build Coastguard Worker mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, false);
410*8975f5c5SAndroid Build Coastguard Worker }
411*8975f5c5SAndroid Build Coastguard Worker mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
412*8975f5c5SAndroid Build Coastguard Worker updateCachedArrayBuffersMasks(false, false, false, binding->getBoundAttributesMask());
413*8975f5c5SAndroid Build Coastguard Worker }
414*8975f5c5SAndroid Build Coastguard Worker }
415*8975f5c5SAndroid Build Coastguard Worker
416*8975f5c5SAndroid Build Coastguard Worker binding->setOffset(offset);
417*8975f5c5SAndroid Build Coastguard Worker binding->setStride(stride);
418*8975f5c5SAndroid Build Coastguard Worker updateCachedBufferBindingSize(binding);
419*8975f5c5SAndroid Build Coastguard Worker
420*8975f5c5SAndroid Build Coastguard Worker return dirtyBindingBits;
421*8975f5c5SAndroid Build Coastguard Worker }
422*8975f5c5SAndroid Build Coastguard Worker
bindVertexBuffer(const Context * context,size_t bindingIndex,Buffer * boundBuffer,GLintptr offset,GLsizei stride)423*8975f5c5SAndroid Build Coastguard Worker void VertexArray::bindVertexBuffer(const Context *context,
424*8975f5c5SAndroid Build Coastguard Worker size_t bindingIndex,
425*8975f5c5SAndroid Build Coastguard Worker Buffer *boundBuffer,
426*8975f5c5SAndroid Build Coastguard Worker GLintptr offset,
427*8975f5c5SAndroid Build Coastguard Worker GLsizei stride)
428*8975f5c5SAndroid Build Coastguard Worker {
429*8975f5c5SAndroid Build Coastguard Worker const VertexArray::DirtyBindingBits dirtyBindingBits =
430*8975f5c5SAndroid Build Coastguard Worker bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
431*8975f5c5SAndroid Build Coastguard Worker if (dirtyBindingBits.any())
432*8975f5c5SAndroid Build Coastguard Worker {
433*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
434*8975f5c5SAndroid Build Coastguard Worker mDirtyBindingBits[bindingIndex] |= dirtyBindingBits;
435*8975f5c5SAndroid Build Coastguard Worker }
436*8975f5c5SAndroid Build Coastguard Worker }
437*8975f5c5SAndroid Build Coastguard Worker
setVertexAttribBinding(const Context * context,size_t attribIndex,GLuint bindingIndex)438*8975f5c5SAndroid Build Coastguard Worker void VertexArray::setVertexAttribBinding(const Context *context,
439*8975f5c5SAndroid Build Coastguard Worker size_t attribIndex,
440*8975f5c5SAndroid Build Coastguard Worker GLuint bindingIndex)
441*8975f5c5SAndroid Build Coastguard Worker {
442*8975f5c5SAndroid Build Coastguard Worker ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
443*8975f5c5SAndroid Build Coastguard Worker
444*8975f5c5SAndroid Build Coastguard Worker if (mState.mVertexAttributes[attribIndex].bindingIndex == bindingIndex)
445*8975f5c5SAndroid Build Coastguard Worker {
446*8975f5c5SAndroid Build Coastguard Worker return;
447*8975f5c5SAndroid Build Coastguard Worker }
448*8975f5c5SAndroid Build Coastguard Worker
449*8975f5c5SAndroid Build Coastguard Worker // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
450*8975f5c5SAndroid Build Coastguard Worker ASSERT(context->getClientVersion() >= ES_3_1 && !mState.isDefault());
451*8975f5c5SAndroid Build Coastguard Worker
452*8975f5c5SAndroid Build Coastguard Worker mState.setAttribBinding(context, attribIndex, bindingIndex);
453*8975f5c5SAndroid Build Coastguard Worker
454*8975f5c5SAndroid Build Coastguard Worker setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
455*8975f5c5SAndroid Build Coastguard Worker
456*8975f5c5SAndroid Build Coastguard Worker // Update client attribs mask.
457*8975f5c5SAndroid Build Coastguard Worker bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
458*8975f5c5SAndroid Build Coastguard Worker mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
459*8975f5c5SAndroid Build Coastguard Worker }
460*8975f5c5SAndroid Build Coastguard Worker
setVertexBindingDivisor(const Context * context,size_t bindingIndex,GLuint divisor)461*8975f5c5SAndroid Build Coastguard Worker void VertexArray::setVertexBindingDivisor(const Context *context,
462*8975f5c5SAndroid Build Coastguard Worker size_t bindingIndex,
463*8975f5c5SAndroid Build Coastguard Worker GLuint divisor)
464*8975f5c5SAndroid Build Coastguard Worker {
465*8975f5c5SAndroid Build Coastguard Worker ASSERT(bindingIndex < getMaxBindings());
466*8975f5c5SAndroid Build Coastguard Worker
467*8975f5c5SAndroid Build Coastguard Worker VertexBinding &binding = mState.mVertexBindings[bindingIndex];
468*8975f5c5SAndroid Build Coastguard Worker
469*8975f5c5SAndroid Build Coastguard Worker if (binding.getDivisor() == divisor)
470*8975f5c5SAndroid Build Coastguard Worker {
471*8975f5c5SAndroid Build Coastguard Worker return;
472*8975f5c5SAndroid Build Coastguard Worker }
473*8975f5c5SAndroid Build Coastguard Worker
474*8975f5c5SAndroid Build Coastguard Worker binding.setDivisor(divisor);
475*8975f5c5SAndroid Build Coastguard Worker setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
476*8975f5c5SAndroid Build Coastguard Worker }
477*8975f5c5SAndroid Build Coastguard Worker
setVertexAttribFormatImpl(VertexAttribute * attrib,GLint size,VertexAttribType type,bool normalized,bool pureInteger,GLuint relativeOffset)478*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE bool VertexArray::setVertexAttribFormatImpl(VertexAttribute *attrib,
479*8975f5c5SAndroid Build Coastguard Worker GLint size,
480*8975f5c5SAndroid Build Coastguard Worker VertexAttribType type,
481*8975f5c5SAndroid Build Coastguard Worker bool normalized,
482*8975f5c5SAndroid Build Coastguard Worker bool pureInteger,
483*8975f5c5SAndroid Build Coastguard Worker GLuint relativeOffset)
484*8975f5c5SAndroid Build Coastguard Worker {
485*8975f5c5SAndroid Build Coastguard Worker angle::FormatID formatID = GetVertexFormatID(type, normalized, size, pureInteger);
486*8975f5c5SAndroid Build Coastguard Worker
487*8975f5c5SAndroid Build Coastguard Worker if (formatID != attrib->format->id || attrib->relativeOffset != relativeOffset)
488*8975f5c5SAndroid Build Coastguard Worker {
489*8975f5c5SAndroid Build Coastguard Worker attrib->relativeOffset = relativeOffset;
490*8975f5c5SAndroid Build Coastguard Worker attrib->format = &angle::Format::Get(formatID);
491*8975f5c5SAndroid Build Coastguard Worker return true;
492*8975f5c5SAndroid Build Coastguard Worker }
493*8975f5c5SAndroid Build Coastguard Worker
494*8975f5c5SAndroid Build Coastguard Worker return false;
495*8975f5c5SAndroid Build Coastguard Worker }
496*8975f5c5SAndroid Build Coastguard Worker
setVertexAttribFormat(size_t attribIndex,GLint size,VertexAttribType type,bool normalized,bool pureInteger,GLuint relativeOffset)497*8975f5c5SAndroid Build Coastguard Worker void VertexArray::setVertexAttribFormat(size_t attribIndex,
498*8975f5c5SAndroid Build Coastguard Worker GLint size,
499*8975f5c5SAndroid Build Coastguard Worker VertexAttribType type,
500*8975f5c5SAndroid Build Coastguard Worker bool normalized,
501*8975f5c5SAndroid Build Coastguard Worker bool pureInteger,
502*8975f5c5SAndroid Build Coastguard Worker GLuint relativeOffset)
503*8975f5c5SAndroid Build Coastguard Worker {
504*8975f5c5SAndroid Build Coastguard Worker VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
505*8975f5c5SAndroid Build Coastguard Worker
506*8975f5c5SAndroid Build Coastguard Worker ComponentType componentType = GetVertexAttributeComponentType(pureInteger, type);
507*8975f5c5SAndroid Build Coastguard Worker SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask);
508*8975f5c5SAndroid Build Coastguard Worker
509*8975f5c5SAndroid Build Coastguard Worker if (setVertexAttribFormatImpl(&attrib, size, type, normalized, pureInteger, relativeOffset))
510*8975f5c5SAndroid Build Coastguard Worker {
511*8975f5c5SAndroid Build Coastguard Worker setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
512*8975f5c5SAndroid Build Coastguard Worker }
513*8975f5c5SAndroid Build Coastguard Worker
514*8975f5c5SAndroid Build Coastguard Worker attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
515*8975f5c5SAndroid Build Coastguard Worker }
516*8975f5c5SAndroid Build Coastguard Worker
setVertexAttribDivisor(const Context * context,size_t attribIndex,GLuint divisor)517*8975f5c5SAndroid Build Coastguard Worker void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
518*8975f5c5SAndroid Build Coastguard Worker {
519*8975f5c5SAndroid Build Coastguard Worker ASSERT(attribIndex < getMaxAttribs());
520*8975f5c5SAndroid Build Coastguard Worker
521*8975f5c5SAndroid Build Coastguard Worker setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
522*8975f5c5SAndroid Build Coastguard Worker setVertexBindingDivisor(context, attribIndex, divisor);
523*8975f5c5SAndroid Build Coastguard Worker }
524*8975f5c5SAndroid Build Coastguard Worker
enableAttribute(size_t attribIndex,bool enabledState)525*8975f5c5SAndroid Build Coastguard Worker void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
526*8975f5c5SAndroid Build Coastguard Worker {
527*8975f5c5SAndroid Build Coastguard Worker ASSERT(attribIndex < getMaxAttribs());
528*8975f5c5SAndroid Build Coastguard Worker
529*8975f5c5SAndroid Build Coastguard Worker VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
530*8975f5c5SAndroid Build Coastguard Worker
531*8975f5c5SAndroid Build Coastguard Worker if (mState.mEnabledAttributesMask.test(attribIndex) == enabledState)
532*8975f5c5SAndroid Build Coastguard Worker {
533*8975f5c5SAndroid Build Coastguard Worker return;
534*8975f5c5SAndroid Build Coastguard Worker }
535*8975f5c5SAndroid Build Coastguard Worker
536*8975f5c5SAndroid Build Coastguard Worker attrib.enabled = enabledState;
537*8975f5c5SAndroid Build Coastguard Worker
538*8975f5c5SAndroid Build Coastguard Worker // Update state cache
539*8975f5c5SAndroid Build Coastguard Worker mState.mEnabledAttributesMask.set(attribIndex, enabledState);
540*8975f5c5SAndroid Build Coastguard Worker bool enableChanged = (mState.mEnabledAttributesMask.test(attribIndex) !=
541*8975f5c5SAndroid Build Coastguard Worker mState.mLastSyncedEnabledAttributesMask.test(attribIndex));
542*8975f5c5SAndroid Build Coastguard Worker
543*8975f5c5SAndroid Build Coastguard Worker if (enableChanged)
544*8975f5c5SAndroid Build Coastguard Worker {
545*8975f5c5SAndroid Build Coastguard Worker setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
546*8975f5c5SAndroid Build Coastguard Worker }
547*8975f5c5SAndroid Build Coastguard Worker else
548*8975f5c5SAndroid Build Coastguard Worker {
549*8975f5c5SAndroid Build Coastguard Worker clearDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
550*8975f5c5SAndroid Build Coastguard Worker }
551*8975f5c5SAndroid Build Coastguard Worker
552*8975f5c5SAndroid Build Coastguard Worker mState.updateCachedMutableOrNonPersistentArrayBuffers(attribIndex);
553*8975f5c5SAndroid Build Coastguard Worker mState.mCachedInvalidMappedArrayBuffer = mState.mCachedMappedArrayBuffers &
554*8975f5c5SAndroid Build Coastguard Worker mState.mEnabledAttributesMask &
555*8975f5c5SAndroid Build Coastguard Worker mState.mCachedMutableOrImpersistentArrayBuffers;
556*8975f5c5SAndroid Build Coastguard Worker }
557*8975f5c5SAndroid Build Coastguard Worker
setVertexAttribPointerImpl(const Context * context,ComponentType componentType,bool pureInteger,size_t attribIndex,Buffer * boundBuffer,GLint size,VertexAttribType type,bool normalized,GLsizei stride,const void * pointer)558*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context,
559*8975f5c5SAndroid Build Coastguard Worker ComponentType componentType,
560*8975f5c5SAndroid Build Coastguard Worker bool pureInteger,
561*8975f5c5SAndroid Build Coastguard Worker size_t attribIndex,
562*8975f5c5SAndroid Build Coastguard Worker Buffer *boundBuffer,
563*8975f5c5SAndroid Build Coastguard Worker GLint size,
564*8975f5c5SAndroid Build Coastguard Worker VertexAttribType type,
565*8975f5c5SAndroid Build Coastguard Worker bool normalized,
566*8975f5c5SAndroid Build Coastguard Worker GLsizei stride,
567*8975f5c5SAndroid Build Coastguard Worker const void *pointer)
568*8975f5c5SAndroid Build Coastguard Worker {
569*8975f5c5SAndroid Build Coastguard Worker ASSERT(attribIndex < getMaxAttribs());
570*8975f5c5SAndroid Build Coastguard Worker
571*8975f5c5SAndroid Build Coastguard Worker VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
572*8975f5c5SAndroid Build Coastguard Worker
573*8975f5c5SAndroid Build Coastguard Worker SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask);
574*8975f5c5SAndroid Build Coastguard Worker
575*8975f5c5SAndroid Build Coastguard Worker bool attribDirty = setVertexAttribFormatImpl(&attrib, size, type, normalized, pureInteger, 0);
576*8975f5c5SAndroid Build Coastguard Worker
577*8975f5c5SAndroid Build Coastguard Worker if (attrib.bindingIndex != attribIndex)
578*8975f5c5SAndroid Build Coastguard Worker {
579*8975f5c5SAndroid Build Coastguard Worker setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
580*8975f5c5SAndroid Build Coastguard Worker }
581*8975f5c5SAndroid Build Coastguard Worker
582*8975f5c5SAndroid Build Coastguard Worker GLsizei effectiveStride =
583*8975f5c5SAndroid Build Coastguard Worker stride == 0 ? static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)) : stride;
584*8975f5c5SAndroid Build Coastguard Worker
585*8975f5c5SAndroid Build Coastguard Worker if (attrib.vertexAttribArrayStride != static_cast<GLuint>(stride))
586*8975f5c5SAndroid Build Coastguard Worker {
587*8975f5c5SAndroid Build Coastguard Worker attribDirty = true;
588*8975f5c5SAndroid Build Coastguard Worker }
589*8975f5c5SAndroid Build Coastguard Worker attrib.vertexAttribArrayStride = stride;
590*8975f5c5SAndroid Build Coastguard Worker
591*8975f5c5SAndroid Build Coastguard Worker // If we switch from an array buffer to a client pointer(or vice-versa), we set the whole
592*8975f5c5SAndroid Build Coastguard Worker // attribute dirty. This notifies the Vulkan back-end to update all its caches.
593*8975f5c5SAndroid Build Coastguard Worker const VertexBinding &binding = mState.mVertexBindings[attribIndex];
594*8975f5c5SAndroid Build Coastguard Worker if ((boundBuffer == nullptr) != (binding.getBuffer().get() == nullptr))
595*8975f5c5SAndroid Build Coastguard Worker {
596*8975f5c5SAndroid Build Coastguard Worker attribDirty = true;
597*8975f5c5SAndroid Build Coastguard Worker }
598*8975f5c5SAndroid Build Coastguard Worker
599*8975f5c5SAndroid Build Coastguard Worker // If using client arrays and the pointer changes, set the attribute as dirty
600*8975f5c5SAndroid Build Coastguard Worker if (boundBuffer == nullptr && attrib.pointer != pointer)
601*8975f5c5SAndroid Build Coastguard Worker {
602*8975f5c5SAndroid Build Coastguard Worker attribDirty = true;
603*8975f5c5SAndroid Build Coastguard Worker }
604*8975f5c5SAndroid Build Coastguard Worker
605*8975f5c5SAndroid Build Coastguard Worker // Change of attrib.pointer is not part of attribDirty. Pointer is actually the buffer offset
606*8975f5c5SAndroid Build Coastguard Worker // which is handled within bindVertexBufferImpl and reflected in bufferDirty.
607*8975f5c5SAndroid Build Coastguard Worker attrib.pointer = pointer;
608*8975f5c5SAndroid Build Coastguard Worker GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
609*8975f5c5SAndroid Build Coastguard Worker const VertexArray::DirtyBindingBits dirtyBindingBits =
610*8975f5c5SAndroid Build Coastguard Worker bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
611*8975f5c5SAndroid Build Coastguard Worker
612*8975f5c5SAndroid Build Coastguard Worker if (attribDirty)
613*8975f5c5SAndroid Build Coastguard Worker {
614*8975f5c5SAndroid Build Coastguard Worker setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
615*8975f5c5SAndroid Build Coastguard Worker }
616*8975f5c5SAndroid Build Coastguard Worker else if (dirtyBindingBits.any())
617*8975f5c5SAndroid Build Coastguard Worker {
618*8975f5c5SAndroid Build Coastguard Worker setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER_BUFFER);
619*8975f5c5SAndroid Build Coastguard Worker }
620*8975f5c5SAndroid Build Coastguard Worker
621*8975f5c5SAndroid Build Coastguard Worker mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
622*8975f5c5SAndroid Build Coastguard Worker boundBuffer == nullptr && pointer == nullptr);
623*8975f5c5SAndroid Build Coastguard Worker }
624*8975f5c5SAndroid Build Coastguard Worker
setVertexAttribPointer(const Context * context,size_t attribIndex,Buffer * boundBuffer,GLint size,VertexAttribType type,bool normalized,GLsizei stride,const void * pointer)625*8975f5c5SAndroid Build Coastguard Worker void VertexArray::setVertexAttribPointer(const Context *context,
626*8975f5c5SAndroid Build Coastguard Worker size_t attribIndex,
627*8975f5c5SAndroid Build Coastguard Worker Buffer *boundBuffer,
628*8975f5c5SAndroid Build Coastguard Worker GLint size,
629*8975f5c5SAndroid Build Coastguard Worker VertexAttribType type,
630*8975f5c5SAndroid Build Coastguard Worker bool normalized,
631*8975f5c5SAndroid Build Coastguard Worker GLsizei stride,
632*8975f5c5SAndroid Build Coastguard Worker const void *pointer)
633*8975f5c5SAndroid Build Coastguard Worker {
634*8975f5c5SAndroid Build Coastguard Worker setVertexAttribPointerImpl(context, ComponentType::Float, false, attribIndex, boundBuffer, size,
635*8975f5c5SAndroid Build Coastguard Worker type, normalized, stride, pointer);
636*8975f5c5SAndroid Build Coastguard Worker }
637*8975f5c5SAndroid Build Coastguard Worker
setVertexAttribIPointer(const Context * context,size_t attribIndex,Buffer * boundBuffer,GLint size,VertexAttribType type,GLsizei stride,const void * pointer)638*8975f5c5SAndroid Build Coastguard Worker void VertexArray::setVertexAttribIPointer(const Context *context,
639*8975f5c5SAndroid Build Coastguard Worker size_t attribIndex,
640*8975f5c5SAndroid Build Coastguard Worker Buffer *boundBuffer,
641*8975f5c5SAndroid Build Coastguard Worker GLint size,
642*8975f5c5SAndroid Build Coastguard Worker VertexAttribType type,
643*8975f5c5SAndroid Build Coastguard Worker GLsizei stride,
644*8975f5c5SAndroid Build Coastguard Worker const void *pointer)
645*8975f5c5SAndroid Build Coastguard Worker {
646*8975f5c5SAndroid Build Coastguard Worker ComponentType componentType = GetVertexAttributeComponentType(true, type);
647*8975f5c5SAndroid Build Coastguard Worker setVertexAttribPointerImpl(context, componentType, true, attribIndex, boundBuffer, size, type,
648*8975f5c5SAndroid Build Coastguard Worker false, stride, pointer);
649*8975f5c5SAndroid Build Coastguard Worker }
650*8975f5c5SAndroid Build Coastguard Worker
syncState(const Context * context)651*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexArray::syncState(const Context *context)
652*8975f5c5SAndroid Build Coastguard Worker {
653*8975f5c5SAndroid Build Coastguard Worker if (mDirtyBits.any())
654*8975f5c5SAndroid Build Coastguard Worker {
655*8975f5c5SAndroid Build Coastguard Worker mDirtyBitsGuard = mDirtyBits;
656*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
657*8975f5c5SAndroid Build Coastguard Worker mVertexArray->syncState(context, mDirtyBits, &mDirtyAttribBits, &mDirtyBindingBits));
658*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.reset();
659*8975f5c5SAndroid Build Coastguard Worker mDirtyBitsGuard.reset();
660*8975f5c5SAndroid Build Coastguard Worker
661*8975f5c5SAndroid Build Coastguard Worker // The dirty bits should be reset in the back-end. To simplify ASSERTs only check attrib 0.
662*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDirtyAttribBits[0].none());
663*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDirtyBindingBits[0].none());
664*8975f5c5SAndroid Build Coastguard Worker mState.mLastSyncedEnabledAttributesMask = mState.mEnabledAttributesMask;
665*8975f5c5SAndroid Build Coastguard Worker }
666*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
667*8975f5c5SAndroid Build Coastguard Worker }
668*8975f5c5SAndroid Build Coastguard Worker
669*8975f5c5SAndroid Build Coastguard Worker // This becomes current vertex array on the context
onBind(const Context * context)670*8975f5c5SAndroid Build Coastguard Worker void VertexArray::onBind(const Context *context)
671*8975f5c5SAndroid Build Coastguard Worker {
672*8975f5c5SAndroid Build Coastguard Worker // This vertex array becoming current. Some of the bindings we may have removed from buffer's
673*8975f5c5SAndroid Build Coastguard Worker // observer list. We need to add it back to the buffer's observer list and update dirty bits
674*8975f5c5SAndroid Build Coastguard Worker // that we may have missed while we were not observing.
675*8975f5c5SAndroid Build Coastguard Worker for (size_t bindingIndex : mState.getBufferBindingMask())
676*8975f5c5SAndroid Build Coastguard Worker {
677*8975f5c5SAndroid Build Coastguard Worker const VertexBinding &binding = mState.getVertexBindings()[bindingIndex];
678*8975f5c5SAndroid Build Coastguard Worker Buffer *bufferGL = binding.getBuffer().get();
679*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferGL != nullptr);
680*8975f5c5SAndroid Build Coastguard Worker
681*8975f5c5SAndroid Build Coastguard Worker bufferGL->addObserver(&mArrayBufferObserverBindings[bindingIndex]);
682*8975f5c5SAndroid Build Coastguard Worker updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[bindingIndex]);
683*8975f5c5SAndroid Build Coastguard Worker
684*8975f5c5SAndroid Build Coastguard Worker if (mBufferAccessValidationEnabled)
685*8975f5c5SAndroid Build Coastguard Worker {
686*8975f5c5SAndroid Build Coastguard Worker for (size_t boundAttribute :
687*8975f5c5SAndroid Build Coastguard Worker mState.mVertexBindings[bindingIndex].getBoundAttributesMask())
688*8975f5c5SAndroid Build Coastguard Worker {
689*8975f5c5SAndroid Build Coastguard Worker mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(
690*8975f5c5SAndroid Build Coastguard Worker mState.mVertexBindings[bindingIndex]);
691*8975f5c5SAndroid Build Coastguard Worker }
692*8975f5c5SAndroid Build Coastguard Worker }
693*8975f5c5SAndroid Build Coastguard Worker
694*8975f5c5SAndroid Build Coastguard Worker if (context->isWebGL())
695*8975f5c5SAndroid Build Coastguard Worker {
696*8975f5c5SAndroid Build Coastguard Worker updateCachedTransformFeedbackBindingValidation(bindingIndex, bufferGL);
697*8975f5c5SAndroid Build Coastguard Worker }
698*8975f5c5SAndroid Build Coastguard Worker }
699*8975f5c5SAndroid Build Coastguard Worker
700*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_LOST_OBSERVATION);
701*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::ContentsChanged);
702*8975f5c5SAndroid Build Coastguard Worker }
703*8975f5c5SAndroid Build Coastguard Worker
704*8975f5c5SAndroid Build Coastguard Worker // This becomes non-current vertex array on the context
onUnbind(const Context * context)705*8975f5c5SAndroid Build Coastguard Worker void VertexArray::onUnbind(const Context *context)
706*8975f5c5SAndroid Build Coastguard Worker {
707*8975f5c5SAndroid Build Coastguard Worker // This vertex array becoming non-current. For performance reason, we remove it from the
708*8975f5c5SAndroid Build Coastguard Worker // buffers' observer list so that the cost of buffer sending signal to observers will not be too
709*8975f5c5SAndroid Build Coastguard Worker // expensive.
710*8975f5c5SAndroid Build Coastguard Worker for (size_t bindingIndex : mState.mBufferBindingMask)
711*8975f5c5SAndroid Build Coastguard Worker {
712*8975f5c5SAndroid Build Coastguard Worker const VertexBinding &binding = mState.getVertexBindings()[bindingIndex];
713*8975f5c5SAndroid Build Coastguard Worker Buffer *bufferGL = binding.getBuffer().get();
714*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferGL != nullptr);
715*8975f5c5SAndroid Build Coastguard Worker bufferGL->removeObserver(&mArrayBufferObserverBindings[bindingIndex]);
716*8975f5c5SAndroid Build Coastguard Worker }
717*8975f5c5SAndroid Build Coastguard Worker }
718*8975f5c5SAndroid Build Coastguard Worker
onBindingChanged(const Context * context,int incr)719*8975f5c5SAndroid Build Coastguard Worker void VertexArray::onBindingChanged(const Context *context, int incr)
720*8975f5c5SAndroid Build Coastguard Worker {
721*8975f5c5SAndroid Build Coastguard Worker // When vertex array gets unbound, we remove it from bound buffers' observer list so that when
722*8975f5c5SAndroid Build Coastguard Worker // buffer changes, it wont has to loop over all these non-current vertex arrays and set dirty
723*8975f5c5SAndroid Build Coastguard Worker // bit on them. To compensate for that, when we bind a vertex array, we have to check against
724*8975f5c5SAndroid Build Coastguard Worker // each bound buffers and see if they have changed and needs to update vertex array's dirty bits
725*8975f5c5SAndroid Build Coastguard Worker // accordingly
726*8975f5c5SAndroid Build Coastguard Worker ASSERT(incr == 1 || incr == -1);
727*8975f5c5SAndroid Build Coastguard Worker if (incr < 0)
728*8975f5c5SAndroid Build Coastguard Worker {
729*8975f5c5SAndroid Build Coastguard Worker onUnbind(context);
730*8975f5c5SAndroid Build Coastguard Worker }
731*8975f5c5SAndroid Build Coastguard Worker else
732*8975f5c5SAndroid Build Coastguard Worker {
733*8975f5c5SAndroid Build Coastguard Worker onBind(context);
734*8975f5c5SAndroid Build Coastguard Worker }
735*8975f5c5SAndroid Build Coastguard Worker
736*8975f5c5SAndroid Build Coastguard Worker if (context->isWebGL())
737*8975f5c5SAndroid Build Coastguard Worker {
738*8975f5c5SAndroid Build Coastguard Worker if (mState.mElementArrayBuffer.get())
739*8975f5c5SAndroid Build Coastguard Worker {
740*8975f5c5SAndroid Build Coastguard Worker mState.mElementArrayBuffer->onNonTFBindingChanged(incr);
741*8975f5c5SAndroid Build Coastguard Worker }
742*8975f5c5SAndroid Build Coastguard Worker for (size_t bindingIndex : mState.mBufferBindingMask)
743*8975f5c5SAndroid Build Coastguard Worker {
744*8975f5c5SAndroid Build Coastguard Worker mState.mVertexBindings[bindingIndex].onContainerBindingChanged(context, incr);
745*8975f5c5SAndroid Build Coastguard Worker }
746*8975f5c5SAndroid Build Coastguard Worker }
747*8975f5c5SAndroid Build Coastguard Worker }
748*8975f5c5SAndroid Build Coastguard Worker
getDirtyBitFromIndex(bool contentsChanged,angle::SubjectIndex index) const749*8975f5c5SAndroid Build Coastguard Worker VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
750*8975f5c5SAndroid Build Coastguard Worker angle::SubjectIndex index) const
751*8975f5c5SAndroid Build Coastguard Worker {
752*8975f5c5SAndroid Build Coastguard Worker if (IsElementArrayBufferSubjectIndex(index))
753*8975f5c5SAndroid Build Coastguard Worker {
754*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.invalidate();
755*8975f5c5SAndroid Build Coastguard Worker return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
756*8975f5c5SAndroid Build Coastguard Worker : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
757*8975f5c5SAndroid Build Coastguard Worker }
758*8975f5c5SAndroid Build Coastguard Worker else
759*8975f5c5SAndroid Build Coastguard Worker {
760*8975f5c5SAndroid Build Coastguard Worker // Note: this currently just gets the top-level dirty bit.
761*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < mArrayBufferObserverBindings.size());
762*8975f5c5SAndroid Build Coastguard Worker return static_cast<DirtyBitType>(
763*8975f5c5SAndroid Build Coastguard Worker (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
764*8975f5c5SAndroid Build Coastguard Worker }
765*8975f5c5SAndroid Build Coastguard Worker }
766*8975f5c5SAndroid Build Coastguard Worker
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)767*8975f5c5SAndroid Build Coastguard Worker void VertexArray::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
768*8975f5c5SAndroid Build Coastguard Worker {
769*8975f5c5SAndroid Build Coastguard Worker switch (message)
770*8975f5c5SAndroid Build Coastguard Worker {
771*8975f5c5SAndroid Build Coastguard Worker case angle::SubjectMessage::SubjectChanged:
772*8975f5c5SAndroid Build Coastguard Worker if (!IsElementArrayBufferSubjectIndex(index))
773*8975f5c5SAndroid Build Coastguard Worker {
774*8975f5c5SAndroid Build Coastguard Worker updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
775*8975f5c5SAndroid Build Coastguard Worker }
776*8975f5c5SAndroid Build Coastguard Worker setDependentDirtyBit(false, index);
777*8975f5c5SAndroid Build Coastguard Worker break;
778*8975f5c5SAndroid Build Coastguard Worker
779*8975f5c5SAndroid Build Coastguard Worker case angle::SubjectMessage::BindingChanged:
780*8975f5c5SAndroid Build Coastguard Worker if (!IsElementArrayBufferSubjectIndex(index))
781*8975f5c5SAndroid Build Coastguard Worker {
782*8975f5c5SAndroid Build Coastguard Worker const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
783*8975f5c5SAndroid Build Coastguard Worker updateCachedTransformFeedbackBindingValidation(index, buffer);
784*8975f5c5SAndroid Build Coastguard Worker }
785*8975f5c5SAndroid Build Coastguard Worker break;
786*8975f5c5SAndroid Build Coastguard Worker
787*8975f5c5SAndroid Build Coastguard Worker case angle::SubjectMessage::SubjectMapped:
788*8975f5c5SAndroid Build Coastguard Worker if (!IsElementArrayBufferSubjectIndex(index))
789*8975f5c5SAndroid Build Coastguard Worker {
790*8975f5c5SAndroid Build Coastguard Worker updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
791*8975f5c5SAndroid Build Coastguard Worker }
792*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectMapped);
793*8975f5c5SAndroid Build Coastguard Worker break;
794*8975f5c5SAndroid Build Coastguard Worker
795*8975f5c5SAndroid Build Coastguard Worker case angle::SubjectMessage::SubjectUnmapped:
796*8975f5c5SAndroid Build Coastguard Worker setDependentDirtyBit(true, index);
797*8975f5c5SAndroid Build Coastguard Worker
798*8975f5c5SAndroid Build Coastguard Worker if (!IsElementArrayBufferSubjectIndex(index))
799*8975f5c5SAndroid Build Coastguard Worker {
800*8975f5c5SAndroid Build Coastguard Worker updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
801*8975f5c5SAndroid Build Coastguard Worker }
802*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectUnmapped);
803*8975f5c5SAndroid Build Coastguard Worker break;
804*8975f5c5SAndroid Build Coastguard Worker
805*8975f5c5SAndroid Build Coastguard Worker case angle::SubjectMessage::InternalMemoryAllocationChanged:
806*8975f5c5SAndroid Build Coastguard Worker setDependentDirtyBit(false, index);
807*8975f5c5SAndroid Build Coastguard Worker break;
808*8975f5c5SAndroid Build Coastguard Worker
809*8975f5c5SAndroid Build Coastguard Worker default:
810*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
811*8975f5c5SAndroid Build Coastguard Worker break;
812*8975f5c5SAndroid Build Coastguard Worker }
813*8975f5c5SAndroid Build Coastguard Worker }
814*8975f5c5SAndroid Build Coastguard Worker
setDependentDirtyBit(bool contentsChanged,angle::SubjectIndex index)815*8975f5c5SAndroid Build Coastguard Worker void VertexArray::setDependentDirtyBit(bool contentsChanged, angle::SubjectIndex index)
816*8975f5c5SAndroid Build Coastguard Worker {
817*8975f5c5SAndroid Build Coastguard Worker DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
818*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
819*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(dirtyBit);
820*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::ContentsChanged);
821*8975f5c5SAndroid Build Coastguard Worker }
822*8975f5c5SAndroid Build Coastguard Worker
hasTransformFeedbackBindingConflict(const Context * context) const823*8975f5c5SAndroid Build Coastguard Worker bool VertexArray::hasTransformFeedbackBindingConflict(const Context *context) const
824*8975f5c5SAndroid Build Coastguard Worker {
825*8975f5c5SAndroid Build Coastguard Worker // Fast check first.
826*8975f5c5SAndroid Build Coastguard Worker if (!mCachedTransformFeedbackConflictedBindingsMask.any())
827*8975f5c5SAndroid Build Coastguard Worker {
828*8975f5c5SAndroid Build Coastguard Worker return false;
829*8975f5c5SAndroid Build Coastguard Worker }
830*8975f5c5SAndroid Build Coastguard Worker
831*8975f5c5SAndroid Build Coastguard Worker const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
832*8975f5c5SAndroid Build Coastguard Worker
833*8975f5c5SAndroid Build Coastguard Worker // Slow check. We must ensure that the conflicting attributes are enabled/active.
834*8975f5c5SAndroid Build Coastguard Worker for (size_t attribIndex : activeAttribues)
835*8975f5c5SAndroid Build Coastguard Worker {
836*8975f5c5SAndroid Build Coastguard Worker const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
837*8975f5c5SAndroid Build Coastguard Worker if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
838*8975f5c5SAndroid Build Coastguard Worker {
839*8975f5c5SAndroid Build Coastguard Worker return true;
840*8975f5c5SAndroid Build Coastguard Worker }
841*8975f5c5SAndroid Build Coastguard Worker }
842*8975f5c5SAndroid Build Coastguard Worker
843*8975f5c5SAndroid Build Coastguard Worker return false;
844*8975f5c5SAndroid Build Coastguard Worker }
845*8975f5c5SAndroid Build Coastguard Worker
getIndexRangeImpl(const Context * context,DrawElementsType type,GLsizei indexCount,const void * indices,IndexRange * indexRangeOut) const846*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexArray::getIndexRangeImpl(const Context *context,
847*8975f5c5SAndroid Build Coastguard Worker DrawElementsType type,
848*8975f5c5SAndroid Build Coastguard Worker GLsizei indexCount,
849*8975f5c5SAndroid Build Coastguard Worker const void *indices,
850*8975f5c5SAndroid Build Coastguard Worker IndexRange *indexRangeOut) const
851*8975f5c5SAndroid Build Coastguard Worker {
852*8975f5c5SAndroid Build Coastguard Worker Buffer *elementArrayBuffer = mState.mElementArrayBuffer.get();
853*8975f5c5SAndroid Build Coastguard Worker if (!elementArrayBuffer)
854*8975f5c5SAndroid Build Coastguard Worker {
855*8975f5c5SAndroid Build Coastguard Worker *indexRangeOut = ComputeIndexRange(type, indices, indexCount,
856*8975f5c5SAndroid Build Coastguard Worker context->getState().isPrimitiveRestartEnabled());
857*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
858*8975f5c5SAndroid Build Coastguard Worker }
859*8975f5c5SAndroid Build Coastguard Worker
860*8975f5c5SAndroid Build Coastguard Worker size_t offset = reinterpret_cast<uintptr_t>(indices);
861*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(elementArrayBuffer->getIndexRange(context, type, offset, indexCount,
862*8975f5c5SAndroid Build Coastguard Worker context->getState().isPrimitiveRestartEnabled(),
863*8975f5c5SAndroid Build Coastguard Worker indexRangeOut));
864*8975f5c5SAndroid Build Coastguard Worker
865*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.put(type, indexCount, offset, *indexRangeOut);
866*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
867*8975f5c5SAndroid Build Coastguard Worker }
868*8975f5c5SAndroid Build Coastguard Worker
869*8975f5c5SAndroid Build Coastguard Worker VertexArray::IndexRangeCache::IndexRangeCache() = default;
870*8975f5c5SAndroid Build Coastguard Worker
put(DrawElementsType type,GLsizei indexCount,size_t offset,const IndexRange & indexRange)871*8975f5c5SAndroid Build Coastguard Worker void VertexArray::IndexRangeCache::put(DrawElementsType type,
872*8975f5c5SAndroid Build Coastguard Worker GLsizei indexCount,
873*8975f5c5SAndroid Build Coastguard Worker size_t offset,
874*8975f5c5SAndroid Build Coastguard Worker const IndexRange &indexRange)
875*8975f5c5SAndroid Build Coastguard Worker {
876*8975f5c5SAndroid Build Coastguard Worker ASSERT(type != DrawElementsType::InvalidEnum);
877*8975f5c5SAndroid Build Coastguard Worker
878*8975f5c5SAndroid Build Coastguard Worker mTypeKey = type;
879*8975f5c5SAndroid Build Coastguard Worker mIndexCountKey = indexCount;
880*8975f5c5SAndroid Build Coastguard Worker mOffsetKey = offset;
881*8975f5c5SAndroid Build Coastguard Worker mPayload = indexRange;
882*8975f5c5SAndroid Build Coastguard Worker }
883*8975f5c5SAndroid Build Coastguard Worker
onBufferContentsChange(uint32_t bufferIndex)884*8975f5c5SAndroid Build Coastguard Worker void VertexArray::onBufferContentsChange(uint32_t bufferIndex)
885*8975f5c5SAndroid Build Coastguard Worker {
886*8975f5c5SAndroid Build Coastguard Worker setDependentDirtyBit(true, bufferIndex);
887*8975f5c5SAndroid Build Coastguard Worker }
888*8975f5c5SAndroid Build Coastguard Worker
VertexArrayBufferContentsObservers(VertexArray * vertexArray)889*8975f5c5SAndroid Build Coastguard Worker VertexArrayBufferContentsObservers::VertexArrayBufferContentsObservers(VertexArray *vertexArray)
890*8975f5c5SAndroid Build Coastguard Worker : mVertexArray(vertexArray)
891*8975f5c5SAndroid Build Coastguard Worker {}
892*8975f5c5SAndroid Build Coastguard Worker
enableForBuffer(Buffer * buffer,uint32_t attribIndex)893*8975f5c5SAndroid Build Coastguard Worker void VertexArrayBufferContentsObservers::enableForBuffer(Buffer *buffer, uint32_t attribIndex)
894*8975f5c5SAndroid Build Coastguard Worker {
895*8975f5c5SAndroid Build Coastguard Worker buffer->addContentsObserver(mVertexArray, attribIndex);
896*8975f5c5SAndroid Build Coastguard Worker mBufferObserversBitMask.set(attribIndex);
897*8975f5c5SAndroid Build Coastguard Worker }
898*8975f5c5SAndroid Build Coastguard Worker
disableForBuffer(Buffer * buffer,uint32_t attribIndex)899*8975f5c5SAndroid Build Coastguard Worker void VertexArrayBufferContentsObservers::disableForBuffer(Buffer *buffer, uint32_t attribIndex)
900*8975f5c5SAndroid Build Coastguard Worker {
901*8975f5c5SAndroid Build Coastguard Worker if (mBufferObserversBitMask.test(attribIndex))
902*8975f5c5SAndroid Build Coastguard Worker {
903*8975f5c5SAndroid Build Coastguard Worker buffer->removeContentsObserver(mVertexArray, attribIndex);
904*8975f5c5SAndroid Build Coastguard Worker mBufferObserversBitMask.reset(attribIndex);
905*8975f5c5SAndroid Build Coastguard Worker }
906*8975f5c5SAndroid Build Coastguard Worker }
907*8975f5c5SAndroid Build Coastguard Worker } // namespace gl
908