Skip to main content

ferroui_base/platform/
i_render_target.rs

1use super::IDrawingContextImpl;
2use crate::rendering::composition::CompositionTransparencyLevel;
3use crate::{PixelSize, RenderTargetCorruptedException, RenderTargetNotReadyException, Size};
4use std::any::Any;
5use std::error::Error;
6use std::fmt;
7
8/// Why a frame could not be begun on a render target: the two exceptions
9/// the compositor of the reference catches around the creation of a
10/// drawing context. Neither is a fault: a target that is not ready is
11/// asked again later, and a corrupted one is released and created anew.
12#[derive(Clone, Debug)]
13pub enum RenderTargetError {
14    /// The target cannot be drawn to yet.
15    NotReady(RenderTargetNotReadyException),
16    /// The target can no longer be drawn to.
17    Corrupted(RenderTargetCorruptedException),
18}
19
20impl fmt::Display for RenderTargetError {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        match self {
23            RenderTargetError::NotReady(error) => error.fmt(f),
24            RenderTargetError::Corrupted(error) => error.fmt(f),
25        }
26    }
27}
28
29impl Error for RenderTargetError {
30    fn source(&self) -> Option<&(dyn Error + 'static)> {
31        match self {
32            RenderTargetError::NotReady(error) => Some(error),
33            RenderTargetError::Corrupted(error) => Some(error),
34        }
35    }
36}
37
38impl From<RenderTargetNotReadyException> for RenderTargetError {
39    fn from(error: RenderTargetNotReadyException) -> Self {
40        RenderTargetError::NotReady(error)
41    }
42}
43
44impl From<RenderTargetCorruptedException> for RenderTargetError {
45    fn from(error: RenderTargetCorruptedException) -> Self {
46        RenderTargetError::Corrupted(error)
47    }
48}
49
50/// The readiness of a platform render target.
51#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
52pub struct PlatformRenderTargetState {
53    pub is_ready: bool,
54    pub will_wake_up_render_loop_when_ready: bool,
55    pub is_corrupted: bool,
56}
57
58impl PlatformRenderTargetState {
59    pub const READY: Self = Self { is_ready: true, will_wake_up_render_loop_when_ready: false, is_corrupted: false };
60    pub const NOT_READY_TRY_LATER: Self =
61        Self { is_ready: false, will_wake_up_render_loop_when_ready: false, is_corrupted: false };
62    pub const CORRUPTED: Self = Self { is_ready: true, will_wake_up_render_loop_when_ready: false, is_corrupted: true };
63    pub const DISPOSED: Self = Self { is_ready: false, will_wake_up_render_loop_when_ready: false, is_corrupted: true };
64    pub const NOT_READY_WILL_WAKEUP_RENDER_LOOP: Self =
65        Self { is_ready: false, will_wake_up_render_loop_when_ready: true, is_corrupted: false };
66}
67
68/// Static properties of a render target.
69#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
70pub struct RenderTargetProperties {
71    /// Whether the render target retains the contents of the previous frame
72    /// when a new drawing context is created.
73    pub retains_previous_frame_contents: bool,
74    /// Whether it's worth to render directly to this target rather than
75    /// through an intermediate surface.
76    pub is_suitable_for_direct_rendering: bool,
77}
78
79/// Properties of one drawing context created from a render target.
80#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
81pub struct RenderTargetDrawingContextProperties {
82    /// Whether the previous frame's contents are available in this context.
83    pub previous_frame_is_retained: bool,
84}
85
86/// Describes the scene a drawing context is requested for.
87#[derive(Clone)]
88pub struct RenderTargetSceneInfo {
89    /// The scene size in device pixels.
90    pub size: PixelSize,
91    /// The scaling from logical units to device pixels.
92    pub scaling: f64,
93    /// The scene size in logical units.
94    pub logical_size: Size,
95    /// The transparency level the scene is composed with.
96    pub transparency_level: CompositionTransparencyLevel,
97    /// Backend-specific information about the scene.
98    pub platform_specific_scene_info: Option<std::sync::Arc<dyn Any + Send + Sync>>,
99}
100
101impl RenderTargetSceneInfo {
102    pub fn new(size: PixelSize, scaling: f64, transparency_level: CompositionTransparencyLevel) -> Self {
103        Self {
104            size,
105            scaling,
106            logical_size: size.to_size(scaling),
107            transparency_level,
108            platform_specific_scene_info: None,
109        }
110    }
111}
112
113/// Represents a render target: something a scene can be drawn to.
114pub trait IRenderTarget {
115    /// The properties of this render target.
116    fn properties(&self) -> RenderTargetProperties;
117
118    /// Creates a drawing context for a rendering session.
119    fn create_drawing_context(
120        &self,
121        scene_info: &RenderTargetSceneInfo,
122    ) -> (Box<dyn IDrawingContextImpl>, RenderTargetDrawingContextProperties);
123
124    /// Creates a drawing context for a rendering session, or says that the
125    /// target is not ready or is corrupted: what the reference reports by
126    /// throwing `RenderTargetNotReadyException` or
127    /// `RenderTargetCorruptedException` out of `CreateDrawingContext`. The
128    /// compositor calls this member. A target that cannot report either
129    /// keeps the default.
130    fn try_create_drawing_context(
131        &self,
132        scene_info: &RenderTargetSceneInfo,
133    ) -> Result<(Box<dyn IDrawingContextImpl>, RenderTargetDrawingContextProperties), RenderTargetError> {
134        Ok(self.create_drawing_context(scene_info))
135    }
136
137    /// The readiness of the underlying platform target.
138    fn platform_render_target_state(&self) -> PlatformRenderTargetState {
139        PlatformRenderTargetState::READY
140    }
141
142    /// Releases the render target.
143    fn dispose(&self);
144}