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}