srs2dge_core/target/
surface.rs1use std::{
2 ops::{Deref, DerefMut},
3 sync::Arc,
4};
5use wgpu::{
6 Adapter, Device, Instance, PresentMode, SurfaceConfiguration, SurfaceError, SurfaceTexture,
7 TextureFormat, TextureUsages,
8};
9use winit::window::Window;
10
11pub struct ISurface {
14 instance: Arc<Instance>,
15 surface: wgpu::Surface,
16 window: Arc<Window>,
17}
18
19pub struct Surface {
20 device: Arc<Device>,
21 surface: ISurface,
22 format: TextureFormat,
23 present_mode: PresentMode,
24
25 width: u32,
26 height: u32,
27}
28
29impl ISurface {
32 pub fn new(window: Arc<Window>, instance: Arc<Instance>) -> Self {
33 let surface = unsafe { instance.create_surface(window.as_ref()) };
43
44 Self {
45 instance,
46 surface,
47 window,
48 }
49 }
50
51 pub fn complete(self, adapter: &Adapter, device: Arc<Device>) -> Surface {
52 let surface = self;
53 let format = surface
54 .surface
55 .get_preferred_format(adapter)
56 .expect("Surface is not incompatible");
57
58 let mut surface = Surface {
59 device,
60 surface,
61 format,
62 present_mode: PresentMode::Mailbox,
63
64 width: 0, height: 0,
66 };
67 surface.configure();
68 surface
69 }
70
71 pub fn get_window(&self) -> Arc<Window> {
72 self.window.clone()
73 }
74}
75
76impl Surface {
77 pub fn set_vsync(&mut self, on: bool) {
78 let new = if on {
79 PresentMode::Mailbox } else {
81 PresentMode::Immediate
82 };
83 let updated = self.present_mode != new;
84 self.present_mode = new;
85
86 if updated {
87 self.configure();
88 }
89 }
90
91 pub fn get_vsync(&self) -> bool {
92 match self.present_mode {
93 PresentMode::Immediate => false,
94 PresentMode::Mailbox => true,
95 PresentMode::Fifo => true,
96 }
97 }
98
99 pub fn configure(&mut self) {
100 let window = self.surface.window.as_ref();
101 let size = window.inner_size();
102 let (width, height) = (size.width, size.height);
103 let format = self.format;
104
105 self.width = width;
106 self.height = height;
107 self.surface.surface.configure(
108 &self.device,
109 &SurfaceConfiguration {
110 usage: TextureUsages::RENDER_ATTACHMENT,
111 format,
112 width,
113 height,
114 present_mode: self.present_mode,
115 },
116 );
117 }
118
119 pub fn recreate(&mut self) {
120 let window = self.surface.window.clone();
121 let instance = self.surface.instance.clone();
122 self.surface = ISurface::new(window, instance);
123 }
124
125 pub fn acquire(&mut self) -> SurfaceTexture {
126 loop {
127 match self.surface.get_current_texture() {
128 Ok(
130 texture @ SurfaceTexture {
131 suboptimal: false, ..
132 },
133 ) => return texture,
134
135 Err(SurfaceError::OutOfMemory) => panic!("Out of memory"),
137
138 Err(SurfaceError::Timeout) => {
140 log::debug!("Timeout");
141 }
142
143 Err(SurfaceError::Lost) => {
145 log::debug!("Lost");
146 self.recreate();
147 }
148
149 x @ (Ok(SurfaceTexture {
151 suboptimal: true, ..
152 })
153 | Err(SurfaceError::Outdated)) => {
154 log::debug!("Outdated | Suboptimal");
155 drop(x);
156 self.configure();
157 }
158 }
159 }
160 }
161
162 pub fn format(&self) -> TextureFormat {
163 self.format
164 }
165
166 pub fn get_window(&self) -> Arc<Window> {
167 self.surface.get_window()
168 }
169
170 pub fn get_dim(&self) -> (u32, u32) {
171 (self.width, self.height)
172 }
173}
174
175impl Deref for ISurface {
176 type Target = wgpu::Surface;
177
178 fn deref(&self) -> &Self::Target {
179 &self.surface
180 }
181}
182
183impl DerefMut for ISurface {
184 fn deref_mut(&mut self) -> &mut Self::Target {
185 &mut self.surface
186 }
187}
188
189impl Deref for Surface {
190 type Target = wgpu::Surface;
191
192 fn deref(&self) -> &Self::Target {
193 &self.surface
194 }
195}
196
197impl DerefMut for Surface {
198 fn deref_mut(&mut self) -> &mut Self::Target {
199 &mut self.surface
200 }
201}