blob: 06362d011d9a247ea4eb5a7cfc190126b359803e [file] [log] [blame]
Jamie Madill57a89722013-07-02 11:57:03 -04001//
2// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
7//
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/VertexArray.h"
10#include "libANGLE/Buffer.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040011#include "libANGLE/Context.h"
Jamie Madill09463932018-04-04 05:26:59 -040012#include "libANGLE/renderer/BufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040013#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/renderer/VertexArrayImpl.h"
Jamie Madill57a89722013-07-02 11:57:03 -040015
16namespace gl
17{
Jamie Madillbcef3222018-04-13 15:19:11 -040018// VertexArrayState implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080019VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
Jamie Madilld078c682018-01-02 11:50:24 -050020 : mLabel(), mVertexBindings(maxAttribBindings)
Jamie Madill57a89722013-07-02 11:57:03 -040021{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080022 ASSERT(maxAttribs <= maxAttribBindings);
23
24 for (size_t i = 0; i < maxAttribs; i++)
25 {
26 mVertexAttributes.emplace_back(static_cast<GLuint>(i));
27 }
Jamie Madill8e344942015-07-09 14:22:07 -040028}
29
Jamie Madill3f572682016-04-26 13:41:36 -040030VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040031{
Jamie Madill8e344942015-07-09 14:22:07 -040032}
33
Jamie Madillbcef3222018-04-13 15:19:11 -040034gl::AttributesMask VertexArrayState::getEnabledClientMemoryAttribsMask() const
35{
36 return (mClientMemoryAttribsMask & mEnabledAttributesMask);
37}
38
39// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080040VertexArray::VertexArray(rx::GLImplFactory *factory,
41 GLuint id,
42 size_t maxAttribs,
43 size_t maxAttribBindings)
44 : mId(id),
45 mState(maxAttribs, maxAttribBindings),
Jamie Madill09463932018-04-04 05:26:59 -040046 mVertexArray(factory->createVertexArray(mState)),
47 mElementArrayBufferObserverBinding(this, maxAttribBindings)
Jamie Madill8e344942015-07-09 14:22:07 -040048{
Jamie Madill09463932018-04-04 05:26:59 -040049 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
50 {
51 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
52 }
Jamie Madill004a6f92013-07-10 15:13:38 -040053}
54
Jamie Madill4928b7c2017-06-20 12:57:39 -040055void VertexArray::onDestroy(const Context *context)
56{
James Darpiniane8a93c62018-01-04 18:02:24 -080057 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -040058 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -040059 {
James Darpiniane8a93c62018-01-04 18:02:24 -080060 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -040061 }
James Darpiniane8a93c62018-01-04 18:02:24 -080062 if (isBound && mState.mElementArrayBuffer.get())
63 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -040064 mState.mElementArrayBuffer.set(context, nullptr);
65 mVertexArray->destroy(context);
66 SafeDelete(mVertexArray);
67 delete this;
68}
69
Jamie Madill004a6f92013-07-10 15:13:38 -040070VertexArray::~VertexArray()
71{
Jamie Madill4928b7c2017-06-20 12:57:39 -040072 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -040073}
74
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040075GLuint VertexArray::id() const
76{
77 return mId;
78}
79
Geoff Lang70d0f492015-12-10 17:45:46 -050080void VertexArray::setLabel(const std::string &label)
81{
Jamie Madill3f572682016-04-26 13:41:36 -040082 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -050083}
84
85const std::string &VertexArray::getLabel() const
86{
Jamie Madill3f572682016-04-26 13:41:36 -040087 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -050088}
89
Jamie Madill4928b7c2017-06-20 12:57:39 -040090void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040091{
James Darpiniane8a93c62018-01-04 18:02:24 -080092 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +080093 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -040094 {
Martin Radevdd5f27e2017-06-07 10:17:09 +030095 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040096 {
James Darpiniane8a93c62018-01-04 18:02:24 -080097 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -040098 }
99 }
100
Jamie Madill3f572682016-04-26 13:41:36 -0400101 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400102 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800103 if (isBound && mState.mElementArrayBuffer.get())
104 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::Array);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400105 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400106 }
107}
108
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800109const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400110{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800111 ASSERT(attribIndex < getMaxAttribs());
112 return mState.mVertexAttributes[attribIndex];
113}
114
115const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
116{
117 ASSERT(bindingIndex < getMaxBindings());
118 return mState.mVertexBindings[bindingIndex];
119}
120
Shaodde78e82017-05-22 14:13:27 +0800121size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122{
123 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
124 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800125 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400126 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
127}
128
129void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
130{
131 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
132 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
133}
134
135void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
136{
137 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
138 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800139}
140
Shaodde78e82017-05-22 14:13:27 +0800141void VertexArray::bindVertexBufferImpl(const Context *context,
142 size_t bindingIndex,
143 Buffer *boundBuffer,
144 GLintptr offset,
145 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800146{
147 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800148 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800149
150 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
151
James Darpiniane8a93c62018-01-04 18:02:24 -0800152 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300153 binding->setOffset(offset);
154 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400155
156 updateObserverBinding(bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800157}
158
159void VertexArray::bindVertexBuffer(const Context *context,
160 size_t bindingIndex,
161 Buffer *boundBuffer,
162 GLintptr offset,
163 GLsizei stride)
164{
165 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400166 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800167}
168
Shaodde78e82017-05-22 14:13:27 +0800169void VertexArray::setVertexAttribBinding(const Context *context,
170 size_t attribIndex,
171 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800172{
173 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
174
Shaodde78e82017-05-22 14:13:27 +0800175 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
176 {
177 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
178 ASSERT(context->getClientVersion() >= ES_3_1);
179 mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
180
Jamie Madille858cb12018-03-27 09:44:32 -0400181 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Shaodde78e82017-05-22 14:13:27 +0800182 }
Jamie Madille858cb12018-03-27 09:44:32 -0400183 mState.mVertexAttributes[attribIndex].bindingIndex = static_cast<GLuint>(bindingIndex);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800184}
185
186void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
187{
188 ASSERT(bindingIndex < getMaxBindings());
189
Martin Radevdd5f27e2017-06-07 10:17:09 +0300190 mState.mVertexBindings[bindingIndex].setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400191 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800192}
193
Shaodde78e82017-05-22 14:13:27 +0800194void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
195 GLint size,
196 GLenum type,
197 bool normalized,
198 bool pureInteger,
199 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800200{
201 ASSERT(attribIndex < getMaxAttribs());
202
203 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
204
205 attrib->size = size;
206 attrib->type = type;
207 attrib->normalized = normalized;
208 attrib->pureInteger = pureInteger;
209 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800210 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800211}
212
213void VertexArray::setVertexAttribFormat(size_t attribIndex,
214 GLint size,
215 GLenum type,
216 bool normalized,
217 bool pureInteger,
218 GLuint relativeOffset)
219{
220 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400221 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madill57a89722013-07-02 11:57:03 -0400222}
223
Shaodde78e82017-05-22 14:13:27 +0800224void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400225{
Shaodde78e82017-05-22 14:13:27 +0800226 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800227
Shaodde78e82017-05-22 14:13:27 +0800228 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
229 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400230}
231
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800232void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400233{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800234 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800235
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800236 mState.mVertexAttributes[attribIndex].enabled = enabledState;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800237 mState.mVertexAttributesTypeMask.setIndex(
238 GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800239
Jamie Madille858cb12018-03-27 09:44:32 -0400240 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400241
242 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500243 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madill57a89722013-07-02 11:57:03 -0400244}
245
Shaodde78e82017-05-22 14:13:27 +0800246void VertexArray::setVertexAttribPointer(const Context *context,
247 size_t attribIndex,
248 gl::Buffer *boundBuffer,
249 GLint size,
250 GLenum type,
251 bool normalized,
252 bool pureInteger,
253 GLsizei stride,
254 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400255{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800256 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400257
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800258 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400259
Shaodde78e82017-05-22 14:13:27 +0800260 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
261 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800262
263 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800264
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800265 GLsizei effectiveStride =
266 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
267 attrib.pointer = pointer;
268 attrib.vertexAttribArrayStride = stride;
269
Shaodde78e82017-05-22 14:13:27 +0800270 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800271
Jamie Madille858cb12018-03-27 09:44:32 -0400272 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400273
274 mState.mClientMemoryAttribsMask.set(attribIndex, boundBuffer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700275}
276
Jamie Madill4928b7c2017-06-20 12:57:39 -0400277void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700278{
James Darpiniane8a93c62018-01-04 18:02:24 -0800279 bool isBound = context->isCurrentVertexArray(this);
280 if (isBound && mState.mElementArrayBuffer.get())
281 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400282 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800283 if (isBound && mState.mElementArrayBuffer.get())
284 mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray);
Jamie Madill09463932018-04-04 05:26:59 -0400285 mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000286 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
287}
288
Frank Henigman0af5b862018-03-27 20:19:33 -0400289gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000290{
291 if (mDirtyBits.any())
292 {
Jamie Madill09463932018-04-04 05:26:59 -0400293 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400294 ANGLE_TRY(
295 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000296 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400297 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400298
299 // This is a bit of an implementation hack - but since we know the implementation
300 // details of the dirty bit class it should always have the same effect as iterating
301 // individual attribs. We could also look into schemes where iterating the dirty
302 // bit set also resets it as you pass through it.
303 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
304 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000305 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400306 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400307}
308
James Darpiniane8a93c62018-01-04 18:02:24 -0800309void VertexArray::onBindingChanged(bool bound)
310{
311 if (mState.mElementArrayBuffer.get())
312 mState.mElementArrayBuffer->onBindingChanged(bound, BufferBinding::ElementArray);
313 for (auto &binding : mState.mVertexBindings)
314 {
315 binding.onContainerBindingChanged(bound);
316 }
317}
318
Jamie Madill09463932018-04-04 05:26:59 -0400319VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
320 angle::SubjectIndex index) const
321{
322 if (index == mArrayBufferObserverBindings.size())
323 {
324 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
325 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
326 }
327 else
328 {
329 // Note: this currently just gets the top-level dirty bit.
330 ASSERT(index < mArrayBufferObserverBindings.size());
331 return static_cast<DirtyBitType>(
332 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
333 }
334}
335
336void VertexArray::onSubjectStateChange(const gl::Context *context,
337 angle::SubjectIndex index,
338 angle::SubjectMessage message)
339{
340 bool contentsChanged = (message == angle::SubjectMessage::CONTENTS_CHANGED);
341 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
342 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
343 mDirtyBits.set(dirtyBit);
344 context->getGLState().setVertexArrayDirty(this);
345}
346
347void VertexArray::updateObserverBinding(size_t bindingIndex)
348{
349 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
350 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
351 : nullptr);
352}
353
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800354} // namespace gl