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(
59        &mut self,
60        surface: &mut Self::Surface,
61        width: u32,
62        height: u32,
63    );
64
65    /// Returns [`Information`] used by this [`Compositor`].
66    fn information(&self) -> Information;
67
68    /// Loads a font from its bytes.
69    fn load_font(&mut self, font: Cow<'static, [u8]>) {
70        crate::text::font_system()
71            .write()
72            .expect("Write to font system")
73            .load_font(font);
74    }
75
76    /// Presents the [`Renderer`] primitives to the next frame of the given [`Surface`].
77    ///
78    /// [`Renderer`]: Self::Renderer
79    /// [`Surface`]: Self::Surface
80    fn present(
81        &mut self,
82        renderer: &mut Self::Renderer,
83        surface: &mut Self::Surface,
84        viewport: &Viewport,
85        background_color: Color,
86        on_pre_present: impl FnOnce(),
87    ) -> Result<(), SurfaceError>;
88
89    /// Screenshots the current [`Renderer`] primitives to an offscreen texture, and returns the bytes of
90    /// the texture ordered as `RGBA` in the `sRGB` color space.
91    ///
92    /// [`Renderer`]: Self::Renderer
93    fn screenshot(
94        &mut self,
95        renderer: &mut Self::Renderer,
96        viewport: &Viewport,
97        background_color: Color,
98    ) -> Vec<u8>;
99}
100
101/// A window that can be used in a [`Compositor`].
102///
103/// This is just a convenient super trait of the `raw-window-handle`
104/// traits.
105pub trait Window:
106    HasWindowHandle + HasDisplayHandle + MaybeSend + MaybeSync + 'static
107{
108}
109
110impl<T> Window for T where
111    T: HasWindowHandle + HasDisplayHandle + MaybeSend + MaybeSync + 'static
112{
113}
114
115/// An owned display handle that can be used in a [`Compositor`].
116///
117/// This is just a convenient super trait of the `raw-window-handle`
118/// trait.
119pub trait Display: HasDisplayHandle + MaybeSend + MaybeSync + 'static {}
120
121impl<T> Display for T where T: HasDisplayHandle + MaybeSend + MaybeSync + 'static
122{}
123
124/// Defines the default compositor of a renderer.
125pub trait Default {
126    /// The compositor of the renderer.
127    type Compositor: Compositor<Renderer = Self>;
128}
129
130/// Result of an unsuccessful call to [`Compositor::present`].
131#[derive(Clone, PartialEq, Eq, Debug, Error)]
132pub enum SurfaceError {
133    /// A timeout was encountered while trying to acquire the next frame.
134    #[error("A timeout was encountered while trying to acquire the next frame")]
135    Timeout,
136    /// The underlying surface has changed, and therefore the surface must be updated.
137    #[error(
138        "The underlying surface has changed, and therefore the surface must be updated."
139    )]
140    Outdated,
141    /// The swap chain has been lost and needs to be recreated.
142    #[error("The surface has been lost and needs to be recreated")]
143    Lost,
144    /// There is no more memory left to allocate a new frame.
145    #[error("There is no more memory left to allocate a new frame")]
146    OutOfMemory,
147    /// Acquiring a texture failed with a generic error.
148    #[error("Acquiring a texture failed with a generic error")]
149    Other,
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(
167        _settings: Settings,
168        _display: impl Display,
169        _compatible_window: impl Window + Clone,
170        _shell: Shell,
171        _preferred_backend: Option<&str>,
172    ) -> Result<Self, Error> {
173        Ok(())
174    }
175
176    fn create_renderer(&self) -> Self::Renderer {}
177
178    fn create_surface<W: Window + Clone>(
179        &mut self,
180        _window: W,
181        _width: u32,
182        _height: u32,
183    ) -> Self::Surface {
184    }
185
186    fn configure_surface(
187        &mut self,
188        _surface: &mut Self::Surface,
189        _width: u32,
190        _height: u32,
191    ) {
192    }
193
194    fn load_font(&mut self, _font: Cow<'static, [u8]>) {}
195
196    fn information(&self) -> Information {
197        Information {
198            adapter: String::from("Null Renderer"),
199            backend: String::from("Null"),
200        }
201    }
202
203    fn present(
204        &mut self,
205        _renderer: &mut Self::Renderer,
206        _surface: &mut Self::Surface,
207        _viewport: &Viewport,
208        _background_color: Color,
209        _on_pre_present: impl FnOnce(),
210    ) -> Result<(), SurfaceError> {
211        Ok(())
212    }
213
214    fn screenshot(
215        &mut self,
216        _renderer: &mut Self::Renderer,
217        _viewport: &Viewport,
218        _background_color: Color,
219    ) -> Vec<u8> {
220        vec![]
221    }
222}
223
224#[cfg(debug_assertions)]
225impl Default for () {
226    type Compositor = ();
227}