webgl_rc/
data_buffer.rs

1use crate::buffer_usage::BufferUsage;
2use std::cell::Cell;
3use std::marker::PhantomData;
4use std::rc::Rc;
5use web_sys::{WebGlBuffer, WebGlRenderingContext as Context, WebGlRenderingContext};
6
7use super::gl::{Gl, GlError};
8use super::settings::Settings;
9use super::types::DataType;
10
11pub trait Writable: Copy {
12    fn write(&self, output: &mut Vec<f32>);
13    fn stride() -> usize;
14}
15
16#[derive(Debug, Clone)]
17pub struct ArrayBufferData {
18    pub(self) gl: Gl,
19    pub(self) handle: WebGlBuffer,
20    pub(self) length: Cell<usize>,
21}
22
23impl Drop for ArrayBufferData {
24    fn drop(&mut self) {
25        self.gl.context().delete_buffer(Some(&self.handle));
26    }
27}
28
29#[derive(Debug, Clone)]
30pub struct ArrayBuffer {
31    pub(self) data: Rc<ArrayBufferData>,
32}
33
34impl PartialEq<ArrayBuffer> for ArrayBuffer {
35    fn eq(&self, other: &ArrayBuffer) -> bool {
36        self.data.handle == other.data.handle
37    }
38}
39
40impl Eq for ArrayBuffer {}
41
42impl ArrayBuffer {
43    pub fn new<T: Writable>(
44        gl: Gl,
45        data: &[T],
46        usage: BufferUsage,
47    ) -> Result<ArrayBuffer, GlError> {
48        let ref context: &WebGlRenderingContext = gl.context();
49        let buffer = context
50            .create_buffer()
51            .ok_or(GlError::BufferAllocationError)?;
52
53        let result = ArrayBuffer {
54            data: Rc::new(ArrayBufferData {
55                gl: gl.clone(),
56                handle: buffer,
57                length: Default::default(),
58            }),
59        };
60
61        result.set_content(data, usage);
62
63        return Ok(result);
64    }
65
66    pub(crate) fn handle(&self) -> WebGlBuffer {
67        self.data.handle.clone()
68    }
69
70    pub fn set_content<T: Writable>(&self, items: &[T], usage: BufferUsage) {
71        let mut data: Vec<f32> = Vec::with_capacity(T::stride() * items.len());
72        for i in items {
73            i.write(&mut data);
74        }
75
76        self.data
77            .gl
78            .apply(Gl::settings().array_buffer(self.clone()), || {
79                let bytes = unsafe {
80                    std::slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * 4)
81                };
82                self.data.gl.context().buffer_data_with_u8_array(
83                    Context::ARRAY_BUFFER,
84                    &bytes,
85                    usage.into(),
86                );
87            });
88
89        self.data.length.set(items.len());
90    }
91
92    pub fn len(&self) -> usize {
93        self.data.length.get()
94    }
95}
96
97#[derive(Clone, Copy, PartialEq, Eq, Debug)]
98pub struct Layout {
99    pub name: &'static str,
100    pub data_type: DataType,
101}
102
103pub trait Item: Writable {
104    fn layout() -> Vec<Layout>;
105}
106
107#[derive(Clone, Debug, PartialEq, Eq)]
108pub struct ItemsBuffer<T: Item> {
109    pub(self) phantom: PhantomData<T>,
110    pub(crate) buffer: ArrayBuffer,
111}
112
113impl<T: Item> ItemsBuffer<T> {
114    pub fn new(gl: Gl, data: &[T], usage: BufferUsage) -> Result<ItemsBuffer<T>, GlError> {
115        Ok(ItemsBuffer {
116            phantom: Default::default(),
117            buffer: ArrayBuffer::new(gl, data, usage)?,
118        })
119    }
120
121    pub fn set_content(&self, items: &[T], usage: BufferUsage) {
122        self.buffer.set_content(items, usage);
123    }
124
125    pub fn len(&self) -> usize {
126        self.buffer.len()
127    }
128}