1use crate::{gl, prelude::*, GLboolean, GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
2
3#[derive(Clone, Default, Debug)]
4pub struct Buffer {
5 buffer_type: GLuint,
6 vbo: GLuint,
7}
8
9impl Buffer {
10 pub fn new_array() -> Buffer {
11 Self::new(gl::ARRAY_BUFFER)
12 }
13
14 pub fn new_element_array() -> Buffer {
15 Self::new(gl::ELEMENT_ARRAY_BUFFER)
16 }
17
18 pub fn new_draw_indirect() -> Buffer {
19 Self::new(gl::DRAW_INDIRECT_BUFFER)
20 }
21
22 pub fn new(buffer_type: GLuint) -> Buffer {
23 let vbo = crate::new_buffer();
24 crate::bind_buffer(buffer_type, vbo);
25 Buffer { buffer_type, vbo }
26 }
27
28 pub fn static_draw_data<T>(&self, data: &[T])
29 where
30 T: Sized,
31 {
32 crate::buffer_data(
33 self.buffer_type, -1, Some(data), gl::STATIC_DRAW, );
38 }
39
40 pub fn stream_draw_data<T>(&self, data: &[T])
41 where
42 T: Sized,
43 {
44 crate::buffer_data(
45 self.buffer_type, -1, Some(data), gl::STREAM_DRAW, );
50 }
51
52 pub fn stream_draw_data_null<T>(&self, size: usize)
53 where
54 T: Sized,
55 {
56 crate::buffer_data::<T>(
57 self.buffer_type, (size * std::mem::size_of::<T>()) as GLsizeiptr, None, gl::STREAM_DRAW, );
62 }
63
64 #[cfg(feature = "gl4")]
65 pub unsafe fn map_buffer_range_write_invalidate<'r, T>(
66 &self,
67 offset: usize,
68 size: usize,
69 ) -> Option<MappedBuffer<'r, T>>
70 where
71 T: Sized,
72 {
73 let ptr = crate::map_buffer_range(
74 self.buffer_type, (offset * std::mem::size_of::<T>()) as GLsizeiptr, (size * std::mem::size_of::<T>()) as GLsizeiptr, gl::MAP_WRITE_BIT | gl::MAP_INVALIDATE_RANGE_BIT, );
79 if ptr == ::std::ptr::null_mut() {
80 return None;
81 }
82 return Some(MappedBuffer {
83 buffer_type: self.buffer_type,
84 data: ::std::slice::from_raw_parts_mut(ptr as *mut T, size),
85 position: 0,
86 });
87 }
88
89 pub fn update<T>(&self, data: &[T])
90 where
91 T: Sized,
92 {
93 crate::buffer_sub_data(
94 self.buffer_type, 0, data, );
98 }
99
100 pub fn update_partial<T>(&self, offset: isize, data: &[T])
101 where
102 T: Sized,
103 {
104 crate::buffer_sub_data(
105 self.buffer_type, offset, data, );
109 }
110}
111
112impl Drop for Buffer {
113 fn drop(&mut self) {
114 crate::delete_buffers(&[self.vbo]);
115 }
116}
117
118impl Bindable for Buffer {
119 fn bind(&self) {
120 crate::bind_buffer(self.buffer_type, self.vbo);
121 }
122
123 fn unbind(&self) {
124 crate::bind_buffer(self.buffer_type, 0);
125 }
126}
127
128#[cfg(feature = "gl4")]
129pub struct MappedBuffer<'a, DataT: 'a> {
130 buffer_type: GLuint,
131 data: &'a mut [DataT],
132 position: usize,
133}
134
135#[cfg(feature = "gl4")]
136impl<'a, DataT: 'a> MappedBuffer<'a, DataT> {
137 pub fn clear(&mut self) {
138 self.position = 0;
139 }
140
141 pub fn push(&mut self, data: DataT) {
142 if self.position < self.data.len() {
143 *unsafe { self.data.get_unchecked_mut(self.position) } = data;
144 self.position += 1;
145 }
146 }
147}
148
149#[cfg(feature = "gl4")]
150impl<'a, DataT: 'a> ::std::ops::Deref for MappedBuffer<'a, DataT> {
151 type Target = [DataT];
152
153 fn deref(&self) -> &Self::Target {
154 self.data
155 }
156}
157
158#[cfg(feature = "gl4")]
159impl<'a, DataT: 'a> ::std::ops::DerefMut for MappedBuffer<'a, DataT> {
160 fn deref_mut(&mut self) -> &mut Self::Target {
161 self.data
162 }
163}
164
165#[cfg(feature = "gl4")]
166impl<'a, DataT: 'a> Drop for MappedBuffer<'a, DataT> {
167 fn drop(&mut self) {
168 crate::unmap_buffer(self.buffer_type);
169 }
170}
171
172#[derive(Clone, Copy, Debug)]
173pub struct VertexAttrib {
174 location: GLuint,
175 components: GLint,
176 data_type: GLenum,
177 normalized: GLboolean,
178 stride: GLsizei,
179 offset: GLsizeiptr,
180}
181
182impl VertexAttrib {
183 pub fn new(
184 location: GLuint,
185 components: GLint,
186 data_type: GLenum,
187 normalized: GLboolean,
188 stride: GLsizei,
189 offset: GLsizeiptr,
190 ) -> Self {
191 Self {
192 location,
193 components,
194 data_type,
195 normalized,
196 stride,
197 offset,
198 }
199 }
200}
201
202impl Bindable for VertexAttrib {
203 fn bind(&self) {
204 crate::enable_vertex_attrib_array(self.location);
205 crate::vertex_attrib_pointer(
206 self.location,
207 self.components,
208 self.data_type,
209 self.normalized,
210 self.stride,
211 self.offset,
212 );
213 }
214 fn unbind(&self) {
215 crate::disable_vertex_attrib_array(self.location);
216 }
217}
218
219#[derive(Clone, Default, Debug)]
220pub struct VertexArray {
221 vao: GLuint,
222}
223
224impl VertexArray {
225 pub fn new() -> VertexArray {
226 VertexArray {
227 vao: crate::new_vertex_array(),
228 }
229 }
230
231 pub fn enable_attrib(&self, attr: &VertexAttrib) {
232 crate::enable_vertex_attrib_array(attr.location);
233 crate::vertex_attrib_pointer(
234 attr.location,
235 attr.components,
236 attr.data_type,
237 attr.normalized,
238 attr.stride,
239 attr.offset,
240 );
241 }
242
243 pub fn disable_attrib(self, attr: &VertexAttrib) {
244 crate::disable_vertex_attrib_array(attr.location);
245 }
246}
247
248impl Drop for VertexArray {
249 fn drop(&mut self) {
250 crate::delete_vertex_arrays(&[self.vao]);
251 }
252}
253
254impl Bindable for VertexArray {
255 fn bind(&self) {
256 crate::bind_vertex_array(self.vao);
257 }
258
259 fn unbind(&self) {
260 crate::bind_vertex_array(0);
261 }
262}