blob: 272debc7d48e4421d5a3519ae4bfc2a5f6dcbab6 [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())
James Darpinian09303e42018-06-22 17:53:57 -0700110 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray,
111 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400112 mState.mElementArrayBuffer.set(context, nullptr);
113 mVertexArray->destroy(context);
114 SafeDelete(mVertexArray);
115 delete this;
116}
117
Jamie Madill004a6f92013-07-10 15:13:38 -0400118VertexArray::~VertexArray()
119{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400120 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -0400121}
122
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400123GLuint VertexArray::id() const
124{
125 return mId;
126}
127
Geoff Lang70d0f492015-12-10 17:45:46 -0500128void VertexArray::setLabel(const std::string &label)
129{
Jamie Madill3f572682016-04-26 13:41:36 -0400130 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500131}
132
133const std::string &VertexArray::getLabel() const
134{
Jamie Madill3f572682016-04-26 13:41:36 -0400135 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500136}
137
Jamie Madill4928b7c2017-06-20 12:57:39 -0400138void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400139{
James Darpiniane8a93c62018-01-04 18:02:24 -0800140 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800141 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -0400142 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300143 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400144 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800145 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400146 }
147 }
148
Jamie Madill3f572682016-04-26 13:41:36 -0400149 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400150 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800151 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700152 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::Array,
153 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400154 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400155 }
156}
157
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800158const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400159{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800160 ASSERT(attribIndex < getMaxAttribs());
161 return mState.mVertexAttributes[attribIndex];
162}
163
164const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
165{
166 ASSERT(bindingIndex < getMaxBindings());
167 return mState.mVertexBindings[bindingIndex];
168}
169
Shaodde78e82017-05-22 14:13:27 +0800170size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800171{
172 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
173 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800174 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400175 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
176}
177
178void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
179{
180 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
181 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
182}
183
184void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
185{
186 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
187 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800188}
189
Shaodde78e82017-05-22 14:13:27 +0800190void VertexArray::bindVertexBufferImpl(const Context *context,
191 size_t bindingIndex,
192 Buffer *boundBuffer,
193 GLintptr offset,
194 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800195{
196 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800197 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800198
199 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
200
James Darpiniane8a93c62018-01-04 18:02:24 -0800201 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300202 binding->setOffset(offset);
203 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400204
205 updateObserverBinding(bindingIndex);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400206 updateCachedBufferBindingSize(binding);
Jamie Madill7267aa62018-04-17 15:28:21 -0400207 updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400208 updateCachedMappedArrayBuffers(binding);
Jamie Madilldc358af2018-07-31 11:22:13 -0400209
210 // Update client memory attribute pointers. Affects all bound attributes.
211 if (boundBuffer)
212 {
Jamie Madillad637282018-07-31 11:22:14 -0400213 mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400214 }
215 else
216 {
Jamie Madillad637282018-07-31 11:22:14 -0400217 mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400218 }
Shaodde78e82017-05-22 14:13:27 +0800219}
220
221void VertexArray::bindVertexBuffer(const Context *context,
222 size_t bindingIndex,
223 Buffer *boundBuffer,
224 GLintptr offset,
225 GLsizei stride)
226{
227 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400228 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800229}
230
Shaodde78e82017-05-22 14:13:27 +0800231void VertexArray::setVertexAttribBinding(const Context *context,
232 size_t attribIndex,
233 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800234{
235 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
236
Shaodde78e82017-05-22 14:13:27 +0800237 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
238 {
239 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
240 ASSERT(context->getClientVersion() >= ES_3_1);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +0800241
242 mState.setAttribBinding(attribIndex, bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800243
Jamie Madille858cb12018-03-27 09:44:32 -0400244 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Jamie Madilldc358af2018-07-31 11:22:13 -0400245
246 // Update client attribs mask.
247 bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
248 mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
Shaodde78e82017-05-22 14:13:27 +0800249 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800250}
251
252void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
253{
254 ASSERT(bindingIndex < getMaxBindings());
255
Jamie Madillbdc610a2018-07-30 10:26:00 -0400256 VertexBinding &binding = mState.mVertexBindings[bindingIndex];
257
258 binding.setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400259 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400260
261 // Trigger updates in all bound attributes.
262 for (size_t attribIndex : binding.getBoundAttributesMask())
263 {
264 mState.mVertexAttributes[attribIndex].updateCachedElementLimit(binding);
265 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800266}
267
Shaodde78e82017-05-22 14:13:27 +0800268void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
269 GLint size,
270 GLenum type,
271 bool normalized,
272 bool pureInteger,
273 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800274{
275 ASSERT(attribIndex < getMaxAttribs());
276
277 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
278
279 attrib->size = size;
280 attrib->type = type;
281 attrib->normalized = normalized;
282 attrib->pureInteger = pureInteger;
283 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800284 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800285}
286
287void VertexArray::setVertexAttribFormat(size_t attribIndex,
288 GLint size,
289 GLenum type,
290 bool normalized,
291 bool pureInteger,
292 GLuint relativeOffset)
293{
294 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400295 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400296
297 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
298 attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
Jamie Madill57a89722013-07-02 11:57:03 -0400299}
300
Shaodde78e82017-05-22 14:13:27 +0800301void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400302{
Shaodde78e82017-05-22 14:13:27 +0800303 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800304
Shaodde78e82017-05-22 14:13:27 +0800305 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
306 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400307}
308
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800309void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400310{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800311 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800312
Jamie Madillbdc610a2018-07-30 10:26:00 -0400313 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
314
315 attrib.enabled = enabledState;
316 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800317
Jamie Madille858cb12018-03-27 09:44:32 -0400318 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400319
320 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500321 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400322 mState.mCachedEnabledMappedArrayBuffers =
323 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madill57a89722013-07-02 11:57:03 -0400324}
325
Shaodde78e82017-05-22 14:13:27 +0800326void VertexArray::setVertexAttribPointer(const Context *context,
327 size_t attribIndex,
328 gl::Buffer *boundBuffer,
329 GLint size,
330 GLenum type,
331 bool normalized,
332 bool pureInteger,
333 GLsizei stride,
334 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400335{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800336 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400337
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800338 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400339
Shaodde78e82017-05-22 14:13:27 +0800340 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
341 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800342
343 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800344
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800345 GLsizei effectiveStride =
346 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
347 attrib.pointer = pointer;
348 attrib.vertexAttribArrayStride = stride;
349
Shaodde78e82017-05-22 14:13:27 +0800350 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800351
Jamie Madille858cb12018-03-27 09:44:32 -0400352 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400353
Jamie Madill51af38b2018-04-15 08:50:56 -0400354 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
355 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700356}
357
Jamie Madill4928b7c2017-06-20 12:57:39 -0400358void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700359{
James Darpiniane8a93c62018-01-04 18:02:24 -0800360 bool isBound = context->isCurrentVertexArray(this);
361 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700362 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray,
363 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400364 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800365 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700366 mState.mElementArrayBuffer->onBindingChanged(context, true, BufferBinding::ElementArray,
367 false);
Jamie Madill09463932018-04-04 05:26:59 -0400368 mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000369 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
370}
371
Frank Henigman0af5b862018-03-27 20:19:33 -0400372gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000373{
374 if (mDirtyBits.any())
375 {
Jamie Madill09463932018-04-04 05:26:59 -0400376 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400377 ANGLE_TRY(
378 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000379 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400380 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400381
382 // This is a bit of an implementation hack - but since we know the implementation
383 // details of the dirty bit class it should always have the same effect as iterating
384 // individual attribs. We could also look into schemes where iterating the dirty
385 // bit set also resets it as you pass through it.
386 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
387 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000388 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400389 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400390}
391
Jamie Madill7267aa62018-04-17 15:28:21 -0400392void VertexArray::onBindingChanged(const Context *context, bool bound)
James Darpiniane8a93c62018-01-04 18:02:24 -0800393{
394 if (mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700395 mState.mElementArrayBuffer->onBindingChanged(context, bound, BufferBinding::ElementArray,
396 false);
James Darpiniane8a93c62018-01-04 18:02:24 -0800397 for (auto &binding : mState.mVertexBindings)
398 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400399 binding.onContainerBindingChanged(context, bound);
James Darpiniane8a93c62018-01-04 18:02:24 -0800400 }
401}
402
Jamie Madill09463932018-04-04 05:26:59 -0400403VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
404 angle::SubjectIndex index) const
405{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400406 if (IsElementArrayBufferSubjectIndex(index))
Jamie Madill09463932018-04-04 05:26:59 -0400407 {
408 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
409 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
410 }
411 else
412 {
413 // Note: this currently just gets the top-level dirty bit.
414 ASSERT(index < mArrayBufferObserverBindings.size());
415 return static_cast<DirtyBitType>(
416 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
417 }
418}
419
420void VertexArray::onSubjectStateChange(const gl::Context *context,
421 angle::SubjectIndex index,
422 angle::SubjectMessage message)
423{
Jamie Madill7267aa62018-04-17 15:28:21 -0400424 switch (message)
425 {
426 case angle::SubjectMessage::CONTENTS_CHANGED:
427 setDependentDirtyBit(context, true, index);
428 break;
429
430 case angle::SubjectMessage::STORAGE_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400431 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400432 {
Jamie Madillbdc610a2018-07-30 10:26:00 -0400433 updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
Jamie Madill7267aa62018-04-17 15:28:21 -0400434 }
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400435 setDependentDirtyBit(context, false, index);
Jamie Madill7267aa62018-04-17 15:28:21 -0400436 break;
437
438 case angle::SubjectMessage::BINDING_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400439 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400440 {
441 const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
442 updateCachedTransformFeedbackBindingValidation(index, buffer);
443 }
444 break;
445
Jamie Madilld69a5f12018-08-01 11:34:48 -0400446 case angle::SubjectMessage::RESOURCE_MAPPED:
447 if (!IsElementArrayBufferSubjectIndex(index))
448 {
449 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
450 }
451 break;
452
453 case angle::SubjectMessage::RESOURCE_UNMAPPED:
454 setDependentDirtyBit(context, true, index);
455
456 if (!IsElementArrayBufferSubjectIndex(index))
457 {
458 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
459 }
460 break;
461
Jamie Madill7267aa62018-04-17 15:28:21 -0400462 default:
463 UNREACHABLE();
464 break;
465 }
466}
467
468void VertexArray::setDependentDirtyBit(const gl::Context *context,
469 bool contentsChanged,
470 angle::SubjectIndex index)
471{
Jamie Madill09463932018-04-04 05:26:59 -0400472 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
473 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
474 mDirtyBits.set(dirtyBit);
Jamie Madilla11819d2018-07-30 10:26:01 -0400475 onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
Jamie Madill09463932018-04-04 05:26:59 -0400476}
477
478void VertexArray::updateObserverBinding(size_t bindingIndex)
479{
480 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
481 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
482 : nullptr);
483}
484
Jamie Madillbdc610a2018-07-30 10:26:00 -0400485void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
Jamie Madill02c9c042018-04-17 13:43:48 -0400486{
Jamie Madillbdc610a2018-07-30 10:26:00 -0400487 for (size_t boundAttribute : binding->getBoundAttributesMask())
488 {
489 mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
490 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400491}
492
Jamie Madill7267aa62018-04-17 15:28:21 -0400493void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
494 const Buffer *buffer)
495{
496 const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
497 mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
498}
499
Jamie Madillac43aaa2018-07-31 11:22:13 -0400500bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
Jamie Madill7267aa62018-04-17 15:28:21 -0400501{
502 // Fast check first.
503 if (!mCachedTransformFeedbackConflictedBindingsMask.any())
504 {
505 return false;
506 }
507
Jamie Madillac43aaa2018-07-31 11:22:13 -0400508 const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
509
Jamie Madill7267aa62018-04-17 15:28:21 -0400510 // Slow check. We must ensure that the conflicting attributes are enabled/active.
511 for (size_t attribIndex : activeAttribues)
512 {
513 const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
514 if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
515 {
516 return true;
517 }
518 }
519
520 return false;
521}
522
Jamie Madilld69a5f12018-08-01 11:34:48 -0400523void VertexArray::updateCachedMappedArrayBuffers(VertexBinding *binding)
Jamie Madillcc73f242018-08-01 11:34:48 -0400524{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400525 Buffer *buffer = binding->getBuffer().get();
526 if (buffer && buffer->isMapped())
Jamie Madillcc73f242018-08-01 11:34:48 -0400527 {
Jamie Madilld69a5f12018-08-01 11:34:48 -0400528 mState.mCachedMappedArrayBuffers |= binding->getBoundAttributesMask();
529 }
530 else
531 {
532 mState.mCachedMappedArrayBuffers &= ~binding->getBoundAttributesMask();
Jamie Madillcc73f242018-08-01 11:34:48 -0400533 }
534
Jamie Madilld69a5f12018-08-01 11:34:48 -0400535 mState.mCachedEnabledMappedArrayBuffers =
536 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madillcc73f242018-08-01 11:34:48 -0400537}
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800538} // namespace gl