This commit is contained in:
Brandon Thomas committed 2026-10-10 02:02:20 -04:00
commit b31e0e2ec6
3 files changed
+51 -4

No files matched your search

+6 -1
View File
@@ -215,6 +215,9 @@ pub struct Headless {
pub view: HeadlessView,
/// The largest texture the pretend GPU takes (what a WebGL device may report: 2048).
pub max_texture_side: usize,
/// The limit egui was last told. Like a native host (egui-winit) it is reported once, not in
/// every frame's input: code that reads the raw input sees `None` from then on (issue #652).
reported_texture_side: Option<usize>,
/// Logical size (points) and scale.
pub size: egui::Vec2,
pub pixels_per_point: f32,
@@ -248,6 +251,7 @@ impl Headless {
app,
view: HeadlessView::new(),
max_texture_side: 16384,
reported_texture_side: None,
size,
pixels_per_point,
time: 0.0,
@@ -280,7 +284,8 @@ impl Headless {
(self.size, self.pixels_per_point) = bounded_viewport(self.size, self.pixels_per_point);
let mut raw = HeadlessView::raw_input(self.size, self.pixels_per_point, self.time, std::mem::take(&mut self.events));
raw.viewports.entry(ViewportId::ROOT).or_default().maximized = Some(self.window_maximized);
raw.max_texture_side = Some(self.max_texture_side);
raw.max_texture_side = (self.reported_texture_side != Some(self.max_texture_side)).then_some(self.max_texture_side);
self.reported_texture_side = Some(self.max_texture_side);
self.app.raw_input_hook(&mut raw);
let app = &mut self.app;
let mut cursor = egui::CursorIcon::Default;
+23 -3
View File
@@ -187,10 +187,14 @@ pub(crate) fn navigate_gesture(app: &mut LightcraftApp, ui: &mut egui::Ui, resp:
true
}
/// The largest texture the GPU behind `ctx` takes (egui reports it; 2048 when it doesn't, the
/// The largest texture the GPU behind `ctx` takes (egui reports it; 2048 until it does, the
/// smallest limit WebGL devices have).
///
/// The value egui keeps, not the frame's raw input: a native host (egui-winit) reports the limit
/// in the first frame's input only, so the raw value is `None` from the second frame on
/// (issue #652: every window render was cut to 2048 px, with blurry strips beside it).
pub(crate) fn texture_side(ctx: &egui::Context) -> usize {
ctx.input(|i| i.raw.max_texture_side).unwrap_or(2048)
ctx.input(|i| i.max_texture_side)
}
/// The photo's own pixels as it is shown: its size after the crop and the user's rotation (what
@@ -2139,7 +2143,23 @@ fn straighten_overlay(app: &mut LightcraftApp, ui: &mut egui::Ui, resp: &egui::R
#[cfg(test)]
mod tests {
use super::film_label;
use super::{film_label, texture_side};
/// Issue #652: a native host reports the GPU's texture limit in the first frame's input only.
/// The loupe must still know it in every later frame (it read the raw input, found nothing and
/// cut every window render to 2048 px).
#[test]
fn the_texture_limit_outlives_the_frame_it_was_reported_in() {
let ctx = egui::Context::default();
assert_eq!(texture_side(&ctx), 2048, "until the host says: the smallest limit there is");
let mut seen = Vec::new();
for reported in [Some(8192), None, None] {
let raw = egui::RawInput { max_texture_side: reported, ..Default::default() };
let mut out = ctx.run_ui(raw, |ui| seen.push(texture_side(ui.ctx())));
out.textures_delta.clear();
}
assert_eq!(seen, [8192, 8192, 8192]);
}
#[test]
fn film_labels_cut_on_characters_not_bytes() {
+22
View File
@@ -352,6 +352,28 @@ mod in_the_loupe {
}
}
// Issue #652: given a canvas wider than 2048 px on a desktop GPU (which reports its texture
// limit to egui once, in the first frame), when I zoom to 1:1, then the window render covers
// the whole canvas: no strip of the magnified whole-frame render beside it
#[test]
fn a_window_covers_a_canvas_wider_than_2048_px() {
let (mut h, native) = detail_in([2600.0, 1200.0]);
assert!(native > 2600, "the photo is wider than the canvas at 1:1: {native}");
h.request("engine.execute", json!({"command": "view.zoom100"}), T);
h.settle(SETTLE);
let canvas = h.app.canvas_rect.expect("the loupe was drawn");
let image = h.app.image_rect.expect("the photo was drawn");
let region = h.app.region_view.expect("a window");
// the canvas in pixels of the window's frame (scale 1, at 100 %: a point is a pixel)
let to_px = region.full.0 as f32 / image.width();
let (left, right) = (to_px * (canvas.left() - image.left()), to_px * (canvas.right() - image.left()));
assert!(right - left > 2048.0, "the canvas shows more than 2048 px: {left}..{right}");
let (x0, x1) = (region.window.x as f32, (region.window.x + region.window.w) as f32);
assert!(x0 <= left + 0.5 && x1 >= right - 0.5, "the window {x0}..{x1} leaves part of the canvas {left}..{right} to the preview");
let (w, _) = region_tile(&h).expect("the window rendered");
assert_eq!(w, region.window.w, "and that is the texture drawn");
}
// Given 400 % on a big photo, when a slider is dragged, then the work per frame follows the
// canvas, not the zoom: a draft of the whole frame at canvas scale and a draft of the window
#[test]