Skip to content

Commit 1239d71

Browse files
committed
Bug 1924152 - Support rendering without presenting. r=gw
The goal for this initial implementation is to be able to render picture snapshots without presenting the frame, but it could be extended to supporting some picture cache slices without presenting (for example if we know that the picture is not affected by scrolling or animated properties and want to start rendering it early). Differential Revision: https://phabricator.services.mozilla.com/D234162
1 parent 88b772d commit 1239d71

File tree

7 files changed

+82
-37
lines changed

7 files changed

+82
-37
lines changed

webrender/src/frame_builder.rs

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ impl FrameBuilder {
274274
fn build_layer_screen_rects_and_cull_layers(
275275
&mut self,
276276
scene: &mut BuiltScene,
277+
present: bool,
277278
global_screen_world_rect: WorldRect,
278279
resource_cache: &mut ResourceCache,
279280
gpu_cache: &mut GpuCache,
@@ -294,6 +295,8 @@ impl FrameBuilder {
294295
) {
295296
profile_scope!("build_layer_screen_rects_and_cull_layers");
296297

298+
let render_picture_cache_slices = present;
299+
297300
let root_spatial_node_index = spatial_tree.root_reference_frame_index();
298301

299302
const MAX_CLIP_COORD: f32 = 1.0e9;
@@ -427,6 +430,9 @@ impl FrameBuilder {
427430
}
428431

429432
for pic_index in scene.tile_cache_pictures.iter().rev() {
433+
if !render_picture_cache_slices {
434+
break;
435+
}
430436
let pic = &mut scene.prim_store.pictures[pic_index.0];
431437

432438
match pic.raster_config {
@@ -583,6 +589,10 @@ impl FrameBuilder {
583589
frame_state.push_dirty_region(default_dirty_region);
584590

585591
for pic_index in &scene.tile_cache_pictures {
592+
if !render_picture_cache_slices {
593+
break;
594+
}
595+
586596
prepare_picture(
587597
*pic_index,
588598
&mut scene.prim_store,
@@ -617,6 +627,7 @@ impl FrameBuilder {
617627
pub fn build(
618628
&mut self,
619629
scene: &mut BuiltScene,
630+
present: bool,
620631
resource_cache: &mut ResourceCache,
621632
gpu_cache: &mut GpuCache,
622633
rg_builder: &mut RenderTaskGraphBuilder,
@@ -682,6 +693,7 @@ impl FrameBuilder {
682693

683694
self.build_layer_screen_rects_and_cull_layers(
684695
scene,
696+
present,
685697
screen_world_rect,
686698
resource_cache,
687699
gpu_cache,
@@ -772,33 +784,35 @@ impl FrameBuilder {
772784
passes.push(pass);
773785
}
774786

775-
let mut ctx = RenderTargetContext {
776-
global_device_pixel_scale,
777-
clip_store: &scene.clip_store,
778-
prim_store: &scene.prim_store,
779-
resource_cache,
780-
use_dual_source_blending,
781-
use_advanced_blending: scene.config.gpu_supports_advanced_blend,
782-
break_advanced_blend_batches: !scene.config.advanced_blend_is_coherent,
783-
batch_lookback_count: scene.config.batch_lookback_count,
784-
spatial_tree,
785-
data_stores,
786-
surfaces: &scene.surfaces,
787-
scratch: &mut scratch.primitive,
788-
screen_world_rect,
789-
globals: &self.globals,
790-
tile_caches,
791-
root_spatial_node_index: spatial_tree.root_reference_frame_index(),
792-
frame_memory: &mut frame_memory,
793-
};
787+
if present {
788+
let mut ctx = RenderTargetContext {
789+
global_device_pixel_scale,
790+
clip_store: &scene.clip_store,
791+
prim_store: &scene.prim_store,
792+
resource_cache,
793+
use_dual_source_blending,
794+
use_advanced_blending: scene.config.gpu_supports_advanced_blend,
795+
break_advanced_blend_batches: !scene.config.advanced_blend_is_coherent,
796+
batch_lookback_count: scene.config.batch_lookback_count,
797+
spatial_tree,
798+
data_stores,
799+
surfaces: &scene.surfaces,
800+
scratch: &mut scratch.primitive,
801+
screen_world_rect,
802+
globals: &self.globals,
803+
tile_caches,
804+
root_spatial_node_index: spatial_tree.root_reference_frame_index(),
805+
frame_memory: &mut frame_memory,
806+
};
794807

795-
self.build_composite_pass(
796-
scene,
797-
&mut ctx,
798-
gpu_cache,
799-
&mut deferred_resolves,
800-
&mut composite_state,
801-
);
808+
self.build_composite_pass(
809+
scene,
810+
&mut ctx,
811+
gpu_cache,
812+
&mut deferred_resolves,
813+
&mut composite_state,
814+
);
815+
}
802816
}
803817

804818
profile.end_time(profiler::FRAME_BATCHING_TIME);
@@ -822,6 +836,7 @@ impl FrameBuilder {
822836
device_origin,
823837
scene.output_rect.size(),
824838
),
839+
present,
825840
passes,
826841
transform_palette: transform_palette.finish(),
827842
render_tasks,
@@ -1274,6 +1289,7 @@ pub fn build_render_pass(
12741289
pub struct Frame {
12751290
/// The rectangle to show the frame in, on screen.
12761291
pub device_rect: DeviceIntRect,
1292+
pub present: bool,
12771293
pub passes: FrameVec<RenderPass>,
12781294

12791295
pub transform_palette: FrameVec<TransformData>,

webrender/src/render_api.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ pub enum GenerateFrame {
122122
/// An id that allows tracking the frame transaction through the various
123123
/// frame stages. Specified by the caller of generate_frame().
124124
id: u64,
125+
/// If false, (a subset of) the frame will be rendered, but nothing will
126+
/// be presented on the window.
127+
present: bool,
125128
},
126129
/// Don't generate a frame even if something has changed.
127130
No,
@@ -136,10 +139,19 @@ impl GenerateFrame {
136139
}
137140
}
138141

142+
/// If false, a frame may be (partially) generated but it will not be
143+
/// presented to the window.
144+
pub fn present(&self) -> bool {
145+
match self {
146+
GenerateFrame::Yes { present, .. } => *present,
147+
GenerateFrame::No => false,
148+
}
149+
}
150+
139151
/// Return the frame ID, if a frame is generated.
140152
pub fn id(&self) -> Option<u64> {
141153
match self {
142-
GenerateFrame::Yes { id } => Some(*id),
154+
GenerateFrame::Yes { id, .. } => Some(*id),
143155
GenerateFrame::No => None,
144156
}
145157
}
@@ -363,8 +375,8 @@ impl Transaction {
363375
/// as to when happened.
364376
///
365377
/// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
366-
pub fn generate_frame(&mut self, id: u64, reasons: RenderReasons) {
367-
self.generate_frame = GenerateFrame::Yes{ id };
378+
pub fn generate_frame(&mut self, id: u64, present: bool, reasons: RenderReasons) {
379+
self.generate_frame = GenerateFrame::Yes{ id, present };
368380
self.render_reasons |= reasons;
369381
}
370382

webrender/src/render_backend.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ impl Document {
515515
debug_flags: DebugFlags,
516516
tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
517517
frame_stats: Option<FullFrameStats>,
518+
present: bool,
518519
render_reasons: RenderReasons,
519520
frame_memory: FrameMemory,
520521
) -> RenderedDocument {
@@ -529,6 +530,7 @@ impl Document {
529530
let frame = {
530531
let frame = self.frame_builder.build(
531532
&mut self.scene,
533+
present,
532534
resource_cache,
533535
gpu_cache,
534536
&mut self.rg_builder,
@@ -959,6 +961,7 @@ impl RenderBackend {
959961
txn.frame_ops.take(),
960962
txn.notifications.take(),
961963
txn.render_frame,
964+
txn.present,
962965
RenderReasons::SCENE,
963966
None,
964967
txn.invalidate_rendered_frame,
@@ -1309,6 +1312,7 @@ impl RenderBackend {
13091312
txn.frame_ops.take(),
13101313
txn.notifications.take(),
13111314
txn.generate_frame.as_bool(),
1315+
txn.generate_frame.present(),
13121316
txn.render_reasons,
13131317
txn.generate_frame.id(),
13141318
txn.invalidate_rendered_frame,
@@ -1348,6 +1352,7 @@ impl RenderBackend {
13481352
Vec::default(),
13491353
Vec::default(),
13501354
false,
1355+
false,
13511356
RenderReasons::empty(),
13521357
None,
13531358
false,
@@ -1370,6 +1375,7 @@ impl RenderBackend {
13701375
mut frame_ops: Vec<FrameMsg>,
13711376
mut notifications: Vec<NotificationRequest>,
13721377
mut render_frame: bool,
1378+
present: bool,
13731379
render_reasons: RenderReasons,
13741380
generated_frame_id: Option<u64>,
13751381
invalidate_rendered_frame: bool,
@@ -1469,6 +1475,7 @@ impl RenderBackend {
14691475
self.debug_flags,
14701476
&mut self.tile_caches,
14711477
frame_stats,
1478+
present,
14721479
render_reasons,
14731480
frame_memory,
14741481
);
@@ -1675,6 +1682,7 @@ impl RenderBackend {
16751682
self.debug_flags,
16761683
&mut self.tile_caches,
16771684
None,
1685+
true,
16781686
RenderReasons::empty(),
16791687
frame_memory,
16801688
);

webrender/src/renderer/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,7 +1444,7 @@ impl Renderer {
14441444
&mut self,
14451445
doc_id: DocumentId,
14461446
active_doc: &mut RenderedDocument,
1447-
device_size: Option<DeviceIntSize>,
1447+
mut device_size: Option<DeviceIntSize>,
14481448
buffer_age: usize,
14491449
) -> Result<RenderResults, Vec<RendererError>> {
14501450
profile_scope!("render");
@@ -1512,6 +1512,12 @@ impl Renderer {
15121512
frame_id
15131513
};
15141514

1515+
if !active_doc.frame.present {
1516+
// Setting device_size to None is what ensures compositing/presenting
1517+
// the frame is skipped in the rest of this module.
1518+
device_size = None;
1519+
}
1520+
15151521
if let Some(device_size) = device_size {
15161522
// Inform the client that we are starting a composition transaction if native
15171523
// compositing is enabled. This needs to be done early in the frame, so that
@@ -3494,7 +3500,7 @@ impl Renderer {
34943500
// to the swapchain tile list
34953501
match tile.kind {
34963502
TileKind::Opaque | TileKind::Alpha => {
3497-
// Store (index of tile, index of layer) so we can segment them below
3503+
// Store (index of tile, index of layer) so we can segment them below
34983504
occlusion.add(&rect, is_opaque, idx); // (idx, input_layers.len() - 1));
34993505
}
35003506
TileKind::Clear => {

webrender/src/scene_builder_thread.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub struct BuiltTransaction {
6969
pub interner_updates: Option<InternerUpdates>,
7070
pub spatial_tree_updates: Option<SpatialTreeUpdates>,
7171
pub render_frame: bool,
72+
pub present: bool,
7273
pub invalidate_rendered_frame: bool,
7374
pub profile: TransactionProfile,
7475
pub frame_stats: FullFrameStats,
@@ -477,6 +478,7 @@ impl SceneBuilderThread {
477478
let txns = vec![Box::new(BuiltTransaction {
478479
document_id: item.document_id,
479480
render_frame: item.build_frame,
481+
present: true,
480482
invalidate_rendered_frame: false,
481483
built_scene,
482484
view: item.view,
@@ -664,6 +666,7 @@ impl SceneBuilderThread {
664666
Box::new(BuiltTransaction {
665667
document_id: txn.document_id,
666668
render_frame: txn.generate_frame.as_bool(),
669+
present: txn.generate_frame.present(),
667670
invalidate_rendered_frame: txn.invalidate_rendered_frame,
668671
built_scene,
669672
view: doc.view,

wrench/src/rawtest.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl<'a> RawtestHarness<'a> {
9797
);
9898
epoch.0 += 1;
9999

100-
txn.generate_frame(0, RenderReasons::TESTING);
100+
txn.generate_frame(0, true, RenderReasons::TESTING);
101101
self.wrench.api.send_transaction(self.wrench.document_id, txn);
102102
}
103103

@@ -1237,7 +1237,7 @@ impl<'a> RawtestHarness<'a> {
12371237
Epoch(0),
12381238
builder.end(),
12391239
);
1240-
txn.generate_frame(0, RenderReasons::TESTING);
1240+
txn.generate_frame(0, true, RenderReasons::TESTING);
12411241

12421242
self.wrench.api.send_transaction(self.wrench.document_id, txn);
12431243

@@ -1270,7 +1270,7 @@ impl<'a> RawtestHarness<'a> {
12701270
// 6. rebuild the scene and compare again
12711271
let mut txn = Transaction::new();
12721272
txn.set_root_pipeline(captured.root_pipeline_id.unwrap());
1273-
txn.generate_frame(0, RenderReasons::TESTING);
1273+
txn.generate_frame(0, true, RenderReasons::TESTING);
12741274
self.wrench.api.send_transaction(captured.document_id, txn);
12751275
let pixels2 = self.render_and_get_pixels(window_rect);
12761276
self.compare_pixels(pixels0, pixels2, window_rect.size());
@@ -1300,7 +1300,7 @@ impl<'a> RawtestHarness<'a> {
13001300
Epoch(1),
13011301
builder.end(),
13021302
);
1303-
txn.generate_frame(0, RenderReasons::TESTING);
1303+
txn.generate_frame(0, true, RenderReasons::TESTING);
13041304
self.wrench.api.send_transaction(doc_id, txn);
13051305

13061306
// Ensure we get a notification from rendering the above, even though

wrench/src/wrench.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ impl Wrench {
567567
txn.set_scroll_offsets(*id, offsets.clone());
568568
}
569569

570-
txn.generate_frame(0, RenderReasons::TESTING);
570+
txn.generate_frame(0, true, RenderReasons::TESTING);
571571
self.api.send_transaction(self.document_id, txn);
572572
}
573573

@@ -588,7 +588,7 @@ impl Wrench {
588588
pub fn refresh(&mut self) {
589589
self.begin_frame();
590590
let mut txn = Transaction::new();
591-
txn.generate_frame(0, RenderReasons::TESTING);
591+
txn.generate_frame(0, true, RenderReasons::TESTING);
592592
self.api.send_transaction(self.document_id, txn);
593593
}
594594

0 commit comments

Comments
 (0)