use std::mem;
use gl;
use gl::types::*;
use super::{BufferTarget, Usage};
#[derive(Debug, Hash)]
pub struct GLBuffer {
id: GLuint,
stride: usize,
kind: BufferTarget,
usage: Usage,
size: usize,
kind_size: usize,
length: usize,
}
impl GLBuffer {
#[inline]
pub fn new<T>(kind: BufferTarget, stride: usize, usage: Usage, data: &[T]) -> Self {
let mut id = 0;
let length = data.len();
let kind_size = mem::size_of::<T>();
let size = kind_size * length;
let gl_kind = kind.into();
let gl_usage = usage.into();
unsafe {
gl::GenBuffers(1, &mut id);
gl::BindBuffer(gl_kind, id);
gl::BufferData(
gl_kind,
size as GLsizeiptr,
data.as_ptr() as *const GLvoid,
gl_usage,
);
};
GLBuffer {
id: id,
stride: stride * kind_size,
kind: kind,
usage: usage,
size: size,
kind_size: kind_size,
length: length,
}
}
#[inline(always)]
pub fn id(&self) -> GLuint {
self.id
}
#[inline(always)]
pub fn stride(&self) -> usize {
self.stride
}
#[inline(always)]
pub fn kind(&self) -> &BufferTarget {
&self.kind
}
#[inline(always)]
pub fn usage(&self) -> &Usage {
&self.usage
}
#[inline(always)]
pub fn size(&self) -> usize {
self.size
}
#[inline(always)]
pub fn kind_size(&self) -> usize {
self.kind_size
}
#[inline(always)]
pub fn length(&self) -> usize {
self.length
}
#[inline]
pub fn bind(&self) -> &Self {
unsafe {
gl::BindBuffer(self.kind.into(), self.id);
}
self
}
#[inline]
pub fn unbind(&self) -> &Self {
unsafe {
gl::BindBuffer(self.kind.into(), 0);
}
self
}
#[inline]
pub fn update<T>(&mut self, data: &[T]) -> &mut Self {
let length = data.len();
let kind_size = mem::size_of::<T>();
let size = kind_size * length;
let gl_kind = self.kind.into();
let gl_usage = self.usage.into();
unsafe {
gl::BindBuffer(gl_kind, self.id);
gl::BufferData(
gl_kind,
size as GLsizeiptr,
data.as_ptr() as *const GLvoid,
gl_usage,
);
};
self.size = size;
self.kind_size = kind_size;
self.length = length;
self
}
}
impl Drop for GLBuffer {
#[inline]
fn drop(&mut self) {
if self.id != 0 {
unsafe {
gl::DeleteBuffers(1, &self.id);
}
}
}
}