ass_renderer/backends/
mod.rs1use crate::pipeline::{IntermediateLayer, Pipeline};
4use crate::renderer::RenderContext;
5use crate::utils::{DirtyRegion, RenderError};
6
7#[cfg(feature = "nostd")]
8use alloc::{boxed::Box, format, vec::Vec};
9#[cfg(not(feature = "nostd"))]
10use std::{boxed::Box, vec::Vec};
11
12#[cfg(feature = "software-backend")]
13pub mod blur;
14
15#[cfg(feature = "software-backend")]
16pub mod coverage;
17
18#[cfg(feature = "software-backend")]
19pub mod geometry;
20
21#[cfg(feature = "software-backend")]
22pub mod raster;
23
24#[cfg(feature = "software-backend")]
25pub mod software;
26
27#[cfg(feature = "gpu")]
28pub mod gpu;
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum BackendType {
33 Auto,
35 Software,
37 Gpu,
39}
40
41impl BackendType {
42 pub fn as_str(&self) -> &'static str {
44 match self {
45 Self::Auto => "Auto",
46 Self::Software => "Software",
47 Self::Gpu => "Gpu",
48 }
49 }
50}
51
52pub trait RenderBackend: Send + Sync {
54 fn backend_type(&self) -> BackendType;
56
57 fn create_pipeline(&self) -> Result<Box<dyn Pipeline>, RenderError>;
59
60 fn composite_layers(
62 &mut self,
63 layers: &[IntermediateLayer],
64 context: &RenderContext,
65 ) -> Result<Vec<u8>, RenderError>;
66
67 fn composite_layers_incremental(
69 &mut self,
70 layers: &[IntermediateLayer],
71 dirty_regions: &[DirtyRegion],
72 previous_frame: &[u8],
73 context: &RenderContext,
74 ) -> Result<Vec<u8>, RenderError> {
75 let _ = (dirty_regions, previous_frame);
77 self.composite_layers(layers, context)
78 }
79
80 #[cfg(feature = "software-backend")]
84 fn render_layers_to_bitmaps(
85 &mut self,
86 layers: &[IntermediateLayer],
87 context: &RenderContext,
88 ) -> Result<Vec<crate::backends::coverage::RenderBitmap>, RenderError> {
89 let _ = (layers, context);
90 Err(RenderError::BackendError(
91 "bitmap-list output not supported by this backend".into(),
92 ))
93 }
94
95 fn supports_feature(&self, feature: BackendFeature) -> bool {
97 match feature {
98 BackendFeature::IncrementalRendering => false,
99 BackendFeature::HardwareAcceleration => false,
100 BackendFeature::ComputeShaders => false,
101 BackendFeature::AsyncRendering => false,
102 }
103 }
104
105 #[cfg(feature = "backend-metrics")]
107 fn metrics(&self) -> Option<BackendMetrics> {
108 None
109 }
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub enum BackendFeature {
115 IncrementalRendering,
117 HardwareAcceleration,
119 ComputeShaders,
121 AsyncRendering,
123}
124
125#[cfg(feature = "backend-metrics")]
127#[derive(Debug, Clone)]
128pub struct BackendMetrics {
129 pub vram_usage: u64,
131 pub draw_calls: usize,
133 pub batch_threshold: usize,
135 pub avg_frame_time_ms: f32,
137 pub peak_frame_time_ms: f32,
139}
140
141#[cfg(feature = "backend-metrics")]
142impl BackendMetrics {
143 pub fn new() -> Self {
145 Self {
146 vram_usage: 0,
147 draw_calls: 0,
148 batch_threshold: 100,
149 avg_frame_time_ms: 0.0,
150 peak_frame_time_ms: 0.0,
151 }
152 }
153}
154
155#[cfg(feature = "backend-metrics")]
156impl Default for BackendMetrics {
157 fn default() -> Self {
158 Self::new()
159 }
160}
161
162pub fn create_backend(
164 backend_type: BackendType,
165 width: u32,
166 height: u32,
167) -> Result<Box<dyn RenderBackend>, RenderError> {
168 match backend_type {
169 BackendType::Auto => {
170 #[cfg(feature = "software-backend")]
173 return create_backend(BackendType::Software, width, height);
174
175 #[allow(unreachable_code)]
176 Err(RenderError::BackendError("No backend available".into()))
177 }
178
179 #[cfg(feature = "software-backend")]
180 BackendType::Software => {
181 let context = crate::renderer::RenderContext::new(width, height);
182 let backend = software::SoftwareBackend::new(&context)?;
183 Ok(Box::new(backend))
184 }
185
186 #[cfg(feature = "gpu")]
187 BackendType::Gpu => {
188 let backend = gpu::GpuBackend::new(width, height)?;
189 Ok(Box::new(backend))
190 }
191
192 #[allow(unreachable_patterns)]
193 _ => {
194 let backend_name = backend_type.as_str();
195 Err(RenderError::BackendError(format!(
196 "{backend_name} backend not available in this build"
197 )))
198 }
199 }
200}