diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index c96db4f47..ba8bcadb8 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -2599,7 +2599,17 @@ impl ContextImpl { } // Inform the backend of all textures that have been updated (including font atlas). - let textures_delta = self.tex_manager.0.write().take_delta(); + // + // A hosted viewport is the exception. It is painted by the application, which also + // paints the viewport hosting it, so leaving the uploads in place lets that one pick + // them up. Taking them here would hand them to code with no way to give them back: + // a freed texture cannot be re-queued, because `TextureManager::free` decrements a + // retain count that has already reached zero. + let textures_delta = if viewport.class == ViewportClass::Hosted { + Default::default() + } else { + self.tex_manager.0.write().take_delta() + }; let mut platform_output: PlatformOutput = std::mem::take(&mut viewport.output); diff --git a/crates/epaint/src/textures.rs b/crates/epaint/src/textures.rs index 1c4104a6e..c51f20e38 100644 --- a/crates/epaint/src/textures.rs +++ b/crates/epaint/src/textures.rs @@ -103,6 +103,15 @@ impl TextureManager { std::mem::take(&mut self.delta) } + /// Changes since the last [`Self::take_delta`], without taking them. + /// + /// Useful if you need to paint something part-way through a frame, before whoever owns + /// the painting subsystem has had a chance to apply these. Applying them twice does no + /// harm; the second time simply re-uploads the same data. + pub fn pending_delta(&self) -> &TexturesDelta { + &self.delta + } + /// Get meta-data about a specific texture. pub fn meta(&self, id: TextureId) -> Option<&TextureMeta> { self.metas.get(&id)