Skip to main content

iced_graphics/
compositor.rs

1//! A compositor is responsible for initializing a renderer and managing window
2//! surfaces.
3use crate::core::Color;
4use crate::core::backend;
5use crate::core::font;
6use crate::core::renderer;
7use crate::futures::{MaybeSend, MaybeSync};
8use crate::{Shell, Viewport};
9
10use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
11use thiserror::Error;
12
13use std::borrow::Cow;
14use std::fmt::Debug;
15
16/// A graphics compositor that can draw to windows.
17pub trait Compositor: Sized {
18    /// The iced renderer of the backend.
19    type Renderer;
20
21    /// The surface of the backend.
22    type Surface;
23
24    /// Creates a new [`Compositor`] with the given [`backend::Settings`].
25    fn new(
26        settings: backend::Settings,
27        display: impl Display + Clone,
28        compatible_window: impl Window + Clone,
29        shell: Shell,
30    ) -> impl Future<Output = Result<Self, backend::Error>>;
31
32    /// Creates a [`Self::Renderer`] for the [`Compositor`].
33    fn create_renderer(&self, settings: renderer::Settings) -> Self::Renderer;
34
35    /// Crates a new [`Surface`] for the given window.
36    ///
37    /// [`Surface`]: Self::Surface
38    fn create_surface(&mut self, window: impl Window + Clone) -> Self::Surface;
39
40    /// Configures a new [`Surface`] with the given dimensions.
41    ///
42    /// [`Surface`]: Self::Surface
43    fn configure_surface(&mut self, surface: &mut Self::Surface, width: u32, height: u32);
44
45    /// Returns [`Information`] used by this [`Compositor`].
46    fn information(&self) -> Information;
47
48    /// Loads a font from its bytes.
49    fn load_font(&mut self, font: Cow<'static, [u8]>) -> Result<(), font::Error> {
50        crate::text::font_system()
51            .write()
52            .expect("Write to font system")
53            .load_font(font);
54
55        // TODO: Error handling
56        Ok(())
57    }
58
59    /// Lists all the available font families.
60    fn list_fonts(&mut self) -> Result<Vec<font::Family>, font::Error> {
61        use std::collections::BTreeSet;
62
63        let font_system = crate::text::font_system()
64            .read()
65            .expect("Read from font system");
66
67        let families = BTreeSet::from_iter(font_system.families());
68
69        Ok(families.into_iter().map(font::Family::name).collect())
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(
77        &mut self,
78        renderer: &mut Self::Renderer,
79        surface: &mut Self::Surface,
80        viewport: &Viewport,
81        background_color: Color,
82        on_pre_present: impl FnOnce(),
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(
90        &mut self,
91        renderer: &mut Self::Renderer,
92        viewport: &Viewport,
93        background_color: Color,
94    ) -> Vec<u8>;
95}
96
97/// A window that can be used in a [`Compositor`].
98///
99/// This is just a convenient super trait of the `raw-window-handle`
100/// traits.
101pub trait Window: HasWindowHandle + Debug + MaybeSend + MaybeSync + 'static {}
102
103impl<T> Window for T where T: HasWindowHandle + Debug + MaybeSend + MaybeSync + 'static {}
104
105/// An owned display handle that can be used in a [`Compositor`].
106///
107/// This is just a convenient super trait of the `raw-window-handle`
108/// trait.
109pub trait Display: HasDisplayHandle + Debug + Send + Sync + 'static {}
110
111impl<T> Display for T where T: HasDisplayHandle + Debug + Send + Sync + 'static {}
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("A timeout was encountered while trying to acquire the next frame")]
124    Timeout,
125    /// The underlying surface has changed, and therefore the surface must be updated.
126    #[error("The underlying surface has changed, and therefore the surface must be updated.")]
127    Outdated,
128    /// The swap chain has been lost and needs to be recreated.
129    #[error("The surface has been lost and needs to be recreated")]
130    Lost,
131    /// There is no more memory left to allocate a new frame.
132    #[error("There is no more memory left to allocate a new frame")]
133    OutOfMemory,
134    /// The surface is occluded and must not be drawn to.
135    #[error("The surface is occluded and must not be drawn to")]
136    Occluded,
137    /// Acquiring a texture failed with a generic error.
138    #[error("Acquiring a texture failed with a generic error")]
139    Other,
140}
141
142/// Contains information about the graphics (e.g. graphics adapter, graphics backend).
143#[derive(Debug)]
144pub struct Information {
145    /// Contains the graphics adapter.
146    pub adapter: String,
147    /// Contains the graphics backend.
148    pub backend: String,
149}
150
151#[cfg(debug_assertions)]
152impl Compositor for () {
153    type Renderer = ();
154    type Surface = ();
155
156    async fn new(
157        _settings: backend::Settings,
158        _display: impl Display,
159        _compatible_window: impl Window + Clone,
160        _shell: Shell,
161    ) -> Result<Self, backend::Error> {
162        Ok(())
163    }
164
165    fn create_renderer(&self, _settings: renderer::Settings) -> Self::Renderer {}
166
167    fn create_surface(&mut self, _window: impl Window + Clone) -> Self::Surface {}
168
169    fn configure_surface(&mut self, _surface: &mut Self::Surface, _width: u32, _height: u32) {}
170
171    fn load_font(&mut self, _font: Cow<'static, [u8]>) -> Result<(), font::Error> {
172        Ok(())
173    }
174
175    fn list_fonts(&mut self) -> Result<Vec<font::Family>, font::Error> {
176        Ok(Vec::new())
177    }
178
179    fn information(&self) -> Information {
180        Information {
181            adapter: String::from("Null Renderer"),
182            backend: String::from("Null"),
183        }
184    }
185
186    fn present(
187        &mut self,
188        _renderer: &mut Self::Renderer,
189        _surface: &mut Self::Surface,
190        _viewport: &Viewport,
191        _background_color: Color,
192        _on_pre_present: impl FnOnce(),
193    ) -> Result<(), SurfaceError> {
194        Ok(())
195    }
196
197    fn screenshot(
198        &mut self,
199        _renderer: &mut Self::Renderer,
200        _viewport: &Viewport,
201        _background_color: Color,
202    ) -> Vec<u8> {
203        vec![]
204    }
205}
206
207#[cfg(debug_assertions)]
208impl Default for () {
209    type Compositor = ();
210}