139 lines
3.8 KiB
C++
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);
|
|
}
|
|
|
|
}
|