From 645bd031422576d902b3f9000e434bf152681383 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 4 Oct 2021 15:51:36 -0400 Subject: [PATCH] Make sure ui draw commands are cleared if the renderer's resolution changes --- Cargo.lock | 2 +- voxygen/src/ui/mod.rs | 43 ++++++++++++++++++++++++++++++----------- voxygen/src/ui/scale.rs | 3 +++ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7978a41a6f..2dc5d8324d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5780,7 +5780,7 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "rand 0.8.4", "static_assertions", ] diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index a7ad28ab68..83b04859e0 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -235,15 +235,13 @@ impl Ui { } pub fn replace_graphic(&mut self, id: ImageId, graphic: Graphic) { - let graphic_id = if let Some((graphic_id, _)) = self.image_map.get(&id) { - *graphic_id + if let Some(&(graphic_id, _)) = self.image_map.get(&id) { + self.cache.replace_graphic(graphic_id, graphic); + self.image_map.replace(id, (graphic_id, Rotation::None)); + self.graphic_replaced = true; } else { - error!("Failed to replace graphic the provided id is not in use"); - return; + error!("Failed to replace graphic, the provided id is not in use."); }; - self.cache.replace_graphic(graphic_id, graphic); - self.image_map.replace(id, (graphic_id, Rotation::None)); - self.graphic_replaced = true; } pub fn new_font(&mut self, font: crate::ui::ice::RawFont) -> font::Id { @@ -346,6 +344,10 @@ impl Ui { false }; + // Used to tell if we need to clear out the draw commands (which contain scissor + // commands that can be invalidated by this change) + let physical_resolution_changed = renderer.resolution() != self.scale.physical_resolution(); + // Handle window resizing. let need_resize = if self.window_resized { self.window_resized = false; @@ -379,10 +381,16 @@ impl Ui { } let mut retry = false; - self.maintain_internal(renderer, pool, view_projection_mat, &mut retry); + self.maintain_internal( + renderer, + pool, + view_projection_mat, + &mut retry, + physical_resolution_changed, + ); if retry { // Update the glyph cache and try again. - self.maintain_internal(renderer, pool, view_projection_mat, &mut retry); + self.maintain_internal(renderer, pool, view_projection_mat, &mut retry, false); } } @@ -392,14 +400,27 @@ impl Ui { pool: Option<&SlowJobPool>, view_projection_mat: Option>, retry: &mut bool, + physical_resolution_changed: bool, ) { span!(_guard, "internal", "Ui::maintain_internal"); let (graphic_cache, text_cache, glyph_cache, cache_tex) = self.cache.cache_mut_and_tex(); - let mut primitives = if *retry || self.graphic_replaced { + // If the physical resolution changed draw commands need to be cleared since + // scissors commands will be invalid. A resize usually means everything + // needs to be redrawn anyway but certain error cases below can cause an + // early return. + if physical_resolution_changed { + self.draw_commands.clear(); + } + + let mut primitives = if *retry || self.graphic_replaced || physical_resolution_changed { // If this is a retry, always redraw. + // // Also redraw if a texture was swapped out by replace_graphic in order to - // regenerate invalidated textures and clear out any invalid `TexId`s + // regenerate invalidated textures and clear out any invalid `TexId`s. + // + // Also redraw if the physical resolution changed since we need to regenerate + // the invalid scissor rect commands. self.graphic_replaced = false; self.ui.draw() } else { diff --git a/voxygen/src/ui/scale.rs b/voxygen/src/ui/scale.rs index c3759c3766..65873e051a 100644 --- a/voxygen/src/ui/scale.rs +++ b/voxygen/src/ui/scale.rs @@ -101,6 +101,9 @@ impl Scale { old_scale_factor != self.scale_factor } + /// Get physical resolution. + pub fn physical_resolution(&self) -> Vec2 { self.physical_resolution } + /// Get scaled window size. pub fn scaled_resolution(&self) -> Vec2 { self.physical_resolution.map(f64::from) / self.scale_factor_physical()