diff --git a/gfx/wr/webrender/src/composite.rs b/gfx/wr/webrender/src/composite.rs index 1a11c985782c..4d47c2afa41b 100644 --- a/gfx/wr/webrender/src/composite.rs +++ b/gfx/wr/webrender/src/composite.rs @@ -140,12 +140,26 @@ pub struct CompositeState { pub native_surface_updates: Vec, /// The kind of compositor for picture cache tiles (e.g. drawn by WR, or OS compositor) pub compositor_kind: CompositorKind, + /// Picture caching may be disabled dynamically, based on debug flags, pinch zoom etc. + pub picture_caching_is_enabled: bool, } impl CompositeState { /// Construct a new state for compositing picture tiles. This is created /// during each frame construction and passed to the renderer. - pub fn new(compositor_kind: CompositorKind) -> Self { + pub fn new( + compositor_kind: CompositorKind, + mut picture_caching_is_enabled: bool, + ) -> Self { + // The native compositor interface requires picture caching to work, so + // force it here and warn if it was disabled. + if let CompositorKind::Native { .. } = compositor_kind { + if !picture_caching_is_enabled { + warn!("Picture caching cannot be disabled in native compositor config"); + } + picture_caching_is_enabled = true; + } + CompositeState { opaque_tiles: Vec::new(), alpha_tiles: Vec::new(), @@ -154,6 +168,7 @@ impl CompositeState { dirty_rects_are_valid: true, native_surface_updates: Vec::new(), compositor_kind, + picture_caching_is_enabled, } } diff --git a/gfx/wr/webrender/src/frame_builder.rs b/gfx/wr/webrender/src/frame_builder.rs index af6e1f46eeb3..a09e9bbfe210 100644 --- a/gfx/wr/webrender/src/frame_builder.rs +++ b/gfx/wr/webrender/src/frame_builder.rs @@ -56,7 +56,8 @@ pub struct FrameBuilderConfig { pub dual_source_blending_is_supported: bool, pub dual_source_blending_is_enabled: bool, pub chase_primitive: ChasePrimitive, - pub enable_picture_caching: bool, + /// The immutable global picture caching enable from `RendererOptions` + pub global_enable_picture_caching: bool, /// True if we're running tests (i.e. via wrench). pub testing: bool, pub gpu_supports_fast_clears: bool, @@ -314,6 +315,7 @@ impl FrameBuilder { gpu_cache, &scene.clip_store, data_stores, + composite_state, ); { @@ -495,7 +497,18 @@ impl FrameBuilder { let output_size = scene.output_rect.size.to_i32(); let screen_world_rect = (scene.output_rect.to_f32() / global_device_pixel_scale).round_out(); - let mut composite_state = CompositeState::new(scene.config.compositor_kind); + + // Determine if we will draw this frame with picture caching enabled. This depends on: + // (1) If globally enabled when WR was initialized + // (2) If current debug flags allow picture caching + // (3) [In future] Whether we are currently pinch zooming + let picture_caching_is_enabled = + scene.config.global_enable_picture_caching && + !debug_flags.contains(DebugFlags::DISABLE_PICTURE_CACHING); + let mut composite_state = CompositeState::new( + scene.config.compositor_kind, + picture_caching_is_enabled, + ); let main_render_task_id = self.build_layer_screen_rects_and_cull_layers( scene, diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs index 57aed03d63df..302b081f0083 100644 --- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -1949,6 +1949,7 @@ pub struct PictureUpdateState<'a> { surface_stack: Vec, picture_stack: Vec, are_raster_roots_assigned: bool, + composite_state: &'a CompositeState, } impl<'a> PictureUpdateState<'a> { @@ -1960,6 +1961,7 @@ impl<'a> PictureUpdateState<'a> { gpu_cache: &mut GpuCache, clip_store: &ClipStore, data_stores: &mut DataStores, + composite_state: &CompositeState, ) { profile_marker!("UpdatePictures"); @@ -1968,6 +1970,7 @@ impl<'a> PictureUpdateState<'a> { surface_stack: vec![SurfaceIndex(0)], picture_stack: Vec::new(), are_raster_roots_assigned: true, + composite_state, }; state.update( @@ -3656,14 +3659,20 @@ impl PicturePrimitive { let actual_composite_mode = match self.requested_composite_mode { Some(PictureCompositeMode::Filter(ref filter)) if filter.is_noop() => None, Some(PictureCompositeMode::TileCache { .. }) => { - // Disable tile cache if the scroll root has a perspective transform, since - // this breaks many assumptions (it's a very rare edge case anyway, and - // is probably (?) going to be moving / animated in this case). - let spatial_node = &frame_context - .clip_scroll_tree - .spatial_nodes[self.spatial_node_index.0 as usize]; - if spatial_node.coordinate_system_id == CoordinateSystemId::root() { - Some(PictureCompositeMode::TileCache { }) + // Only allow picture caching composite mode if global picture caching setting + // is enabled this frame. + if state.composite_state.picture_caching_is_enabled { + // Disable tile cache if the scroll root has a perspective transform, since + // this breaks many assumptions (it's a very rare edge case anyway, and + // is probably (?) going to be moving / animated in this case). + let spatial_node = &frame_context + .clip_scroll_tree + .spatial_nodes[self.spatial_node_index.0 as usize]; + if spatial_node.coordinate_system_id == CoordinateSystemId::root() { + Some(PictureCompositeMode::TileCache { }) + } else { + None + } } else { None } diff --git a/gfx/wr/webrender/src/renderer.rs b/gfx/wr/webrender/src/renderer.rs index 7419f9e0efa5..f668f9444138 100644 --- a/gfx/wr/webrender/src/renderer.rs +++ b/gfx/wr/webrender/src/renderer.rs @@ -1763,7 +1763,6 @@ pub struct Renderer { clear_color: Option, enable_clear_scissor: bool, - enable_picture_caching: bool, enable_advanced_blend_barriers: bool, debug: LazyInitializedDebugRenderer, @@ -2135,7 +2134,7 @@ impl Renderer { dual_source_blending_is_enabled: true, dual_source_blending_is_supported: use_dual_source_blending, chase_primitive: options.chase_primitive, - enable_picture_caching: options.enable_picture_caching, + global_enable_picture_caching: options.enable_picture_caching, testing: options.testing, gpu_supports_fast_clears: options.gpu_supports_fast_clears, gpu_supports_advanced_blend: ext_blend_equation_advanced, @@ -2252,7 +2251,7 @@ impl Renderer { let texture_cache = TextureCache::new( max_texture_size, max_texture_layers, - if config.enable_picture_caching { + if config.global_enable_picture_caching { picture_tile_sizes } else { &[] @@ -2332,7 +2331,6 @@ impl Renderer { clear_color: options.clear_color, enable_clear_scissor: options.enable_clear_scissor, enable_advanced_blend_barriers: !ext_blend_equation_advanced_coherent, - enable_picture_caching: options.enable_picture_caching, last_time: 0, gpu_profile, vaos: RendererVAOs { @@ -4987,7 +4985,10 @@ impl Renderer { surface_is_y_flipped, }; - if self.enable_picture_caching { + // Picture caching can be enabled / disabled dynamically from frame to + // frame. This is determined by what the frame builder selected, and is + // passed to the renderer via the composite state. + if frame.composite_state.picture_caching_is_enabled { // If we have a native OS compositor, then make use of that interface // to specify how to composite each of the picture cache surfaces. match self.compositor_config { diff --git a/gfx/wr/webrender/src/scene.rs b/gfx/wr/webrender/src/scene.rs index 8e6797bed1fd..d8156a1499e7 100644 --- a/gfx/wr/webrender/src/scene.rs +++ b/gfx/wr/webrender/src/scene.rs @@ -247,7 +247,7 @@ impl BuiltScene { dual_source_blending_is_enabled: true, dual_source_blending_is_supported: false, chase_primitive: ChasePrimitive::Nothing, - enable_picture_caching: false, + global_enable_picture_caching: false, testing: false, gpu_supports_fast_clears: false, gpu_supports_advanced_blend: false, diff --git a/gfx/wr/webrender/src/scene_building.rs b/gfx/wr/webrender/src/scene_building.rs index 0cf2bf90494d..e61e392d6bf7 100644 --- a/gfx/wr/webrender/src/scene_building.rs +++ b/gfx/wr/webrender/src/scene_building.rs @@ -488,7 +488,7 @@ impl<'a> SceneBuilder<'a> { &mut self, main_prim_list: &mut PrimitiveList, ) { - if !self.config.enable_picture_caching { + if !self.config.global_enable_picture_caching { return; } @@ -1693,7 +1693,7 @@ impl<'a> SceneBuilder<'a> { None }; - if is_pipeline_root && create_tile_cache && self.config.enable_picture_caching { + if is_pipeline_root && create_tile_cache && self.config.global_enable_picture_caching { // we don't expect any nested tile-cache-enabled stacking contexts debug_assert!(!self.sc_stack.iter().any(|sc| sc.create_tile_cache)); } diff --git a/gfx/wr/webrender_api/src/api.rs b/gfx/wr/webrender_api/src/api.rs index 30f81d2189cb..41b7a8b5a26d 100644 --- a/gfx/wr/webrender_api/src/api.rs +++ b/gfx/wr/webrender_api/src/api.rs @@ -1144,6 +1144,8 @@ bitflags! { const OBSCURE_IMAGES = 1 << 24; /// The profiler only displays information that is out of the ordinary. const SMART_PROFILER = 1 << 26; + /// Dynamically control whether picture caching is enabled. + const DISABLE_PICTURE_CACHING = 1 << 27; } } diff --git a/gfx/wr/wrench/src/main.rs b/gfx/wr/wrench/src/main.rs index f1281dc421a4..390d53011f61 100644 --- a/gfx/wr/wrench/src/main.rs +++ b/gfx/wr/wrench/src/main.rs @@ -705,6 +705,11 @@ fn render<'a>( VirtualKeyCode::Escape => { return winit::ControlFlow::Break; } + VirtualKeyCode::A => { + debug_flags.toggle(DebugFlags::DISABLE_PICTURE_CACHING); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } VirtualKeyCode::P => { debug_flags.toggle(DebugFlags::PROFILER_DBG); wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));