Skip to main content

euv_chart/backend/common/
impl.rs

1use super::*;
2
3/// Inherent implementation of [`BackendKind`].
4impl BackendKind {
5    /// Returns the name of the backend.
6    ///
7    /// # Returns
8    ///
9    /// - `&'static str` - A `'static str` value.
10    pub fn name(&self) -> &'static str {
11        match self {
12            BackendKind::WebGpu => "webgpu",
13            BackendKind::WebGl2 => "webgl2",
14            BackendKind::Canvas2D => "canvas2d",
15        }
16    }
17
18    /// Returns `true` when the backend runs on the GPU.
19    ///
20    /// # Returns
21    ///
22    /// - `bool` - A boolean.
23    pub fn is_gpu(&self) -> bool {
24        matches!(self, BackendKind::WebGpu | BackendKind::WebGl2)
25    }
26}
27
28/// Inherent implementation of [`BackendFactory`].
29impl BackendFactory {
30    /// Returns a factory.
31    pub fn new() -> Self {
32        Self
33    }
34
35    /// Creates the best backend for the given canvas.
36    ///
37    /// `preferred` is the backend the caller would like; the factory
38    /// falls back to the next one down when the host cannot provide it.
39    /// The fallback chain is always WebGPU, WebGL2, Canvas2D.
40    ///
41    /// # Arguments
42    ///
43    /// - `&HtmlCanvasElement` - The `&HtmlCanvasElement` value.
44    /// - `BackendKind` - The `BackendKind` value.
45    ///
46    /// # Returns
47    ///
48    /// - `Option<Box<dyn ChartBackend>>` - The `Option<Box<dyn ChartBackend>>` value.
49    pub async fn create(
50        canvas: &HtmlCanvasElement,
51        preferred: BackendKind,
52    ) -> Option<Box<dyn ChartBackend>> {
53        let order: &[BackendKind] = match preferred {
54            BackendKind::WebGpu => &[
55                BackendKind::WebGpu,
56                BackendKind::WebGl2,
57                BackendKind::Canvas2D,
58            ],
59            BackendKind::WebGl2 => &[BackendKind::WebGl2, BackendKind::Canvas2D],
60            BackendKind::Canvas2D => &[BackendKind::Canvas2D],
61        };
62
63        for kind in order {
64            match kind {
65                BackendKind::WebGpu => {
66                    if let Some(backend) = webgpu::WebGpuChartBackend::create(canvas).await {
67                        return Some(Box::new(backend));
68                    }
69                }
70                BackendKind::WebGl2 => {
71                    if let Some(backend) = webgl::WebGl2ChartBackend::create(canvas) {
72                        return Some(Box::new(backend));
73                    }
74                }
75                BackendKind::Canvas2D => {
76                    if let Some(backend) = canvas2d::Canvas2dChartBackend::create(canvas) {
77                        return Some(Box::new(backend));
78                    }
79                }
80            }
81        }
82        None
83    }
84
85    /// Returns the backend the host would pick, without creating it.
86    ///
87    /// The check is cheap and synchronous, so a chart can report the
88    /// backend it is about to use before the asynchronous creation
89    /// finishes.
90    ///
91    /// # Arguments
92    ///
93    /// - `BackendKind` - A `BackendKind` parameter.
94    ///
95    /// # Returns
96    ///
97    /// - `BackendKind` - A `BackendKind` value.
98    pub fn detect(preferred: BackendKind) -> BackendKind {
99        if preferred == BackendKind::WebGpu && !webgpu::WebGpuChartBackend::is_supported() {
100            return if webgl::WebGl2ChartBackend::is_supported() {
101                BackendKind::WebGl2
102            } else {
103                BackendKind::Canvas2D
104            };
105        }
106        if preferred == BackendKind::WebGl2 && !webgl::WebGl2ChartBackend::is_supported() {
107            return BackendKind::Canvas2D;
108        }
109        preferred
110    }
111}