#include namespace nb { const ConstantMap BufferTypes({ {GL_ARRAY_BUFFER, "GL_ARRAY_BUFFER"}, {GL_ELEMENT_ARRAY_BUFFER, "GL_ELEMENT_BUFFER"} }); using BufferErrorCodes = BufferError::Codes; const std::string BufferError::type = "nb::BufferError"; const ErrorCodeMap BufferError::ErrorMessages = { { BufferErrorCodes::UNDEFINED, "Error" }, { BufferErrorCodes::DATA_OVERFLOW, "Attempting buffer overflow" }, { BufferErrorCodes::DATA_ERROR, "Invalid memory operation" }, { BufferErrorCodes::BAD_DATA_TYPE, "Entered data type not allowed for buffer type"} }; // class Buffer Buffer::Buffer(GLenum target_) : OpenGLObject(), Target(target_) { declare(); } Buffer::Buffer(GLenum target_, const ByteVector& data_, GLenum usage_) : Buffer(target_) { bind(); data(data_, usage_); } Buffer::Buffer(Buffer&& rval) : Target(rval.Target) { *this = std::move(rval); } Buffer& Buffer::operator=(Buffer&& rhs) { if (Target != rhs.Target) { auto targ_name = BufferTypes[Target]; THROW(OpenGLObjectError( OpenGLObjectError::Codes::INVALID_OBJECT, "w/ BufferType "+targ_name+" != BufferType "+BufferTypes[Target] )); } OpenGLObject::operator=(std::move(rhs)); _usage = rhs._usage; _size = rhs._size; rhs._usage = GL_STATIC_DRAW; rhs._size = 0; return *this; } GLenum Buffer::usage() const { return _usage; } size_t Buffer::size() const { return _size; } ByteVector Buffer::data() const { bind(); ByteVector ret(_size); OPENGL_CALL(glGetBufferSubData(Target, 0, _size, ret.data())); return ret; } void Buffer::data(const void* data_, size_t size_, GLenum usage_) { declare(); OPENGL_CALL(glBufferData(Target, size_, data_, usage_)); _size = size_; _usage = usage_; } void Buffer::data(const ByteVector& data_, GLenum usage_) { declare(); data(data_.data(), data_.size(), usage_); } void Buffer::subdata(const void* data_, size_t size_, GLintptr offset_) { bind(); if (offset_+size_ <= _size) { THROW(BufferError(BufferError::Codes::DATA_OVERFLOW)); } OPENGL_CALL(glBufferSubData(Target, offset_, size_, data_)); } void Buffer::subdata(const ByteVector& data_, GLintptr offset_) { bind(); size_t size_ = data_.size(); subdata(data_.data(), size_); } // class UniformBuffer UniformBuffer::UniformBuffer() : Buffer(GL_UNIFORM_BUFFER) {} void UniformBuffer::bind() const { Buffer::bind(); OPENGL_CALL(glBindBufferBase(GL_UNIFORM_BUFFER, _index, id())); } GLuint UniformBuffer::bufferIndex() const { return _index; } GLuint UniformBuffer::bufferIndex(GLuint idx) { return (_index = idx); } // class ElementBuffer template void ElementBuffer::data(const std::vector& data, GLenum usage); template void ElementBuffer::data(const std::vector& data, GLenum usage); template void ElementBuffer::data(const std::vector& data, GLenum usage); template void ElementBuffer::data(const uint8_t* const data, size_t size, GLenum usage); template void ElementBuffer::data(const uint16_t* const data, size_t size, GLenum usage); template void ElementBuffer::data(const uint32_t* const data, size_t size, GLenum usage); template void ElementBuffer::subdata(const uint8_t* const data, size_t size, GLintptr offset=0); template void ElementBuffer::subdata(const uint16_t* const data, size_t size, GLintptr offset=0); template void ElementBuffer::subdata(const uint32_t* const data, size_t size, GLintptr offset=0); template void ElementBuffer::subdata(const std::vector& data, GLintptr offset=0); template void ElementBuffer::subdata(const std::vector& data, GLintptr offset=0); template void ElementBuffer::subdata(const std::vector& data, GLintptr offset=0); }