Skip to main content

lgui_core/application/
error.rs

1use std::sync::Arc;
2
3use super::WindowId;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub enum RenderErrorStage {
7    Create,
8    Prepare,
9    Draw,
10    Copy,
11    Present,
12    Commit,
13}
14
15impl RenderErrorStage {
16    pub const fn as_str(self) -> &'static str {
17        match self {
18            Self::Create => "create",
19            Self::Prepare => "prepare",
20            Self::Draw => "draw",
21            Self::Copy => "copy",
22            Self::Present => "present",
23            Self::Commit => "commit",
24        }
25    }
26}
27
28type RenderErrorHandler = Arc<dyn Fn(&RenderError) + Send + Sync + 'static>;
29
30#[derive(Clone)]
31pub(crate) struct RenderErrorRegistration {
32    handler: RenderErrorHandler,
33}
34
35impl RenderErrorRegistration {
36    pub(crate) fn new(handler: impl Fn(&RenderError) + Send + Sync + 'static) -> Self {
37        Self {
38            handler: Arc::new(handler),
39        }
40    }
41
42    pub(crate) fn report(&self, error: &RenderError) {
43        (self.handler)(error);
44    }
45}
46
47/// A renderer failure reported at the application boundary.
48///
49/// Rendering backends remain independent from the application's logging stack. Applications can
50/// install a handler with [`super::Application::on_render_error`] and decide whether a failure
51/// belongs in a local log, diagnostics UI, telemetry, or another reporting destination.
52#[derive(Clone, Debug, PartialEq, Eq)]
53pub struct RenderError {
54    window: WindowId,
55    renderer: &'static str,
56    stage: RenderErrorStage,
57    operation: &'static str,
58    code: i32,
59    message: String,
60}
61
62impl RenderError {
63    pub(crate) fn new(
64        window: WindowId,
65        renderer: &'static str,
66        stage: RenderErrorStage,
67        operation: &'static str,
68        code: i32,
69        message: impl Into<String>,
70    ) -> Self {
71        Self {
72            window,
73            renderer,
74            stage,
75            operation,
76            code,
77            message: message.into(),
78        }
79    }
80
81    pub fn window(&self) -> &WindowId {
82        &self.window
83    }
84
85    pub const fn renderer(&self) -> &'static str {
86        self.renderer
87    }
88
89    pub const fn stage(&self) -> RenderErrorStage {
90        self.stage
91    }
92
93    pub const fn operation(&self) -> &'static str {
94        self.operation
95    }
96
97    pub const fn code(&self) -> i32 {
98        self.code
99    }
100
101    pub fn message(&self) -> &str {
102        &self.message
103    }
104}
105
106impl std::fmt::Display for RenderError {
107    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        write!(
109            formatter,
110            "renderer '{}' failed to {} window '{}' during {} (0x{:08X}): {}",
111            self.renderer,
112            self.operation,
113            self.window.as_str(),
114            self.stage.as_str(),
115            self.code as u32,
116            self.message
117        )
118    }
119}
120
121impl std::error::Error for RenderError {}