kas_core/runner/
common.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Public items common to all backends
7
8use crate::draw::color::Rgba;
9use crate::draw::{DrawIface, DrawSharedImpl, WindowCommon};
10use crate::geom::Size;
11use raw_window_handle as rwh;
12use std::time::Instant;
13use thiserror::Error;
14
15/// Possible launch failures
16///
17/// Some variants are undocumented. Users should not match these variants since
18/// they are not considered part of the public API.
19#[non_exhaustive]
20#[derive(Error, Debug)]
21pub enum Error {
22    /// Window-handle error
23    #[error(transparent)]
24    Handle(#[from] rwh::HandleError),
25
26    /// Failure from the graphics sub-system
27    #[error("error from graphics sub-system")]
28    Graphics(Box<dyn std::error::Error + 'static>),
29
30    /// Config load/save error
31    #[error("config load/save error")]
32    Config(#[from] kas::config::Error),
33
34    /// Event loop error
35    #[error("event loop")]
36    EventLoop(#[from] winit::error::EventLoopError),
37}
38
39impl From<winit::error::OsError> for Error {
40    fn from(error: winit::error::OsError) -> Self {
41        Error::EventLoop(winit::error::EventLoopError::Os(error))
42    }
43}
44
45/// A `Result` type representing `T` or [`enum@Error`]
46pub type Result<T> = std::result::Result<T, Error>;
47
48/// Enumeration of platforms
49///
50/// Each option is compile-time enabled only if that platform is possible.
51/// Methods like [`Self::is_wayland`] are available on all platforms.
52#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
53#[non_exhaustive]
54pub enum Platform {
55    #[cfg(target_os = "android")]
56    Android,
57    #[cfg(target_os = "ios")]
58    IOS,
59    #[cfg(target_os = "macos")]
60    MacOS,
61    #[cfg(any(
62        target_os = "linux",
63        target_os = "dragonfly",
64        target_os = "freebsd",
65        target_os = "netbsd",
66        target_os = "openbsd"
67    ))]
68    Wayland,
69    #[cfg(target_arch = "wasm32")]
70    Web,
71    #[cfg(target_os = "windows")]
72    Windows,
73    #[cfg(any(
74        target_os = "linux",
75        target_os = "dragonfly",
76        target_os = "freebsd",
77        target_os = "netbsd",
78        target_os = "openbsd"
79    ))]
80    X11,
81}
82
83impl Platform {
84    /// True if the platform is Android
85    pub fn is_android(&self) -> bool {
86        cfg_if::cfg_if! {
87            if #[cfg(target_os = "android")] {
88                true
89            } else {
90                false
91            }
92        }
93    }
94
95    /// True if the platform is IOS
96    pub fn is_ios(&self) -> bool {
97        cfg_if::cfg_if! {
98            if #[cfg(target_os = "ios")] {
99                true
100            } else {
101                false
102            }
103        }
104    }
105
106    /// True if the platform is MacOS
107    pub fn is_macos(&self) -> bool {
108        cfg_if::cfg_if! {
109            if #[cfg(target_os = "macos")] {
110                true
111            } else {
112                false
113            }
114        }
115    }
116
117    /// True if the platform is Wayland
118    pub fn is_wayland(&self) -> bool {
119        cfg_if::cfg_if! {
120            if #[cfg(any(
121                target_os = "linux",
122                target_os = "dragonfly",
123                target_os = "freebsd",
124                target_os = "netbsd",
125                target_os = "openbsd"
126            ))] {
127                matches!(self, Platform::Wayland)
128            } else {
129                false
130            }
131        }
132    }
133
134    /// True if the platform is Web
135    pub fn is_web(&self) -> bool {
136        cfg_if::cfg_if! {
137            if #[cfg(target_arch = "wasm32")] {
138                true
139            } else {
140                false
141            }
142        }
143    }
144
145    /// True if the platform is Windows
146    pub fn is_windows(&self) -> bool {
147        cfg_if::cfg_if! {
148            if #[cfg(target_os = "windows")] {
149                true
150            } else {
151                false
152            }
153        }
154    }
155
156    /// True if the platform is X11
157    pub fn is_x11(&self) -> bool {
158        cfg_if::cfg_if! {
159            if #[cfg(any(
160                target_os = "linux",
161                target_os = "dragonfly",
162                target_os = "freebsd",
163                target_os = "netbsd",
164                target_os = "openbsd"
165            ))] {
166                matches!(self, Platform::X11)
167            } else {
168                false
169            }
170        }
171    }
172}
173
174/// Context for a graphics backend
175pub trait GraphicsInstance {
176    /// Draw state shared by all windows
177    type Shared: DrawSharedImpl;
178
179    /// Window surface
180    type Surface<'a>: WindowSurface<Shared = Self::Shared>;
181
182    /// Construct shared state
183    ///
184    /// Providing a `surface` may aid construction of a graphics adapter
185    /// (see [`compatible_surface`](https://docs.rs/wgpu/latest/wgpu/type.RequestAdapterOptions.html#structfield.compatible_surface)).
186    fn new_shared(&mut self, surface: Option<&Self::Surface<'_>>) -> Result<Self::Shared>;
187
188    /// Construct a window surface
189    ///
190    /// It is required to call [`WindowSurface::configure`] after this.
191    fn new_surface<'window, W>(
192        &mut self,
193        window: W,
194        transparent: bool,
195    ) -> Result<Self::Surface<'window>>
196    where
197        W: rwh::HasWindowHandle + rwh::HasDisplayHandle + Send + Sync + 'window,
198        Self: Sized;
199}
200
201/// Window graphical surface requirements
202pub trait WindowSurface {
203    /// Shared draw state
204    type Shared: kas::draw::DrawSharedImpl;
205
206    /// Get current surface size
207    fn size(&self) -> Size;
208
209    /// Resize surface
210    ///
211    /// Returns `true` when the new `size` did not match the old surface size.
212    fn configure(&mut self, shared: &mut Self::Shared, size: Size) -> bool;
213
214    /// Construct a DrawIface object
215    fn draw_iface<'iface>(
216        &'iface mut self,
217        shared: &'iface mut kas::draw::SharedState<Self::Shared>,
218    ) -> DrawIface<'iface, Self::Shared>;
219
220    /// Access common data
221    fn common_mut(&mut self) -> &mut WindowCommon;
222
223    /// Present frame
224    ///
225    /// Return time at which render finishes
226    fn present(&mut self, shared: &mut Self::Shared, clear_color: Rgba) -> Instant;
227}