blob: c5d57881e8ba5e47a9c8a52b8ba4c0c95aee2202 [file] [log] [blame]
//
// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This class contains prototypes for representing GLES 3 Vertex Array Objects:
//
// The buffer objects that are to be used by the vertex stage of the GL are collected
// together to form a vertex array object. All state related to the definition of data used
// by the vertex processor is encapsulated in a vertex array object.
//
#ifndef LIBANGLE_VERTEXARRAY_H_
#define LIBANGLE_VERTEXARRAY_H_
#include "libANGLE/Constants.h"
#include "libANGLE/Debug.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/State.h"
#include "libANGLE/VertexAttribute.h"
#include <vector>
namespace rx
{
class GLImplFactory;
class VertexArrayImpl;
} // namespace rx
namespace gl
{
class Buffer;
class VertexArrayState final : angle::NonCopyable
{
public:
VertexArrayState(size_t maxAttribs, size_t maxBindings);
~VertexArrayState();
const std::string &getLabel() const { return mLabel; }
const BindingPointer<Buffer> &getElementArrayBuffer() const { return mElementArrayBuffer; }
size_t getMaxAttribs() const { return mVertexAttributes.size(); }
size_t getMaxBindings() const { return mVertexBindings.size(); }
const AttributesMask &getEnabledAttributesMask() const { return mEnabledAttributesMask; }
const std::vector<VertexAttribute> &getVertexAttributes() const { return mVertexAttributes; }
const VertexAttribute &getVertexAttribute(size_t attribIndex) const
{
return mVertexAttributes[attribIndex];
}
const std::vector<VertexBinding> &getVertexBindings() const { return mVertexBindings; }
const VertexBinding &getVertexBinding(size_t bindingIndex) const
{
return mVertexBindings[bindingIndex];
}
const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
{
return mVertexBindings[mVertexAttributes[attribIndex].bindingIndex];
}
size_t getBindingIndexFromAttribIndex(size_t attribIndex) const
{
return mVertexAttributes[attribIndex].bindingIndex;
}
private:
friend class VertexArray;
std::string mLabel;
std::vector<VertexAttribute> mVertexAttributes;
BindingPointer<Buffer> mElementArrayBuffer;
std::vector<VertexBinding> mVertexBindings;
AttributesMask mEnabledAttributesMask;
ComponentTypeMask mVertexAttributesTypeMask;
};
class VertexArray final : public LabeledObject
{
public:
VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs, size_t maxAttribBindings);
void onDestroy(const Context *context);
GLuint id() const;
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
const VertexBinding &getVertexBinding(size_t bindingIndex) const;
const VertexAttribute &getVertexAttribute(size_t attribIndex) const;
const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
{
return mState.getBindingFromAttribIndex(attribIndex);
}
void detachBuffer(const Context *context, GLuint bufferName);
void setVertexAttribDivisor(const Context *context, size_t index, GLuint divisor);
void enableAttribute(size_t attribIndex, bool enabledState);
void setVertexAttribPointer(const Context *context,
size_t attribIndex,
Buffer *boundBuffer,
GLint size,
GLenum type,
bool normalized,
bool pureInteger,
GLsizei stride,
const void *pointer);
void setVertexAttribFormat(size_t attribIndex,
GLint size,
GLenum type,
bool normalized,
bool pureInteger,
GLuint relativeOffset);
void bindVertexBuffer(const Context *context,
size_t bindingIndex,
Buffer *boundBuffer,
GLintptr offset,
GLsizei stride);
void setVertexAttribBinding(const Context *context, size_t attribIndex, GLuint bindingIndex);
void setVertexBindingDivisor(size_t bindingIndex, GLuint divisor);
void setVertexAttribFormatImpl(size_t attribIndex,
GLint size,
GLenum type,
bool normalized,
bool pureInteger,
GLuint relativeOffset);
void bindVertexBufferImpl(const Context *context,
size_t bindingIndex,
Buffer *boundBuffer,
GLintptr offset,
GLsizei stride);
void setElementArrayBuffer(const Context *context, Buffer *buffer);
const BindingPointer<Buffer> &getElementArrayBuffer() const
{
return mState.getElementArrayBuffer();
}
size_t getMaxAttribs() const { return mState.getMaxAttribs(); }
size_t getMaxBindings() const { return mState.getMaxBindings(); }
const std::vector<VertexAttribute> &getVertexAttributes() const
{
return mState.getVertexAttributes();
}
const std::vector<VertexBinding> &getVertexBindings() const
{
return mState.getVertexBindings();
}
rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
const AttributesMask &getEnabledAttributesMask() const
{
return mState.getEnabledAttributesMask();
}
// Dirty bits for VertexArrays use a heirarchical design. At the top level, each attribute
// has a single dirty bit. Then an array of MAX_ATTRIBS dirty bits each has a dirty bit for
// enabled/pointer/format/binding. Bindings are handled similarly. Note that because the
// total number of dirty bits is 33, it will not be as fast on a 32-bit machine, which
// can't support the advanced 64-bit scanning intrinsics. We could consider packing the
// binding and attribute bits together if this becomes a problem.
enum DirtyBitType
{
DIRTY_BIT_ELEMENT_ARRAY_BUFFER,
// Dirty bits for attributes.
DIRTY_BIT_ATTRIB_0,
DIRTY_BIT_ATTRIB_MAX = DIRTY_BIT_ATTRIB_0 + gl::MAX_VERTEX_ATTRIBS,
// Dirty bits for bindings.
DIRTY_BIT_BINDING_0 = DIRTY_BIT_ATTRIB_MAX,
DIRTY_BIT_BINDING_MAX = DIRTY_BIT_BINDING_0 + gl::MAX_VERTEX_ATTRIB_BINDINGS,
DIRTY_BIT_UNKNOWN = DIRTY_BIT_BINDING_MAX,
DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
};
// We want to keep the number of dirty bits within 64 to keep iteration times fast.
static_assert(DIRTY_BIT_MAX <= 64, "Too many vertex array dirty bits.");
enum DirtyAttribBitType
{
DIRTY_ATTRIB_ENABLED,
DIRTY_ATTRIB_POINTER,
DIRTY_ATTRIB_FORMAT,
DIRTY_ATTRIB_BINDING,
DIRTY_ATTRIB_UNKNOWN,
DIRTY_ATTRIB_MAX = DIRTY_ATTRIB_UNKNOWN,
};
enum DirtyBindingBitType
{
DIRTY_BINDING_BUFFER,
DIRTY_BINDING_DIVISOR,
DIRTY_BINDING_UNKNOWN,
DIRTY_BINDING_MAX = DIRTY_BINDING_UNKNOWN,
};
using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
using DirtyAttribBits = angle::BitSet<DIRTY_ATTRIB_MAX>;
using DirtyBindingBits = angle::BitSet<DIRTY_BINDING_MAX>;
using DirtyAttribBitsArray = std::array<DirtyAttribBits, gl::MAX_VERTEX_ATTRIBS>;
using DirtyBindingBitsArray = std::array<DirtyBindingBits, gl::MAX_VERTEX_ATTRIB_BINDINGS>;
static size_t GetVertexIndexFromDirtyBit(size_t dirtyBit);
void syncState(const Context *context);
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
ComponentTypeMask getAttributesTypeMask() const { return mState.mVertexAttributesTypeMask; }
AttributesMask getAttributesMask() const { return mState.mEnabledAttributesMask; }
void onBindingChanged(bool bound);
private:
~VertexArray() override;
void setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit);
void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit);
GLuint mId;
VertexArrayState mState;
DirtyBits mDirtyBits;
DirtyAttribBitsArray mDirtyAttribBits;
DirtyBindingBitsArray mDirtyBindingBits;
rx::VertexArrayImpl *mVertexArray;
};
} // namespace gl
#endif // LIBANGLE_VERTEXARRAY_H_