Skip to main content

goud_engine/libs/graphics/backend/null/
trait_impl.rs

1//! Sub-trait and `RenderBackend` implementations for `NullBackend`.
2
3use crate::libs::error::{GoudError, GoudResult};
4use crate::libs::graphics::backend::blend::{BlendFactor, CullFace};
5use crate::libs::graphics::backend::capabilities::BackendInfo;
6use crate::libs::graphics::backend::render_backend::{
7    BufferOps, ClearOps, DrawOps, FrameOps, RenderBackend, ShaderOps, StateOps, TextureOps,
8};
9use crate::libs::graphics::backend::types::{
10    BufferHandle, BufferType, BufferUsage, DepthFunc, FrontFace, PrimitiveTopology, ShaderHandle,
11    TextureFilter, TextureFormat, TextureHandle, TextureWrap, VertexLayout,
12};
13
14use super::backend::{NullBufferMeta, NullTextureMeta};
15use super::NullBackend;
16
17// ========================================================================
18// RenderBackend (supertrait)
19// ========================================================================
20
21impl RenderBackend for NullBackend {
22    fn info(&self) -> &BackendInfo {
23        &self.info
24    }
25}
26
27// ========================================================================
28// FrameOps
29// ========================================================================
30
31impl FrameOps for NullBackend {
32    fn begin_frame(&mut self) -> GoudResult<()> {
33        Ok(())
34    }
35
36    fn end_frame(&mut self) -> GoudResult<()> {
37        Ok(())
38    }
39}
40
41// ========================================================================
42// ClearOps
43// ========================================================================
44
45impl ClearOps for NullBackend {
46    fn set_clear_color(&mut self, r: f32, g: f32, b: f32, a: f32) {
47        self.clear_color = [r, g, b, a];
48    }
49
50    fn clear_color(&mut self) {
51        // no-op
52    }
53
54    fn clear_depth(&mut self) {
55        // no-op
56    }
57}
58
59// ========================================================================
60// StateOps
61// ========================================================================
62
63impl StateOps for NullBackend {
64    fn set_viewport(&mut self, x: i32, y: i32, width: u32, height: u32) {
65        self.viewport = (x, y, width, height);
66    }
67
68    fn enable_depth_test(&mut self) {
69        self.depth_test_enabled = true;
70    }
71
72    fn disable_depth_test(&mut self) {
73        self.depth_test_enabled = false;
74    }
75
76    fn enable_blending(&mut self) {
77        self.blending_enabled = true;
78    }
79
80    fn disable_blending(&mut self) {
81        self.blending_enabled = false;
82    }
83
84    fn set_blend_func(&mut self, _src: BlendFactor, _dst: BlendFactor) {
85        // no-op
86    }
87
88    fn enable_culling(&mut self) {
89        self.culling_enabled = true;
90    }
91
92    fn disable_culling(&mut self) {
93        self.culling_enabled = false;
94    }
95
96    fn set_cull_face(&mut self, _face: CullFace) {
97        // no-op
98    }
99
100    fn set_depth_func(&mut self, _func: DepthFunc) {
101        // no-op
102    }
103
104    fn set_front_face(&mut self, _face: FrontFace) {
105        // no-op
106    }
107
108    fn set_depth_mask(&mut self, enabled: bool) {
109        self.depth_mask_enabled = enabled;
110    }
111
112    fn set_line_width(&mut self, width: f32) {
113        self.line_width = width;
114    }
115}
116
117// ========================================================================
118// BufferOps
119// ========================================================================
120
121impl BufferOps for NullBackend {
122    fn create_buffer(
123        &mut self,
124        buffer_type: BufferType,
125        _usage: BufferUsage,
126        data: &[u8],
127    ) -> GoudResult<BufferHandle> {
128        let handle = self.buffer_allocator.allocate();
129        self.buffers.insert(
130            handle,
131            NullBufferMeta {
132                size: data.len(),
133                _buffer_type: buffer_type,
134            },
135        );
136        Ok(handle)
137    }
138
139    fn update_buffer(
140        &mut self,
141        handle: BufferHandle,
142        _offset: usize,
143        _data: &[u8],
144    ) -> GoudResult<()> {
145        if self.buffer_allocator.is_alive(handle) {
146            Ok(())
147        } else {
148            Err(GoudError::InvalidHandle)
149        }
150    }
151
152    fn destroy_buffer(&mut self, handle: BufferHandle) -> bool {
153        if self.buffer_allocator.deallocate(handle) {
154            self.buffers.remove(&handle);
155            true
156        } else {
157            false
158        }
159    }
160
161    fn is_buffer_valid(&self, handle: BufferHandle) -> bool {
162        self.buffer_allocator.is_alive(handle)
163    }
164
165    fn buffer_size(&self, handle: BufferHandle) -> Option<usize> {
166        self.buffers.get(&handle).map(|m| m.size)
167    }
168
169    fn bind_buffer(&mut self, handle: BufferHandle) -> GoudResult<()> {
170        if self.buffer_allocator.is_alive(handle) {
171            Ok(())
172        } else {
173            Err(GoudError::InvalidHandle)
174        }
175    }
176
177    fn unbind_buffer(&mut self, _buffer_type: BufferType) {
178        // no-op
179    }
180}
181
182// ========================================================================
183// TextureOps
184// ========================================================================
185
186impl TextureOps for NullBackend {
187    fn create_texture(
188        &mut self,
189        width: u32,
190        height: u32,
191        _format: TextureFormat,
192        _filter: TextureFilter,
193        _wrap: TextureWrap,
194        _data: &[u8],
195    ) -> GoudResult<TextureHandle> {
196        let handle = self.texture_allocator.allocate();
197        self.textures
198            .insert(handle, NullTextureMeta { width, height });
199        Ok(handle)
200    }
201
202    fn update_texture(
203        &mut self,
204        handle: TextureHandle,
205        _x: u32,
206        _y: u32,
207        _width: u32,
208        _height: u32,
209        _data: &[u8],
210    ) -> GoudResult<()> {
211        if self.texture_allocator.is_alive(handle) {
212            Ok(())
213        } else {
214            Err(GoudError::InvalidHandle)
215        }
216    }
217
218    fn destroy_texture(&mut self, handle: TextureHandle) -> bool {
219        if self.texture_allocator.deallocate(handle) {
220            self.textures.remove(&handle);
221            true
222        } else {
223            false
224        }
225    }
226
227    fn is_texture_valid(&self, handle: TextureHandle) -> bool {
228        self.texture_allocator.is_alive(handle)
229    }
230
231    fn texture_size(&self, handle: TextureHandle) -> Option<(u32, u32)> {
232        self.textures.get(&handle).map(|m| (m.width, m.height))
233    }
234
235    fn bind_texture(&mut self, handle: TextureHandle, _unit: u32) -> GoudResult<()> {
236        if self.texture_allocator.is_alive(handle) {
237            Ok(())
238        } else {
239            Err(GoudError::InvalidHandle)
240        }
241    }
242
243    fn unbind_texture(&mut self, _unit: u32) {
244        // no-op
245    }
246}
247
248// ========================================================================
249// ShaderOps
250// ========================================================================
251
252impl ShaderOps for NullBackend {
253    fn create_shader(
254        &mut self,
255        _vertex_src: &str,
256        _fragment_src: &str,
257    ) -> GoudResult<ShaderHandle> {
258        let handle = self.shader_allocator.allocate();
259        Ok(handle)
260    }
261
262    fn destroy_shader(&mut self, handle: ShaderHandle) -> bool {
263        self.shader_allocator.deallocate(handle)
264    }
265
266    fn is_shader_valid(&self, handle: ShaderHandle) -> bool {
267        self.shader_allocator.is_alive(handle)
268    }
269
270    fn bind_shader(&mut self, handle: ShaderHandle) -> GoudResult<()> {
271        if self.shader_allocator.is_alive(handle) {
272            Ok(())
273        } else {
274            Err(GoudError::InvalidHandle)
275        }
276    }
277
278    fn unbind_shader(&mut self) {
279        // no-op
280    }
281
282    fn get_uniform_location(&self, handle: ShaderHandle, _name: &str) -> Option<i32> {
283        if self.shader_allocator.is_alive(handle) {
284            Some(0)
285        } else {
286            None
287        }
288    }
289
290    fn set_uniform_int(&mut self, _location: i32, _value: i32) {
291        // no-op
292    }
293
294    fn set_uniform_float(&mut self, _location: i32, _value: f32) {
295        // no-op
296    }
297
298    fn set_uniform_vec2(&mut self, _location: i32, _x: f32, _y: f32) {
299        // no-op
300    }
301
302    fn set_uniform_vec3(&mut self, _location: i32, _x: f32, _y: f32, _z: f32) {
303        // no-op
304    }
305
306    fn set_uniform_vec4(&mut self, _location: i32, _x: f32, _y: f32, _z: f32, _w: f32) {
307        // no-op
308    }
309
310    fn set_uniform_mat4(&mut self, _location: i32, _matrix: &[f32; 16]) {
311        // no-op
312    }
313}
314
315// ========================================================================
316// DrawOps
317// ========================================================================
318
319impl DrawOps for NullBackend {
320    fn set_vertex_attributes(&mut self, _layout: &VertexLayout) {
321        // no-op
322    }
323
324    fn draw_arrays(
325        &mut self,
326        _topology: PrimitiveTopology,
327        _first: u32,
328        _count: u32,
329    ) -> GoudResult<()> {
330        Ok(())
331    }
332
333    fn draw_indexed(
334        &mut self,
335        _topology: PrimitiveTopology,
336        _count: u32,
337        _offset: usize,
338    ) -> GoudResult<()> {
339        Ok(())
340    }
341
342    fn draw_indexed_u16(
343        &mut self,
344        _topology: PrimitiveTopology,
345        _count: u32,
346        _offset: usize,
347    ) -> GoudResult<()> {
348        Ok(())
349    }
350
351    fn draw_arrays_instanced(
352        &mut self,
353        _topology: PrimitiveTopology,
354        _first: u32,
355        _count: u32,
356        _instance_count: u32,
357    ) -> GoudResult<()> {
358        Ok(())
359    }
360
361    fn draw_indexed_instanced(
362        &mut self,
363        _topology: PrimitiveTopology,
364        _count: u32,
365        _offset: usize,
366        _instance_count: u32,
367    ) -> GoudResult<()> {
368        Ok(())
369    }
370}