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;
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<W: Window + Clone>(
22        settings: Settings,
23        compatible_window: W,
24    ) -> impl Future<Output = Result<Self, Error>> {
25        Self::with_backend(settings, compatible_window, None)
26    }
27
28    /// Creates a new [`Compositor`] with a backend preference.
29    ///
30    /// If the backend does not match the preference, it will return
31    /// [`Error::GraphicsAdapterNotFound`].
32    fn with_backend<W: Window + Clone>(
33        _settings: Settings,
34        _compatible_window: W,
35        _backend: Option<&str>,
36    ) -> impl Future<Output = Result<Self, Error>>;
37
38    /// Creates a [`Self::Renderer`] for the [`Compositor`].
39    fn create_renderer(&self) -> Self::Renderer;
40
41    /// Crates a new [`Surface`] for the given window.
42    ///
43    /// [`Surface`]: Self::Surface
44    fn create_surface<W: Window + Clone>(
45        &mut self,
46        window: W,
47        width: u32,
48        height: u32,
49    ) -> Self::Surface;
50
51    /// Configures a new [`Surface`] with the given dimensions.
52    ///
53    /// [`Surface`]: Self::Surface
54    fn configure_surface(
55        &mut self,
56        surface: &mut Self::Surface,
57        width: u32,
58        height: u32,
59    );
60
61    /// Returns [`Information`] used by this [`Compositor`].
62    fn fetch_information(&self) -> Information;
63
64    /// Loads a font from its bytes.
65    fn load_font(&mut self, font: Cow<'static, [u8]>) {
66        crate::text::font_system()
67            .write()
68            .expect("Write to font system")
69            .load_font(font);
70    }
71
72    /// Presents the [`Renderer`] primitives to the next frame of the given [`Surface`].
73    ///
74    /// [`Renderer`]: Self::Renderer
75    /// [`Surface`]: Self::Surface
76    fn present<T: AsRef<str>>(
77        &mut self,
78        renderer: &mut Self::Renderer,
79        surface: &mut Self::Surface,
80        viewport: &Viewport,
81        background_color: Color,
82        overlay: &[T],
83    ) -> Result<(), SurfaceError>;
84
85    /// Screenshots the current [`Renderer`] primitives to an offscreen texture, and returns the bytes of
86    /// the texture ordered as `RGBA` in the `sRGB` color space.
87    ///
88    /// [`Renderer`]: Self::Renderer
89    fn screenshot<T: AsRef<str>>(
90        &mut self,
91        renderer: &mut Self::Renderer,
92        viewport: &Viewport,
93        background_color: Color,
94        overlay: &[T],
95    ) -> Vec<u8>;
96}
97
98/// A window that can be used in a [`Compositor`].
99///
100/// This is just a convenient super trait of the `raw-window-handle`
101/// traits.
102pub trait Window:
103    HasWindowHandle + HasDisplayHandle + MaybeSend + MaybeSync + 'static
104{
105}
106
107impl<T> Window for T where
108    T: HasWindowHandle + HasDisplayHandle + MaybeSend + MaybeSync + 'static
109{
110}
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(
126        "The underlying surface has changed, and therefore the surface must be updated."
127    )]
128    Outdated,
129    /// The swap chain has been lost and needs to be recreated.
130    #[error("The surface has been lost and needs to be recreated")]
131    Lost,
132    /// There is no more memory left to allocate a new frame.
133    #[error("There is no more memory left to allocate a new frame")]
134    OutOfMemory,
135    /// Acquiring a texture failed with a generic error.
136    #[error("Acquiring a texture failed with a generic error")]
137    Other,
138}
139
140/// Contains information about the graphics (e.g. graphics adapter, graphics backend).
141#[derive(Debug)]
142pub struct Information {
143    /// Contains the graphics adapter.
144    pub adapter: String,
145    /// Contains the graphics backend.
146    pub backend: String,
147}
148
149#[cfg(debug_assertions)]
150impl Compositor for () {
151    type Renderer = ();
152    type Surface = ();
153
154    async fn with_backend<W: Window + Clone>(
155        _settings: Settings,
156        _compatible_window: W,
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(
173        &mut self,
174        _surface: &mut Self::Surface,
175        _width: u32,
176        _height: u32,
177    ) {
178    }
179
180    fn load_font(&mut self, _font: Cow<'static, [u8]>) {}
181
182    fn fetch_information(&self) -> Information {
183        Information {
184            adapter: String::from("Null Renderer"),
185            backend: String::from("Null"),
186        }
187    }
188
189    fn present<T: AsRef<str>>(
190        &mut self,
191        _renderer: &mut Self::Renderer,
192        _surface: &mut Self::Surface,
193        _viewport: &Viewport,
194        _background_color: Color,
195        _overlay: &[T],
196    ) -> Result<(), SurfaceError> {
197        Ok(())
198    }
199
200    fn screenshot<T: AsRef<str>>(
201        &mut self,
202        _renderer: &mut Self::Renderer,
203        _viewport: &Viewport,
204        _background_color: Color,
205        _overlay: &[T],
206    ) -> Vec<u8> {
207        vec![]
208    }
209}
210
211#[cfg(debug_assertions)]
212impl Default for () {
213    type Compositor = ();
214}