blob: a750c86e990c18b09b058cdbfaa078428ddba3ea [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
Jamie Madill51af38b2018-04-15 08:50:56 -040039bool VertexArrayState::hasEnabledNullPointerClientArray() const
40{
41 return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
42}
43
Jamie Madillbcef3222018-04-13 15:19:11 -040044// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080045VertexArray::VertexArray(rx::GLImplFactory *factory,
46 GLuint id,
47 size_t maxAttribs,
48 size_t maxAttribBindings)
49 : mId(id),
50 mState(maxAttribs, maxAttribBindings),
Jamie Madill09463932018-04-04 05:26:59 -040051 mVertexArray(factory->createVertexArray(mState)),
52 mElementArrayBufferObserverBinding(this, maxAttribBindings)
Jamie Madill8e344942015-07-09 14:22:07 -040053{
Jamie Madill09463932018-04-04 05:26:59 -040054 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
55 {
56 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
57 }
Jamie Madill004a6f92013-07-10 15:13:38 -040058}
59
Jamie Madill4928b7c2017-06-20 12:57:39 -040060void VertexArray::onDestroy(const Context *context)
61{
James Darpiniane8a93c62018-01-04 18:02:24 -080062 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -040063 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -040064 {
James Darpiniane8a93c62018-01-04 18:02:24 -080065 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -040066 }
James Darpiniane8a93c62018-01-04 18:02:24 -080067 if (isBound && mState.mElementArrayBuffer.get())
68 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -040069 mState.mElementArrayBuffer.set(context, nullptr);
70 mVertexArray->destroy(context);
71 SafeDelete(mVertexArray);
72 delete this;
73}
74
Jamie Madill004a6f92013-07-10 15:13:38 -040075VertexArray::~VertexArray()
76{
Jamie Madill4928b7c2017-06-20 12:57:39 -040077 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -040078}
79
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040080GLuint VertexArray::id() const
81{
82 return mId;
83}
84
Geoff Lang70d0f492015-12-10 17:45:46 -050085void VertexArray::setLabel(const std::string &label)
86{
Jamie Madill3f572682016-04-26 13:41:36 -040087 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -050088}
89
90const std::string &VertexArray::getLabel() const
91{
Jamie Madill3f572682016-04-26 13:41:36 -040092 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -050093}
94
Jamie Madill4928b7c2017-06-20 12:57:39 -040095void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040096{
James Darpiniane8a93c62018-01-04 18:02:24 -080097 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +080098 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -040099 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400101 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800102 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400103 }
104 }
105
Jamie Madill3f572682016-04-26 13:41:36 -0400106 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400107 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800108 if (isBound && mState.mElementArrayBuffer.get())
109 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::Array);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400110 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400111 }
112}
113
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800114const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400115{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800116 ASSERT(attribIndex < getMaxAttribs());
117 return mState.mVertexAttributes[attribIndex];
118}
119
120const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
121{
122 ASSERT(bindingIndex < getMaxBindings());
123 return mState.mVertexBindings[bindingIndex];
124}
125
Shaodde78e82017-05-22 14:13:27 +0800126size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800127{
128 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
129 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800130 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400131 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
132}
133
134void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
135{
136 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
137 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
138}
139
140void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
141{
142 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
143 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800144}
145
Shaodde78e82017-05-22 14:13:27 +0800146void VertexArray::bindVertexBufferImpl(const Context *context,
147 size_t bindingIndex,
148 Buffer *boundBuffer,
149 GLintptr offset,
150 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800151{
152 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800153 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800154
155 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
156
James Darpiniane8a93c62018-01-04 18:02:24 -0800157 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300158 binding->setOffset(offset);
159 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400160
161 updateObserverBinding(bindingIndex);
Jamie Madill02c9c042018-04-17 13:43:48 -0400162 updateCachedBufferBindingSize(bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800163}
164
165void VertexArray::bindVertexBuffer(const Context *context,
166 size_t bindingIndex,
167 Buffer *boundBuffer,
168 GLintptr offset,
169 GLsizei stride)
170{
171 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400172 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800173}
174
Shaodde78e82017-05-22 14:13:27 +0800175void VertexArray::setVertexAttribBinding(const Context *context,
176 size_t attribIndex,
177 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800178{
179 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
180
Shaodde78e82017-05-22 14:13:27 +0800181 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
182 {
183 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
184 ASSERT(context->getClientVersion() >= ES_3_1);
185 mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
186
Jamie Madille858cb12018-03-27 09:44:32 -0400187 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Shaodde78e82017-05-22 14:13:27 +0800188 }
Jamie Madille858cb12018-03-27 09:44:32 -0400189 mState.mVertexAttributes[attribIndex].bindingIndex = static_cast<GLuint>(bindingIndex);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800190}
191
192void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
193{
194 ASSERT(bindingIndex < getMaxBindings());
195
Martin Radevdd5f27e2017-06-07 10:17:09 +0300196 mState.mVertexBindings[bindingIndex].setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400197 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800198}
199
Shaodde78e82017-05-22 14:13:27 +0800200void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
201 GLint size,
202 GLenum type,
203 bool normalized,
204 bool pureInteger,
205 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800206{
207 ASSERT(attribIndex < getMaxAttribs());
208
209 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
210
211 attrib->size = size;
212 attrib->type = type;
213 attrib->normalized = normalized;
214 attrib->pureInteger = pureInteger;
215 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800216 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Jamie Madill02c9c042018-04-17 13:43:48 -0400217 attrib->updateCachedSizePlusRelativeOffset();
Shaodde78e82017-05-22 14:13:27 +0800218}
219
220void VertexArray::setVertexAttribFormat(size_t attribIndex,
221 GLint size,
222 GLenum type,
223 bool normalized,
224 bool pureInteger,
225 GLuint relativeOffset)
226{
227 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400228 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madill57a89722013-07-02 11:57:03 -0400229}
230
Shaodde78e82017-05-22 14:13:27 +0800231void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400232{
Shaodde78e82017-05-22 14:13:27 +0800233 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800234
Shaodde78e82017-05-22 14:13:27 +0800235 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
236 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400237}
238
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800239void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400240{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800241 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800242
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800243 mState.mVertexAttributes[attribIndex].enabled = enabledState;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800244 mState.mVertexAttributesTypeMask.setIndex(
245 GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800246
Jamie Madille858cb12018-03-27 09:44:32 -0400247 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400248
249 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500250 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madill57a89722013-07-02 11:57:03 -0400251}
252
Shaodde78e82017-05-22 14:13:27 +0800253void VertexArray::setVertexAttribPointer(const Context *context,
254 size_t attribIndex,
255 gl::Buffer *boundBuffer,
256 GLint size,
257 GLenum type,
258 bool normalized,
259 bool pureInteger,
260 GLsizei stride,
261 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400262{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800263 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400264
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800265 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400266
Shaodde78e82017-05-22 14:13:27 +0800267 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
268 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800269
270 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800271
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800272 GLsizei effectiveStride =
273 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
274 attrib.pointer = pointer;
275 attrib.vertexAttribArrayStride = stride;
276
Shaodde78e82017-05-22 14:13:27 +0800277 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800278
Jamie Madille858cb12018-03-27 09:44:32 -0400279 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400280
281 mState.mClientMemoryAttribsMask.set(attribIndex, boundBuffer == nullptr);
Jamie Madill51af38b2018-04-15 08:50:56 -0400282 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
283 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700284}
285
Jamie Madill4928b7c2017-06-20 12:57:39 -0400286void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700287{
James Darpiniane8a93c62018-01-04 18:02:24 -0800288 bool isBound = context->isCurrentVertexArray(this);
289 if (isBound && mState.mElementArrayBuffer.get())
290 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400291 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800292 if (isBound && mState.mElementArrayBuffer.get())
293 mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray);
Jamie Madill09463932018-04-04 05:26:59 -0400294 mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000295 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
296}
297
Frank Henigman0af5b862018-03-27 20:19:33 -0400298gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000299{
300 if (mDirtyBits.any())
301 {
Jamie Madill09463932018-04-04 05:26:59 -0400302 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400303 ANGLE_TRY(
304 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000305 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400306 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400307
308 // This is a bit of an implementation hack - but since we know the implementation
309 // details of the dirty bit class it should always have the same effect as iterating
310 // individual attribs. We could also look into schemes where iterating the dirty
311 // bit set also resets it as you pass through it.
312 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
313 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000314 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400315 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400316}
317
James Darpiniane8a93c62018-01-04 18:02:24 -0800318void VertexArray::onBindingChanged(bool bound)
319{
320 if (mState.mElementArrayBuffer.get())
321 mState.mElementArrayBuffer->onBindingChanged(bound, BufferBinding::ElementArray);
322 for (auto &binding : mState.mVertexBindings)
323 {
324 binding.onContainerBindingChanged(bound);
325 }
326}
327
Jamie Madill09463932018-04-04 05:26:59 -0400328VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
329 angle::SubjectIndex index) const
330{
331 if (index == mArrayBufferObserverBindings.size())
332 {
333 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
334 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
335 }
336 else
337 {
338 // Note: this currently just gets the top-level dirty bit.
339 ASSERT(index < mArrayBufferObserverBindings.size());
340 return static_cast<DirtyBitType>(
341 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
342 }
343}
344
345void VertexArray::onSubjectStateChange(const gl::Context *context,
346 angle::SubjectIndex index,
347 angle::SubjectMessage message)
348{
349 bool contentsChanged = (message == angle::SubjectMessage::CONTENTS_CHANGED);
350 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
351 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
352 mDirtyBits.set(dirtyBit);
353 context->getGLState().setVertexArrayDirty(this);
Jamie Madill02c9c042018-04-17 13:43:48 -0400354
355 if (message == angle::SubjectMessage::STORAGE_CHANGED &&
356 index < mArrayBufferObserverBindings.size())
357 {
358 updateCachedBufferBindingSize(index);
359 }
Jamie Madill09463932018-04-04 05:26:59 -0400360}
361
362void VertexArray::updateObserverBinding(size_t bindingIndex)
363{
364 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
365 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
366 : nullptr);
367}
368
Jamie Madill02c9c042018-04-17 13:43:48 -0400369void VertexArray::updateCachedVertexAttributeSize(size_t attribIndex)
370{
371 mState.mVertexAttributes[attribIndex].updateCachedSizePlusRelativeOffset();
372}
373
374void VertexArray::updateCachedBufferBindingSize(size_t bindingIndex)
375{
376 mState.mVertexBindings[bindingIndex].updateCachedBufferSizeMinusOffset();
377}
378
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800379} // namespace gl