Merge branch 'master' of ssh://ka.blankertz.org/home/matthias/git/openglplayground

This commit is contained in:
2015-02-13 16:01:07 +01:00
19 changed files with 955 additions and 471 deletions

146
VBOManager.cc Normal file
View File

@@ -0,0 +1,146 @@
#include <glbinding/gl/gl.h>
#include <cassert>
#include "VBOManager.hh"
using namespace gl;
VBOManager::VBOManager()
{
}
VBOManager::~VBOManager()
{
}
VBOManager::VBOAlloc::~VBOAlloc()
{
if(_vbo)
_vbo->free(*this);
_vbo = nullptr;
}
VBOManager::VBOAlloc::VBOAlloc(VBOAlloc&& move)
: _vbo(move._vbo), _ofs(move._ofs), _size(move._size)
{
move._vbo = nullptr;
}
VBOManager::VBOAlloc& VBOManager::VBOAlloc::operator=(VBOAlloc&& move)
{
_vbo = move._vbo;
_ofs = move._ofs;
_size = move._size;
move._vbo = nullptr;
return *this;
}
VBOManager::VBOAlloc::VBOAlloc()
: _vbo(nullptr), _ofs(0), _size(0)
{
}
VBOManager::VBOAlloc::VBOAlloc(VBO &vbo, size_t ofs, size_t size)
: _vbo(&vbo), _ofs(ofs), _size(size)
{
}
VBOManager::VBOAlloc VBOManager::alloc(size_t size, GLenum type)
{
for(auto& vbo : _vbos[type]) {
try {
return vbo.alloc(size);
} catch (AllocFailed &ex) {
continue;
}
}
_vbos[type].emplace_back((size>default_size)?size:default_size, type);
return _vbos[type].back().alloc(size);
}
VBOManager::VBO::VBO(size_t size, GLenum type)
: _bufID(0)
{
glGenBuffers(1, &_bufID);
glBindBuffer(GL_ARRAY_BUFFER, _bufID);
glBufferData(GL_ARRAY_BUFFER, size, NULL, type);
_allocs.emplace_back(_Entry{size, false});
}
VBOManager::VBO::VBO(VBO&& move)
: _bufID(move._bufID), _allocs(std::move(move._allocs))
{
move._bufID = 0;
}
VBOManager::VBO& VBOManager::VBO::operator=(VBO&& move)
{
for (auto ent : _allocs) {
assert(!ent.used);
}
if (_bufID)
glDeleteBuffers(1, &_bufID);
_bufID = move._bufID;
move._bufID = 0;
_allocs = std::move(move._allocs);
return *this;
}
VBOManager::VBO::~VBO()
{
for (auto ent : _allocs) {
assert(!ent.used);
}
if (_bufID)
glDeleteBuffers(1, &_bufID);
_bufID = 0;
}
VBOManager::VBOAlloc VBOManager::VBO::alloc(size_t size)
{
if (size%alignment != 0)
size += (alignment - (size%alignment));
size_t pos = 0;
for (auto it = _allocs.begin();it != _allocs.end();++it) {
if (!it->used && (it->size >= size)) {
size_t leftover = it->size - size;
it->used = true;
it->size = size;
if (leftover > 0)
_allocs.insert(++it, _Entry{leftover, false});
printf("DEBUG: VBO: Allocated %lu @ %lu in %u\n", size, pos, _bufID);
return VBOAlloc(*this, pos, size);
}
pos += it->size;
}
throw AllocFailed();
}
void VBOManager::VBO::free(VBOAlloc& alloc)
{
size_t pos = 0;
for (auto it = _allocs.begin();it != _allocs.end();++it) {
if (pos == alloc._ofs) {
assert(it->size == alloc._size);
printf("DEBUG: VBO: Freed %lu @ %lu in %u\n", alloc._size, pos, _bufID);
it->used = false;
if ((std::next(it) != _allocs.end()) &&
!std::next(it)->used) {
it->size += std::next(it)->size;
_allocs.erase(std::next(it));
}
if ((it != _allocs.begin()) &&
!std::prev(it)->used) {
it->size += std::prev(it)->size;
_allocs.erase(std::prev(it));
}
return;
}
pos += it->size;
}
}