Merge branch 'master' of ssh://ka.blankertz.org/home/matthias/git/openglplayground
This commit is contained in:
146
VBOManager.cc
Normal file
146
VBOManager.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user