diff -r 000000000000 -r 6474c204b198 gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/angle/src/libGLESv2/renderer/VertexBuffer.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,292 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 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. +// + +// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Context.h" + +namespace rx +{ + +unsigned int VertexBuffer::mNextSerial = 1; + +VertexBuffer::VertexBuffer() +{ + updateSerial(); +} + +VertexBuffer::~VertexBuffer() +{ +} + +void VertexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + +unsigned int VertexBuffer::getSerial() const +{ + return mSerial; +} + +VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer) +{ + mDynamic = dynamic; + mWritePosition = 0; + mReservedSpace = 0; + + mVertexBuffer = renderer->createVertexBuffer(); +} + +VertexBufferInterface::~VertexBufferInterface() +{ + delete mVertexBuffer; +} + +unsigned int VertexBufferInterface::getSerial() const +{ + return mVertexBuffer->getSerial(); +} + +unsigned int VertexBufferInterface::getBufferSize() const +{ + return mVertexBuffer->getBufferSize(); +} + +bool VertexBufferInterface::setBufferSize(unsigned int size) +{ + if (mVertexBuffer->getBufferSize() == 0) + { + return mVertexBuffer->initialize(size, mDynamic); + } + else + { + return mVertexBuffer->setBufferSize(size); + } +} + +unsigned int VertexBufferInterface::getWritePosition() const +{ + return mWritePosition; +} + +void VertexBufferInterface::setWritePosition(unsigned int writePosition) +{ + mWritePosition = writePosition; +} + +bool VertexBufferInterface::discard() +{ + return mVertexBuffer->discard(); +} + +bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset) +{ + unsigned int spaceRequired; + if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired)) + { + return false; + } + + if (mWritePosition + spaceRequired < mWritePosition) + { + return false; + } + + if (!reserveSpace(mReservedSpace)) + { + return false; + } + mReservedSpace = 0; + + if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition)) + { + return false; + } + + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } + + mWritePosition += spaceRequired; + + return true; +} + +bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset) +{ + if (mWritePosition + size < mWritePosition) + { + return false; + } + + if (!reserveSpace(mReservedSpace)) + { + return false; + } + mReservedSpace = 0; + + if (!mVertexBuffer->storeRawData(data, size, mWritePosition)) + { + return false; + } + + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } + + mWritePosition += size; + + return true; +} + +bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) +{ + unsigned int requiredSpace; + if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace)) + { + return false; + } + + // Protect against integer overflow + if (mReservedSpace + requiredSpace < mReservedSpace) + { + return false; + } + + mReservedSpace += requiredSpace; + return true; +} + +bool VertexBufferInterface::reserveRawDataSpace(unsigned int size) +{ + // Protect against integer overflow + if (mReservedSpace + size < mReservedSpace) + { + return false; + } + + mReservedSpace += size; + return true; +} + +VertexBuffer* VertexBufferInterface::getVertexBuffer() const +{ + return mVertexBuffer; +} + + +StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) +{ + setBufferSize(initialSize); +} + +StreamingVertexBufferInterface::~StreamingVertexBufferInterface() +{ +} + +bool StreamingVertexBufferInterface::reserveSpace(unsigned int size) +{ + bool result = true; + unsigned int curBufferSize = getBufferSize(); + if (size > curBufferSize) + { + result = setBufferSize(std::max(size, 3 * curBufferSize / 2)); + setWritePosition(0); + } + else if (getWritePosition() + size > curBufferSize) + { + if (!discard()) + { + return false; + } + setWritePosition(0); + } + + return result; +} + +StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) +{ +} + +StaticVertexBufferInterface::~StaticVertexBufferInterface() +{ +} + +bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset) +{ + for (unsigned int element = 0; element < mCache.size(); element++) + { + if (mCache[element].type == attribute.mType && + mCache[element].size == attribute.mSize && + mCache[element].stride == attribute.stride() && + mCache[element].normalized == attribute.mNormalized) + { + if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) + { + if (outStreamOffset) + { + *outStreamOffset = mCache[element].streamOffset; + } + return true; + } + } + } + + return false; +} + +bool StaticVertexBufferInterface::reserveSpace(unsigned int size) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + setBufferSize(size); + return true; + } + else if (curSize >= size) + { + return true; + } + else + { + UNREACHABLE(); // Static vertex buffers can't be resized + return false; + } +} + +bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset) +{ + unsigned int streamOffset; + if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset)) + { + int attributeOffset = attrib.mOffset % attrib.stride(); + VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset }; + mCache.push_back(element); + + if (outStreamOffset) + { + *outStreamOffset = streamOffset; + } + + return true; + } + else + { + return false; + } +} + +}