Skip to content

Commit 03aed52

Browse files
committed
Bug 1924152 - Add multi-frame reftests to wrench. r=gw
Also add a test to exercise the feature as well as the new render-without-present mode in WebRender. Differential Revision: https://phabricator.services.mozilla.com/D234163
1 parent 2616bc1 commit 03aed52

File tree

5 files changed

+119
-20
lines changed

5 files changed

+119
-20
lines changed

wrench/reftests/image/reftest.list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ fuzzy(1,160000) == image-filter-stretch-tile.yaml green-alpha-ref.yaml
2525
== snapshot-filters-01.yaml snapshot-filters-01-ref.yaml
2626
== snapshot-filters-02.yaml snapshot-filters-02-ref.yaml
2727
fuzzy(3,3000) == snapshot-shadow.yaml snapshot-shadow-ref.yaml
28+
== snapshot-multiframe.yaml snapshot-multiframe-ref.yaml
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
root:
3+
items:
4+
- type: stacking-context
5+
bounds: [0, 0, 200, 200]
6+
items:
7+
- type: rect
8+
bounds: [ 0, 0, 90, 100 ]
9+
color: [0, 150, 0]
10+
- type: rect
11+
bounds: [ 10, 100, 90, 100 ]
12+
color: [150, 0, 0]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# This test exercises wrench's multi-frame reftest feature by capturing an
2+
# out-of-view stacking context snapshot in the first frame and displaying it
3+
# as an image in the second frame.
4+
# It also exercises webrender's ability to render a frame without compositing
5+
# it into the window.
6+
---
7+
frames:
8+
# First frame
9+
- root:
10+
# Don't present this frame into the window.
11+
present: false
12+
items:
13+
- type: stacking-context
14+
bounds: [0, 0, 100, 100]
15+
items:
16+
- type: rect
17+
bounds: [ 0, 0, 320, 250 ]
18+
color: [100, 50, 10]
19+
- type: stacking-context
20+
# The snapshotted stacking context is far out of the view
21+
bounds: [100000, 0, 200, 200]
22+
snapshot:
23+
name: "snap0"
24+
area: [0, 0, 100, 200]
25+
items:
26+
- type: rect
27+
bounds: [ 0, 0, 90, 100 ]
28+
color: [0, 150, 0]
29+
- type: rect
30+
bounds: [ 10, 100, 90, 100 ]
31+
color: [150, 0, 0]
32+
# This red rectangle that covers the view should not be shown because
33+
# it is not part of a snapshot and the frame is not presented.
34+
- type: rect
35+
bounds: [0, 0, 1000, 1000]
36+
color: red
37+
# Second frame
38+
- root:
39+
items:
40+
- image: snapshot(snap0)
41+
bounds: [0, 0, 100, 200]

wrench/src/wrench.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ use webrender::api::units::*;
2121
use webrender::{DebugFlags, RenderResults, ShaderPrecacheFlags, LayerCompositor};
2222
use crate::{WindowWrapper, NotifierEvent};
2323

