Skip to content

Commit 2616bc1

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 9f97122 commit 2616bc1

File tree

13 files changed

+90
-45
lines changed

13 files changed

+90
-45
lines changed

examples/animation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ impl Example for App {
233233
colors: vec![],
234234
},
235235
);
236-
txn.generate_frame(0, RenderReasons::empty());
236+
txn.generate_frame(0, true, RenderReasons::empty());
237237
api.send_transaction(document_id, txn);
238238
}
239239
_ => (),

examples/common/boilerplate.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ pub fn main_wrapper<E: Example>(
211211
builder.end(),
212212
);
213213
txn.set_root_pipeline(pipeline_id);
214-
txn.generate_frame(0, RenderReasons::empty());
214+
txn.generate_frame(0, true, RenderReasons::empty());
215215
api.send_transaction(document_id, txn);
216216

217217
println!("Entering event loop");
@@ -307,7 +307,7 @@ pub fn main_wrapper<E: Example>(
307307
epoch,
308308
builder.end(),
309309
);
310-
txn.generate_frame(0, RenderReasons::empty());
310+
txn.generate_frame(0, true, RenderReasons::empty());
311311
}
312312
api.send_transaction(document_id, txn);
313313

examples/document.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl Example for App {
122122
Epoch(0),
123123
builder.end(),
124124
);
125-
txn.generate_frame(0, RenderReasons::empty());
125+
txn.generate_frame(0, true, RenderReasons::empty());
126126
api.send_transaction(doc.id, txn);
127127
}
128128
}

examples/image_resize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl Example for App {
110110
&DirtyRect::All,
111111
);
112112
let mut txn = Transaction::new();
113-
txn.generate_frame(0, RenderReasons::empty());
113+
txn.generate_frame(0, true, RenderReasons::empty());
114114
api.send_transaction(document_id, txn);
115115
}
116116
_ => {}

examples/multiwindow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ impl Window {
279279
builder.end(),
280280
);
281281
txn.set_root_pipeline(self.pipeline_id);
282-
txn.generate_frame(0, RenderReasons::empty());
282+
txn.generate_frame(0, true, RenderReasons::empty());
283283
api.send_transaction(self.document_id, txn);
284284

285285
renderer.update();

examples/scrolling.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ impl Example for App {
243243
generation: APZScrollGeneration::default(),
244244
}],
245245
);
246-
txn.generate_frame(0, RenderReasons::empty());
246+
txn.generate_frame(0, true, RenderReasons::empty());
247247
}
248248
}
249249
winit::event::WindowEvent::CursorMoved { position, .. } => {
@@ -267,7 +267,7 @@ impl Example for App {
267267
}],
268268
);
269269

270-
txn.generate_frame(0, RenderReasons::empty());
270+
txn.generate_frame(0, true, RenderReasons::empty());
271271
}
272272
winit::event::WindowEvent::MouseInput { .. } => {
273273
let results = api.hit_test(

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 => {

0 commit comments

Comments
 (0)