| // | |
| // 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/GLImplFactory.h" | |
| #include "libANGLE/renderer/VertexArrayImpl.h" | |
| namespace gl | |
| { | |
| VertexArrayState::VertexArrayState(size_t maxAttribs) | |
| : mLabel(), mVertexAttributes(maxAttribs), mMaxEnabledAttribute(0) | |
| { | |
| } | |
| VertexArrayState::~VertexArrayState() | |
| { | |
| for (size_t i = 0; i < getMaxAttribs(); i++) | |
| { | |
| mVertexAttributes[i].buffer.set(nullptr); | |
| } | |
| mElementArrayBuffer.set(nullptr); | |
| } | |
| VertexArray::VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs) | |
| : mId(id), mState(maxAttribs), mVertexArray(factory->createVertexArray(mState)) | |
| { | |
| } | |
| VertexArray::~VertexArray() | |
| { | |
| SafeDelete(mVertexArray); | |
| } | |
| GLuint VertexArray::id() const | |
| { | |
| return mId; | |
| } | |
| void VertexArray::setLabel(const std::string &label) | |
| { | |
| mState.mLabel = label; | |
| } | |
| const std::string &VertexArray::getLabel() const | |
| { | |
| return mState.mLabel; | |
| } | |
| void VertexArray::detachBuffer(GLuint bufferName) | |
| { | |
| for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++) | |
| { | |
| if (mState.mVertexAttributes[attribute].buffer.id() == bufferName) | |
| { | |
| mState.mVertexAttributes[attribute].buffer.set(nullptr); | |
| } | |
| } | |
| if (mState.mElementArrayBuffer.id() == bufferName) | |
| { | |
| mState.mElementArrayBuffer.set(nullptr); | |
| } | |
| } | |
| const VertexAttribute &VertexArray::getVertexAttribute(size_t attributeIndex) const | |
| { | |
| ASSERT(attributeIndex < getMaxAttribs()); | |
| return mState.mVertexAttributes[attributeIndex]; | |
| } | |
| void VertexArray::setVertexAttribDivisor(size_t index, GLuint divisor) | |
| { | |
| ASSERT(index < getMaxAttribs()); | |
| mState.mVertexAttributes[index].divisor = divisor; | |
| mDirtyBits.set(DIRTY_BIT_ATTRIB_0_DIVISOR + index); | |
| } | |
| void VertexArray::enableAttribute(size_t attributeIndex, bool enabledState) | |
| { | |
| ASSERT(attributeIndex < getMaxAttribs()); | |
| mState.mVertexAttributes[attributeIndex].enabled = enabledState; | |
| mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attributeIndex); | |
| // Update state cache | |
| if (enabledState) | |
| { | |
| mState.mMaxEnabledAttribute = std::max(attributeIndex + 1, mState.mMaxEnabledAttribute); | |
| } | |
| else if (mState.mMaxEnabledAttribute == attributeIndex + 1) | |
| { | |
| while (mState.mMaxEnabledAttribute > 0 && | |
| !mState.mVertexAttributes[mState.mMaxEnabledAttribute - 1].enabled) | |
| { | |
| --mState.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 = &mState.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) | |
| { | |
| mState.mElementArrayBuffer.set(buffer); | |
| mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER); | |
| } | |
| void VertexArray::syncImplState() | |
| { | |
| if (mDirtyBits.any()) | |
| { | |
| mVertexArray->syncState(mDirtyBits); | |
| mDirtyBits.reset(); | |
| } | |
| } | |
| } |