Bug 1522017 - Make picture caching explicit. r=gw
authorBobby Holley <bobbyholley@gmail.com>
Wed, 23 Jan 2019 10:32:40 -0800
changeset 515322 7ba7f98526f43fff32e7dfced3917400b1eb14eb
parent 515321 145d739c4139f2767cb7e1475e17ab7d600dead4
child 515323 44febac9160b71d7b9317d09e7ff7a3f4bc8c46f
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1522017
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1522017 - Make picture caching explicit. r=gw Differential Revision: https://phabricator.services.mozilla.com/D17435
gfx/layers/wr/WebRenderCommandBuilder.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/wr/examples/alpha_perf.rs
gfx/wr/examples/animation.rs
gfx/wr/examples/basic.rs
gfx/wr/examples/blob.rs
gfx/wr/examples/document.rs
gfx/wr/examples/frame_output.rs
gfx/wr/examples/iframe.rs
gfx/wr/examples/image_resize.rs
gfx/wr/examples/multiwindow.rs
gfx/wr/examples/scrolling.rs
gfx/wr/examples/texture_cache_stress.rs
gfx/wr/examples/yuv.rs
gfx/wr/webrender/src/display_list_flattener.rs
gfx/wr/webrender_api/src/display_item.rs
gfx/wr/webrender_api/src/display_list.rs
gfx/wr/wrench/src/yaml_frame_reader.rs
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -1446,19 +1446,26 @@ void WebRenderCommandBuilder::BuildWebRe
 
   {
     if (!mZoomProp && gfxPrefs::APZAllowZooming() && XRE_IsContentProcess()) {
       mZoomProp.emplace();
       mZoomProp->effect_type = wr::WrAnimationType::Transform;
       mZoomProp->id = AnimationHelper::GetNextCompositorAnimationsId();
     }
 
+    nsPresContext* presContext =
+        aDisplayListBuilder->RootReferenceFrame()->PresContext();
+    bool isTopLevelContent =
+        presContext->Document()->IsTopLevelContentDocument();
+
     wr::StackingContextParams params;
     params.mFilters = std::move(aFilters);
     params.animation = mZoomProp.ptrOr(nullptr);
+    params.cache_tiles = isTopLevelContent;
+
     StackingContextHelper pageRootSc(sc, nullptr, nullptr, nullptr, aBuilder,
                                      params);
     if (ShouldDumpDisplayList(aDisplayListBuilder)) {
       mBuilderDumpIndex =
           aBuilder.Dump(mDumpIndent + 1, Some(mBuilderDumpIndex), Nothing());
     }
     CreateWebRenderCommandsFromDisplayList(aDisplayList, nullptr,
                                            aDisplayListBuilder, pageRootSc,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -314,16 +314,17 @@ class MOZ_RAII AutoTransactionSender {
 struct MOZ_STACK_CLASS StackingContextParams : public WrStackingContextParams {
   StackingContextParams()
       : WrStackingContextParams{WrStackingContextClip::None(),
                                 nullptr,
                                 nullptr,
                                 wr::TransformStyle::Flat,
                                 wr::ReferenceFrameKind::Transform,
                                 /* is_backface_visible = */ true,
+                                /* cache_tiles = */ false,
                                 wr::MixBlendMode::Normal} {}
 
   void SetPreserve3D(bool aPreserve) {
     transform_style =
         aPreserve ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat;
   }
 
   nsTArray<wr::FilterOp> mFilters;
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1900,16 +1900,18 @@ pub extern "C" fn wr_dp_clear_save(state
 #[repr(C)]
 pub struct WrStackingContextParams {
     pub clip: WrStackingContextClip,
     pub animation: *const WrAnimationProperty,
     pub opacity: *const f32,
     pub transform_style: TransformStyle,
     pub reference_frame_kind: ReferenceFrameKind,
     pub is_backface_visible: bool,
+    /// True if picture caching should be enabled for this stacking context.
+    pub cache_tiles: bool,
     pub mix_blend_mode: MixBlendMode,
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_push_stacking_context(
     state: &mut WrState,
     mut bounds: LayoutRect,
     spatial_id: WrSpatialId,
@@ -1994,17 +1996,18 @@ pub extern "C" fn wr_dp_push_stacking_co
     state.frame_builder
          .dl_builder
          .push_stacking_context(&prim_info,
                                 wr_spatial_id,
                                 wr_clip_id,
                                 params.transform_style,
                                 params.mix_blend_mode,
                                 &filters,
-                                glyph_raster_space);
+                                glyph_raster_space,
+                                params.cache_tiles);
 
     result
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState,
                                              is_reference_frame: bool) {
     debug_assert!(unsafe { !is_in_render_thread() });
--- a/gfx/wr/examples/alpha_perf.rs
+++ b/gfx/wr/examples/alpha_perf.rs
@@ -28,24 +28,19 @@ impl Example for App {
         _framebuffer_size: DeviceIntSize,
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let bounds = (0, 0).to(1920, 1080);
         let info = LayoutPrimitiveInfo::new(bounds);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         for _ in 0 .. self.rect_count {
             builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 1.0, 0.05));
         }
 
         builder.pop_stacking_context();
     }
--- a/gfx/wr/examples/animation.rs
+++ b/gfx/wr/examples/animation.rs
@@ -58,24 +58,20 @@ impl App {
         let spatial_id = builder.push_reference_frame(
             &LayoutRect::new(bounds.origin, LayoutSize::zero()),
             SpatialId::root_scroll_node(pipeline_id),
             TransformStyle::Flat,
             PropertyBinding::Binding(property_key, LayoutTransform::identity()),
             ReferenceFrameKind::Transform,
         );
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context_with_filters(
             &LayoutPrimitiveInfo::new(LayoutRect::zero()),
             spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
             &filters,
-            RasterSpace::Screen,
         );
 
         let space_and_clip = SpaceAndClipInfo {
             spatial_id,
             clip_id: ClipId::root(pipeline_id),
         };
         let clip_bounds = LayoutRect::new(LayoutPoint::zero(), bounds.size);
         let complex_clip = ComplexClipRegion {
--- a/gfx/wr/examples/basic.rs
+++ b/gfx/wr/examples/basic.rs
@@ -189,24 +189,19 @@ impl Example for App {
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
         let info = LayoutPrimitiveInfo::new(bounds);
         let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
         let spatial_id = root_space_and_clip.spatial_id;
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let image_mask_key = api.generate_image_key();
         txn.add_image(
             image_mask_key,
             ImageDescriptor::new(2, 2, ImageFormat::R8, true, false),
             ImageData::new(vec![0, 80, 180, 255]),
             None,
--- a/gfx/wr/examples/blob.rs
+++ b/gfx/wr/examples/blob.rs
@@ -217,24 +217,19 @@ impl Example for App {
             api::ImageDescriptor::new(200, 200, api::ImageFormat::BGRA8, true, false),
             serialize_blob(api::ColorU::new(50, 150, 50, 255)),
             None,
         );
 
         let bounds = api::LayoutRect::new(api::LayoutPoint::zero(), builder.content_size());
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &api::LayoutPrimitiveInfo::new(bounds),
             space_and_clip.spatial_id,
-            None,
-            api::TransformStyle::Flat,
-            api::MixBlendMode::Normal,
-            &[],
-            api::RasterSpace::Screen,
         );
 
         builder.push_image(
             &api::LayoutPrimitiveInfo::new((30, 30).by(500, 500)),
             &space_and_clip,
             api::LayoutSize::new(500.0, 500.0),
             api::LayoutSize::new(0.0, 0.0),
             api::ImageRendering::Auto,
--- a/gfx/wr/examples/document.rs
+++ b/gfx/wr/examples/document.rs
@@ -107,24 +107,19 @@ impl Example for App {
                 doc.pipeline_id,
                 doc.content_rect.size,
             );
             let local_rect = LayoutRect::new(
                 LayoutPoint::zero(),
                 doc.content_rect.size,
             );
 
-            builder.push_stacking_context(
+            builder.push_simple_stacking_context(
                 &LayoutPrimitiveInfo::new(doc.content_rect),
                 space_and_clip.spatial_id,
-                None,
-                TransformStyle::Flat,
-                MixBlendMode::Normal,
-                &[],
-                RasterSpace::Screen,
             );
             builder.push_rect(
                 &LayoutPrimitiveInfo::new(local_rect),
                 &space_and_clip,
                 doc.color,
             );
             builder.pop_stacking_context();
 
--- a/gfx/wr/examples/frame_output.rs
+++ b/gfx/wr/examples/frame_output.rs
@@ -108,24 +108,19 @@ impl App {
 
         let info = LayoutPrimitiveInfo::new(document.content_rect);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
         let mut builder = DisplayListBuilder::new(
             document.pipeline_id,
             document.content_rect.size,
         );
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 0.0, 1.0));
         builder.pop_stacking_context();
 
         txn.set_root_pipeline(pipeline_id);
         txn.set_display_list(
             Epoch(0),
@@ -154,24 +149,19 @@ impl Example for App {
             let device_pixel_ratio = framebuffer_size.width as f32 /
                 builder.content_size().width;
             self.init_output_document(api, DeviceIntSize::new(200, 200), device_pixel_ratio);
         }
 
         let info = LayoutPrimitiveInfo::new((100, 100).to(200, 200));
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         builder.push_image(
             &info,
             &space_and_clip,
             info.rect.size,
             LayoutSize::zero(),
             ImageRendering::Auto,
--- a/gfx/wr/examples/iframe.rs
+++ b/gfx/wr/examples/iframe.rs
@@ -33,24 +33,19 @@ impl Example for App {
         let sub_size = DeviceIntSize::new(100, 100);
         let sub_bounds = (0, 0).to(sub_size.width as i32, sub_size.height as i32);
 
         let sub_pipeline_id = PipelineId(pipeline_id.0, 42);
         let mut sub_builder = DisplayListBuilder::new(sub_pipeline_id, sub_bounds.size);
         let mut space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
         let info = LayoutPrimitiveInfo::new(sub_bounds);
-        sub_builder.push_stacking_context(
+        sub_builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         // green rect visible == success
         sub_builder.push_rect(&info, &space_and_clip, ColorF::new(0.0, 1.0, 0.0, 1.0));
         sub_builder.pop_stacking_context();
 
         let mut txn = Transaction::new();
         txn.set_display_list(
@@ -67,24 +62,19 @@ impl Example for App {
             space_and_clip.spatial_id,
             TransformStyle::Flat,
             PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity()),
             ReferenceFrameKind::Transform,
         );
 
         // And this is for the root pipeline
         let info = LayoutPrimitiveInfo::new(sub_bounds);
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
         // red rect under the iframe: if this is visible, things have gone wrong
         builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 0.0, 0.0, 1.0));
         builder.push_iframe(&info, &space_and_clip, sub_pipeline_id, false);
         builder.pop_stacking_context();
         builder.pop_reference_frame();
     }
 }
--- a/gfx/wr/examples/image_resize.rs
+++ b/gfx/wr/examples/image_resize.rs
@@ -36,24 +36,19 @@ impl Example for App {
             image_data,
             None,
         );
 
         let bounds = (0, 0).to(512, 512);
         let info = LayoutPrimitiveInfo::new(bounds);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let image_size = LayoutSize::new(100.0, 100.0);
 
         let info = LayoutPrimitiveInfo::with_clip_rect(
             LayoutRect::new(LayoutPoint::new(100.0, 100.0), image_size),
             bounds,
         );
--- a/gfx/wr/examples/multiwindow.rs
+++ b/gfx/wr/examples/multiwindow.rs
@@ -186,24 +186,19 @@ impl Window {
         };
         let layout_size = framebuffer_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
         let mut txn = Transaction::new();
         let mut builder = DisplayListBuilder::new(self.pipeline_id, layout_size);
         let space_and_clip = SpaceAndClipInfo::root_scroll(self.pipeline_id);
 
         let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
         let info = LayoutPrimitiveInfo::new(bounds);
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let info = LayoutPrimitiveInfo::new(LayoutRect::new(
             LayoutPoint::new(100.0, 100.0),
             LayoutSize::new(100.0, 200.0)
         ));
         builder.push_rect(&info, &space_and_clip, ColorF::new(0.0, 1.0, 0.0, 1.0));
 
--- a/gfx/wr/examples/scrolling.rs
+++ b/gfx/wr/examples/scrolling.rs
@@ -29,38 +29,28 @@ impl Example for App {
         _framebuffer_size: DeviceIntSize,
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let info = LayoutPrimitiveInfo::new(
             LayoutRect::new(LayoutPoint::zero(), builder.content_size())
         );
         let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             root_space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         if true {
             // scrolling and clips stuff
             // let's make a scrollbox
             let scrollbox = (0, 0).to(300, 400);
-            builder.push_stacking_context(
+            builder.push_simple_stacking_context(
                 &LayoutPrimitiveInfo::new((10, 10).by(0, 0)),
                 root_space_and_clip.spatial_id,
-                None,
-                TransformStyle::Flat,
-                MixBlendMode::Normal,
-                &[],
-                RasterSpace::Screen,
             );
             // set the scrolling clip
             let space_and_clip1 = builder.define_scroll_frame(
                 &root_space_and_clip,
                 None,
                 (0, 0).by(1000, 1000),
                 scrollbox,
                 vec![],
--- a/gfx/wr/examples/texture_cache_stress.rs
+++ b/gfx/wr/examples/texture_cache_stress.rs
@@ -93,24 +93,19 @@ impl Example for App {
         _framebuffer_size: DeviceIntSize,
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let bounds = (0, 0).to(512, 512);
         let info = LayoutPrimitiveInfo::new(bounds);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let x0 = 50.0;
         let y0 = 50.0;
         let image_size = LayoutSize::new(4.0, 4.0);
 
         if self.swap_keys.is_empty() {
             let key0 = api.generate_image_key();
--- a/gfx/wr/examples/yuv.rs
+++ b/gfx/wr/examples/yuv.rs
@@ -90,24 +90,19 @@ impl Example for App {
         _framebuffer_size: DeviceIntSize,
         pipeline_id: PipelineId,
         _document_id: DocumentId,
     ) {
         let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
         let info = LayoutPrimitiveInfo::new(bounds);
         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
 
-        builder.push_stacking_context(
+        builder.push_simple_stacking_context(
             &info,
             space_and_clip.spatial_id,
-            None,
-            TransformStyle::Flat,
-            MixBlendMode::Normal,
-            &[],
-            RasterSpace::Screen,
         );
 
         let yuv_chanel1 = api.generate_image_key();
         let yuv_chanel2 = api.generate_image_key();
         let yuv_chanel2_1 = api.generate_image_key();
         let yuv_chanel3 = api.generate_image_key();
         txn.add_image(
             yuv_chanel1,
--- a/gfx/wr/webrender/src/display_list_flattener.rs
+++ b/gfx/wr/webrender/src/display_list_flattener.rs
@@ -446,16 +446,17 @@ impl<'a> DisplayListFlattener<'a> {
         let pipeline_id = pipeline.pipeline_id;
 
         self.push_stacking_context(
             pipeline_id,
             CompositeOps::default(),
             TransformStyle::Flat,
             true,
             true,
+            false,
             ROOT_SPATIAL_NODE_INDEX,
             ClipChainId::NONE,
             RasterSpace::Screen,
         );
 
         // For the root pipeline, there's no need to add a full screen rectangle
         // here, as it's handled by the framebuffer clear.
         // TODO(gw): In future, we can probably remove this code completely and handle
@@ -636,16 +637,17 @@ impl<'a> DisplayListFlattener<'a> {
         };
 
         self.push_stacking_context(
             pipeline_id,
             composition_operations,
             stacking_context.transform_style,
             is_backface_visible,
             false,
+            stacking_context.cache_tiles,
             spatial_node_index,
             clip_chain_id,
             stacking_context.raster_space,
         );
 
         self.flatten_items(
             traversal,
             pipeline_id,
@@ -1207,31 +1209,29 @@ impl<'a> DisplayListFlattener<'a> {
 
     pub fn push_stacking_context(
         &mut self,
         pipeline_id: PipelineId,
         composite_ops: CompositeOps,
         transform_style: TransformStyle,
         is_backface_visible: bool,
         is_pipeline_root: bool,
+        create_tile_cache: bool,
         spatial_node_index: SpatialNodeIndex,
         clip_chain_id: ClipChainId,
         requested_raster_space: RasterSpace,
     ) {
         // Check if this stacking context is the root of a pipeline, and the caller
         // has requested it as an output frame.
         let frame_output_pipeline_id = if is_pipeline_root && self.output_pipelines.contains(&pipeline_id) {
             Some(pipeline_id)
         } else {
             None
         };
 
-        let create_tile_cache = is_pipeline_root &&
-                                self.sc_stack.len() == 2;
-
         // Get the transform-style of the parent stacking context,
         // which determines if we *might* need to draw this on
         // an intermediate surface for plane splitting purposes.
         let (parent_is_3d, extra_3d_instance) = match self.sc_stack.last_mut() {
             Some(sc) => {
                 // Cut the sequence of flat children before starting a child stacking context,
                 // so that the relative order between them and our current SC is preserved.
                 let extra_instance = sc.cut_flat_item_sequence(
@@ -2567,18 +2567,18 @@ impl FlattenedStackingContext {
             return false;
         }
 
         // If represents a transform, it may affect backface visibility of children
         if !clip_scroll_tree.node_is_identity(self.spatial_node_index) {
             return false;
         }
 
-        // If the pipelines are different, we care for purposes of selecting tile caches
-        if self.pipeline_id != parent.pipeline_id {
+        // If this stacking context gets picture caching, we need it.
+        if self.create_tile_cache {
             return false;
         }
 
         // It is redundant!
         true
     }
 
     /// For a Preserve3D context, cut the sequence of the immediate flat children
--- a/gfx/wr/webrender_api/src/display_item.rs
+++ b/gfx/wr/webrender_api/src/display_item.rs
@@ -547,16 +547,18 @@ pub struct PushStackingContextDisplayIte
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct StackingContext {
     pub transform_style: TransformStyle,
     pub mix_blend_mode: MixBlendMode,
     pub clip_id: Option<ClipId>,
     pub raster_space: RasterSpace,
+    /// True if picture caching should be used on this stacking context.
+    pub cache_tiles: bool,
 } // IMPLICIT: filters: Vec<FilterOp>
 
 
 #[repr(u32)]
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum TransformStyle {
     Flat = 0,
     Preserve3D = 1,
--- a/gfx/wr/webrender_api/src/display_list.rs
+++ b/gfx/wr/webrender_api/src/display_list.rs
@@ -1299,33 +1299,63 @@ impl DisplayListBuilder {
         &mut self,
         layout: &LayoutPrimitiveInfo,
         spatial_id: SpatialId,
         clip_id: Option<ClipId>,
         transform_style: TransformStyle,
         mix_blend_mode: MixBlendMode,
         filters: &[FilterOp],
         raster_space: RasterSpace,
+        cache_tiles: bool,
     ) {
         let item = SpecificDisplayItem::PushStackingContext(PushStackingContextDisplayItem {
             stacking_context: StackingContext {
                 transform_style,
                 mix_blend_mode,
                 clip_id,
                 raster_space,
+                cache_tiles,
             },
         });
 
         self.push_item(&item, layout, &SpaceAndClipInfo {
             spatial_id,
             clip_id: ClipId::invalid(),
         });
         self.push_iter(filters);
     }
 
+    /// Helper for examples/ code.
+    pub fn push_simple_stacking_context(
+        &mut self,
+        layout: &LayoutPrimitiveInfo,
+        spatial_id: SpatialId,
+    ) {
+        self.push_simple_stacking_context_with_filters(layout, spatial_id, &[]);
+    }
+
+    /// Helper for examples/ code.
+    pub fn push_simple_stacking_context_with_filters(
+        &mut self,
+        layout: &LayoutPrimitiveInfo,
+        spatial_id: SpatialId,
+        filters: &[FilterOp],
+    ) {
+        self.push_stacking_context(
+            layout,
+            spatial_id,
+            None,
+            TransformStyle::Flat,
+            MixBlendMode::Normal,
+            filters,
+            RasterSpace::Screen,
+            /* cache_tiles = */ false,
+        );
+    }
+
     pub fn pop_stacking_context(&mut self) {
         self.push_new_empty_item(&SpecificDisplayItem::PopStackingContext);
     }
 
     pub fn push_stops(&mut self, stops: &[GradientStop]) {
         if stops.is_empty() {
             return;
         }
--- a/gfx/wr/wrench/src/yaml_frame_reader.rs
+++ b/gfx/wr/wrench/src/yaml_frame_reader.rs
@@ -1772,16 +1772,17 @@ impl YamlFrameReader {
         dl.push_stacking_context(
             &info,
             *self.spatial_id_stack.last().unwrap(),
             clip_node_id,
             transform_style,
             mix_blend_mode,
             &filters,
             raster_space,
+            /* cache_tiles = */ false,
         );
 
         if !yaml["items"].is_badvalue() {
             self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
         }
 
         dl.pop_stacking_context();