mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Prevent accidentally dropping TexturesDelta (#8356)
We had a ton of issues around `TexturesDelta` that weren't properly applied because we early-out of some function: * https://github.com/emilk/egui/pull/8313 * https://github.com/emilk/egui/pull/8250 * https://github.com/emilk/egui/pull/8279 This PR changes texture updates, so that we always store them after taking them out of `FullOutput` and keep the delta around until it's actually applied (by passing &mut refs and draining instead of iterating). So even if we add a new early return somewhere, that can't break texture updates. It also optimizes `TexturesDelta::append` by dropping any previous deltas if there's a new `whole` delta or a `free`. It also adds a debug assert that any `TexturesDelta` is empty when dropped, as an additional safeguard in case the bug sneaks back in. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -358,17 +358,21 @@ impl Painter {
|
||||
screen_size_px: [u32; 2],
|
||||
pixels_per_point: f32,
|
||||
clipped_primitives: &[egui::ClippedPrimitive],
|
||||
textures_delta: &egui::TexturesDelta,
|
||||
textures_delta: &mut egui::TexturesDelta,
|
||||
) {
|
||||
profiling::function_scope!();
|
||||
|
||||
for (id, image_delta) in &textures_delta.set {
|
||||
self.set_texture(*id, image_delta);
|
||||
#[expect(clippy::iter_over_hash_type)] // Order doesn't matter here
|
||||
for (id, image_deltas) in textures_delta.set.drain() {
|
||||
for image_delta in image_deltas {
|
||||
self.set_texture(id, &image_delta);
|
||||
}
|
||||
}
|
||||
|
||||
self.paint_primitives(screen_size_px, pixels_per_point, clipped_primitives);
|
||||
|
||||
for &id in &textures_delta.free {
|
||||
#[expect(clippy::iter_over_hash_type)] // Order doesn't matter here
|
||||
for id in textures_delta.free.drain() {
|
||||
self.free_texture(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,11 @@ impl EguiGlow {
|
||||
let shapes = std::mem::take(&mut self.shapes);
|
||||
let mut textures_delta = std::mem::take(&mut self.textures_delta);
|
||||
|
||||
for (id, image_delta) in textures_delta.set {
|
||||
self.painter.set_texture(id, &image_delta);
|
||||
#[expect(clippy::iter_over_hash_type)] // Order doesn't matter here
|
||||
for (id, image_deltas) in textures_delta.set.drain() {
|
||||
for image_delta in image_deltas {
|
||||
self.painter.set_texture(id, &image_delta);
|
||||
}
|
||||
}
|
||||
|
||||
let pixels_per_point = self.pixels_per_point;
|
||||
@@ -117,7 +120,8 @@ impl EguiGlow {
|
||||
self.painter
|
||||
.paint_primitives(dimensions, pixels_per_point, &clipped_primitives);
|
||||
|
||||
for id in textures_delta.free.drain(..) {
|
||||
#[expect(clippy::iter_over_hash_type)] // Order doesn't matter here
|
||||
for id in textures_delta.free.drain() {
|
||||
self.painter.free_texture(id);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user