blob: 4afc361963c478db9fb52cb23fa47616c698de49 [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.
//
// 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)
: 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)
{
ASSERT(mVertexArray != nullptr);
}
VertexArray::~VertexArray()
{
SafeDelete(mVertexArray);
}
GLuint VertexArray::id() const
{
return mId;
}
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();
}
}
}