Skip to main content

zray/display/
mod.rs

1pub mod render;
2
3use crate::display::render::Renderer;
4use std::sync::Arc;
5use wgpu::{
6    CurrentSurfaceTexture, Device, Instance, Queue, RequestAdapterOptions, Surface,
7    SurfaceConfiguration, TextureViewDescriptor,
8};
9use winit::{application::ApplicationHandler, event::WindowEvent, window::Window as WinitWindow};
10
11struct GpuState {
12    surface: Surface<'static>,
13    device: Device,
14    queue: Queue,
15    config: SurfaceConfiguration,
16}
17
18#[derive(Default)]
19pub struct Window {
20    pub inner: Option<Arc<WinitWindow>>,
21    gpu: Option<GpuState>,
22    renderer: Option<Box<dyn Renderer>>,
23}
24impl ApplicationHandler for Window {
25    fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
26        let window = Arc::new(
27            event_loop
28                .create_window(WinitWindow::default_attributes())
29                .unwrap(),
30        );
31        self.inner = Some(window.clone());
32        let instance = Instance::default();
33        let surface = instance
34            .create_surface(window.clone())
35            .expect("Could not create surface.");
36        let adapter = pollster::block_on(instance.request_adapter(&RequestAdapterOptions {
37            compatible_surface: Some(&surface),
38            ..Default::default()
39        }))
40        .expect("Could not find an appropriate adapter.");
41        let (device, queue) =
42            pollster::block_on(adapter.request_device(&wgpu::DeviceDescriptor::default()))
43                .expect("Failed to create device");
44        let size = window.inner_size();
45        let config = surface
46            .get_default_config(&adapter, size.width, size.height)
47            .unwrap();
48        self.gpu = Some(GpuState {
49            surface,
50            device,
51            queue,
52            config,
53        })
54    }
55    fn window_event(
56        &mut self,
57        event_loop: &winit::event_loop::ActiveEventLoop,
58        _window_id: winit::window::WindowId,
59        event: winit::event::WindowEvent,
60    ) {
61        let (Some(gpu), Some(renderer), Some(window)) =
62            (&mut self.gpu, &mut self.renderer, &self.inner)
63        else {
64            return;
65        };
66        match event {
67            WindowEvent::CloseRequested => {
68                event_loop.exit();
69            }
70            WindowEvent::Resized(new_size) => {
71                gpu.config.width = new_size.width;
72                gpu.config.height = new_size.height;
73                gpu.surface.configure(&gpu.device, &gpu.config);
74            }
75            WindowEvent::RedrawRequested => {
76                let frame = gpu.surface.get_current_texture();
77                match frame {
78                    CurrentSurfaceTexture::Success(frame) => {
79                        let view = frame.texture.create_view(&TextureViewDescriptor::default());
80                        renderer
81                            .render(&gpu.device, &gpu.queue, &view, window.inner_size())
82                            .expect("Redraw failed: Renderer panic.");
83                        frame.present();
84                    }
85                    CurrentSurfaceTexture::Outdated => {
86                        gpu.surface.configure(&gpu.device, &gpu.config);
87                    }
88                    _ => {
89                        eprintln!("Dropped frame: {:?}", frame);
90                    }
91                }
92            }
93            _ => {}
94        }
95    }
96}