fyrox_graphics/gl/
geometry_buffer.rs1use crate::{
22 buffer::{Buffer, BufferKind},
23 core::{array_as_u8_slice, math::TriangleDefinition},
24 error::FrameworkError,
25 geometry_buffer::{
26 AttributeKind, ElementsDescriptor, GeometryBuffer, GeometryBufferDescriptor,
27 },
28 gl::{buffer::GlBuffer, server::GlGraphicsServer, ToGlConstant},
29 ElementKind,
30};
31use glow::HasContext;
32use std::{cell::Cell, marker::PhantomData, rc::Weak};
33
34impl AttributeKind {
35 fn gl_type(self) -> u32 {
36 match self {
37 AttributeKind::Float => glow::FLOAT,
38 AttributeKind::UnsignedByte => glow::UNSIGNED_BYTE,
39 AttributeKind::UnsignedShort => glow::UNSIGNED_SHORT,
40 AttributeKind::UnsignedInt => glow::UNSIGNED_INT,
41 }
42 }
43}
44
45pub struct GlGeometryBuffer {
46 pub state: Weak<GlGraphicsServer>,
47 pub vertex_array_object: glow::VertexArray,
48 pub buffers: Vec<GlBuffer>,
49 pub element_buffer: GlBuffer,
50 pub element_count: Cell<usize>,
51 pub element_kind: ElementKind,
52 thread_mark: PhantomData<*const u8>,
54}
55
56impl GlGeometryBuffer {
57 pub fn new(
58 server: &GlGraphicsServer,
59 desc: GeometryBufferDescriptor,
60 ) -> Result<Self, FrameworkError> {
61 let vao = unsafe { server.gl.create_vertex_array()? };
62
63 server.set_vertex_array_object(Some(vao));
64
65 let element_buffer = GlBuffer::new(server, 0, BufferKind::Index, desc.usage)?;
66
67 let (element_count, data) = match desc.elements {
68 ElementsDescriptor::Triangles(triangles) => {
69 (triangles.len(), array_as_u8_slice(triangles))
70 }
71 ElementsDescriptor::Lines(lines) => (lines.len(), array_as_u8_slice(lines)),
72 ElementsDescriptor::Points(points) => (points.len(), array_as_u8_slice(points)),
73 };
74
75 element_buffer.write_data(data)?;
76
77 let mut buffers = Vec::new();
78 for buffer in desc.buffers {
79 unsafe {
80 let data_size = buffer.data.bytes.map(|bytes| bytes.len()).unwrap_or(0);
81
82 let native_buffer =
83 GlBuffer::new(server, data_size, BufferKind::Vertex, buffer.usage)?;
84
85 if let Some(data) = buffer.data.bytes {
86 native_buffer.write_data(data)?;
87 }
88
89 let target = native_buffer.kind.into_gl();
90 server.gl.bind_buffer(target, Some(native_buffer.id));
91
92 let mut offset = 0usize;
93 for definition in buffer.attributes {
94 server.gl.vertex_attrib_pointer_f32(
95 definition.location,
96 definition.component_count as i32,
97 definition.kind.gl_type(),
98 definition.normalized,
99 buffer.data.element_size as i32,
100 offset as i32,
101 );
102 server
103 .gl
104 .vertex_attrib_divisor(definition.location, definition.divisor);
105 server.gl.enable_vertex_attrib_array(definition.location);
106
107 offset += definition.kind.size() * definition.component_count;
108
109 if offset > buffer.data.element_size {
110 return Err(FrameworkError::InvalidAttributeDescriptor);
111 }
112 }
113
114 buffers.push(native_buffer);
115 }
116 }
117
118 server.set_vertex_array_object(None);
119
120 Ok(GlGeometryBuffer {
121 state: server.weak(),
122 vertex_array_object: vao,
123 buffers,
124 element_buffer,
125 element_count: Cell::new(element_count),
126 element_kind: desc.elements.element_kind(),
127 thread_mark: PhantomData,
128 })
129 }
130
131 fn set_elements(&self, data: &[u8]) {
132 self.state
133 .upgrade()
134 .unwrap()
135 .set_vertex_array_object(Some(self.vertex_array_object));
136 self.element_buffer.write_data(data).unwrap()
137 }
138
139 pub fn mode(&self) -> u32 {
140 match self.element_kind {
141 ElementKind::Triangle => glow::TRIANGLES,
142 ElementKind::Line => glow::LINES,
143 ElementKind::Point => glow::POINTS,
144 }
145 }
146}
147
148impl GeometryBuffer for GlGeometryBuffer {
149 fn set_buffer_data(&self, buffer: usize, data: &[u8]) {
150 self.state
151 .upgrade()
152 .unwrap()
153 .set_vertex_array_object(Some(self.vertex_array_object));
154 self.buffers[buffer]
155 .write_data(array_as_u8_slice(data))
156 .unwrap();
157 }
158
159 fn element_count(&self) -> usize {
160 self.element_count.get()
161 }
162
163 fn set_triangles(&self, triangles: &[TriangleDefinition]) {
164 assert_eq!(self.element_kind, ElementKind::Triangle);
165 self.element_count.set(triangles.len());
166 self.set_elements(array_as_u8_slice(triangles));
167 }
168
169 fn set_lines(&self, lines: &[[u32; 2]]) {
170 assert_eq!(self.element_kind, ElementKind::Line);
171 self.element_count.set(lines.len());
172 self.set_elements(array_as_u8_slice(lines));
173 }
174
175 fn set_points(&self, points: &[u32]) {
176 assert_eq!(self.element_kind, ElementKind::Point);
177 self.element_count.set(points.len());
178 self.set_elements(array_as_u8_slice(points));
179 }
180}
181
182impl Drop for GlGeometryBuffer {
183 fn drop(&mut self) {
184 if let Some(state) = self.state.upgrade() {
185 unsafe {
186 self.buffers.clear();
187 state.gl.delete_vertex_array(self.vertex_array_object);
188 }
189 }
190 }
191}