blob: 0735c2a39b5ed3e99df1758439a5bdd2e972b0ee [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{
18
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
Jiawei-Shao2597fb62016-12-09 16:38:02 +080034VertexArray::VertexArray(rx::GLImplFactory *factory,
35 GLuint id,
36 size_t maxAttribs,
37 size_t maxAttribBindings)
38 : mId(id),
39 mState(maxAttribs, maxAttribBindings),
Jamie Madill09463932018-04-04 05:26:59 -040040 mVertexArray(factory->createVertexArray(mState)),
41 mElementArrayBufferObserverBinding(this, maxAttribBindings)
Jamie Madill8e344942015-07-09 14:22:07 -040042{
Jamie Madill09463932018-04-04 05:26:59 -040043 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
44 {
45 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
46 }
Jamie Madill004a6f92013-07-10 15:13:38 -040047}
48
Jamie Madill4928b7c2017-06-20 12:57:39 -040049void VertexArray::onDestroy(const Context *context)
50{
James Darpiniane8a93c62018-01-04 18:02:24 -080051 bool isBound = context->isCurrentVertexArray(this);
Jamie Madill4928b7c2017-06-20 12:57:39 -040052 for (auto &binding : mState.mVertexBindings)
53 {
James Darpiniane8a93c62018-01-04 18:02:24 -080054 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -040055 }
James Darpiniane8a93c62018-01-04 18:02:24 -080056 if (isBound && mState.mElementArrayBuffer.get())
57 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -040058 mState.mElementArrayBuffer.set(context, nullptr);
59 mVertexArray->destroy(context);
60 SafeDelete(mVertexArray);
61 delete this;
62}
63
Jamie Madill004a6f92013-07-10 15:13:38 -040064VertexArray::~VertexArray()
65{
Jamie Madill4928b7c2017-06-20 12:57:39 -040066 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -040067}
68
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040069GLuint VertexArray::id() const
70{
71 return mId;
72}
73
Geoff Lang70d0f492015-12-10 17:45:46 -050074void VertexArray::setLabel(const std::string &label)
75{
Jamie Madill3f572682016-04-26 13:41:36 -040076 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -050077}
78
79const std::string &VertexArray::getLabel() const
80{
Jamie Madill3f572682016-04-26 13:41:36 -040081 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -050082}
83
Jamie Madill4928b7c2017-06-20 12:57:39 -040084void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040085{
James Darpiniane8a93c62018-01-04 18:02:24 -080086 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +080087 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -040088 {
Martin Radevdd5f27e2017-06-07 10:17:09 +030089 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040090 {
James Darpiniane8a93c62018-01-04 18:02:24 -080091 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -040092 }
93 }
94
Jamie Madill3f572682016-04-26 13:41:36 -040095 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040096 {
James Darpiniane8a93c62018-01-04 18:02:24 -080097 if (isBound && mState.mElementArrayBuffer.get())
98 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::Array);
Jamie Madill4928b7c2017-06-20 12:57:39 -040099 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400100 }
101}
102
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800103const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400104{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800105 ASSERT(attribIndex < getMaxAttribs());
106 return mState.mVertexAttributes[attribIndex];
107}
108
109const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
110{
111 ASSERT(bindingIndex < getMaxBindings());
112 return mState.mVertexBindings[bindingIndex];
113}
114
Shaodde78e82017-05-22 14:13:27 +0800115size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800116{
117 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
118 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800119 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400120 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
121}
122
123void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
124{
125 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
126 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
127}
128
129void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
130{
131 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
132 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800133}
134
Shaodde78e82017-05-22 14:13:27 +0800135void VertexArray::bindVertexBufferImpl(const Context *context,
136 size_t bindingIndex,
137 Buffer *boundBuffer,
138 GLintptr offset,
139 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800140{
141 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800142 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800143
144 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
145
James Darpiniane8a93c62018-01-04 18:02:24 -0800146 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300147 binding->setOffset(offset);
148 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400149
150 updateObserverBinding(bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800151}
152
153void VertexArray::bindVertexBuffer(const Context *context,
154 size_t bindingIndex,
155 Buffer *boundBuffer,
156 GLintptr offset,
157 GLsizei stride)
158{
159 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400160 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800161}
162
Shaodde78e82017-05-22 14:13:27 +0800163void VertexArray::setVertexAttribBinding(const Context *context,
164 size_t attribIndex,
165 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800166{
167 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
168
Shaodde78e82017-05-22 14:13:27 +0800169 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
170 {
171 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
172 ASSERT(context->getClientVersion() >= ES_3_1);
173 mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
174
Jamie Madille858cb12018-03-27 09:44:32 -0400175 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Shaodde78e82017-05-22 14:13:27 +0800176 }
Jamie Madille858cb12018-03-27 09:44:32 -0400177 mState.mVertexAttributes[attribIndex].bindingIndex = static_cast<GLuint>(bindingIndex);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800178}
179
180void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
181{
182 ASSERT(bindingIndex < getMaxBindings());
183
Martin Radevdd5f27e2017-06-07 10:17:09 +0300184 mState.mVertexBindings[bindingIndex].setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400185 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800186}
187
Shaodde78e82017-05-22 14:13:27 +0800188void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
189 GLint size,
190 GLenum type,
191 bool normalized,
192 bool pureInteger,
193 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800194{
195 ASSERT(attribIndex < getMaxAttribs());
196
197 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
198
199 attrib->size = size;
200 attrib->type = type;
201 attrib->normalized = normalized;
202 attrib->pureInteger = pureInteger;
203 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800204 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
205 mState.mEnabledAttributesMask.set(attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800206}
207
208void VertexArray::setVertexAttribFormat(size_t attribIndex,
209 GLint size,
210 GLenum type,
211 bool normalized,
212 bool pureInteger,
213 GLuint relativeOffset)
214{
215 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400216 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madill57a89722013-07-02 11:57:03 -0400217}
218
Shaodde78e82017-05-22 14:13:27 +0800219void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400220{
Shaodde78e82017-05-22 14:13:27 +0800221 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800222
Shaodde78e82017-05-22 14:13:27 +0800223 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
224 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400225}
226
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800227void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400228{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800229 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800230
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800231 mState.mVertexAttributes[attribIndex].enabled = enabledState;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800232 mState.mVertexAttributesTypeMask.setIndex(
233 GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800234
Jamie Madille858cb12018-03-27 09:44:32 -0400235 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400236
237 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500238 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madill57a89722013-07-02 11:57:03 -0400239}
240
Shaodde78e82017-05-22 14:13:27 +0800241void VertexArray::setVertexAttribPointer(const Context *context,
242 size_t attribIndex,
243 gl::Buffer *boundBuffer,
244 GLint size,
245 GLenum type,
246 bool normalized,
247 bool pureInteger,
248 GLsizei stride,
249 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400250{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800251 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400252
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800253 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400254
Shaodde78e82017-05-22 14:13:27 +0800255 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
256 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800257
258 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800259
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800260 GLsizei effectiveStride =
261 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
262 attrib.pointer = pointer;
263 attrib.vertexAttribArrayStride = stride;
264
Shaodde78e82017-05-22 14:13:27 +0800265 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800266
Jamie Madille858cb12018-03-27 09:44:32 -0400267 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Brandon Jones5bf98292014-06-06 17:19:38 -0700268}
269
Jamie Madill4928b7c2017-06-20 12:57:39 -0400270void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700271{
James Darpiniane8a93c62018-01-04 18:02:24 -0800272 bool isBound = context->isCurrentVertexArray(this);
273 if (isBound && mState.mElementArrayBuffer.get())
274 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400275 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800276 if (isBound && mState.mElementArrayBuffer.get())
277 mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray);
Jamie Madill09463932018-04-04 05:26:59 -0400278 mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000279 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
280}
281
Frank Henigman0af5b862018-03-27 20:19:33 -0400282gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000283{
284 if (mDirtyBits.any())
285 {
Jamie Madill09463932018-04-04 05:26:59 -0400286 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400287 ANGLE_TRY(
288 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000289 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400290 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400291
292 // This is a bit of an implementation hack - but since we know the implementation
293 // details of the dirty bit class it should always have the same effect as iterating
294 // individual attribs. We could also look into schemes where iterating the dirty
295 // bit set also resets it as you pass through it.
296 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
297 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000298 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400299 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400300}
301
James Darpiniane8a93c62018-01-04 18:02:24 -0800302void VertexArray::onBindingChanged(bool bound)
303{
304 if (mState.mElementArrayBuffer.get())
305 mState.mElementArrayBuffer->onBindingChanged(bound, BufferBinding::ElementArray);
306 for (auto &binding : mState.mVertexBindings)
307 {
308 binding.onContainerBindingChanged(bound);
309 }
310}
311
Jamie Madill09463932018-04-04 05:26:59 -0400312VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
313 angle::SubjectIndex index) const
314{
315 if (index == mArrayBufferObserverBindings.size())
316 {
317 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
318 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
319 }
320 else
321 {
322 // Note: this currently just gets the top-level dirty bit.
323 ASSERT(index < mArrayBufferObserverBindings.size());
324 return static_cast<DirtyBitType>(
325 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
326 }
327}
328
329void VertexArray::onSubjectStateChange(const gl::Context *context,
330 angle::SubjectIndex index,
331 angle::SubjectMessage message)
332{
333 bool contentsChanged = (message == angle::SubjectMessage::CONTENTS_CHANGED);
334 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
335 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
336 mDirtyBits.set(dirtyBit);
337 context->getGLState().setVertexArrayDirty(this);
338}
339
340void VertexArray::updateObserverBinding(size_t bindingIndex)
341{
342 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
343 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
344 : nullptr);
345}
346
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800347} // namespace gl