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