1
2use crate::prelude::*;
3use std::{
4 cmp::min,
5 ffi::c_void,
6 fmt::{self, Debug, Formatter},
7 mem::size_of,
8 rc::Rc,
9};
10
11#[derive(Clone, Copy, PartialEq)]
13pub enum BufferTarget {
14 ArrayBuffer = GL_ARRAY_BUFFER as isize,
15 AtomicCounterBuffer = GL_ATOMIC_COUNTER_BUFFER as isize,
16 CopyReadBuffer = GL_COPY_READ_BUFFER as isize,
17 CopyWriteBuffer = GL_COPY_WRITE_BUFFER as isize,
18 DispatchIndirectBuffer = GL_DISPATCH_INDIRECT_BUFFER as isize,
19 DrawIndirectBuffer = GL_DRAW_INDIRECT_BUFFER as isize,
20 ElementArrayBuffer = GL_ELEMENT_ARRAY_BUFFER as isize,
21 PixelPackBuffer = GL_PIXEL_PACK_BUFFER as isize,
22 PixelUnpackBuffer = GL_PIXEL_UNPACK_BUFFER as isize,
23 QueryBuffer = GL_QUERY_BUFFER as isize,
24 ShaderStorageBuffer = GL_SHADER_STORAGE_BUFFER as isize,
25 TextureBuffer = GL_TEXTURE_BUFFER as isize,
26 TransformFeedbackBuffer = GL_TRANSFORM_FEEDBACK_BUFFER as isize,
27 UniformBuffer = GL_UNIFORM_BUFFER as isize,
28}
29
30#[derive(Clone, Copy, PartialEq)]
32pub enum BufferUsage {
33 StreamDraw = GL_STREAM_DRAW as isize,
34 StreamRead = GL_STREAM_READ as isize,
35 StreamCopy = GL_STREAM_COPY as isize,
36 StaticDraw = GL_STATIC_DRAW as isize,
37 StaticRead = GL_STATIC_READ as isize,
38 StaticCopy = GL_STATIC_COPY as isize,
39 DynamicDraw = GL_DYNAMIC_DRAW as isize,
40 DynamicRead = GL_DYNAMIC_READ as isize,
41 DynamicCopy = GL_DYNAMIC_COPY as isize,
42}
43
44#[derive(Clone, Copy, PartialEq)]
46pub enum MapAccess {
47 ReadOnly = GL_READ_ONLY as isize,
48 WriteOnly = GL_WRITE_ONLY as isize,
49 ReadWrite = GL_READ_WRITE as isize,
50}
51
52pub struct Buffer {
54 pub glcore: Rc<GLCore>,
55 name: u32,
56 usage: BufferUsage,
57 target: BufferTarget,
58 size: usize,
59}
60
61#[derive(Debug)]
63pub struct BufferBind<'a> {
64 pub buffer: &'a Buffer,
65 target: BufferTarget,
66}
67
68#[derive(Debug)]
70pub struct BufferMapping<'a> {
71 pub buffer: &'a Buffer,
72 target: BufferTarget,
73 access: MapAccess,
74 address: *mut c_void,
75}
76
77impl Buffer {
78 pub fn get_name(&self) -> u32 {
80 self.name
81 }
82
83 pub unsafe fn to_raw(mut self) -> u32 {
88 let ret = self.name;
89 self.name = 0;
90 ret
91 }
92
93 pub unsafe fn from_raw(glcore: Rc<GLCore>, name: u32, target: BufferTarget) -> Result<Self, GLCoreError> {
99 glcore.glBindBuffer(target as u32, name)?;
100 let mut size = 0;
101 let mut usage = 0;
102 glcore.glGetBufferParameteriv(target as u32, GL_BUFFER_SIZE, &mut size as *mut _)?;
103 glcore.glGetBufferParameteriv(target as u32, GL_BUFFER_USAGE, &mut usage as *mut _)?;
104 glcore.glBindBuffer(target as u32, 0)?;
105 let usage = match usage as u32 {
106 GL_STREAM_DRAW => BufferUsage::StreamDraw,
107 GL_STREAM_READ => BufferUsage::StreamRead,
108 GL_STREAM_COPY => BufferUsage::StreamCopy,
109 GL_STATIC_DRAW => BufferUsage::StaticDraw,
110 GL_STATIC_READ => BufferUsage::StaticRead,
111 GL_STATIC_COPY => BufferUsage::StaticCopy,
112 GL_DYNAMIC_DRAW => BufferUsage::DynamicDraw,
113 GL_DYNAMIC_READ => BufferUsage::DynamicRead,
114 GL_DYNAMIC_COPY => BufferUsage::DynamicCopy,
115 _ => panic!("Unknown buffer usage: `{usage}`"),
116 };
117 Ok(Self {
118 glcore,
119 name,
120 usage,
121 target,
122 size: size as usize,
123 })
124 }
125
126 pub fn new(glcore: Rc<GLCore>, target: BufferTarget, size: usize, usage: BufferUsage, data_ptr: *const c_void) -> Result<Self, GLCoreError> {
128 let mut name: u32 = 0;
129 glcore.glGenBuffers(1, &mut name as *mut u32)?;
130 glcore.glBindBuffer(target as u32, name)?;
131 glcore.glBufferData(target as u32, size, data_ptr, usage as u32)?;
132 glcore.glBindBuffer(target as u32, 0)?;
133 Ok(Self {
134 glcore,
135 name,
136 usage,
137 target,
138 size,
139 })
140 }
141
142 pub fn size(&self) -> usize {
144 self.size
145 }
146
147 pub fn get_target(&self) -> BufferTarget {
149 self.target
150 }
151
152 pub fn get_usage(&self) -> BufferUsage {
154 self.usage
155 }
156
157 pub fn resize<T: Copy + Sized>(&mut self, new_len: usize, value: T) -> Result<(), GLCoreError> {
159 let new_len = min(self.size, new_len);
160 let data = vec![value; new_len / size_of::<T>()];
161 let mut name: u32 = 0;
162 self.glcore.glGenBuffers(1, &mut name as *mut u32)?;
163 self.glcore.glBindBuffer(BufferTarget::CopyReadBuffer as u32, self.name)?;
164 self.glcore.glBindBuffer(BufferTarget::CopyWriteBuffer as u32, name)?;
165 self.glcore.glBufferData(BufferTarget::CopyWriteBuffer as u32, new_len,
166 if new_len > self.size {
167 data.as_ptr() as *const c_void
168 } else {
169 std::ptr::null()
170 },
171 self.usage as u32)?;
172 self.glcore.glCopyBufferSubData(BufferTarget::CopyReadBuffer as u32, BufferTarget::CopyWriteBuffer as u32, 0, 0, new_len)?;
173 self.glcore.glBindBuffer(BufferTarget::CopyReadBuffer as u32, 0)?;
174 self.glcore.glBindBuffer(BufferTarget::CopyWriteBuffer as u32, 0)?;
175 self.glcore.glDeleteBuffers(1, &self.name as *const u32)?;
176 self.name = name;
177 Ok(())
178 }
179
180 pub fn set_target(&mut self, target: BufferTarget) {
182 self.target = target;
183 }
184
185 pub fn bind<'a>(&'a self) -> Result<BufferBind<'a>, GLCoreError> {
187 BufferBind::new(self, self.target)
188 }
189
190 pub fn bind_to<'a>(&'a self, target: BufferTarget) -> Result<BufferBind<'a>, GLCoreError> {
192 BufferBind::new(self, target)
193 }
194}
195
196impl Drop for Buffer {
197 fn drop(&mut self) {
199 if self.name != 0 {
200 self.glcore.glDeleteBuffers(1, &self.name as *const u32).unwrap();
201 }
202 }
203}
204
205impl Clone for Buffer {
206 fn clone(&self) -> Self {
207 let mut name: u32 = 0;
208 self.glcore.glGenBuffers(1, &mut name as *mut u32).unwrap();
209 self.glcore.glBindBuffer(self.target as u32, name).unwrap();
210 self.glcore.glBindBuffer(BufferTarget::CopyReadBuffer as u32, self.name).unwrap();
211 self.glcore.glBufferData(BufferTarget::CopyWriteBuffer as u32, self.size, std::ptr::null(), self.usage as u32).unwrap();
212 self.glcore.glCopyBufferSubData(BufferTarget::CopyReadBuffer as u32, self.target as u32, 0, 0, self.size).unwrap();
213 self.glcore.glBindBuffer(self.target as u32, 0).unwrap();
214 self.glcore.glBindBuffer(BufferTarget::CopyReadBuffer as u32, 0).unwrap();
215 Self {
216 glcore: self.glcore.clone(),
217 name,
218 usage: self.usage,
219 target: self.target,
220 size: self.size,
221 }
222 }
223}
224
225impl Debug for Buffer {
226 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
227 f.debug_struct("Buffer")
228 .field("name", &self.name)
229 .field("usage", &self.usage)
230 .field("target", &self.target)
231 .field("size", &self.size)
232 .finish()
233 }
234}
235
236impl<'a> BufferBind<'a> {
237 fn new(buffer: &'a Buffer, target: BufferTarget) -> Result<Self, GLCoreError> {
239 buffer.glcore.glBindBuffer(target as u32, buffer.name)?;
240 Ok(Self {
241 buffer,
242 target,
243 })
244 }
245
246 pub fn unbind(self) {} pub fn map(&self, access: MapAccess) -> Result<(BufferMapping<'a>, *mut c_void), GLCoreError> {
251 BufferMapping::new(self.buffer, self.target, access)
252 }
253
254 pub fn map_ranged(&self, offset: usize, length: usize, access: MapAccess) -> Result<(BufferMapping<'a>, *mut c_void), GLCoreError> {
256 BufferMapping::new_ranged(self.buffer, self.target, offset, length, access)
257 }
258
259 pub fn get_target(&self) -> BufferTarget {
261 self.target
262 }
263}
264
265impl<'a> Drop for BufferBind<'a> {
266 fn drop(&mut self) {
268 self.buffer.glcore.glBindBuffer(self.target as u32, 0).unwrap();
269 }
270}
271
272impl<'a> BufferMapping<'a> {
273 fn new(buffer: &'a Buffer, target: BufferTarget, access: MapAccess) -> Result<(Self, *mut c_void), GLCoreError> {
275 let address = buffer.glcore.glMapBuffer(target as u32, access as u32)?;
276 Ok((Self {
277 buffer,
278 target,
279 access,
280 address,
281 }, address))
282 }
283
284 fn new_ranged(buffer: &'a Buffer, target: BufferTarget, offset: usize, length: usize, access: MapAccess) -> Result<(Self, *mut c_void), GLCoreError> {
286 let address = buffer.glcore.glMapBufferRange(target as u32, offset, length, access as u32)?;
287 Ok((Self {
288 buffer,
289 target,
290 access,
291 address,
292 }, address))
293 }
294
295 pub fn unmap(self) {} pub fn get_target(&self) -> BufferTarget {
300 self.target
301 }
302
303 pub fn get_access(&self) -> MapAccess {
305 self.access
306 }
307
308 pub fn get_mapping_address(&self) -> *mut c_void {
310 self.address
311 }
312}
313
314impl<'a> Drop for BufferMapping<'a> {
315 fn drop(&mut self) {
317 self.buffer.glcore.glUnmapBuffer(self.target as u32).unwrap();
318 }
319}
320
321impl Debug for BufferTarget {
322 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
323 match self {
324 Self::ArrayBuffer => write!(f, "ArrayBuffer"),
325 Self::AtomicCounterBuffer => write!(f, "AtomicCounterBuffer"),
326 Self::CopyReadBuffer => write!(f, "CopyReadBuffer"),
327 Self::CopyWriteBuffer => write!(f, "CopyWriteBuffer"),
328 Self::DispatchIndirectBuffer => write!(f, "DispatchIndirectBuffer"),
329 Self::DrawIndirectBuffer => write!(f, "DrawIndirectBuffer"),
330 Self::ElementArrayBuffer => write!(f, "ElementArrayBuffer"),
331 Self::PixelPackBuffer => write!(f, "PixelPackBuffer"),
332 Self::PixelUnpackBuffer => write!(f, "PixelUnpackBuffer"),
333 Self::QueryBuffer => write!(f, "QueryBuffer"),
334 Self::ShaderStorageBuffer => write!(f, "ShaderStorageBuffer"),
335 Self::TextureBuffer => write!(f, "TextureBuffer"),
336 Self::TransformFeedbackBuffer => write!(f, "TransformFeedbackBuffer"),
337 Self::UniformBuffer => write!(f, "UniformBuffer"),
338 }
339 }
340}
341
342impl Debug for BufferUsage {
343 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
344 match self {
345 Self::StreamDraw => write!(f, "StreamDraw"),
346 Self::StreamRead => write!(f, "StreamRead"),
347 Self::StreamCopy => write!(f, "StreamCopy"),
348 Self::StaticDraw => write!(f, "StaticDraw"),
349 Self::StaticRead => write!(f, "StaticRead"),
350 Self::StaticCopy => write!(f, "StaticCopy"),
351 Self::DynamicDraw => write!(f, "DynamicDraw"),
352 Self::DynamicRead => write!(f, "DynamicRead"),
353 Self::DynamicCopy => write!(f, "DynamicCopy"),
354 }
355 }
356}
357
358impl Debug for MapAccess {
359 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
360 match self {
361 Self::ReadOnly => write!(f, "StreamDraw"),
362 Self::WriteOnly => write!(f, "StreamRead"),
363 Self::ReadWrite => write!(f, "StreamCopy"),
364 }
365 }
366}