mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-28 04:16:46 -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.
|
/// A preview has this many times fewer pixels each way than the view it stands in for.
|
||||||
pub const PREVIEW_FACTOR: f64 = 4.0;
|
pub const PREVIEW_FACTOR: f64 = 4.0;
|
||||||
/// Full renders quicker than this (about a frame) show without a preview first.
|
/// 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)]
|
#[derive(Clone)]
|
||||||
pub struct Job {
|
pub struct Job {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use figcraft_render::{View, Work};
|
|||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use super::{CanvasState, shows};
|
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.
|
/// A page of ellipses with a rectangle on top; the session and the rectangle.
|
||||||
fn document() -> (Session, NodeId) {
|
fn document() -> (Session, NodeId) {
|
||||||
@@ -27,6 +27,35 @@ fn document() -> (Session, NodeId) {
|
|||||||
(s, rect)
|
(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`.
|
/// 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 {
|
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 }
|
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]
|
#[test]
|
||||||
fn the_browser_worker_previews_by_measured_render_time_then_refines_the_next_frame() {
|
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².
|
// Renders from scratch at 200% and 100% (whose times decide the previews below) well over the
|
||||||
let (mut s, rect) = document();
|
// threshold, wherever this runs.
|
||||||
s.execute("effect.add", &json!({"ids": [rect], "type": "GLASS"})).unwrap();
|
let view = |scale| view_at((300.0, 200.0), scale, 1200, 1200);
|
||||||
s.execute("effect.add", &json!({"ids": [rect], "type": "BACKGROUND_BLUR"})).unwrap();
|
let s = slow_scene(&[view(2.0), view(1.0)], 3.0 * PREVIEW_AFTER_MS);
|
||||||
let ds = s.ds().unwrap();
|
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.
|
// The production threshold, as the browser has it.
|
||||||
let mut w = Inline::new(egui::Context::default());
|
let mut w = Inline::new(egui::Context::default());
|
||||||
w.submit(at(2.0));
|
w.submit(at(2.0));
|
||||||
let first = w.poll().expect("the first image");
|
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.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.
|
// A new zoom: the preview this frame, the refined image the next.
|
||||||
w.submit(at(1.0));
|
w.submit(at(1.0));
|
||||||
let p = w.poll().expect("a preview");
|
let p = w.poll().expect("a preview");
|
||||||
|
|||||||
Reference in New Issue
Block a user