Bug 1409446 - Wire up the DefineClip and DefineScrollLayer APIs to allow specifying ancestry. r=jrmuizel
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 24 Oct 2017 15:45:57 -0400
changeset 388001 793acbd73126d1ce000657503ecb32c37f1c9e5b
parent 388000 cb757b237396115d23516005b66c71427d227d43
child 388002 4ae5fc22aecf326e49b0bcdd3068a4a690e2a27f
push id32739
push useracraciun@mozilla.com
push dateWed, 25 Oct 2017 09:29:21 +0000
treeherdermozilla-central@252a8528c5ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1409446
milestone58.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 1409446 - Wire up the DefineClip and DefineScrollLayer APIs to allow specifying ancestry. r=jrmuizel The APIs now allow providing the parent clip or scroll info explicitly instead of having to push it on the stack. For now we just pass Nothing() to preserve the existing behaviour, so this change is a functinoal no-op. MozReview-Commit-ID: dtNamN595
gfx/layers/wr/ScrollingLayersHelper.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
layout/painting/nsCSSRenderingBorders.cpp
layout/painting/nsDisplayList.cpp
--- a/gfx/layers/wr/ScrollingLayersHelper.cpp
+++ b/gfx/layers/wr/ScrollingLayersHelper.cpp
@@ -152,17 +152,17 @@ ScrollingLayersHelper::DefineAndPushChai
   }
   if (!clipId || aBuilder.HasExtraClip()) {
     // If we don't have a clip id for this chain item yet, define the clip in WR
     // and save the id
     LayoutDeviceRect clip = LayoutDeviceRect::FromAppUnits(
         aChain->mClip.GetClipRect(), aAppUnitsPerDevPixel);
     nsTArray<wr::ComplexClipRegion> wrRoundedRects;
     aChain->mClip.ToComplexClipRegions(aAppUnitsPerDevPixel, aStackingContext, wrRoundedRects);
-    clipId = Some(aBuilder.DefineClip(aStackingContext.ToRelativeLayoutRect(clip), &wrRoundedRects));
+    clipId = Some(aBuilder.DefineClip(Nothing(), Nothing(), aStackingContext.ToRelativeLayoutRect(clip), &wrRoundedRects));
     if (!aBuilder.HasExtraClip()) {
       aCache[aChain] = clipId.value();
     }
   }
   // Finally, push the clip onto the WR stack
   MOZ_ASSERT(clipId);
   aBuilder.PushClip(clipId.value());
   mPushedClips.push_back(wr::ScrollOrClipId(clipId.value()));
@@ -185,17 +185,17 @@ ScrollingLayersHelper::DefineAndPushScro
   // is, both of them should be relative to the stacking context `aStackingContext`.
   // However, when we get the scrollable rect from the FrameMetrics, the origin
   // has nothing to do with the position of the frame but instead represents
   // the minimum allowed scroll offset of the scrollable content. While APZ
   // uses this to clamp the scroll position, we don't need to send this to
   // WebRender at all. Instead, we take the position from the composition
   // bounds.
   contentRect.MoveTo(clipBounds.TopLeft());
