fyrox_graphics/gl/
buffer.rs1use crate::gl::server::GlGraphicsServer;
22use crate::gl::ToGlConstant;
23use crate::{
24 buffer::{Buffer, BufferKind, BufferUsage},
25 error::FrameworkError,
26};
27use glow::HasContext;
28use std::{cell::Cell, rc::Weak};
29
30impl ToGlConstant for BufferKind {
31 fn into_gl(self) -> u32 {
32 match self {
33 BufferKind::Vertex => glow::ARRAY_BUFFER,
34 BufferKind::Index => glow::ELEMENT_ARRAY_BUFFER,
35 BufferKind::Uniform => glow::UNIFORM_BUFFER,
36 BufferKind::PixelRead => glow::PIXEL_PACK_BUFFER,
37 BufferKind::PixelWrite => glow::PIXEL_UNPACK_BUFFER,
38 }
39 }
40}
41
42impl ToGlConstant for BufferUsage {
43 fn into_gl(self) -> u32 {
44 match self {
45 BufferUsage::StaticDraw => glow::STATIC_DRAW,
46 BufferUsage::StaticCopy => glow::STATIC_COPY,
47 BufferUsage::DynamicDraw => glow::DYNAMIC_DRAW,
48 BufferUsage::DynamicCopy => glow::DYNAMIC_COPY,
49 BufferUsage::StreamDraw => glow::STREAM_DRAW,
50 BufferUsage::StreamRead => glow::STREAM_READ,
51 BufferUsage::StreamCopy => glow::STREAM_COPY,
52 BufferUsage::StaticRead => glow::STATIC_READ,
53 BufferUsage::DynamicRead => glow::DYNAMIC_READ,
54 }
55 }
56}
57
58pub struct GlBuffer {
59 pub state: Weak<GlGraphicsServer>,
60 pub id: glow::Buffer,
61 pub size: Cell<usize>,
62 pub kind: BufferKind,
63 pub usage: BufferUsage,
64}
65
66impl GlBuffer {
67 pub fn new(
68 server: &GlGraphicsServer,
69 size_bytes: usize,
70 kind: BufferKind,
71 usage: BufferUsage,
72 ) -> Result<Self, FrameworkError> {
73 unsafe {
74 let gl_kind = kind.into_gl();
75 let gl_usage = usage.into_gl();
76 let id = server.gl.create_buffer()?;
77 server.gl.bind_buffer(gl_kind, Some(id));
78 if size_bytes > 0 {
79 server
80 .gl
81 .buffer_data_size(gl_kind, size_bytes as i32, gl_usage);
82 }
83 server.gl.bind_buffer(gl_kind, None);
84 Ok(Self {
85 state: server.weak(),
86 id,
87 size: Cell::new(size_bytes),
88 kind,
89 usage,
90 })
91 }
92 }
93}
94
95impl Drop for GlBuffer {
96 fn drop(&mut self) {
97 unsafe {
98 if let Some(state) = self.state.upgrade() {
99 state.gl.delete_buffer(self.id);
100 }
101 }
102 }
103}
104
105impl Buffer for GlBuffer {
106 fn usage(&self) -> BufferUsage {
107 self.usage
108 }
109
110 fn kind(&self) -> BufferKind {
111 self.kind
112 }
113
114 fn size(&self) -> usize {
115 self.size.get()
116 }
117
118 fn write_data(&self, data: &[u8]) -> Result<(), FrameworkError> {
119 if data.is_empty() {
120 return Ok(());
121 }
122
123 let Some(server) = self.state.upgrade() else {
124 return Err(FrameworkError::GraphicsServerUnavailable);
125 };
126
127 let gl_kind = self.kind.into_gl();
128 let gl_usage = self.usage.into_gl();
129
130 unsafe {
131 server.gl.bind_buffer(gl_kind, Some(self.id));
132 if data.len() <= self.size.get() {
133 server.gl.buffer_sub_data_u8_slice(gl_kind, 0, data);
135 } else {
136 server.gl.buffer_data_u8_slice(gl_kind, data, gl_usage);
138 self.size.set(data.len());
139 }
140 }
141
142 Ok(())
143 }
144
145 fn read_data(&self, data: &mut [u8]) -> Result<(), FrameworkError> {
146 let Some(server) = self.state.upgrade() else {
147 return Err(FrameworkError::GraphicsServerUnavailable);
148 };
149
150 let gl_kind = self.kind.into_gl();
151
152 unsafe {
153 server.gl.bind_buffer(gl_kind, Some(self.id));
154
155 #[cfg(not(target_arch = "wasm32"))]
156 {
157 let gl_storage =
158 server
159 .gl
160 .map_buffer_range(gl_kind, 0, data.len() as i32, glow::MAP_READ_BIT);
161 assert_ne!(gl_storage, std::ptr::null_mut());
162 std::ptr::copy_nonoverlapping(gl_storage, data.as_mut_ptr(), data.len());
163 server.gl.unmap_buffer(gl_kind);
164 }
165
166 #[cfg(target_arch = "wasm32")]
167 {
168 server.gl.get_buffer_sub_data(gl_kind, 0, data);
171 }
172
173 server.gl.bind_buffer(gl_kind, None);
174 }
175
176 Ok(())
177 }
178}