Skip to main content

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