mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-24 02:16:56 -06:00
Lands #312's test-only follow-up commit and records #326, #317 and #306's rebased heads (no content change) so they show as merged.
This commit is contained in:
@@ -20,7 +20,7 @@ use web_time::Instant;
|
||||
/// A preview has this many times fewer pixels each way than the view it stands in for.
|
||||
pub const PREVIEW_FACTOR: f64 = 4.0;
|
||||
/// Full renders quicker than this (about a frame) show without a preview first.
|
||||
const PREVIEW_AFTER_MS: f64 = 12.0;
|
||||
pub const PREVIEW_AFTER_MS: f64 = 12.0;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Job {
|
||||
|
||||
@@ -13,7 +13,7 @@ use figcraft_render::{View, Work};
|
||||
use serde_json::json;
|
||||
|
||||
use super::{CanvasState, shows};
|
||||
use crate::render_worker::{Done, Inline, Job, PREVIEW_FACTOR, Renders, coarse_view, render_now};
|
||||
use crate::render_worker::{Done, Inline, Job, PREVIEW_AFTER_MS, PREVIEW_FACTOR, Renders, coarse_view, render_now};
|
||||
|
||||
/// A page of ellipses with a rectangle on top; the session and the rectangle.
|
||||
fn document() -> (Session, NodeId) {
|
||||
@@ -27,6 +27,35 @@ fn document() -> (Session, NodeId) {
|
||||
(s, rect)
|
||||
}
|
||||
|
||||
/// A page whose renders from scratch of each of `views` take at least `ms`: the rectangle with glass
|
||||
/// and a background blur, and more and more blurred rectangles over the views until they do (a
|
||||
/// fixed scene would turn quick on a faster machine or renderer).
|
||||
fn slow_scene(views: &[View], ms: f64) -> Session {
|
||||
let (mut s, rect) = document();
|
||||
s.execute("effect.add", &json!({"ids": [rect], "type": "GLASS"})).unwrap();
|
||||
s.execute("effect.add", &json!({"ids": [rect], "type": "BACKGROUND_BLUR"})).unwrap();
|
||||
let area = views.iter().map(View::page_rect).reduce(|a, b| a.union(b)).unwrap();
|
||||
let mut more = 8;
|
||||
for _ in 0..12 {
|
||||
let ds = s.ds().unwrap();
|
||||
let quickest = views.iter().map(|v| render_now(&job(&ds.doc, ds.page, ds.uid, v.clone())).unwrap().ms).fold(f64::INFINITY, f64::min);
|
||||
if quickest >= ms {
|
||||
return s;
|
||||
}
|
||||
let (w, h) = (area.width() / 4.0, area.height() / 4.0);
|
||||
let ids: Vec<NodeId> = (0..more)
|
||||
.map(|k| {
|
||||
let (fx, fy) = (f64::from(k * 37 % 101) / 101.0, f64::from(k * 59 % 103) / 103.0);
|
||||
let p = json!({"x": area.x0 + fx * (area.width() - w), "y": area.y0 + fy * (area.height() - h), "width": w, "height": h});
|
||||
id_of(&s.execute("shape.rectangle", &p).unwrap()["id"]).unwrap()
|
||||
})
|
||||
.collect();
|
||||
s.execute("effect.add", &json!({"ids": ids, "type": "BACKGROUND_BLUR"})).unwrap();
|
||||
more *= 2;
|
||||
}
|
||||
panic!("no scene renders slower than {ms} ms");
|
||||
}
|
||||
|
||||
/// A `w` × `h` device-pixel view at `scale` centred on page point `c`.
|
||||
fn view_at(c: (f64, f64), scale: f64, w: u32, h: u32) -> View {
|
||||
View { origin: (c.0 - f64::from(w) / scale / 2.0, c.1 - f64::from(h) / scale / 2.0), scale, width: w, height: h }
|
||||
@@ -254,18 +283,18 @@ fn a_preview_replaces_a_refined_image_of_the_same_zoom_elsewhere_on_the_page() {
|
||||
|
||||
#[test]
|
||||
fn the_browser_worker_previews_by_measured_render_time_then_refines_the_next_frame() {
|
||||
// Big enough that a render from scratch takes well over a frame: blurs and glass on 2400².
|
||||
let (mut s, rect) = document();
|
||||
s.execute("effect.add", &json!({"ids": [rect], "type": "GLASS"})).unwrap();
|
||||
s.execute("effect.add", &json!({"ids": [rect], "type": "BACKGROUND_BLUR"})).unwrap();
|
||||
// Renders from scratch at 200% and 100% (whose times decide the previews below) well over the
|
||||
// threshold, wherever this runs.
|
||||
let view = |scale| view_at((300.0, 200.0), scale, 1200, 1200);
|
||||
let s = slow_scene(&[view(2.0), view(1.0)], 3.0 * PREVIEW_AFTER_MS);
|
||||
let ds = s.ds().unwrap();
|
||||
let at = |scale| job(&ds.doc, ds.page, ds.uid, view_at((300.0, 200.0), scale, 2400, 2400));
|
||||
let at = |scale| job(&ds.doc, ds.page, ds.uid, view(scale));
|
||||
// The production threshold, as the browser has it.
|
||||
let mut w = Inline::new(egui::Context::default());
|
||||
w.submit(at(2.0));
|
||||
let first = w.poll().expect("the first image");
|
||||
assert!(!first.coarse && !w.in_flight(), "the first render has no measure to preview by");
|
||||
assert!(first.ms >= 12.0, "renders are timed in the browser worker too (and this one is slow): {} ms", first.ms);
|
||||
assert!(first.ms >= PREVIEW_AFTER_MS, "renders are timed in the browser worker too (and this one is slow): {} ms", first.ms);
|
||||
// A new zoom: the preview this frame, the refined image the next.
|
||||
w.submit(at(1.0));
|
||||
let p = w.poll().expect("a preview");
|
||||
|
||||
Reference in New Issue
Block a user