freya_winit/drivers/
mod.rs1#[cfg(any(target_os = "linux", target_os = "windows", target_os = "android"))]
2mod gl;
3#[cfg(target_os = "macos")]
4mod metal;
5#[cfg(any(target_os = "linux", target_os = "windows"))]
6mod vulkan;
7
8use freya_engine::prelude::Surface as SkiaSurface;
9use winit::{
10 dpi::PhysicalSize,
11 event_loop::ActiveEventLoop,
12 window::{
13 Window,
14 WindowAttributes,
15 },
16};
17
18#[allow(clippy::large_enum_variant)]
19pub enum GraphicsDriver {
20 #[cfg(any(target_os = "linux", target_os = "windows", target_os = "android"))]
21 OpenGl(gl::OpenGLDriver),
22 #[cfg(target_os = "macos")]
23 Metal(metal::MetalDriver),
24 #[cfg(any(target_os = "linux", target_os = "windows"))]
25 Vulkan(vulkan::VulkanDriver),
26}
27
28impl GraphicsDriver {
29 #[allow(clippy::needless_return)]
30 pub fn new(
31 event_loop: &ActiveEventLoop,
32 window_attributes: WindowAttributes,
33 ) -> (Self, Window) {
34 #[cfg(target_os = "macos")]
36 {
37 let (driver, window) = metal::MetalDriver::new(event_loop, window_attributes);
38
39 return (Self::Metal(driver), window);
40 }
41
42 #[cfg(target_os = "android")]
44 {
45 let (driver, window) = gl::OpenGLDriver::new(event_loop, window_attributes);
46
47 return (Self::OpenGl(driver), window);
48 }
49
50 #[cfg(all(not(target_os = "macos"), not(target_os = "android")))]
53 {
54 let force_opengl =
55 std::env::var("FREYA_RENDERER").is_ok_and(|v| v.eq_ignore_ascii_case("opengl"));
56
57 if !force_opengl {
58 let vk_attrs = window_attributes.clone();
59 match vulkan::VulkanDriver::new(event_loop, vk_attrs) {
60 Ok((driver, window)) => return (Self::Vulkan(driver), window),
61 Err(err) => {
62 tracing::warn!(
63 "Vulkan initialization failed, falling back to OpenGL: {err}"
64 );
65 }
66 }
67 }
68
69 let (driver, window) = gl::OpenGLDriver::new(event_loop, window_attributes);
70
71 return (Self::OpenGl(driver), window);
72 }
73 }
74
75 pub fn present(
76 &mut self,
77 _size: PhysicalSize<u32>,
78 window: &Window,
79 render: impl FnOnce(&mut SkiaSurface),
80 ) {
81 match self {
82 #[cfg(any(target_os = "linux", target_os = "windows", target_os = "android"))]
83 Self::OpenGl(gl) => gl.present(window, render),
84 #[cfg(target_os = "macos")]
85 Self::Metal(mtl) => mtl.present(_size, window, render),
86 #[cfg(any(target_os = "linux", target_os = "windows"))]
87 Self::Vulkan(vk) => vk.present(_size, window, render),
88 }
89 }
90
91 pub fn name(&self) -> &'static str {
93 match self {
94 #[cfg(any(target_os = "linux", target_os = "windows", target_os = "android"))]
95 Self::OpenGl(_) => "OpenGL",
96 #[cfg(target_os = "macos")]
97 Self::Metal(_) => "Metal",
98 #[cfg(any(target_os = "linux", target_os = "windows"))]
99 Self::Vulkan(_) => "Vulkan",
100 }
101 }
102
103 pub fn resize(&mut self, size: PhysicalSize<u32>) {
104 match self {
105 #[cfg(any(target_os = "linux", target_os = "windows", target_os = "android"))]
106 Self::OpenGl(gl) => gl.resize(size),
107 #[cfg(target_os = "macos")]
108 Self::Metal(mtl) => mtl.resize(size),
109 #[cfg(any(target_os = "linux", target_os = "windows"))]
110 Self::Vulkan(vk) => vk.resize(size),
111 }
112 }
113}