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