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 renderer = std::env::var("FREYA_RENDERER");
55
56 let use_vulkan = if cfg!(target_os = "windows") {
57 renderer.is_ok_and(|v| v.eq_ignore_ascii_case("vulkan"))
58 } else {
59 !renderer.is_ok_and(|v| v.eq_ignore_ascii_case("opengl"))
60 };
61
62 if use_vulkan {
63 let vk_attrs = window_attributes.clone();
64 match vulkan::VulkanDriver::new(event_loop, vk_attrs) {
65 Ok((driver, window)) => return (Self::Vulkan(driver), window),
66 Err(err) => {
67 tracing::warn!(
68 "Vulkan initialization failed, falling back to OpenGL: {err}"
69 );
70 }
71 }
72 }
73
74 let (driver, window) = gl::OpenGLDriver::new(event_loop, window_attributes);
75
76 return (Self::OpenGl(driver), window);
77 }
78 }
79
80 pub fn present(
81 &mut self,
82 _size: PhysicalSize<u32>,
83 window: &Window,
84 render: impl FnOnce(&mut SkiaSurface),
85 ) {
86 match self {
87 #[cfg(any(target_os = "linux", target_os = "windows", target_os = "android"))]
88 Self::OpenGl(gl) => gl.present(window, render),
89 #[cfg(target_os = "macos")]
90 Self::Metal(mtl) => mtl.present(_size, window, render),
91 #[cfg(any(target_os = "linux", target_os = "windows"))]
92 Self::Vulkan(vk) => vk.present(_size, window, render),
93 }
94 }
95
96 pub fn name(&self) -> &'static str {
98 match self {
99 #[cfg(any(target_os = "linux", target_os = "windows", target_os = "android"))]
100 Self::OpenGl(_) => "OpenGL",
101 #[cfg(target_os = "macos")]
102 Self::Metal(_) => "Metal",
103 #[cfg(any(target_os = "linux", target_os = "windows"))]
104 Self::Vulkan(_) => "Vulkan",
105 }
106 }
107
108 pub fn resize(&mut self, size: PhysicalSize<u32>) {
109 match self {
110 #[cfg(any(target_os = "linux", target_os = "windows", target_os = "android"))]
111 Self::OpenGl(gl) => gl.resize(size),
112 #[cfg(target_os = "macos")]
113 Self::Metal(mtl) => mtl.resize(size),
114 #[cfg(any(target_os = "linux", target_os = "windows"))]
115 Self::Vulkan(vk) => vk.resize(size),
116 }
117 }
118}