#![cfg_attr(windows, windows_subsystem = "windows")] use std::iter::once; use wgpu::{ Backends, Color, CommandEncoderDescriptor, Device, DeviceDescriptor, Features, Instance, InstanceDescriptor, Limits, LoadOp, Operations, PowerPreference, Queue, RenderPassColorAttachment, RenderPassDescriptor, RequestAdapterOptions, Surface, SurfaceConfiguration, SurfaceError, TextureUsages, TextureViewDescriptor, }; use winit::{ dpi::PhysicalSize, event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::{Window, WindowBuilder}, }; use winit_fullscreen::*; fn main() { pollster::block_on(run()); } async fn run() { let event_loop = EventLoop::new(); let window = WindowBuilder::new() .with_title("winit-fullscreen example") .with_inner_size(PhysicalSize::new(800, 600)) .build(&event_loop) .unwrap(); let mut state = State::new(window).await; event_loop.run(move |event, _target, control_flow| { *control_flow = ControlFlow::Poll; match event { Event::WindowEvent { event, window_id, .. } if window_id == state.window().id() => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, WindowEvent::KeyboardInput { input, .. } => match input { KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. } => *control_flow = ControlFlow::Exit, KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Return), .. } => { // Toggle fullscreen state.window().toggle_fullscreen(); } _ => {} }, WindowEvent::Resized(physical_size) => state.resize(physical_size), WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { state.resize(*new_inner_size) } _ => {} }, Event::RedrawRequested(window_id) if window_id == state.window().id() => { match state.render() { Ok(_) => {} Err(SurfaceError::Lost) => state.resize(state.size), Err(SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, Err(e) => eprintln!("{:?}", e), } } Event::MainEventsCleared => { state.window().request_redraw(); } _ => {} } }) } struct State { surface: Surface, device: Device, queue: Queue, config: SurfaceConfiguration, size: PhysicalSize, window: Window, } impl State { async fn new(window: Window) -> Self { let size = window.inner_size(); let instance = Instance::new(InstanceDescriptor { backends: Backends::all(), dx12_shader_compiler: Default::default(), }); let surface = unsafe { instance.create_surface(&window) }.unwrap(); let adapter = instance .request_adapter(&RequestAdapterOptions { power_preference: PowerPreference::default(), compatible_surface: Some(&surface), force_fallback_adapter: false, }) .await .unwrap(); let (device, queue) = adapter .request_device( &DeviceDescriptor { features: Features::empty(), limits: Limits::default(), label: None, }, None, ) .await .unwrap(); let surface_caps = surface.get_capabilities(&adapter); let surface_format = surface_caps .formats .iter() .copied() .find(|f| f.describe().srgb) .unwrap_or(surface_caps.formats[0]); let config = SurfaceConfiguration { usage: TextureUsages::RENDER_ATTACHMENT, format: surface_format, width: size.width, height: size.height, present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], }; surface.configure(&device, &config); Self { window, surface, device, queue, config, size, } } pub fn window(&self) -> &Window { &self.window } fn resize(&mut self, new_size: PhysicalSize) { if new_size.width > 0 && new_size.height > 0 { self.size = new_size; self.config.width = new_size.width; self.config.height = new_size.height; self.surface.configure(&self.device, &self.config); } } fn render(&mut self) -> Result<(), SurfaceError> { let output = self.surface.get_current_texture()?; let view = output .texture .create_view(&TextureViewDescriptor::default()); let mut encoder = self .device .create_command_encoder(&CommandEncoderDescriptor { label: Some("Render Encoder"), }); { let _render_pass = encoder.begin_render_pass(&RenderPassDescriptor { label: Some("Render Pass"), color_attachments: &[Some(RenderPassColorAttachment { view: &view, resolve_target: None, ops: Operations { load: LoadOp::Clear(Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0, }), store: true, }, })], depth_stencil_attachment: None, }); } self.queue.submit(once(encoder.finish())); output.present(); Ok(()) } }