blob: ac3a4b5e696b47e6271ee7d664f64c67ab7b8bc6 [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 Madilld69a5f12018-08-01 11:34:48 -040018namespace
19{
20bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex)
21{
22 return (subjectIndex == MAX_VERTEX_ATTRIBS);
23}
24} // anonymous namespce
25
Jamie Madillbcef3222018-04-13 15:19:11 -040026// VertexArrayState implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080027VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
Jamie Madillad637282018-07-31 11:22:14 -040028 : mLabel(), mVertexBindings()
Jamie Madill57a89722013-07-02 11:57:03 -040029{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080030 ASSERT(maxAttribs <= maxAttribBindings);
31
32 for (size_t i = 0; i < maxAttribs; i++)
33 {
34 mVertexAttributes.emplace_back(static_cast<GLuint>(i));
Jamie Madillad637282018-07-31 11:22:14 -040035 mVertexBindings.emplace_back(static_cast<GLuint>(i));
Jiawei-Shao2597fb62016-12-09 16:38:02 +080036 }
Jamie Madilldc358af2018-07-31 11:22:13 -040037
38 // Initially all attributes start as "client" with no buffer bound.
39 mClientMemoryAttribsMask.set();
Jamie Madill8e344942015-07-09 14:22:07 -040040}
41
Jamie Madill3f572682016-04-26 13:41:36 -040042VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040043{
Jamie Madill8e344942015-07-09 14:22:07 -040044}
45
Jamie Madill51af38b2018-04-15 08:50:56 -040046bool VertexArrayState::hasEnabledNullPointerClientArray() const
47{
48 return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
49}
50
Jamie Madillad637282018-07-31 11:22:14 -040051AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080052{
53 ASSERT(bindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
Jamie Madillad637282018-07-31 11:22:14 -040054 return mVertexBindings[bindingIndex].getBoundAttributesMask();
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080055}
56
57// Set an attribute using a new binding.
58void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
59{
60 ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
61
Jamie Madillbdc610a2018-07-30 10:26:00 -040062 VertexAttribute &attrib = mVertexAttributes[attribIndex];
63
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080064 // Update the binding-attribute map.
Jamie Madillbdc610a2018-07-30 10:26:00 -040065 const GLuint oldBindingIndex = attrib.bindingIndex;
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080066 ASSERT(oldBindingIndex != newBindingIndex);
67
Jamie Madilld69a5f12018-08-01 11:34:48 -040068 VertexBinding &oldBinding = mVertexBindings[oldBindingIndex];
69 VertexBinding &newBinding = mVertexBindings[newBindingIndex];
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080070
Jamie Madilld69a5f12018-08-01 11:34:48 -040071 ASSERT(oldBinding.getBoundAttributesMask().test(attribIndex) &&
72 !newBinding.getBoundAttributesMask().test(attribIndex));
73
74 oldBinding.resetBoundAttribute(attribIndex);
75 newBinding.setBoundAttribute(attribIndex);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080076
77 // Set the attribute using the new binding.
Jamie Madillbdc610a2018-07-30 10:26:00 -040078 attrib.bindingIndex = newBindingIndex;
Jamie Madilld69a5f12018-08-01 11:34:48 -040079 attrib.updateCachedElementLimit(newBinding);
80
81 bool isMapped = newBinding.getBuffer().get() && newBinding.getBuffer()->isMapped();
82 mCachedMappedArrayBuffers.set(attribIndex, isMapped);
83 mCachedEnabledMappedArrayBuffers.set(attribIndex, isMapped && attrib.enabled);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080084}
85
Jamie Madillbcef3222018-04-13 15:19:11 -040086// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080087VertexArray::VertexArray(rx::GLImplFactory *factory,
88 GLuint id,
89 size_t maxAttribs,
90 size_t maxAttribBindings)
91 : mId(id),
92 mState(maxAttribs, maxAttribBindings),
Jamie Madill09463932018-04-04 05:26:59 -040093 mVertexArray(factory->createVertexArray(mState)),
Jamie Madilld69a5f12018-08-01 11:34:48 -040094 mElementArrayBufferObserverBinding(this, MAX_VERTEX_ATTRIBS)
Jamie Madill8e344942015-07-09 14:22:07 -040095{
Jamie Madill09463932018-04-04 05:26:59 -040096 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
97 {
98 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
99 }
Jamie Madill004a6f92013-07-10 15:13:38 -0400100}
101
Jamie Madill4928b7c2017-06-20 12:57:39 -0400102void VertexArray::onDestroy(const Context *context)
103{
James Darpiniane8a93c62018-01-04 18:02:24 -0800104 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -0400105 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -0400106 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800107 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400108 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800109 if (isBound && mState.mElementArrayBuffer.get())
Jamie Madillbf5177d2018-08-21 12:58:20 -0400110 mState.mElementArrayBuffer->onNonTFBindingChanged(context, -1);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400111 mState.mElementArrayBuffer.set(context, nullptr);
112 mVertexArray->destroy(context);
113 SafeDelete(mVertexArray);
114 delete this;
115}
116
Jamie Madill004a6f92013-07-10 15:13:38 -0400117VertexArray::~VertexArray()
118{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400119 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -0400120}
121
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400122GLuint VertexArray::id() const
123{
124 return mId;
125}
126
Geoff Lang70d0f492015-12-10 17:45:46 -0500127void VertexArray::setLabel(const std::string &label)
128{
Jamie Madill3f572682016-04-26 13:41:36 -0400129 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500130}
131
132const std::string &VertexArray::getLabel() const
133{
Jamie Madill3f572682016-04-26 13:41:36 -0400134 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500135}
136
Jamie Madill4928b7c2017-06-20 12:57:39 -0400137void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400138{
James Darpiniane8a93c62018-01-04 18:02:24 -0800139 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800140 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -0400141 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300142 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400143 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800144 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400145 }
146 }
147
Jamie Madill3f572682016-04-26 13:41:36 -0400148 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400149 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800150 if (isBound && mState.mElementArrayBuffer.get())
Jamie Madillbf5177d2018-08-21 12:58:20 -0400151 mState.mElementArrayBuffer->onNonTFBindingChanged(context, -1);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400152 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400153 }
154}
155
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800156const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400157{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800158 ASSERT(attribIndex < getMaxAttribs());
159 return mState.mVertexAttributes[attribIndex];
160}
161
162const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
163{
164 ASSERT(bindingIndex < getMaxBindings());
165 return mState.mVertexBindings[bindingIndex];
166}
167
Shaodde78e82017-05-22 14:13:27 +0800168size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800169{
170 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
171 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800172 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400173 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
174}
175
176void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
177{
178 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
179 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
180}
181
182void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
183{
184 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
185 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800186}
187
Shaodde78e82017-05-22 14:13:27 +0800188void VertexArray::bindVertexBufferImpl(const Context *context,
189 size_t bindingIndex,
190 Buffer *boundBuffer,
191 GLintptr offset,
192 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800193{
194 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800195 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800196
197 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
198
James Darpiniane8a93c62018-01-04 18:02:24 -0800199 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300200 binding->setOffset(offset);
201 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400202
203 updateObserverBinding(bindingIndex);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400204 updateCachedBufferBindingSize(binding);
Jamie Madill7267aa62018-04-17 15:28:21 -0400205 updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400206 updateCachedMappedArrayBuffers(binding);
Jamie Madilldc358af2018-07-31 11:22:13 -0400207
208 // Update client memory attribute pointers. Affects all bound attributes.
209 if (boundBuffer)
210 {
Jamie Madillad637282018-07-31 11:22:14 -0400211 mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400212 }
213 else
214 {
Jamie Madillad637282018-07-31 11:22:14 -0400215 mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400216 }
Shaodde78e82017-05-22 14:13:27 +0800217}
218
219void VertexArray::bindVertexBuffer(const Context *context,
220 size_t bindingIndex,
221 Buffer *boundBuffer,
222 GLintptr offset,
223 GLsizei stride)
224{
225 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400226 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800227}
228
Shaodde78e82017-05-22 14:13:27 +0800229void VertexArray::setVertexAttribBinding(const Context *context,
230 size_t attribIndex,
231 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800232{
233 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
234
Shaodde78e82017-05-22 14:13:27 +0800235 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
236 {
237 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
238 ASSERT(context->getClientVersion() >= ES_3_1);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +0800239
240 mState.setAttribBinding(attribIndex, bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800241
Jamie Madille858cb12018-03-27 09:44:32 -0400242 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Jamie Madilldc358af2018-07-31 11:22:13 -0400243
244 // Update client attribs mask.
245 bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
246 mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
Shaodde78e82017-05-22 14:13:27 +0800247 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800248}
249
250void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
251{
252 ASSERT(bindingIndex < getMaxBindings());
253
Jamie Madillbdc610a2018-07-30 10:26:00 -0400254 VertexBinding &binding = mState.mVertexBindings[bindingIndex];
255
256 binding.setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400257 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400258
259 // Trigger updates in all bound attributes.
260 for (size_t attribIndex : binding.getBoundAttributesMask())
261 {
262 mState.mVertexAttributes[attribIndex].updateCachedElementLimit(binding);
263 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800264}
265
Shaodde78e82017-05-22 14:13:27 +0800266void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
267 GLint size,
268 GLenum type,
269 bool normalized,
270 bool pureInteger,
271 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800272{
273 ASSERT(attribIndex < getMaxAttribs());
274
275 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
276
277 attrib->size = size;
278 attrib->type = type;
279 attrib->normalized = normalized;
280 attrib->pureInteger = pureInteger;
281 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800282 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800283}
284
285void VertexArray::setVertexAttribFormat(size_t attribIndex,
286 GLint size,
287 GLenum type,
288 bool normalized,
289 bool pureInteger,
290 GLuint relativeOffset)
291{
292 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400293 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400294
295 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
296 attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
Jamie Madill57a89722013-07-02 11:57:03 -0400297}
298
Shaodde78e82017-05-22 14:13:27 +0800299void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400300{
Shaodde78e82017-05-22 14:13:27 +0800301 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800302
Shaodde78e82017-05-22 14:13:27 +0800303 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
304 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400305}
306
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800307void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400308{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800309 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800310
Jamie Madillbdc610a2018-07-30 10:26:00 -0400311 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
312
Shahbaz Youssefi337bd692018-08-22 16:16:38 -0400313 if (mState.mEnabledAttributesMask.test(attribIndex) == enabledState)
314 {
315 return;
316 }
317
Jamie Madillbdc610a2018-07-30 10:26:00 -0400318 attrib.enabled = enabledState;
Shaodde78e82017-05-22 14:13:27 +0800319
Jamie Madille858cb12018-03-27 09:44:32 -0400320 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400321
322 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500323 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400324 mState.mCachedEnabledMappedArrayBuffers =
325 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madill57a89722013-07-02 11:57:03 -0400326}
327
Shaodde78e82017-05-22 14:13:27 +0800328void VertexArray::setVertexAttribPointer(const Context *context,
329 size_t attribIndex,
330 gl::Buffer *boundBuffer,
331 GLint size,
332 GLenum type,
333 bool normalized,
334 bool pureInteger,
335 GLsizei stride,
336 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400337{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800338 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400339
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800340 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400341
Shaodde78e82017-05-22 14:13:27 +0800342 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
343 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800344
345 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800346
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800347 GLsizei effectiveStride =
348 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
349 attrib.pointer = pointer;
350 attrib.vertexAttribArrayStride = stride;
351
Shaodde78e82017-05-22 14:13:27 +0800352 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800353
Jamie Madille858cb12018-03-27 09:44:32 -0400354 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400355
Jamie Madill51af38b2018-04-15 08:50:56 -0400356 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
357 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700358}
359
Jamie Madill4928b7c2017-06-20 12:57:39 -0400360void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700361{
Jamie Madill7b2f0272018-08-27 10:16:08 -0400362 ASSERT(context->isCurrentVertexArray(this));
363 if (mState.mElementArrayBuffer.get())
Jamie Madillbf5177d2018-08-21 12:58:20 -0400364 {
Jamie Madill7b2f0272018-08-27 10:16:08 -0400365 mState.mElementArrayBuffer->onNonTFBindingChanged(context, -1);
366 }
Jamie Madilld84b6732018-09-06 15:54:35 -0400367 mState.mElementArrayBuffer.set(context, buffer);
Jamie Madill7b2f0272018-08-27 10:16:08 -0400368 if (buffer)
369 {
Jamie Madill7b2f0272018-08-27 10:16:08 -0400370 mElementArrayBufferObserverBinding.bind(buffer->getImplementation());
Jamie Madilld84b6732018-09-06 15:54:35 -0400371 buffer->onNonTFBindingChanged(context, 1);
Jamie Madill7b2f0272018-08-27 10:16:08 -0400372 }
373 else
374 {
375 mElementArrayBufferObserverBinding.bind(nullptr);
Jamie Madillbf5177d2018-08-21 12:58:20 -0400376 }
Jamie Madill0b9e9032015-08-17 11:51:52 +0000377 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
378}
379
Jamie Madill6f755b22018-10-09 12:48:54 -0400380angle::Result VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000381{
382 if (mDirtyBits.any())
383 {
Jamie Madill09463932018-04-04 05:26:59 -0400384 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400385 ANGLE_TRY(
386 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000387 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400388 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400389
390 // This is a bit of an implementation hack - but since we know the implementation
391 // details of the dirty bit class it should always have the same effect as iterating
392 // individual attribs. We could also look into schemes where iterating the dirty
393 // bit set also resets it as you pass through it.
394 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
395 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000396 }
Jamie Madill6f755b22018-10-09 12:48:54 -0400397 return angle::Result::Continue();
Jamie Madill57a89722013-07-02 11:57:03 -0400398}
399
Jamie Madillbf5177d2018-08-21 12:58:20 -0400400void VertexArray::onBindingChanged(const Context *context, int incr)
James Darpiniane8a93c62018-01-04 18:02:24 -0800401{
402 if (mState.mElementArrayBuffer.get())
Jamie Madillbf5177d2018-08-21 12:58:20 -0400403 mState.mElementArrayBuffer->onNonTFBindingChanged(context, incr);
James Darpiniane8a93c62018-01-04 18:02:24 -0800404 for (auto &binding : mState.mVertexBindings)
405 {
Jamie Madillbf5177d2018-08-21 12:58:20 -0400406 binding.onContainerBindingChanged(context, incr);
James Darpiniane8a93c62018-01-04 18:02:24 -0800407 }
408}
409
Jamie Madill09463932018-04-04 05:26:59 -0400410VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
411 angle::SubjectIndex index) const
412{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400413 if (IsElementArrayBufferSubjectIndex(index))
Jamie Madill09463932018-04-04 05:26:59 -0400414 {
415 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
416 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
417 }
418 else
419 {
420 // Note: this currently just gets the top-level dirty bit.
421 ASSERT(index < mArrayBufferObserverBindings.size());
422 return static_cast<DirtyBitType>(
423 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
424 }
425}
426
427void VertexArray::onSubjectStateChange(const gl::Context *context,
428 angle::SubjectIndex index,
429 angle::SubjectMessage message)
430{
Jamie Madill7267aa62018-04-17 15:28:21 -0400431 switch (message)
432 {
433 case angle::SubjectMessage::CONTENTS_CHANGED:
434 setDependentDirtyBit(context, true, index);
435 break;
436
437 case angle::SubjectMessage::STORAGE_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400438 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400439 {
Jamie Madillbdc610a2018-07-30 10:26:00 -0400440 updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
Jamie Madill7267aa62018-04-17 15:28:21 -0400441 }
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400442 setDependentDirtyBit(context, false, index);
Jamie Madill7267aa62018-04-17 15:28:21 -0400443 break;
444
445 case angle::SubjectMessage::BINDING_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400446 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400447 {
448 const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
449 updateCachedTransformFeedbackBindingValidation(index, buffer);
450 }
451 break;
452
Jamie Madilld69a5f12018-08-01 11:34:48 -0400453 case angle::SubjectMessage::RESOURCE_MAPPED:
454 if (!IsElementArrayBufferSubjectIndex(index))
455 {
456 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
Jamie Madilld84b6732018-09-06 15:54:35 -0400457 onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400458 }
459 break;
460
461 case angle::SubjectMessage::RESOURCE_UNMAPPED:
462 setDependentDirtyBit(context, true, index);
463
464 if (!IsElementArrayBufferSubjectIndex(index))
465 {
466 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
Jamie Madilld84b6732018-09-06 15:54:35 -0400467 onStateChange(context, angle::SubjectMessage::RESOURCE_UNMAPPED);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400468 }
469 break;
470
Jamie Madill7267aa62018-04-17 15:28:21 -0400471 default:
472 UNREACHABLE();
473 break;
474 }
475}
476
477void VertexArray::setDependentDirtyBit(const gl::Context *context,
478 bool contentsChanged,
479 angle::SubjectIndex index)
480{
Jamie Madill09463932018-04-04 05:26:59 -0400481 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
482 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
483 mDirtyBits.set(dirtyBit);
Jamie Madilla11819d2018-07-30 10:26:01 -0400484 onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
Jamie Madill09463932018-04-04 05:26:59 -0400485}
486
487void VertexArray::updateObserverBinding(size_t bindingIndex)
488{
489 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
490 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
491 : nullptr);
492}
493
Jamie Madillbdc610a2018-07-30 10:26:00 -0400494void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
Jamie Madill02c9c042018-04-17 13:43:48 -0400495{
Jamie Madillbdc610a2018-07-30 10:26:00 -0400496 for (size_t boundAttribute : binding->getBoundAttributesMask())
497 {
498 mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
499 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400500}
501
Jamie Madill7267aa62018-04-17 15:28:21 -0400502void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
503 const Buffer *buffer)
504{
505 const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
506 mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
507}
508
Jamie Madillac43aaa2018-07-31 11:22:13 -0400509bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
Jamie Madill7267aa62018-04-17 15:28:21 -0400510{
511 // Fast check first.
512 if (!mCachedTransformFeedbackConflictedBindingsMask.any())
513 {
514 return false;
515 }
516
Jamie Madillac43aaa2018-07-31 11:22:13 -0400517 const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
518
Jamie Madill7267aa62018-04-17 15:28:21 -0400519 // Slow check. We must ensure that the conflicting attributes are enabled/active.
520 for (size_t attribIndex : activeAttribues)
521 {
522 const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
523 if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
524 {
525 return true;
526 }
527 }
528
529 return false;
530}
531
Jamie Madilld69a5f12018-08-01 11:34:48 -0400532void VertexArray::updateCachedMappedArrayBuffers(VertexBinding *binding)
Jamie Madillcc73f242018-08-01 11:34:48 -0400533{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400534 Buffer *buffer = binding->getBuffer().get();
535 if (buffer && buffer->isMapped())
Jamie Madillcc73f242018-08-01 11:34:48 -0400536 {
Jamie Madilld69a5f12018-08-01 11:34:48 -0400537 mState.mCachedMappedArrayBuffers |= binding->getBoundAttributesMask();
538 }
539 else
540 {
541 mState.mCachedMappedArrayBuffers &= ~binding->getBoundAttributesMask();
Jamie Madillcc73f242018-08-01 11:34:48 -0400542 }
543
Jamie Madilld69a5f12018-08-01 11:34:48 -0400544 mState.mCachedEnabledMappedArrayBuffers =
545 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madillcc73f242018-08-01 11:34:48 -0400546}
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800547} // namespace gl