Bug 1368496 - Track the pushed clip and scroll IDs. r=jrmuizel
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 08 Jun 2017 11:34:00 -0400
changeset 411145 fd266694b1f8a5d81ce30382bde54d505139329e
parent 411144 6ca11746a8fc0914f47c00b526155348a9db8087
child 411146 c48397f4c2e2c2b8152abc7370bc615047130de3
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1368496
milestone55.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 1368496 - Track the pushed clip and scroll IDs. r=jrmuizel Tracking the active clips and scroll layers is helpful for implementing fixed-position type stuff, because we will need to answer questions like "what is the ancestor scroll layer of this other scroll layer that is somewhere on the stack" and "what is the currently active stack of non-scrolling clips". This patch also adds a couple of methods to WebRenderAPI that answers questions like these. MozReview-Commit-ID: 9bgOW3Z8Tbp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -577,24 +577,27 @@ DisplayListBuilder::PopStackingContext()
   WRDL_LOG("PopStackingContext\n");
   wr_dp_pop_stacking_context(mWrState);
 }
 
 void
 DisplayListBuilder::PushClip(const WrRect& aClipRect,
                              const WrImageMask* aMask)
 {
-  WRDL_LOG("PushClip r=%s m=%p\n", Stringify(aClipRect).c_str(), aMask);
-  wr_dp_push_clip(mWrState, aClipRect, aMask);
+  uint64_t clip_id = wr_dp_push_clip(mWrState, aClipRect, aMask);
+  WRDL_LOG("PushClip id=%" PRIu64 " r=%s m=%p\n", clip_id,
+      Stringify(aClipRect).c_str(), aMask);
+  mClipIdStack.push_back(clip_id);
 }
 
 void
 DisplayListBuilder::PopClip()
 {
-  WRDL_LOG("PopClip\n");
+  WRDL_LOG("PopClip id=%" PRIu64 "\n", mClipIdStack.back());
+  mClipIdStack.pop_back();
   wr_dp_pop_clip(mWrState);
 }
 
 void
 DisplayListBuilder::PushBuiltDisplayList(BuiltDisplayList dl)
 {
   wr_dp_push_built_display_list(mWrState,
                                 dl.dl_desc,
@@ -604,22 +607,24 @@ DisplayListBuilder::PushBuiltDisplayList
 void
 DisplayListBuilder::PushScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
                                     const WrRect& aContentRect,
                                     const WrRect& aClipRect)
 {
   WRDL_LOG("PushScrollLayer id=%" PRIu64 " co=%s cl=%s\n",
       aScrollId, Stringify(aContentRect).c_str(), Stringify(aClipRect).c_str());
   wr_dp_push_scroll_layer(mWrState, aScrollId, aContentRect, aClipRect);
+  mScrollIdStack.push_back(aScrollId);
 }
 
 void
 DisplayListBuilder::PopScrollLayer()
 {
-  WRDL_LOG("PopScrollLayer\n");
+  WRDL_LOG("PopScrollLayer id=%" PRIu64 "\n", mScrollIdStack.back());
+  mScrollIdStack.pop_back();
   wr_dp_pop_scroll_layer(mWrState);
 }
 
 void
 DisplayListBuilder::PushRect(const WrRect& aBounds,
                              const WrClipRegionToken aClip,
                              const WrColor& aColor)
 {
@@ -861,10 +866,33 @@ DisplayListBuilder::PushClipRegion(const
   WRDL_LOG("PushClipRegion r=%s cl=%d m=%p\n", Stringify(aMain).c_str(),
       (int)aComplex.Length(), aMask);
   return wr_dp_push_clip_region(mWrState,
                                 aMain,
                                 aComplex.Elements(), aComplex.Length(),
                                 aMask);
 }
 
+Maybe<uint64_t>
+DisplayListBuilder::TopmostClipId()
+{
+  if (mClipIdStack.empty()) {
+    return Nothing();
+  }
+  return Some(mClipIdStack.back());
+}
+
+Maybe<layers::FrameMetrics::ViewID>
+DisplayListBuilder::ParentScrollIdFor(layers::FrameMetrics::ViewID aScrollId)
+{
+  // Finds the scrollId in mScrollIdStack immediately before aScrollId, or
+  // returns Nothing() if it can't find one
+  for (auto it = mScrollIdStack.rbegin(); it != mScrollIdStack.rend(); it++) {
+    if (*it == aScrollId) {
+      it++;
+      return (it == mScrollIdStack.rend() ? Nothing() : Some(*it));
+    }
+  }
+  return Nothing();
+}
+
 } // namespace wr
 } // namespace mozilla
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -2,16 +2,18 @@
 /* vim: set sw=2 sts=2 ts=8 et tw=99 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_LAYERS_WEBRENDERAPI_H
 #define MOZILLA_LAYERS_WEBRENDERAPI_H
 
+#include <vector>
+
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Range.h"
 #include "mozilla/webrender/webrender_ffi.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 #include "FrameMetrics.h"
 #include "GLTypes.h"
 #include "Units.h"
 
@@ -279,21 +281,38 @@ public:
                      const WrBoxShadowClipMode& aClipMode);
 
   WrClipRegionToken PushClipRegion(const WrRect& aMain,
                                    const WrImageMask* aMask = nullptr);
   WrClipRegionToken PushClipRegion(const WrRect& aMain,
                                    const nsTArray<WrComplexClipRegion>& aComplex,
                                    const WrImageMask* aMask = nullptr);
 
+  // Returns the clip id that was most recently pushed with PushClip and that
+  // has not yet been popped with PopClip. Return Nothing() if the clip stack
+  // is empty.
+  Maybe<uint64_t> TopmostClipId();
+  // Returns the scroll id that was pushed just before the given scroll id.
+  // If the given scroll id is not in the stack of active scrolled layers, or if
+  // it is the rootmost scroll id (and therefore has no ancestor), this function
+  // returns Nothing().
+  Maybe<layers::FrameMetrics::ViewID> ParentScrollIdFor(layers::FrameMetrics::ViewID aScrollId);
+
   // Try to avoid using this when possible.
   WrState* Raw() { return mWrState; }
 protected:
   WrState* mWrState;
 
+  // Track the stack of clip ids and scroll layer ids that have been pushed
+  // (by PushClip and PushScrollLayer, respectively) and are still active.
+  // This is helpful for knowing e.g. what the ancestor scroll id of a particular
+  // scroll id is, and doing other "queries" of current state.
+  std::vector<uint64_t> mClipIdStack;
+  std::vector<layers::FrameMetrics::ViewID> mScrollIdStack;
+
   friend class WebRenderAPI;
 };
 
 Maybe<WrImageFormat>
 SurfaceFormatToWrImageFormat(gfx::SurfaceFormat aFormat);
 
 } // namespace wr
 } // namespace mozilla
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1321,22 +1321,32 @@ pub extern "C" fn wr_dp_push_stacking_co
 pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState) {
     assert!(unsafe { !is_in_render_thread() });
     state.frame_builder.dl_builder.pop_stacking_context();
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_push_clip(state: &mut WrState,
                                   clip_rect: WrRect,
-                                  mask: *const WrImageMask) {
+                                  mask: *const WrImageMask)
+                                  -> u64 {
     assert!(unsafe { is_in_main_thread() });
     let clip_rect = clip_rect.into();
     let mask = unsafe { mask.as_ref() }.map(|x| x.into());
     let clip_region = state.frame_builder.dl_builder.push_clip_region(&clip_rect, vec![], mask);
-    state.frame_builder.dl_builder.push_clip_node(clip_rect, clip_region, None);
+    let clip_id = state.frame_builder.dl_builder.define_clip(clip_rect, clip_region, None);
+    state.frame_builder.dl_builder.push_clip_id(clip_id);
+    // 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"),
+    }
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_clip(state: &mut WrState) {
     assert!(unsafe { !is_in_render_thread() });
     state.frame_builder.dl_builder.pop_clip_node();
 }
 
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -727,19 +727,19 @@ WR_FUNC;
 
 WR_INLINE
 void wr_dp_push_built_display_list(WrState *aState,
                                    WrBuiltDisplayListDescriptor aDlDescriptor,
                                    WrVecU8 aDlData)
 WR_FUNC;
 
 WR_INLINE
-void wr_dp_push_clip(WrState *aState,
-                     WrRect aClipRect,
-                     const WrImageMask *aMask)
+uint64_t wr_dp_push_clip(WrState *aState,
+                         WrRect aClipRect,
+                         const WrImageMask *aMask)
 WR_FUNC;
 
 WR_INLINE
 WrClipRegionToken wr_dp_push_clip_region(WrState *aState,
                                          WrRect aMain,
                                          const WrComplexClipRegion *aComplex,
                                          size_t aComplexCount,
                                          const WrImageMask *aImageMask)