our_dick/src/gfx/ogl/vbo.cpp
2022-02-10 16:56:01 -08:00

139 lines
3.8 KiB
C++

/**
This file is a part of our_dick
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gfx/ogl/vbo.hpp"
#include "config.hpp"
#include <rexy/utility.hpp>
#include <utility> //exchange, swap, move
#include <cstring> //memset
namespace gfx::ogl{
vbo::vbo(size_t size, buffer::usage t):
m_buffer_size(0)
{
glCreateBuffers(1, &m_buffer);
glNamedBufferData(m_buffer, size, NULL, static_cast<GLenum>(t));
}
vbo::vbo(const void* data, size_t size, buffer::usage t):
m_buffer_size(size)
{
glCreateBuffers(1, &m_buffer);
glNamedBufferData(m_buffer, size, data, static_cast<GLenum>(t));
}
vbo::vbo(const vbo& v):
m_buffer_size(v.m_buffer_size)
{
glCreateBuffers(1, &m_buffer);
scoped_buffer_map<void> data = v.map(buffer::maptype::READ);
if(!data)
return;
glNamedBufferData(m_buffer, v.get_size(), data, static_cast<GLenum>(v.get_usage()));
}
vbo::vbo(vbo&& v):
m_buffer(std::exchange(v.m_buffer, 0)),
m_buffer_size(v.m_buffer_size){}
vbo::~vbo(void){
if(m_buffer)
glDeleteBuffers(1, &m_buffer);
}
vbo& vbo::operator=(const vbo& v){
return (*this = vbo(v));
}
vbo& vbo::operator=(vbo&& v){
std::swap(m_buffer, v.m_buffer);
m_buffer_size = v.m_buffer_size;
return *this;
}
bool vbo::buffer(const void* data, size_t datasize){
if(datasize + m_buffer_size > get_cap()){
if(!resize(rexy::max(datasize + m_buffer_size, get_cap() * 2)))
return false;
}
glNamedBufferSubData(m_buffer, get_size(), datasize, data);
m_buffer_size += datasize;
return true;
}
bool vbo::buffer(const void* data, size_t datasize, size_t start){
const size_t capacity = get_cap();
const size_t space_from_end = capacity - start;
if(start > capacity || datasize > space_from_end){
const size_t difference = datasize - space_from_end;
if(!resize(rexy::max(difference, capacity * 2))){
return false;
}
}
glNamedBufferSubData(m_buffer, start, datasize, data);
m_buffer_size = rexy::max(m_buffer_size, datasize + start);
return true;
}
bool vbo::initialize(unsigned char value){
const size_t capacity = get_cap();
auto m = map(buffer::maptype::WRITE);
if(!m){
return false;
}
memset(m, capacity, value);
return true;
}
bool vbo::resize(size_t newsize){
vbo tmp(newsize, get_usage());
if(!copy_buffer(tmp, *this))
return false;
*this = std::move(tmp);
return true;
}
GLuint vbo::raw(void)const{
return m_buffer;
}
scoped_buffer_map<void> vbo::map(buffer::maptype m)const{
return scoped_buffer_map<void>(m_buffer, m);
}
void vbo::clear(void){
m_buffer_size = 0;
}
size_t vbo::get_size(void)const{
return m_buffer_size;
}
size_t vbo::get_cap(void)const{
GLint retval;
glGetNamedBufferParameteriv(m_buffer, GL_BUFFER_SIZE, &retval);
return retval;
}
auto vbo::get_usage(void)const -> buffer::usage{
GLint retval;
glGetNamedBufferParameteriv(m_buffer, GL_BUFFER_USAGE, &retval);
return static_cast<buffer::usage>(retval);
}
bool vbo::copy_buffer(vbo& dest, const vbo& src){
size_t bytes = rexy::min(dest.get_cap(), src.get_size());
scoped_buffer_map<void> data(src.m_buffer, buffer::maptype::READ);
if(!data.valid())
return false;
return dest.buffer(data, bytes);
}
}