blob: 19fedeeb534b1734720546548d94349a457964fc [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);
Jamie Madille858cb12018-03-27 09:44:32 -0400114 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
115}
116
117void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
118{
119 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
120 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
121}
122
123void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
124{
125 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
126 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800127}
128
Shaodde78e82017-05-22 14:13:27 +0800129void VertexArray::bindVertexBufferImpl(const Context *context,
130 size_t bindingIndex,
131 Buffer *boundBuffer,
132 GLintptr offset,
133 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800134{
135 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800136 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800137
138 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
139
James Darpiniane8a93c62018-01-04 18:02:24 -0800140 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300141 binding->setOffset(offset);
142 binding->setStride(stride);
Shaodde78e82017-05-22 14:13:27 +0800143}
144
145void VertexArray::bindVertexBuffer(const Context *context,
146 size_t bindingIndex,
147 Buffer *boundBuffer,
148 GLintptr offset,
149 GLsizei stride)
150{
151 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400152 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800153}
154
Shaodde78e82017-05-22 14:13:27 +0800155void VertexArray::setVertexAttribBinding(const Context *context,
156 size_t attribIndex,
157 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800158{
159 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
160
Shaodde78e82017-05-22 14:13:27 +0800161 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
162 {
163 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
164 ASSERT(context->getClientVersion() >= ES_3_1);
165 mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
166
Jamie Madille858cb12018-03-27 09:44:32 -0400167 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Shaodde78e82017-05-22 14:13:27 +0800168 }
Jamie Madille858cb12018-03-27 09:44:32 -0400169 mState.mVertexAttributes[attribIndex].bindingIndex = static_cast<GLuint>(bindingIndex);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800170}
171
172void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
173{
174 ASSERT(bindingIndex < getMaxBindings());
175
Martin Radevdd5f27e2017-06-07 10:17:09 +0300176 mState.mVertexBindings[bindingIndex].setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400177 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800178}
179
Shaodde78e82017-05-22 14:13:27 +0800180void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
181 GLint size,
182 GLenum type,
183 bool normalized,
184 bool pureInteger,
185 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800186{
187 ASSERT(attribIndex < getMaxAttribs());
188
189 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
190
191 attrib->size = size;
192 attrib->type = type;
193 attrib->normalized = normalized;
194 attrib->pureInteger = pureInteger;
195 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800196 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
197 mState.mEnabledAttributesMask.set(attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800198}
199
200void VertexArray::setVertexAttribFormat(size_t attribIndex,
201 GLint size,
202 GLenum type,
203 bool normalized,
204 bool pureInteger,
205 GLuint relativeOffset)
206{
207 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400208 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madill57a89722013-07-02 11:57:03 -0400209}
210
Shaodde78e82017-05-22 14:13:27 +0800211void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400212{
Shaodde78e82017-05-22 14:13:27 +0800213 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800214
Shaodde78e82017-05-22 14:13:27 +0800215 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
216 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400217}
218
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800219void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400220{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800221 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800222
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800223 mState.mVertexAttributes[attribIndex].enabled = enabledState;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800224 mState.mVertexAttributesTypeMask.setIndex(
225 GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800226
Jamie Madille858cb12018-03-27 09:44:32 -0400227 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400228
229 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500230 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madill57a89722013-07-02 11:57:03 -0400231}
232
Shaodde78e82017-05-22 14:13:27 +0800233void VertexArray::setVertexAttribPointer(const Context *context,
234 size_t attribIndex,
235 gl::Buffer *boundBuffer,
236 GLint size,
237 GLenum type,
238 bool normalized,
239 bool pureInteger,
240 GLsizei stride,
241 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400242{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800243 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400244
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800245 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400246
Shaodde78e82017-05-22 14:13:27 +0800247 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
248 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800249
250 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800251
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800252 GLsizei effectiveStride =
253 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
254 attrib.pointer = pointer;
255 attrib.vertexAttribArrayStride = stride;
256
Shaodde78e82017-05-22 14:13:27 +0800257 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800258
Jamie Madille858cb12018-03-27 09:44:32 -0400259 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Brandon Jones5bf98292014-06-06 17:19:38 -0700260}
261
Jamie Madill4928b7c2017-06-20 12:57:39 -0400262void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700263{
James Darpiniane8a93c62018-01-04 18:02:24 -0800264 bool isBound = context->isCurrentVertexArray(this);
265 if (isBound && mState.mElementArrayBuffer.get())
266 mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400267 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800268 if (isBound && mState.mElementArrayBuffer.get())
269 mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000270 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
271}
272
Frank Henigman0af5b862018-03-27 20:19:33 -0400273gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000274{
275 if (mDirtyBits.any())
276 {
Frank Henigman0af5b862018-03-27 20:19:33 -0400277 ANGLE_TRY(
278 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000279 mDirtyBits.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400280
281 // This is a bit of an implementation hack - but since we know the implementation
282 // details of the dirty bit class it should always have the same effect as iterating
283 // individual attribs. We could also look into schemes where iterating the dirty
284 // bit set also resets it as you pass through it.
285 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
286 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000287 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400288 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400289}
290
James Darpiniane8a93c62018-01-04 18:02:24 -0800291void VertexArray::onBindingChanged(bool bound)
292{
293 if (mState.mElementArrayBuffer.get())
294 mState.mElementArrayBuffer->onBindingChanged(bound, BufferBinding::ElementArray);
295 for (auto &binding : mState.mVertexBindings)
296 {
297 binding.onContainerBindingChanged(bound);
298 }
299}
300
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800301} // namespace gl