summaryrefslogtreecommitdiff
path: root/engine/src/opengl/buffer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/opengl/buffer.rs')
-rw-r--r--engine/src/opengl/buffer.rs94
1 files changed, 94 insertions, 0 deletions
diff --git a/engine/src/opengl/buffer.rs b/engine/src/opengl/buffer.rs
new file mode 100644
index 0000000..34514fd
--- /dev/null
+++ b/engine/src/opengl/buffer.rs
@@ -0,0 +1,94 @@
+use std::marker::PhantomData;
+use std::mem::size_of_val;
+
+use crate::opengl::currently_bound::CurrentlyBound;
+
+#[derive(Debug)]
+pub struct Buffer<Item>
+{
+ buffer: gl::types::GLuint,
+ _item_pd: PhantomData<Item>,
+}
+
+impl<Item> Buffer<Item>
+{
+ pub fn new() -> Self
+ {
+ let mut buffer = gl::types::GLuint::default();
+
+ unsafe {
+ gl::GenBuffers(1, &mut buffer);
+ };
+
+ Self {
+ buffer,
+ _item_pd: PhantomData,
+ }
+ }
+
+ #[allow(clippy::inline_always)]
+ #[inline(always)]
+ pub fn bind(&self, cb: impl FnOnce(CurrentlyBound<'_, Self>))
+ {
+ unsafe {
+ gl::BindBuffer(gl::ARRAY_BUFFER, self.buffer);
+ }
+
+ // SAFETY: The buffer object is bound above
+ let currently_bound = unsafe { CurrentlyBound::new() };
+
+ cb(currently_bound);
+ }
+
+ /// Stores items in the currently bound buffer.
+ pub fn store(_currently_bound: &CurrentlyBound<Self>, items: &[Item], usage: Usage)
+ {
+ unsafe {
+ #[allow(clippy::cast_possible_wrap)]
+ gl::BufferData(
+ gl::ARRAY_BUFFER,
+ size_of_val(items) as gl::types::GLsizeiptr,
+ items.as_ptr().cast(),
+ usage.into_gl(),
+ );
+ }
+ }
+}
+
+impl<Item> Drop for Buffer<Item>
+{
+ fn drop(&mut self)
+ {
+ #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)]
+ unsafe {
+ gl::DeleteBuffers(1, &self.buffer);
+ }
+ }
+}
+
+/// Buffer usage.
+#[derive(Debug)]
+#[allow(dead_code)]
+pub enum Usage
+{
+ /// The buffer data is set only once and used by the GPU at most a few times.
+ Stream,
+
+ /// The buffer data is set only once and used many times.
+ Static,
+
+ /// The buffer data is changed a lot and used many times.
+ Dynamic,
+}
+
+impl Usage
+{
+ fn into_gl(self) -> gl::types::GLenum
+ {
+ match self {
+ Self::Stream => gl::STREAM_DRAW,
+ Self::Static => gl::STATIC_DRAW,
+ Self::Dynamic => gl::DYNAMIC_DRAW,
+ }
+ }
+}