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