From c00c9d549c02492a8e8a691405273d69e97ed903 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Thu, 3 Dec 2020 14:13:09 -0800 Subject: [PATCH] attempt to deal with rounding issue when creating the swap chain on high DPI displays --- crates/bevy_render/src/camera/camera.rs | 5 +- .../render_graph/nodes/window_texture_node.rs | 4 +- crates/bevy_ui/src/flex/mod.rs | 4 +- crates/bevy_wgpu/src/wgpu_type_converter.rs | 4 +- crates/bevy_window/src/window.rs | 63 ++++++++++++------- crates/bevy_winit/src/lib.rs | 19 +++--- crates/bevy_winit/src/winit_windows.rs | 12 ++-- examples/2d/contributors.rs | 8 +-- examples/ecs/parallel_query.rs | 4 +- 9 files changed, 74 insertions(+), 49 deletions(-) diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 0818b18d40c1e..32113ec706ec7 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -77,7 +77,10 @@ pub fn camera_system( for (entity, mut camera, mut camera_projection) in queries.q0_mut().iter_mut() { if let Some(window) = windows.get(camera.window) { if changed_window_ids.contains(&window.id()) || added_cameras.contains(&entity) { - camera_projection.update(window.width() as usize, window.height() as usize); + camera_projection.update( + window.logical_width() as usize, + window.logical_height() as usize, + ); camera.projection_matrix = camera_projection.get_projection_matrix(); camera.depth_calculation = camera_projection.depth_calculation(); } diff --git a/crates/bevy_render/src/render_graph/nodes/window_texture_node.rs b/crates/bevy_render/src/render_graph/nodes/window_texture_node.rs index 7504faebc8707..d287002ab4e29 100644 --- a/crates/bevy_render/src/render_graph/nodes/window_texture_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/window_texture_node.rs @@ -68,8 +68,8 @@ impl Node for WindowTextureNode { render_resource_context.remove_texture(old_texture); } - self.descriptor.size.width = window.scaled_width(); - self.descriptor.size.height = window.scaled_height(); + self.descriptor.size.width = window.physical_width(); + self.descriptor.size.height = window.physical_height(); let texture_resource = render_resource_context.create_texture(self.descriptor); output.set(WINDOW_TEXTURE, RenderResourceId::Texture(texture_resource)); } diff --git a/crates/bevy_ui/src/flex/mod.rs b/crates/bevy_ui/src/flex/mod.rs index abc9bc6084c8c..e813d2aeeb9be 100644 --- a/crates/bevy_ui/src/flex/mod.rs +++ b/crates/bevy_ui/src/flex/mod.rs @@ -116,8 +116,8 @@ impl FlexSurface { *node, stretch::style::Style { size: stretch::geometry::Size { - width: stretch::style::Dimension::Points(window.width() as f32), - height: stretch::style::Dimension::Points(window.height() as f32), + width: stretch::style::Dimension::Points(window.logical_width() as f32), + height: stretch::style::Dimension::Points(window.logical_height() as f32), }, ..Default::default() }, diff --git a/crates/bevy_wgpu/src/wgpu_type_converter.rs b/crates/bevy_wgpu/src/wgpu_type_converter.rs index d1e5d4f996199..e6e176263e045 100644 --- a/crates/bevy_wgpu/src/wgpu_type_converter.rs +++ b/crates/bevy_wgpu/src/wgpu_type_converter.rs @@ -564,8 +564,8 @@ impl WgpuFrom<&Window> for wgpu::SwapChainDescriptor { wgpu::SwapChainDescriptor { usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, format: TextureFormat::default().wgpu_into(), - width: window.scaled_width(), - height: window.scaled_height(), + width: window.physical_width(), + height: window.physical_height(), present_mode: if window.vsync() { wgpu::PresentMode::Mailbox } else { diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index ac0fce771a19f..260ce244152c1 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -35,8 +35,8 @@ impl Default for WindowId { #[derive(Debug)] pub struct Window { id: WindowId, - width: u32, - height: u32, + physical_width: u32, + physical_height: u32, title: String, vsync: bool, resizable: bool, @@ -100,8 +100,10 @@ impl Window { pub fn new(id: WindowId, window_descriptor: &WindowDescriptor) -> Self { Window { id, - height: window_descriptor.height, - width: window_descriptor.width, + //height: window_descriptor.height, + //width: window_descriptor.width, + physical_height: window_descriptor.height, + physical_width: window_descriptor.width, title: window_descriptor.title.clone(), vsync: window_descriptor.vsync, resizable: window_descriptor.resizable, @@ -122,38 +124,55 @@ impl Window { self.id } + //pub fn scaled_width(&self) -> u32 { + // (self.width as f64 * self.scale_factor) as u32 + //} + // + //pub fn scaled_height(&self) -> u32 { + // (self.height as f64 * self.scale_factor) as u32 + //} + #[inline] - pub fn width(&self) -> u32 { - self.width + pub fn logical_width(&self) -> f32 { + (self.physical_width as f64 / self.scale_factor) as f32 } - pub fn scaled_width(&self) -> u32 { - (self.width as f64 * self.scale_factor) as u32 + #[inline] + pub fn logical_height(&self) -> f32 { + (self.physical_height as f64 / self.scale_factor) as f32 } - pub fn scaled_height(&self) -> u32 { - (self.height as f64 * self.scale_factor) as u32 + #[inline] + pub fn physical_width(&self) -> u32 { + self.physical_width } #[inline] - pub fn height(&self) -> u32 { - self.height + pub fn physical_height(&self) -> u32 { + self.physical_height } - pub fn set_resolution(&mut self, width: u32, height: u32) { - self.width = width; - self.height = height; - self.command_queue - .push(WindowCommand::SetResolution { width, height }); - } + //pub fn set_resolution(&mut self, width: u32, height: u32) { + // self.width = width; + // self.height = height; + // self.command_queue + // .push(WindowCommand::SetResolution { width, height }); + //} #[allow(missing_docs)] #[inline] - pub fn update_resolution_from_backend(&mut self, width: u32, height: u32) { - self.width = width; - self.height = height; + pub fn update_physical_size_from_backend(&mut self, width: u32, height: u32) { + self.physical_width = width; + self.physical_height = height; } + //#[allow(missing_docs)] + //#[inline] + //pub fn update_resolution_from_backend(&mut self, width: u32, height: u32) { + // self.width = width; + // self.height = height; + //} + #[allow(missing_docs)] #[inline] pub fn update_scale_factor_from_backend(&mut self, scale_factor: f64) { @@ -256,7 +275,7 @@ impl Window { self.mode = mode; self.command_queue.push(WindowCommand::SetWindowMode { mode, - resolution: (self.width, self.height), + resolution: (self.physical_width, self.physical_height), }); } diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index ca1a328c49051..3e10a35c5205d 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -73,7 +73,7 @@ fn change_window(_: &mut World, resources: &mut Resources) { } bevy_window::WindowCommand::SetResolution { width, height } => { let window = winit_windows.get_window(id).unwrap(); - window.set_inner_size(winit::dpi::LogicalSize::new(width, height)); + window.set_inner_size(winit::dpi::PhysicalSize::new(width, height)); } bevy_window::WindowCommand::SetVsync { .. } => (), bevy_window::WindowCommand::SetResizable { resizable } => { @@ -197,17 +197,16 @@ pub fn winit_runner(mut app: App) { let winit_windows = app.resources.get_mut::().unwrap(); let mut windows = app.resources.get_mut::().unwrap(); let window_id = winit_windows.get_window_id(winit_window_id).unwrap(); - let winit_window = winit_windows.get_window(window_id).unwrap(); let window = windows.get_mut(window_id).unwrap(); - let size = size.to_logical(winit_window.scale_factor()); - window.update_resolution_from_backend(size.width, size.height); + window.update_physical_size_from_backend(size.width, size.height); + println!("new physical size: {:?}", size); let mut resize_events = app.resources.get_mut::>().unwrap(); resize_events.send(WindowResized { id: window_id, - height: window.height() as usize, - width: window.width() as usize, + height: window.logical_height() as usize, + width: window.logical_width() as usize, }); } WindowEvent::CloseRequested => { @@ -305,7 +304,7 @@ pub fn winit_runner(mut app: App) { // FIXME?: On Android window start is top while on PC/Linux/OSX on bottom if cfg!(target_os = "android") { - let window_height = windows.get_primary().unwrap().height(); + let window_height = windows.get_primary().unwrap().logical_height(); location.y = window_height as f32 - location.y; } touch_input_events.send(converters::convert_touch_input(touch, location)); @@ -332,9 +331,11 @@ pub fn winit_runner(mut app: App) { let mut windows = app.resources.get_mut::().unwrap(); let window_id = winit_windows.get_window_id(winit_window_id).unwrap(); let window = windows.get_mut(window_id).unwrap(); - let size = new_inner_size.to_logical(scale_factor); + window.update_physical_size_from_backend( + new_inner_size.width, + new_inner_size.height, + ); window.update_scale_factor_from_backend(scale_factor); - window.update_resolution_from_backend(size.width, size.height); } _ => {} }, diff --git a/crates/bevy_winit/src/winit_windows.rs b/crates/bevy_winit/src/winit_windows.rs index 81e245cebfa32..5b494cff75da4 100644 --- a/crates/bevy_winit/src/winit_windows.rs +++ b/crates/bevy_winit/src/winit_windows.rs @@ -31,16 +31,16 @@ impl WinitWindows { winit::window::Fullscreen::Exclusive(match use_size { true => get_fitting_videomode( &event_loop.primary_monitor().unwrap(), - window.width(), - window.height(), + window.physical_width(), + window.physical_height(), ), false => get_best_videomode(&event_loop.primary_monitor().unwrap()), }), )), _ => winit_window_builder - .with_inner_size(winit::dpi::LogicalSize::new( - window.width(), - window.height(), + .with_inner_size(winit::dpi::PhysicalSize::new( + window.physical_width(), + window.physical_height(), )) .with_resizable(window.resizable()) .with_decorations(window.decorations()), @@ -100,6 +100,8 @@ impl WinitWindows { } } + let inner_size = winit_window.inner_size(); + window.update_physical_size_from_backend(inner_size.width, inner_size.height); window.update_scale_factor_from_backend(winit_window.scale_factor()); self.windows.insert(winit_window.id(), winit_window); diff --git a/examples/2d/contributors.rs b/examples/2d/contributors.rs index 315f5cfcbf9e1..d936fdb3f2115 100644 --- a/examples/2d/contributors.rs +++ b/examples/2d/contributors.rs @@ -237,11 +237,11 @@ fn collision_system( let win = wins.get_primary().unwrap(); - let ceiling = (win.height() / 2) as f32; - let ground = -((win.height() / 2) as f32); + let ceiling = (win.logical_height() / 2.) as f32; + let ground = -((win.logical_height() / 2.) as f32); - let wall_left = -((win.width() / 2) as f32); - let wall_right = (win.width() / 2) as f32; + let wall_left = -((win.logical_width() / 2.) as f32); + let wall_right = (win.logical_width() / 2.) as f32; for (mut v, mut t) in q.iter_mut() { let left = t.translation.x - SPRITE_SIZE / 2.0; diff --git a/examples/ecs/parallel_query.rs b/examples/ecs/parallel_query.rs index fdfa1b9e4f29d..cb59429a2659d 100644 --- a/examples/ecs/parallel_query.rs +++ b/examples/ecs/parallel_query.rs @@ -48,8 +48,8 @@ fn bounce_system( mut sprites: Query<(&Transform, &mut Velocity)>, ) { let window = windows.get_primary().expect("No primary window."); - let width = window.width(); - let height = window.height(); + let width = window.logical_width(); + let height = window.logical_height(); let left = width as f32 / -2.0; let right = width as f32 / 2.0; let bottom = height as f32 / -2.0;