-  mBuilder->DefineScrollLayer(aMetrics.GetScrollId(),
+  mBuilder->DefineScrollLayer(aMetrics.GetScrollId(), Nothing(), Nothing(),
       aStackingContext.ToRelativeLayoutRect(contentRect),
       aStackingContext.ToRelativeLayoutRect(clipBounds));
   mBuilder->PushScrollLayer(aMetrics.GetScrollId());
   return true;
 }
 
 ScrollingLayersHelper::~ScrollingLayersHelper()
 {
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -688,26 +688,37 @@ DisplayListBuilder::PushStackingContext(
 void
 DisplayListBuilder::PopStackingContext()
 {
   WRDL_LOG("PopStackingContext\n", mWrState);
   wr_dp_pop_stacking_context(mWrState);
 }
 
 wr::WrClipId
-DisplayListBuilder::DefineClip(const wr::LayoutRect& aClipRect,
+DisplayListBuilder::DefineClip(const Maybe<layers::FrameMetrics::ViewID>& aAncestorScrollId,
+                               const Maybe<wr::WrClipId>& aAncestorClipId,
+                               const wr::LayoutRect& aClipRect,
                                const nsTArray<wr::ComplexClipRegion>* aComplex,
                                const wr::WrImageMask* aMask)
 {
-  uint64_t clip_id = wr_dp_define_clip(mWrState, aClipRect,
+  const uint64_t* ancestorClipId = nullptr;
+  if (aAncestorClipId) {
+    ancestorClipId = &(aAncestorClipId.ref().id);
+  }
+  uint64_t clip_id = wr_dp_define_clip(mWrState,
+      aAncestorScrollId.ptrOr(nullptr), ancestorClipId,
+      aClipRect,
       aComplex ? aComplex->Elements() : nullptr,
       aComplex ? aComplex->Length() : 0,
       aMask);
-  WRDL_LOG("DefineClip id=%" PRIu64 " r=%s m=%p b=%s complex=%zu\n", mWrState,
-      clip_id, Stringify(aClipRect).c_str(), aMask,
+  WRDL_LOG("DefineClip id=%" PRIu64 " as=%s ac=%s r=%s m=%p b=%s complex=%zu\n", mWrState,
+      clip_id,
+      aAncestorScrollId ? Stringify(aAncestorScrollId.ref()).c_str() : "(nil)",
+      aAncestorClipId ? Stringify(aAncestorClipId.ref().id).c_str() : "(nil)",
+      Stringify(aClipRect).c_str(), aMask,
       aMask ? Stringify(aMask->rect).c_str() : "none",
       aComplex ? aComplex->Length() : 0);
   return wr::WrClipId { clip_id };
 }
 
 void
 DisplayListBuilder::PushClip(const wr::WrClipId& aClipId, bool aExtra)
 {
@@ -767,29 +778,39 @@ DisplayListBuilder::PopStickyFrame()
 bool
 DisplayListBuilder::IsScrollLayerDefined(layers::FrameMetrics::ViewID aScrollId) const
 {
   return mScrollParents.find(aScrollId) != mScrollParents.end();
 }
 
 void
 DisplayListBuilder::DefineScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
+                                      const Maybe<layers::FrameMetrics::ViewID>& aAncestorScrollId,
+                                      const Maybe<wr::WrClipId>& aAncestorClipId,
                                       const wr::LayoutRect& aContentRect,
                                       const wr::LayoutRect& aClipRect)
 {
-  WRDL_LOG("DefineScrollLayer id=%" PRIu64 " co=%s cl=%s\n", mWrState,
-      aScrollId, Stringify(aContentRect).c_str(), Stringify(aClipRect).c_str());
+  WRDL_LOG("DefineScrollLayer id=%" PRIu64 " as=%s ac=%s co=%s cl=%s\n", mWrState,
+      aScrollId,
+      aAncestorScrollId ? Stringify(aAncestorScrollId.ref()).c_str() : "(nil)",
+      aAncestorClipId ? Stringify(aAncestorClipId.ref().id).c_str() : "(nil)",
+      Stringify(aContentRect).c_str(), Stringify(aClipRect).c_str());
 
   Maybe<layers::FrameMetrics::ViewID> parent =
       mScrollIdStack.empty() ? Nothing() : Some(mScrollIdStack.back());
   auto it = mScrollParents.insert({aScrollId, parent});
   if (it.second) {
     // An insertion took place, which means we haven't defined aScrollId before.
     // So let's define it now.
-    wr_dp_define_scroll_layer(mWrState, aScrollId, aContentRect, aClipRect);
+    const uint64_t* ancestorClipId = nullptr;
+    if (aAncestorClipId) {
+      ancestorClipId = &(aAncestorClipId.ref().id);
+    }
+    wr_dp_define_scroll_layer(mWrState, aScrollId, aAncestorScrollId.ptrOr(nullptr),
+        ancestorClipId, aContentRect, aClipRect);
   } else {
     // aScrollId was already a key in mScrollParents so check that the parent
     // value is the same.
     MOZ_ASSERT(it.first->second == parent);
   }
 }
 
 void
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -223,32 +223,36 @@ public:
                            const gfx::Matrix4x4* aTransform,
                            wr::TransformStyle aTransformStyle,
                            const gfx::Matrix4x4* aPerspective,
                            const wr::MixBlendMode& aMixBlendMode,
                            const nsTArray<wr::WrFilterOp>& aFilters,
                            bool aIsBackfaceVisible);
   void PopStackingContext();
 
-  wr::WrClipId DefineClip(const wr::LayoutRect& aClipRect,
+  wr::WrClipId DefineClip(const Maybe<layers::FrameMetrics::ViewID>& aAncestorScrollId,
+                          const Maybe<wr::WrClipId>& aAncestorClipId,
+                          const wr::LayoutRect& aClipRect,
                           const nsTArray<wr::ComplexClipRegion>* aComplex = nullptr,
                           const wr::WrImageMask* aMask = nullptr);
   void PushClip(const wr::WrClipId& aClipId, bool aExtra = false);
   void PopClip(bool aExtra = false);
 
   wr::WrStickyId DefineStickyFrame(const wr::LayoutRect& aContentRect,
                                    const wr::StickySideConstraint* aTop,
                                    const wr::StickySideConstraint* aRight,
                                    const wr::StickySideConstraint* aBottom,
                                    const wr::StickySideConstraint* aLeft);
   void PushStickyFrame(const wr::WrStickyId& aStickyId);
   void PopStickyFrame();
 
   bool IsScrollLayerDefined(layers::FrameMetrics::ViewID aScrollId) const;
   void DefineScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
+                         const Maybe<layers::FrameMetrics::ViewID>& aAncestorScrollId,
+                         const Maybe<wr::WrClipId>& aAncestorClipId,
                          const wr::LayoutRect& aContentRect, // TODO: We should work with strongly typed rects
                          const wr::LayoutRect& aClipRect);
   void PushScrollLayer(const layers::FrameMetrics::ViewID& aScrollId);
   void PopScrollLayer();
 
   void PushClipAndScrollInfo(const layers::FrameMetrics::ViewID& aScrollId,
                              const wr::WrClipId* aClipId);
   void PopClipAndScrollInfo();
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1200,29 +1200,62 @@ pub extern "C" fn wr_dp_push_stacking_co
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState) {
     debug_assert!(unsafe { !is_in_render_thread() });
     state.frame_builder.dl_builder.pop_stacking_context();
 }
 
+fn make_scroll_info(state: &mut WrState,
+                    scroll_id: Option<&u64>,
+                    clip_id: Option<&u64>)
+                    -> Option<ClipAndScrollInfo> {
+    if let Some(&sid) = scroll_id {
+        if let Some(&cid) = clip_id {
+            Some(ClipAndScrollInfo::new(
+                ClipId::new(sid, state.pipeline_id),
+                ClipId::Clip(cid, state.pipeline_id)))
+        } else {
+            Some(ClipAndScrollInfo::simple(
+                ClipId::new(sid, state.pipeline_id)))
+        }
+    } else if let Some(&cid) = clip_id {
+        Some(ClipAndScrollInfo::simple(
+            ClipId::Clip(cid, state.pipeline_id)))
+    } else {
+        None
+    }
+}
+
 #[no_mangle]
 pub extern "C" fn wr_dp_define_clip(state: &mut WrState,
+                                    ancestor_scroll_id: *const u64,
+                                    ancestor_clip_id: *const u64,
                                     clip_rect: LayoutRect,
                                     complex: *const ComplexClipRegion,
                                     complex_count: usize,
                                     mask: *const WrImageMask)
                                     -> u64 {
     debug_assert!(unsafe { is_in_main_thread() });
+
+    let info = make_scroll_info(state,
+                                unsafe { ancestor_scroll_id.as_ref() },
+                                unsafe { ancestor_clip_id.as_ref() });
+
     let complex_slice = make_slice(complex, complex_count);
     let complex_iter = complex_slice.iter().cloned();
     let mask : Option<ImageMask> = unsafe { mask.as_ref() }.map(|x| x.into());
 
-    let clip_id = state.frame_builder.dl_builder.define_clip(None, clip_rect, complex_iter, mask);
+    let clip_id = if info.is_some() {
+        state.frame_builder.dl_builder.define_clip_with_parent(None,
+            info.unwrap().scroll_node_id, clip_rect, complex_iter, mask)
+    } else {
+        state.frame_builder.dl_builder.define_clip(None, clip_rect, complex_iter, mask)
+    };
     // return the u64 id value from inside the ClipId::Clip(..)
     match clip_id {
         ClipId::Clip(id, pipeline_id) => {
             assert!(pipeline_id == state.pipeline_id);
             id
         },
         _ => panic!("Got unexpected clip id type"),
     }
@@ -1263,23 +1296,36 @@ pub extern "C" fn wr_dp_define_sticky_fr
         },
         _ => panic!("Got unexpected clip id type"),
     }
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_define_scroll_layer(state: &mut WrState,
                                             scroll_id: u64,
+                                            ancestor_scroll_id: *const u64,
+                                            ancestor_clip_id: *const u64,
                                             content_rect: LayoutRect,
                                             clip_rect: LayoutRect) {
     assert!(unsafe { is_in_main_thread() });
+
+    let info = make_scroll_info(state,
+                                unsafe { ancestor_scroll_id.as_ref() },
+                                unsafe { ancestor_clip_id.as_ref() });
+
     let clip_id = ClipId::new(scroll_id, state.pipeline_id);
-    state.frame_builder.dl_builder.define_scroll_frame(
-        Some(clip_id), content_rect, clip_rect, vec![], None,
-        ScrollSensitivity::Script);
+    if info.is_some() {
+        state.frame_builder.dl_builder.define_scroll_frame_with_parent(
+            Some(clip_id), info.unwrap().scroll_node_id, content_rect,
+            clip_rect, vec![], None, ScrollSensitivity::Script);
+    } else {
+        state.frame_builder.dl_builder.define_scroll_frame(
+            Some(clip_id), content_rect, clip_rect, vec![], None,
+            ScrollSensitivity::Script);
+    };
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_push_scroll_layer(state: &mut WrState,
                                           scroll_id: u64) {
     debug_assert!(unsafe { is_in_main_thread() });
     let clip_id = ClipId::new(scroll_id, state.pipeline_id);
     state.frame_builder.dl_builder.push_clip_id(clip_id);
@@ -1301,25 +1347,19 @@ pub extern "C" fn wr_scroll_layer_with_i
     dh.api.scroll_node_with_id(dh.document_id, new_scroll_origin, clip_id, ScrollClamping::NoClamping);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_push_clip_and_scroll_info(state: &mut WrState,
                                                   scroll_id: u64,
                                                   clip_id: *const u64) {
     debug_assert!(unsafe { is_in_main_thread() });
-    let scroll_id = ClipId::new(scroll_id, state.pipeline_id);
-    let info = if let Some(&id) = unsafe { clip_id.as_ref() } {
-        ClipAndScrollInfo::new(
-            scroll_id,
-            ClipId::Clip(id, state.pipeline_id))
-    } else {
-        ClipAndScrollInfo::simple(scroll_id)
-    };
-    state.frame_builder.dl_builder.push_clip_and_scroll_info(info);
+    let info = make_scroll_info(state, Some(&scroll_id), unsafe { clip_id.as_ref() });
+    debug_assert!(info.is_some());
+    state.frame_builder.dl_builder.push_clip_and_scroll_info(info.unwrap());
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_clip_and_scroll_info(state: &mut WrState) {
     debug_assert!(unsafe { is_in_main_thread() });
     state.frame_builder.dl_builder.pop_clip_id();
 }
 
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -942,25 +942,29 @@ void wr_dec_ref_arc(const VecU8 *aArc)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_clear_save(WrState *aState)
 WR_FUNC;
 
 WR_INLINE
 uint64_t wr_dp_define_clip(WrState *aState,
+                           const uint64_t *aAncestorScrollId,
+                           const uint64_t *aAncestorClipId,
                            LayoutRect aClipRect,
                            const ComplexClipRegion *aComplex,
                            size_t aComplexCount,
                            const WrImageMask *aMask)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_define_scroll_layer(WrState *aState,
                                uint64_t aScrollId,
+                               const uint64_t *aAncestorScrollId,
+                               const uint64_t *aAncestorClipId,
                                LayoutRect aContentRect,
                                LayoutRect aClipRect)
 WR_FUNC;
 
 WR_INLINE
 uint64_t wr_dp_define_sticky_frame(WrState *aState,
                                    LayoutRect aContentRect,
                                    const StickySideConstraint *aTopRange,
--- a/layout/painting/nsCSSRenderingBorders.cpp
+++ b/layout/painting/nsCSSRenderingBorders.cpp
@@ -3616,17 +3616,17 @@ nsCSSBorderRenderer::CreateWebRenderComm
   wr::BorderRadius borderRadius = wr::ToBorderRadius(LayoutDeviceSize::FromUnknownSize(mBorderRadii[0]),
                                                      LayoutDeviceSize::FromUnknownSize(mBorderRadii[1]),
                                                      LayoutDeviceSize::FromUnknownSize(mBorderRadii[3]),
                                                      LayoutDeviceSize::FromUnknownSize(mBorderRadii[2]));
 
   if (mLocalClip) {
     LayoutDeviceRect clip = LayoutDeviceRect::FromUnknownRect(mLocalClip.value());
     wr::LayoutRect clipRect = aSc.ToRelativeLayoutRect(clip);
-    wr::WrClipId clipId = aBuilder.DefineClip(clipRect);
+    wr::WrClipId clipId = aBuilder.DefineClip(Nothing(), Nothing(), clipRect);
     aBuilder.PushClip(clipId, true);
   }
 
   Range<const wr::BorderSide> wrsides(side, 4);
   aBuilder.PushBorder(transformedRect,
                       transformedRect,
                       mBackfaceIsVisible,
                       wr::ToBorderWidths(mBorderWidths[0], mBorderWidths[1], mBorderWidths[2], mBorderWidths[3]),
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -9403,17 +9403,17 @@ nsDisplayMask::CreateWebRenderCommands(m
   float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   nsRect displayBound = GetBounds(aDisplayListBuilder, &snap);
   LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(displayBound, appUnitsPerDevPixel);
 
   Maybe<wr::WrImageMask> mask = aManager->CommandBuilder().BuildWrMaskImage(this, aBuilder, aResources,
                                                                             aSc, aDisplayListBuilder,
                                                                             bounds);
   if (mask) {
-    wr::WrClipId clipId = aBuilder.DefineClip(
+    wr::WrClipId clipId = aBuilder.DefineClip(Nothing(), Nothing(),
         aSc.ToRelativeLayoutRect(bounds), nullptr, mask.ptr());
     // Don't record this clip push in aBuilder's internal clip stack, because
     // otherwise any nested ScrollingLayersHelper instances that are created
     // will get confused about which clips are pushed.
     aBuilder.PushClip(clipId, /*aMask*/ true);
   }
 
   nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aResources, aSc, aManager, aDisplayListBuilder);