1use crate::{
2 hal_api::HalApi,
3 hub::{HubReport, Hubs},
4 id,
5 identity::GlobalIdentityHandlerFactory,
6 instance::{Instance, Surface},
7 registry::Registry,
8 storage::{Element, StorageReport},
9};
10
11#[derive(Debug)]
12pub struct GlobalReport {
13 pub surfaces: StorageReport,
14 #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
15 pub vulkan: Option<HubReport>,
16 #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
17 pub metal: Option<HubReport>,
18 #[cfg(all(feature = "dx12", windows))]
19 pub dx12: Option<HubReport>,
20 #[cfg(all(feature = "dx11", windows))]
21 pub dx11: Option<HubReport>,
22 #[cfg(feature = "gles")]
23 pub gl: Option<HubReport>,
24}
25
26pub struct Global<G: GlobalIdentityHandlerFactory> {
27 pub instance: Instance,
28 pub surfaces: Registry<Surface, id::SurfaceId, G>,
29 pub(crate) hubs: Hubs<G>,
30}
31
32impl<G: GlobalIdentityHandlerFactory> Global<G> {
33 pub fn new(name: &str, factory: G, instance_desc: wgt::InstanceDescriptor) -> Self {
34 profiling::scope!("Global::new");
35 Self {
36 instance: Instance::new(name, instance_desc),
37 surfaces: Registry::without_backend(&factory, "Surface"),
38 hubs: Hubs::new(&factory),
39 }
40 }
41
42 pub unsafe fn from_hal_instance<A: HalApi>(
46 name: &str,
47 factory: G,
48 hal_instance: A::Instance,
49 ) -> Self {
50 profiling::scope!("Global::new");
51 Self {
52 instance: A::create_instance_from_hal(name, hal_instance),
53 surfaces: Registry::without_backend(&factory, "Surface"),
54 hubs: Hubs::new(&factory),
55 }
56 }
57
58 pub unsafe fn instance_as_hal<A: HalApi>(&self) -> Option<&A::Instance> {
62 A::instance_as_hal(&self.instance)
63 }
64
65 pub unsafe fn from_instance(factory: G, instance: Instance) -> Self {
69 profiling::scope!("Global::new");
70 Self {
71 instance,
72 surfaces: Registry::without_backend(&factory, "Surface"),
73 hubs: Hubs::new(&factory),
74 }
75 }
76
77 pub fn clear_backend<A: HalApi>(&self, _dummy: ()) {
78 let mut surface_guard = self.surfaces.data.write();
79 let hub = A::hub(self);
80 hub.clear(&mut surface_guard, false);
82 }
83
84 pub fn generate_report(&self) -> GlobalReport {
85 GlobalReport {
86 surfaces: self.surfaces.data.read().generate_report(),
87 #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
88 vulkan: if self.instance.vulkan.is_some() {
89 Some(self.hubs.vulkan.generate_report())
90 } else {
91 None
92 },
93 #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
94 metal: if self.instance.metal.is_some() {
95 Some(self.hubs.metal.generate_report())
96 } else {
97 None
98 },
99 #[cfg(all(feature = "dx12", windows))]
100 dx12: if self.instance.dx12.is_some() {
101 Some(self.hubs.dx12.generate_report())
102 } else {
103 None
104 },
105 #[cfg(all(feature = "dx11", windows))]
106 dx11: if self.instance.dx11.is_some() {
107 Some(self.hubs.dx11.generate_report())
108 } else {
109 None
110 },
111 #[cfg(feature = "gles")]
112 gl: if self.instance.gl.is_some() {
113 Some(self.hubs.gl.generate_report())
114 } else {
115 None
116 },
117 }
118 }
119}
120
121impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> {
122 fn drop(&mut self) {
123 profiling::scope!("Global::drop");
124 log::info!("Dropping Global");
125 let mut surface_guard = self.surfaces.data.write();
126
127 #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
129 {
130 self.hubs.vulkan.clear(&mut surface_guard, true);
131 }
132 #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
133 {
134 self.hubs.metal.clear(&mut surface_guard, true);
135 }
136 #[cfg(all(feature = "dx12", windows))]
137 {
138 self.hubs.dx12.clear(&mut surface_guard, true);
139 }
140 #[cfg(all(feature = "dx11", windows))]
141 {
142 self.hubs.dx11.clear(&mut surface_guard, true);
143 }
144 #[cfg(feature = "gles")]
145 {
146 self.hubs.gl.clear(&mut surface_guard, true);
147 }
148
149 for element in surface_guard.map.drain(..) {
151 if let Element::Occupied(surface, _) = element {
152 self.instance.destroy_surface(surface);
153 }
154 }
155 }
156}
157
158#[cfg(all(
159 test,
160 any(
161 not(target_arch = "wasm32"),
162 all(
163 feature = "fragile-send-sync-non-atomic-wasm",
164 not(target_feature = "atomics")
165 )
166 )
167))]
168fn _test_send_sync(global: &Global<crate::identity::IdentityManagerFactory>) {
169 fn test_internal<T: Send + Sync>(_: T) {}
170 test_internal(global)
171}