blob: d738065dbb52a553c663531d1a4c6fc8dcbafbd4 [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 Madill7aea7e02016-05-10 10:39:45 -040012#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/renderer/VertexArrayImpl.h"
Jamie Madill57a89722013-07-02 11:57:03 -040014
15namespace gl
16{
17
Jiawei-Shao2597fb62016-12-09 16:38:02 +080018VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
Jamie Madilld078c682018-01-02 11:50:24 -050019 : mLabel(), mVertexBindings(maxAttribBindings)
Jamie Madill57a89722013-07-02 11:57:03 -040020{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080021 ASSERT(maxAttribs <= maxAttribBindings);
22
23 for (size_t i = 0; i < maxAttribs; i++)
24 {
25 mVertexAttributes.emplace_back(static_cast<GLuint>(i));
26 }
Jamie Madill8e344942015-07-09 14:22:07 -040027}
28
Jamie Madill3f572682016-04-26 13:41:36 -040029VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040030{
Jamie Madill8e344942015-07-09 14:22:07 -040031}
32
Jiawei-Shao2597fb62016-12-09 16:38:02 +080033VertexArray::VertexArray(rx::GLImplFactory *factory,
34 GLuint id,
35 size_t maxAttribs,
36 size_t maxAttribBindings)
37 : mId(id),
38 mState(maxAttribs, maxAttribBindings),
39 mVertexArray(factory->createVertexArray(mState))
Jamie Madill8e344942015-07-09 14:22:07 -040040{
Jamie Madill004a6f92013-07-10 15:13:38 -040041}
42
Jamie Madill4928b7c2017-06-20 12:57:39 -040043void VertexArray::onDestroy(const Context *context)
44{
James Darpiniane8a93c62018-01-04 18:02:24 -080045 bool isBound = context->isCurrentVertexArray(this);
Jamie Madill4928b7c2017-06-20 12:57:39 -040046 for (auto &binding : mState.mVertexBindings)
47 {
James Darpiniane8a93c62018-01-04 18:02:24 -080048 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -040049 }
James Darpiniane8a93c62018-01-04 18:02:24 -080050 if (isBound && mState.mElementArrayBuffer.get())
51 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -040052 mState.mElementArrayBuffer.set(context, nullptr);
53 mVertexArray->destroy(context);
54 SafeDelete(mVertexArray);
55 delete this;
56}
57
Jamie Madill004a6f92013-07-10 15:13:38 -040058VertexArray::~VertexArray()
59{
Jamie Madill4928b7c2017-06-20 12:57:39 -040060 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -040061}
62
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040063GLuint VertexArray::id() const
64{
65 return mId;
66}
67
Geoff Lang70d0f492015-12-10 17:45:46 -050068void VertexArray::setLabel(const std::string &label)
69{
Jamie Madill3f572682016-04-26 13:41:36 -040070 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -050071}
72
73const std::string &VertexArray::getLabel() const
74{
Jamie Madill3f572682016-04-26 13:41:36 -040075 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -050076}
77
Jamie Madill4928b7c2017-06-20 12:57:39 -040078void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040079{
James Darpiniane8a93c62018-01-04 18:02:24 -080080 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +080081 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -040082 {
Martin Radevdd5f27e2017-06-07 10:17:09 +030083 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040084 {
James Darpiniane8a93c62018-01-04 18:02:24 -080085 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -040086 }
87 }
88
Jamie Madill3f572682016-04-26 13:41:36 -040089 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -040090 {
James Darpiniane8a93c62018-01-04 18:02:24 -080091 if (isBound && mState.mElementArrayBuffer.get())
92 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::Array);
Jamie Madill4928b7c2017-06-20 12:57:39 -040093 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -040094 }
95}
96
Jiawei-Shao2597fb62016-12-09 16:38:02 +080097const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -040098{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080099 ASSERT(attribIndex < getMaxAttribs());
100 return mState.mVertexAttributes[attribIndex];
101}
102
103const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
104{
105 ASSERT(bindingIndex < getMaxBindings());
106 return mState.mVertexBindings[bindingIndex];
107}
108
Shaodde78e82017-05-22 14:13:27 +0800109size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800110{
111 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
112 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800113 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
114 return (dirtyBit - DIRTY_BIT_ATTRIB_0_ENABLED) % gl::MAX_VERTEX_ATTRIBS;
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800115}
116
Shaodde78e82017-05-22 14:13:27 +0800117void VertexArray::bindVertexBufferImpl(const Context *context,
118 size_t bindingIndex,
119 Buffer *boundBuffer,
120 GLintptr offset,
121 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122{
123 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800124 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800125
126 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
127
James Darpiniane8a93c62018-01-04 18:02:24 -0800128 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300129 binding->setOffset(offset);
130 binding->setStride(stride);
Shaodde78e82017-05-22 14:13:27 +0800131}
132
133void VertexArray::bindVertexBuffer(const Context *context,
134 size_t bindingIndex,
135 Buffer *boundBuffer,
136 GLintptr offset,
137 GLsizei stride)
138{
139 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
140
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800141 mDirtyBits.set(DIRTY_BIT_BINDING_0_BUFFER + bindingIndex);
142}
143
Shaodde78e82017-05-22 14:13:27 +0800144void VertexArray::setVertexAttribBinding(const Context *context,
145 size_t attribIndex,
146 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800147{
148 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
149
Shaodde78e82017-05-22 14:13:27 +0800150 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
151 {
152 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
153 ASSERT(context->getClientVersion() >= ES_3_1);
154 mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
155
156 mDirtyBits.set(DIRTY_BIT_ATTRIB_0_BINDING + attribIndex);
157 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800158}
159
160void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
161{
162 ASSERT(bindingIndex < getMaxBindings());
163
Martin Radevdd5f27e2017-06-07 10:17:09 +0300164 mState.mVertexBindings[bindingIndex].setDivisor(divisor);
Shaodde78e82017-05-22 14:13:27 +0800165
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800166 mDirtyBits.set(DIRTY_BIT_BINDING_0_DIVISOR + bindingIndex);
167}
168
Shaodde78e82017-05-22 14:13:27 +0800169void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
170 GLint size,
171 GLenum type,
172 bool normalized,
173 bool pureInteger,
174 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800175{
176 ASSERT(attribIndex < getMaxAttribs());
177
178 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
179
180 attrib->size = size;
181 attrib->type = type;
182 attrib->normalized = normalized;
183 attrib->pureInteger = pureInteger;
184 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800185 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
186 mState.mEnabledAttributesMask.set(attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800187}
188
189void VertexArray::setVertexAttribFormat(size_t attribIndex,
190 GLint size,
191 GLenum type,
192 bool normalized,
193 bool pureInteger,
194 GLuint relativeOffset)
195{
196 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
197
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800198 mDirtyBits.set(DIRTY_BIT_ATTRIB_0_FORMAT + attribIndex);
Jamie Madill57a89722013-07-02 11:57:03 -0400199}
200
Shaodde78e82017-05-22 14:13:27 +0800201void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400202{
Shaodde78e82017-05-22 14:13:27 +0800203 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800204
Shaodde78e82017-05-22 14:13:27 +0800205 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
206 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400207}
208
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800209void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400210{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800211 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800212
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800213 mState.mVertexAttributes[attribIndex].enabled = enabledState;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800214 mState.mVertexAttributesTypeMask.setIndex(
215 GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800216
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800217 mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attribIndex);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400218
219 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500220 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madill57a89722013-07-02 11:57:03 -0400221}
222
Shaodde78e82017-05-22 14:13:27 +0800223void VertexArray::setVertexAttribPointer(const Context *context,
224 size_t attribIndex,
225 gl::Buffer *boundBuffer,
226 GLint size,
227 GLenum type,
228 bool normalized,
229 bool pureInteger,
230 GLsizei stride,
231 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400232{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800233 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400234
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800235 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400236
Shaodde78e82017-05-22 14:13:27 +0800237 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
238 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800239
240 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800241
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800242 GLsizei effectiveStride =
243 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
244 attrib.pointer = pointer;
245 attrib.vertexAttribArrayStride = stride;
246
Shaodde78e82017-05-22 14:13:27 +0800247 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800248
249 mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attribIndex);
Brandon Jones5bf98292014-06-06 17:19:38 -0700250}
251
Jamie Madill4928b7c2017-06-20 12:57:39 -0400252void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700253{
James Darpiniane8a93c62018-01-04 18:02:24 -0800254 bool isBound = context->isCurrentVertexArray(this);
255 if (isBound && mState.mElementArrayBuffer.get())
256 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400257 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800258 if (isBound && mState.mElementArrayBuffer.get())
259 mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000260 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
261}
262
Jamie Madill06ef36b2017-09-09 23:32:46 -0400263void VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000264{
265 if (mDirtyBits.any())
266 {
Jamie Madillc564c072017-06-01 12:45:42 -0400267 mVertexArray->syncState(context, mDirtyBits);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000268 mDirtyBits.reset();
269 }
Jamie Madill57a89722013-07-02 11:57:03 -0400270}
271
James Darpiniane8a93c62018-01-04 18:02:24 -0800272void VertexArray::onBindingChanged(bool bound)
273{
274 if (mState.mElementArrayBuffer.get())
275 mState.mElementArrayBuffer->onBindingChanged(bound, BufferBinding::ElementArray);
276 for (auto &binding : mState.mVertexBindings)
277 {
278 binding.onContainerBindingChanged(bound);
279 }
280}
281
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800282} // namespace gl