iced_graphics/
compositor.rs

1//! A compositor is responsible for initializing a renderer and managing window
2//! surfaces.
3use crate::core::Color;
4use crate::futures::{MaybeSend, MaybeSync};
5use crate::{Error, Settings, Viewport};
6
7use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
8use thiserror::Error;
9
10use std::borrow::Cow;
11use std::future::Future;
12
13/// A graphics compositor that can draw to windows.
14pub trait Compositor: Sized {
15    /// The iced renderer of the backend.
16    type Renderer;
17
18    /// The surface of the backend.
19    type Surface;
20
21    /// Creates a new [`Compositor`].
22    fn new<W: Window + Clone>(
23        settings: Settings,
24        compatible_window: W,
25    ) -> impl Future<Output = Result<Self, Error>> {
26        Self::with_backend(settings, compatible_window, None)
27    }
28
29    /// Creates a new [`Compositor`] with a backend preference.
30    ///
31    /// If the backend does not match the preference, it will return
32    /// [`Error::GraphicsAdapterNotFound`].
33    fn with_backend<W: Window + Clone>(
34        _settings: Settings,
35        _compatible_window: W,
36        _backend: Option<&str>,
37    ) -> impl Future<Output = Result<Self, Error>>;
38
39    /// Creates a [`Self::Renderer`] for the [`Compositor`].
40    fn create_renderer(&self) -> Self::Renderer;
41
42    /// Crates a new [`Surface`] for the given window.
43    ///
44    /// [`Surface`]: Self::Surface
45    fn create_surface<W: Window + Clone>(
46        &mut self,
47        window: W,
48        width: u32,
49        height: u32,
50    ) -> Self::Surface;
51
52    /// Configures a new [`Surface`] with the given dimensions.
53    ///
54    /// [`Surface`]: Self::Surface
55    fn configure_surface(
56        &mut self,
57        surface: &mut Self::Surface,
58        width: u32,
59        height: u32,
60    );
61
62    /// Returns [`Information`] used by this [`Compositor`].
63    fn fetch_information(&self) -> Information;
64
65    /// Loads a font from its bytes.
66    fn load_font(&mut self, font: Cow<'static, [u8]>) {
67        crate::text::font_system()
68            .write()
69            .expect("Write to font system")
70            .load_font(font);
71    }
72
73    /// Presents the [`Renderer`] primitives to the next frame of the given [`Surface`].
74    ///
75    /// [`Renderer`]: Self::Renderer
76    /// [`Surface`]: Self::Surface
77    fn present<T: AsRef<str>>(
78        &mut self,
79        renderer: &mut Self::Renderer,
80        surface: &mut Self::Surface,
81        viewport: &Viewport,
82        background_color: Color,
83        overlay: &[T],
84    ) -> Result<(), SurfaceError>;
85
86    /// Screenshots the current [`Renderer`] primitives to an offscreen texture, and returns the bytes of
87    /// the texture ordered as `RGBA` in the `sRGB` color space.
88    ///
89    /// [`Renderer`]: Self::Renderer
90    fn screenshot<T: AsRef<str>>(
91        &mut self,
92        renderer: &mut Self::Renderer,
93        viewport: &Viewport,
94        background_color: Color,
95        overlay: &[T],
96    ) -> Vec<u8>;
97}
98
99/// A window that can be used in a [`Compositor`].
100///
101/// This is just a convenient super trait of the `raw-window-handle`
102/// traits.
103pub trait Window:
104    HasWindowHandle + HasDisplayHandle + MaybeSend + MaybeSync + 'static
105{
106}
107
108impl<T> Window for T where
109    T: HasWindowHandle + HasDisplayHandle + MaybeSend + MaybeSync + 'static
110{
111}
112
113/// Defines the default compositor of a renderer.
114pub trait Default {
115    /// The compositor of the renderer.
116    type Compositor: Compositor<Renderer = Self>;
117}
118
119/// Result of an unsuccessful call to [`Compositor::present`].
120#[derive(Clone, PartialEq, Eq, Debug, Error)]
121pub enum SurfaceError {
122    /// A timeout was encountered while trying to acquire the next frame.
123    #[error(
124        "A timeout was encountered while trying to acquire the next frame"
125    )]
126    Timeout,
127    /// The underlying surface has changed, and therefore the surface must be updated.
128    #[error(
129        "The underlying surface has changed, and therefore the surface must be updated."
130    )]
131    Outdated,
132    /// The swap chain has been lost and needs to be recreated.
133    #[error("The surface has been lost and needs to be recreated")]
134    Lost,
135    /// There is no more memory left to allocate a new frame.
136    #[error("There is no more memory left to allocate a new frame")]
137    OutOfMemory,
138    /// Resize Error
139    #[error("Resize Error")]
140    Resize,
141    /// Invalid dimensions
142    #[error("Invalid dimensions")]
143    InvalidDimensions,
144    /// Present Error
145    #[error("Present Error")]
146    Present(String),
147    /// Present Error
148    #[error("No damage to present")]
149    NoDamage,
150}
151
152/// Contains information about the graphics (e.g. graphics adapter, graphics backend).
153#[derive(Debug)]
154pub struct Information {
155    /// Contains the graphics adapter.
156    pub adapter: String,
157    /// Contains the graphics backend.
158    pub backend: String,
159}
160
161#[cfg(debug_assertions)]
162impl Compositor for () {
163    type Renderer = ();
164    type Surface = ();
165
166    async fn with_backend<W: Window + Clone>(
167        _settings: Settings,
168        _compatible_window: W,
169        _preferred_backend: Option<&str>,
170    ) -> Result<Self, Error> {
171        Ok(())
172    }
173
174    fn create_renderer(&self) -> Self::Renderer {}
175
176    fn create_surface<W: Window + Clone>(
177        &mut self,
178        _window: W,
179        _width: u32,
180        _height: u32,
181    ) -> Self::Surface {
182    }
183
184    fn configure_surface(
185        &mut self,
186        _surface: &mut Self::Surface,
187        _width: u32,
188        _height: u32,
189    ) {
190    }
191
192    fn load_font(&mut self, _font: Cow<'static, [u8]>) {}
193
194    fn fetch_information(&self) -> Information {
195        Information {
196            adapter: String::from("Null Renderer"),
197            backend: String::from("Null"),
198        }
199    }
200
201    fn present<T: AsRef<str>>(
202        &mut self,
203        _renderer: &mut Self::Renderer,
204        _surface: &mut Self::Surface,
205        _viewport: &Viewport,
206        _background_color: Color,
207        _overlay: &[T],
208    ) -> Result<(), SurfaceError> {
209        Ok(())
210    }
211
212    fn screenshot<T: AsRef<str>>(
213        &mut self,
214        _renderer: &mut Self::Renderer,
215        _viewport: &Viewport,
216        _background_color: Color,
217        _overlay: &[T],
218    ) -> Vec<u8> {
219        vec![]
220    }
221}
222
223#[cfg(debug_assertions)]
224impl Default for () {
225    type Compositor = ();
226}