24+
#[derive(Clone)]
25+
pub struct DisplayList {
26+
pub pipeline: PipelineId,
27+
pub payload: BuiltDisplayList,
28+
/// Whether to request that the transaction is presented to the window.
29+
///
30+
/// The transaction will be presented if it contains at least one display list
31+
/// with present set to true.
32+
pub present: bool,
33+
/// If set to true, send the transaction after adding this display list to it.
34+
pub send_transaction: bool,
35+
}
36+
2437
// TODO(gw): This descriptor matches what we currently support for fonts
2538
// but is quite a mess. We should at least document and
2639
// use better types for things like the style and stretch.
@@ -551,24 +564,36 @@ impl Wrench {
551564

552565
pub fn send_lists(
553566
&mut self,
554-
frame_number: u32,
555-
display_lists: Vec<(PipelineId, BuiltDisplayList)>,
567+
frame_number: &mut u32,
568+
display_lists: Vec<DisplayList>,
556569
scroll_offsets: &HashMap<ExternalScrollId, Vec<SampledScrollOffset>>,
557570
) {
558571
let mut txn = Transaction::new();
572+
let mut present = false;
559573
for display_list in display_lists {
574+
present |= display_list.present;
575+
560576
txn.set_display_list(
561-
Epoch(frame_number),
562-
display_list,
577+
Epoch(*frame_number),
578+
(display_list.pipeline, display_list.payload),
563579
);
564-
}
565580

566-
for (id, offsets) in scroll_offsets {
567-
txn.set_scroll_offsets(*id, offsets.clone());
581+
if display_list.send_transaction {
582+
for (id, offsets) in scroll_offsets {
583+
txn.set_scroll_offsets(*id, offsets.clone());
584+
}
585+
586+
txn.generate_frame(0, present, RenderReasons::TESTING);
587+
self.api.send_transaction(self.document_id, txn);
588+
txn = Transaction::new();
589+
590+
present = false;
591+
*frame_number += 1;
592+
}
568593
}
569594

570-
txn.generate_frame(0, true, RenderReasons::TESTING);
571-
self.api.send_transaction(self.document_id, txn);
595+
// The last display lists should be have send_transaction set to true.
596+
assert!(txn.is_empty());
572597
}
573598

574599
pub fn get_frame_profiles(

wrench/src/yaml_frame_reader.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use webrender::api::*;
1717
use webrender::render_api::*;
1818
use webrender::api::units::*;
1919
use webrender::api::FillRule;
20-
use crate::wrench::{FontDescriptor, Wrench, WrenchThing};
20+
use crate::wrench::{FontDescriptor, Wrench, WrenchThing, DisplayList};
2121
use crate::yaml_helper::{StringEnum, YamlHelper, make_perspective};
2222
use yaml_rust::{Yaml, YamlLoader};
2323
use crate::PLATFORM_DEFAULT_FACE_NAME;
@@ -322,7 +322,7 @@ pub struct YamlFrameReader {
322322
aux_dir: PathBuf,
323323
frame_count: u32,
324324

325-
display_lists: Vec<(PipelineId, BuiltDisplayList)>,
325+
display_lists: Vec<DisplayList>,
326326

327327
watch_source: bool,
328328
list_resources: bool,
@@ -447,13 +447,23 @@ impl YamlFrameReader {
447447

448448
if let Some(pipelines) = yaml["pipelines"].as_vec() {
449449
for pipeline in pipelines {
450-
self.build_pipeline(wrench, pipeline["id"].as_pipeline_id().unwrap(), pipeline);
450+
let pipeline_id = pipeline["id"].as_pipeline_id().unwrap();
451+
let mut builder = DisplayListBuilder::new(pipeline_id);
452+
self.build_pipeline(wrench, &mut builder, pipeline_id, false, pipeline);
451453
}
452454
}
453455

454-
let root_stacking_context = &yaml["root"];
455-
assert_ne!(*root_stacking_context, Yaml::BadValue);
456-
self.build_pipeline(wrench, wrench.root_pipeline_id, root_stacking_context);
456+
let mut builder = DisplayListBuilder::new(wrench.root_pipeline_id);
457+
458+
if let Some(frames) = yaml["frames"].as_vec() {
459+
for frame in frames {
460+
self.build_pipeline(wrench, &mut builder, wrench.root_pipeline_id, true, frame);
461+
}
462+
} else {
463+
let root_stacking_context = &yaml["root"];
464+
assert_ne!(*root_stacking_context, Yaml::BadValue);
465+
self.build_pipeline(wrench, &mut builder, wrench.root_pipeline_id, true, root_stacking_context);
466+
}
457467

458468
// If replaying the same frame during interactive use, the frame gets rebuilt,
459469
// but the external image handler has already been consumed by the renderer.
@@ -465,26 +475,37 @@ impl YamlFrameReader {
465475
fn build_pipeline(
466476
&mut self,
467477
wrench: &mut Wrench,
478+
builder: &mut DisplayListBuilder,
468479
pipeline_id: PipelineId,
480+
send_transaction: bool,
469481
yaml: &Yaml
470482
) {
483+
// By default, present if send_transaction is set to true. Can be overridden
484+
// by a field in the pipeline's root.
485+
let present = yaml["present"].as_bool().unwrap_or(send_transaction);
486+
471487
// Don't allow referencing clips between pipelines for now.
472488
self.user_clip_id_map.clear();
473489
self.user_clipchain_id_map.clear();
474490
self.user_spatial_id_map.clear();
475491
self.spatial_id_stack.clear();
476492
self.spatial_id_stack.push(SpatialId::root_scroll_node(pipeline_id));
477493

478-
let mut builder = DisplayListBuilder::new(pipeline_id);
479494
builder.begin();
480495
let mut info = CommonItemProperties {
481496
clip_rect: LayoutRect::zero(),
482497
clip_chain_id: ClipChainId::INVALID,
483498
spatial_id: SpatialId::new(0, PipelineId::dummy()),
484499
flags: PrimitiveFlags::default(),
485500
};
486-
self.add_stacking_context_from_yaml(&mut builder, wrench, yaml, IsRoot(true), &mut info);
487-
self.display_lists.push(builder.end());
501+
self.add_stacking_context_from_yaml(builder, wrench, yaml, IsRoot(true), &mut info);
502+
let (pipeline, payload) = builder.end();
503+
self.display_lists.push(DisplayList {
504+
pipeline,
505+
payload,
506+
present,
507+
send_transaction,
508+
});
488509

489510
assert_eq!(self.spatial_id_stack.len(), 1);
490511
}
@@ -2139,15 +2160,14 @@ impl WrenchThing for YamlFrameReader {
21392160
if should_build_yaml || wrench.should_rebuild_display_lists() {
21402161
wrench.begin_frame();
21412162
wrench.send_lists(
2142-
self.frame_count,
2163+
&mut self.frame_count,
21432164
self.display_lists.clone(),
21442165
&self.scroll_offsets,
21452166
);
21462167
} else {
21472168
wrench.refresh();
21482169
}
21492170

2150-
self.frame_count += 1;
21512171
self.frame_count
21522172
}
21532173

0 commit comments

Comments
 (0)