miniquad/conf.rs
1//! Context creation configuration
2//!
3//! A [`Conf`] struct is used to describe a hardware and platform specific setup,
4//! mostly video display settings.
5//!
6//! ## High DPI rendering
7//!
8//! You can set the [`Conf::high_dpi`] flag during initialization to request
9//! a full-resolution framebuffer on HighDPI displays. The default behaviour
10//! is `high_dpi = false`, this means that the application will
11//! render to a lower-resolution framebuffer on HighDPI displays and the
12//! rendered content will be upscaled by the window system composer.
13//! In a HighDPI scenario, you still request the same window size during
14//! [`miniquad::start`][super::start], but the framebuffer sizes returned by
15//! [`screen_size`] will be scaled up according to the DPI scaling ratio.
16//! You can also get a DPI scaling factor with the function [`dpi_scale`].
17//!
18//! Here's an example on a Mac with Retina display:
19//! ```ignore
20//! Conf {
21//! width = 640,
22//! height = 480,
23//! high_dpi = true,
24//! .. Default::default()
25//! };
26//! ```
27//!
28//! The functions [`screen_size`] and [`dpi_scale`] will return the following values:
29//! ```bash
30//! screen_size -> (1280, 960)
31//! dpi_scale -> 2.0
32//! ```
33//!
34//! If the `high_dpi` flag is false, or you're not running on a Retina display,
35//! the values would be:
36//! ```bash
37//! screen_size -> (640, 480)
38//! dpi_scale -> 1.0
39//! ```
40//!
41//! [`dpi_scale`]: super::window::dpi_scale
42//! [`screen_size`]: super::window::screen_size
43
44/// Specifies how to load an OpenGL context on X11 in Linux.
45#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
46pub enum LinuxX11Gl {
47 /// Use `libGLX.so` (or `libGLX.so.0`) exclusively. Panics if unavailable.
48 GLXOnly,
49 /// Use `libEGL.so` (or `libEGL.so.0`) exclusively. Panics if unavailable.
50 EGLOnly,
51 /// Prefer `libGLX`; fall back to `libEGL` if `libGLX` is unavailable.
52 /// This is the default choice.
53 #[default]
54 GLXWithEGLFallback,
55 /// Prefer `libEGL`; fall back to `libGLX` if `libEGL` is unavailable.
56 EGLWithGLXFallback,
57}
58
59/// On Linux, the backend used for windowing and event handling.
60///
61/// Defaults to `X11Only`. The Wayland implementation is currently unstable
62#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
63pub enum LinuxBackend {
64 /// Use only the X11 backend. Panics if unavailable. This is the default choice.
65 #[default]
66 X11Only,
67 /// Use only the Wayland backend. Panics if unavailable.
68 WaylandOnly,
69 /// Prefer X11, fall back to Wayland if X11 is unavailable.
70 X11WithWaylandFallback,
71 /// Prefer Wayland, fall back to X11 if Wayland is unavailable.
72 WaylandWithX11Fallback,
73}
74
75/// On Apple platforms, choose the rendering API for creating contexts.
76///
77/// Miniquad always links to Metal.framework (assuming it's present),
78/// and links to OpenGL dynamically only if required.
79///
80/// Defaults to AppleGfxApi::GL for legacy reasons.
81#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
82pub enum AppleGfxApi {
83 /// Use OpenGL for Apple platforms. This is the default choice.
84 #[default]
85 OpenGl,
86 /// Use Metal for Apple platforms.
87 Metal,
88}
89
90/// On the Web, specify which WebGL version to use.
91///
92/// While miniquad itself only uses WebGL 1 features, a WebGL 2 context allows to:
93/// - Use GLES3 shaders.
94/// - Do raw WebGL2 OpenGL calls.
95#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
96pub enum WebGLVersion {
97 /// Use WebGL 1.0. This is the default choice.
98 #[default]
99 WebGL1,
100 /// Use WebGL 2.0.
101 WebGL2,
102}
103
104/// On Wayland, specify how to draw client-side decoration (CSD) if server-side decoration (SSD) is
105/// not supported (e.g., on GNOME).
106///
107/// Defaults to ServerWithLibDecorFallback
108#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
109pub enum WaylandDecorations {
110 /// If SSD is not supported, will try to load `libdecor` to draw CSD. This is the default
111 /// choice.
112 #[default]
113 ServerWithLibDecorFallback,
114 /// If SSD is not supported, draw a light gray border.
115 ServerWithMiniquadFallback,
116 /// If SSD is not supported, no CSD will be drawn.
117 ServerOnly,
118}
119
120/// Platform-specific settings.
121#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
122pub struct Platform {
123 /// Determines how to load an OpenGL context on X11 (via GLX or EGL).
124 pub linux_x11_gl: LinuxX11Gl,
125
126 /// Specifies which Linux window system (X11 or Wayland) is preferred or used.
127 pub linux_backend: LinuxBackend,
128
129 /// Specifies which WebGL version to use on the Web (1.0. or 2.0).
130 pub webgl_version: WebGLVersion,
131
132 /// Defines which rendering API to use on Apple platforms (Metal or OpenGL).
133 pub apple_gfx_api: AppleGfxApi,
134
135 /// Optional swap interval (vertical sync).
136 ///
137 /// Note that this is highly platform- and driver-dependent.
138 /// There is no guarantee the FPS will match the specified `swap_interval`.
139 /// In other words, `swap_interval` is only a hint to the GPU driver and
140 /// not a reliable way to limit the game's FPS.
141 pub swap_interval: Option<i32>,
142
143 /// If `true`, the event loop will block until [`schedule_update`] is called.
144 ///
145 /// This can reduce CPU usage to nearly zero while waiting for events.
146 ///
147 /// It is recommended to call `schedule_update` at the end of `resize_event`
148 /// or any relevant mouse/keyboard input.
149 ///
150 /// `schedule_update` may be used from other threads to "wake up" the window.
151 ///
152 /// [`schedule_update`]: super::window::schedule_update
153 pub blocking_event_loop: bool,
154
155 /// If `true`, the framebuffer includes an alpha channel.
156 /// Currently supported only on Android.
157 ///
158 /// - TODO: Make it works on web, on web it should make a transparent HTML5 canvas
159 /// - TODO: Document(and check) what does it actually mean on android. Transparent window?
160 pub framebuffer_alpha: bool,
161
162 /// On Wayland, specifies how to draw client-side decoration (CSD) if server-side decoration (SSD) is
163 /// not supported (e.g., on GNOME).
164 pub wayland_decorations: WaylandDecorations,
165
166 /// Set the `WM_CLASS` window property on X11 and the `app_id` on Wayland. This is used
167 /// by gnome to determine the window icon (together with an external `.desktop` file).
168 // in fact `WM_CLASS` contains two strings "instance name" and "class name"
169 // for most purposes they are the same so we just use class name for simplicity
170 // https://unix.stackexchange.com/questions/494169/
171 pub linux_wm_class: &'static str,
172}
173
174impl Default for Platform {
175 fn default() -> Platform {
176 Platform {
177 linux_x11_gl: LinuxX11Gl::default(),
178 linux_backend: LinuxBackend::default(),
179 apple_gfx_api: AppleGfxApi::default(),
180 webgl_version: WebGLVersion::default(),
181 blocking_event_loop: false,
182 swap_interval: None,
183 framebuffer_alpha: false,
184 wayland_decorations: WaylandDecorations::default(),
185 linux_wm_class: "miniquad-application",
186 }
187 }
188}
189
190/// Describes a hardware and platform-specific setup.
191#[derive(Debug)]
192pub struct Conf {
193 /// Window title. Defaults to an empty string.
194 pub window_title: String,
195
196 /// Preferred window width (ignored on WASM/Android).
197 /// Defaults to `800`.
198 pub window_width: i32,
199
200 /// Preferred window height (ignored on WASM/Android).
201 /// Defaults to `600`.
202 pub window_height: i32,
203
204 /// If `true`, the rendering canvas is scaled for HighDPI displays.
205 /// Defaults to `false`.
206 pub high_dpi: bool,
207
208 /// If `true`, create the window in fullscreen mode (ignored on WASM/Android).
209 /// Defaults to `false`.
210 pub fullscreen: bool,
211
212 /// MSAA sample count.
213 /// Defaults to `1`.
214 pub sample_count: i32,
215
216 /// If `true`, the user can resize the window.
217 pub window_resizable: bool,
218
219 /// Optional icon data used by the OS where applicable:
220 /// - On Windows, taskbar/title bar icon
221 /// - On macOS, Dock/title bar icon
222 /// - TODO: Favicon on HTML5
223 /// - TODO: Taskbar/title bar icon on Linux (depends on WM)
224 /// - Note: on gnome, icon is determined using `WM_CLASS` (can be set under [`Platform`]) and
225 /// an external `.desktop` file
226 pub icon: Option<Icon>,
227
228 /// Platform-specific hints (e.g., context creation, driver settings).
229 pub platform: Platform,
230}
231
232/// Icon image in three levels of detail.
233#[derive(Clone)]
234pub struct Icon {
235 /// 16 * 16 image of RGBA pixels (each 4 * u8) in row-major order.
236 pub small: [u8; 16 * 16 * 4],
237 /// 32 x 32 image of RGBA pixels (each 4 * u8) in row-major order.
238 pub medium: [u8; 32 * 32 * 4],
239 /// 64 x 64 image of RGBA pixels (each 4 * u8) in row-major order.
240 pub big: [u8; 64 * 64 * 4],
241}
242
243impl Icon {
244 pub fn miniquad_logo() -> Icon {
245 Icon {
246 small: crate::default_icon::SMALL,
247 medium: crate::default_icon::MEDIUM,
248 big: crate::default_icon::BIG,
249 }
250 }
251}
252// Printing 64x64 array with a default formatter is not meaningfull,
253// so debug will skip the data fields of an Icon
254impl std::fmt::Debug for Icon {
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 f.debug_struct("Icon").finish()
257 }
258}
259
260// reasonable defaults for PC and mobiles are slightly different
261#[cfg(not(target_os = "android"))]
262impl Default for Conf {
263 fn default() -> Conf {
264 Conf {
265 window_title: "".to_owned(),
266 window_width: 800,
267 window_height: 600,
268 high_dpi: false,
269 fullscreen: false,
270 sample_count: 1,
271 window_resizable: true,
272 icon: Some(Icon::miniquad_logo()),
273 platform: Default::default(),
274 }
275 }
276}
277
278#[cfg(target_os = "android")]
279impl Default for Conf {
280 fn default() -> Conf {
281 Conf {
282 window_title: "".to_owned(),
283 window_width: 800,
284 window_height: 600,
285 high_dpi: true,
286 fullscreen: true, //
287 sample_count: 1,
288 window_resizable: false, //
289 icon: Some(Icon::miniquad_logo()),
290 platform: Default::default(),
291 }
292 }
293}