1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 06:40:06 -04:00

egui_inspection: PNG-encode screenshots on the wire; collapse protocol feature

- FrameScreenshot now carries PNG bytes instead of raw RGBA (PROTOCOL_VERSION 1→2);
  add a shared `encode_png` helper behind a new `png` feature so the live plugin and the
  kittest harness encode frames identically.
- Make the protocol module unconditional: drop the `protocol` feature flag and the
  optional serde/serde_bytes/rmp-serde deps it gated.
- plugin.rs: re-stamp screenshot-bearing frames with the current step (so inspectors
  waiting for step > prev don't reject them) and pump a tail-side repaint while awaiting
  the GPU readback.
This commit is contained in:
lucasmerlin
2026-05-26 16:20:07 +02:00
parent d67862ace6
commit 72389ed5a8
5 changed files with 75 additions and 22 deletions

View File

@@ -211,11 +211,26 @@ impl egui::Plugin for InspectionPlugin {
if let Some(mut frame) = self.pending_frame.take() {
let [w, h] = [image.size[0] as u32, image.size[1] as u32];
let rgba: Vec<u8> = image.pixels.iter().flat_map(|c| c.to_array()).collect();
frame.screenshot = Some(FrameScreenshot {
width: w,
height: h,
rgba,
});
match crate::encode_png(w, h, &rgba) {
Ok(png) => {
frame.screenshot = Some(FrameScreenshot {
width: w,
height: h,
png,
});
}
Err(err) => {
eprintln!("[INSP] PNG encode failed: {err}");
}
}
// Re-stamp the frame with the *current* step. The stashed `step` was
// captured when we dispatched the screenshot command; in the meantime
// intervening frames (without screenshot) may have been emitted with
// higher step numbers. Inspectors that wait for `step > prev_step` would
// otherwise reject the screenshot-bearing frame because its step has
// regressed.
self.step = self.step.saturating_add(1);
frame.step = self.step;
self.send(HarnessMessage::Frame(Box::new(frame)));
}
break;
@@ -296,6 +311,17 @@ impl egui::Plugin for InspectionPlugin {
if !want_screenshot {
// No screenshot needed — emit immediately.
self.send(HarnessMessage::Frame(Box::new(frame)));
// If we're still waiting on a screenshot from a previous dispatch, keep
// pumping repaints from the end of the frame too. `input_hook` already
// does this at frame start, but on reactive apps the GPU readback can
// take several frames to fulfill — without a tail-side repaint the
// integration may go idle between `input_hook` ticks once the captured
// frame finishes presenting.
if self.awaiting_screenshot {
if let Some(ctx) = self.shared_ctx.get() {
ctx.request_repaint();
}
}
return;
}