// // 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. // // Implementation of the state class for mananging GLES 3 Vertex Array Objects. // #include "libANGLE/VertexArray.h" #include "libANGLE/Buffer.h" #include "libANGLE/renderer/ImplFactory.h" #include "libANGLE/renderer/VertexArrayImpl.h" namespace gl { VertexArray::Data::Data(size_t maxAttribs) : mLabel(), mVertexAttributes(maxAttribs), mMaxEnabledAttribute(0) { } VertexArray::Data::~Data() { for (size_t i = 0; i < getMaxAttribs(); i++) { mVertexAttributes[i].buffer.set(nullptr); } mElementArrayBuffer.set(nullptr); } VertexArray::VertexArray(rx::ImplFactory *factory, GLuint id, size_t maxAttribs) : mId(id), mVertexArray(factory->createVertexArray(mData)), mData(maxAttribs) { } VertexArray::~VertexArray() { SafeDelete(mVertexArray); } GLuint VertexArray::id() const { return mId; } void VertexArray::setLabel(const std::string &label) { mData.mLabel = label; } const std::string &VertexArray::getLabel() const { return mData.mLabel; } void VertexArray::detachBuffer(GLuint bufferName) { for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++) { if (mData.mVertexAttributes[attribute].buffer.id() == bufferName) { mData.mVertexAttributes[attribute].buffer.set(nullptr); } } if (mData.mElementArrayBuffer.id() == bufferName) { mData.mElementArrayBuffer.set(nullptr); } } const VertexAttribute &VertexArray::getVertexAttribute(size_t attributeIndex) const { ASSERT(attributeIndex < getMaxAttribs()); return mData.mVertexAttributes[attributeIndex]; } void VertexArray::setVertexAttribDivisor(size_t index, GLuint divisor) { ASSERT(index < getMaxAttribs()); mData.mVertexAttributes[index].divisor = divisor; mDirtyBits.set(DIRTY_BIT_ATTRIB_0_DIVISOR + index); } void VertexArray::enableAttribute(size_t attributeIndex, bool enabledState) { ASSERT(attributeIndex < getMaxAttribs()); mData.mVertexAttributes[attributeIndex].enabled = enabledState; mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attributeIndex); // Update state cache if (enabledState) { mData.mMaxEnabledAttribute = std::max(attributeIndex + 1, mData.mMaxEnabledAttribute); } else if (mData.mMaxEnabledAttribute == attributeIndex + 1) { while (mData.mMaxEnabledAttribute > 0 && !mData.mVertexAttributes[mData.mMaxEnabledAttribute - 1].enabled) { --mData.mMaxEnabledAttribute; } } } void VertexArray::setAttributeState(size_t attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer) { ASSERT(attributeIndex < getMaxAttribs()); VertexAttribute *attrib = &mData.mVertexAttributes[attributeIndex]; attrib->buffer.set(boundBuffer); attrib->size = size; attrib->type = type; attrib->normalized = normalized; attrib->pureInteger = pureInteger; attrib->stride = stride; attrib->pointer = pointer; mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attributeIndex); } void VertexArray::setElementArrayBuffer(Buffer *buffer) { mData.mElementArrayBuffer.set(buffer); mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER); } void VertexArray::syncImplState() { if (mDirtyBits.any()) { mVertexArray->syncState(mDirtyBits); mDirtyBits.reset(); } } }