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