Bug 1399505 - Expose the API to add sticky frames to the WR display list. r?mstange draft
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 15 Sep 2017 15:42:14 -0400
changeset 665624 2c23aed729dc73adb54c9f9e850d45564ba8e9e7
parent 665623 7aceaf8bcb9f582db0f93488b48ef7019e348dba
child 665625 f1c1022a254aedad3544c04e23609786a3824930
push id80126
push userkgupta@mozilla.com
push dateFri, 15 Sep 2017 19:42:41 +0000
reviewersmstange
bugs1399505
milestone57.0a1
Bug 1399505 - Expose the API to add sticky frames to the WR display list. r?mstange MozReview-Commit-ID: LSgQKI7DZcE
gfx/layers/LayersLogging.cpp
gfx/layers/LayersLogging.h
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -98,16 +98,26 @@ AppendToString(std::stringstream& aStrea
   aStream << pfx;
   aStream << nsPrintfCString(
     "(w=%f, h=%f)",
     s.width, s.height).get();
   aStream << sfx;
 }
 
 void
+AppendToString(std::stringstream& aStream, const wr::StickySideConstraint& s,
+               const char* pfx, const char* sfx)
+{
+  aStream << pfx;
+  aStream << nsPrintfCString("(margin=%f max=%f)",
+      s.margin, s.max_offset).get();
+  aStream << sfx;
+}
+
+void
 AppendToString(std::stringstream& aStream, const nsRegion& r,
                const char* pfx, const char* sfx)
 {
   aStream << pfx;
 
   aStream << "< ";
   for (auto iter = r.RectIter(); !iter.Done(); iter.Next()) {
     AppendToString(aStream, iter.Get());
--- a/gfx/layers/LayersLogging.h
+++ b/gfx/layers/LayersLogging.h
@@ -109,16 +109,20 @@ void
 AppendToString(std::stringstream& aStream, const wr::LayoutRect& r,
                const char* pfx="", const char* sfx="");
 
 void
 AppendToString(std::stringstream& aStream, const wr::LayoutSize& s,
                const char* pfx="", const char* sfx="");
 
 void
+AppendToString(std::stringstream& aStream, const wr::StickySideConstraint& s,
+               const char* pfx="", const char* sfx="");
+
+void
 AppendToString(std::stringstream& aStream, const nsRegion& r,
                const char* pfx="", const char* sfx="");
 
 void
 AppendToString(std::stringstream& aStream, const nsIntRegion& r,
                const char* pfx="", const char* sfx="");
 
 template <typename units>
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -720,16 +720,48 @@ DisplayListBuilder::PopClip(bool aRecord
 {
   WRDL_LOG("PopClip id=%" PRIu64 "\n", mWrState, mClipIdStack.back().id);
   if (aRecordInStack) {
     mClipIdStack.pop_back();
   }
   wr_dp_pop_clip(mWrState);
 }
 
+wr::WrStickyId
+DisplayListBuilder::DefineStickyFrame(const wr::LayoutRect& aContentRect,
+                                      const wr::StickySideConstraint* aTop,
+                                      const wr::StickySideConstraint* aRight,
+                                      const wr::StickySideConstraint* aBottom,
+                                      const wr::StickySideConstraint* aLeft)
+{
+  uint64_t id = wr_dp_define_sticky_frame(mWrState, aContentRect, aTop,
+      aRight, aBottom, aLeft);
+  WRDL_LOG("DefineSticky id=%" PRIu64 " c=%s t=%s r=%s b=%s l=%s\n", mWrState, id,
+      Stringify(aContentRect).c_str(),
+      aTop ? Stringify(*aTop).c_str() : "none",
+      aRight ? Stringify(*aRight).c_str() : "none",
+      aBottom ? Stringify(*aBottom).c_str() : "none",
+      aLeft ? Stringify(*aLeft).c_str() : "none");
+  return wr::WrStickyId { id };
+}
+
+void
+DisplayListBuilder::PushStickyFrame(const wr::WrStickyId& aStickyId)
+{
+  wr_dp_push_clip(mWrState, aStickyId.id);
+  WRDL_LOG("PushSticky id=%" PRIu64 "\n", mWrState, aStickyId.id);
+}
+
+void
+DisplayListBuilder::PopStickyFrame()
+{
+  WRDL_LOG("PopSticky\n", mWrState);
+  wr_dp_pop_clip(mWrState);
+}
+
 void
 DisplayListBuilder::PushBuiltDisplayList(BuiltDisplayList &dl)
 {
   WRDL_LOG("PushBuiltDisplayList\n", mWrState);
   wr_dp_push_built_display_list(mWrState,
                                 dl.dl_desc,
                                 &dl.dl.inner);
 }
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -223,16 +223,24 @@ public:
   void PopStackingContext();
 
   wr::WrClipId DefineClip(const wr::LayoutRect& aClipRect,
                           const nsTArray<wr::WrComplexClipRegion>* aComplex = nullptr,
                           const wr::WrImageMask* aMask = nullptr);
   void PushClip(const wr::WrClipId& aClipId, bool aRecordInStack = true);
   void PopClip(bool aRecordInStack = true);
 
+  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();
+
   void PushBuiltDisplayList(wr::BuiltDisplayList &dl);
 
   bool IsScrollLayerDefined(layers::FrameMetrics::ViewID aScrollId) const;
   void DefineScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
                          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();
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -731,16 +731,26 @@ static inline wr::WrFilterOp ToWrFilterO
 struct WrClipId {
   uint64_t id;
 
   bool operator==(const WrClipId& other) const {
     return id == other.id;
   }
 };
 
+// Corresponds to a clip id for a position:sticky clip in webrender. Similar
+// to WrClipId but a separate struct so we don't get them mixed up in C++.
+struct WrStickyId {
+  uint64_t id;
+
+  bool operator==(const WrClipId& other) const {
+    return id == other.id;
+  }
+};
+
 typedef Variant<layers::FrameMetrics::ViewID, WrClipId> ScrollOrClipId;
 
 enum class WebRenderError : int8_t {
   INITIALIZE = 0,
   MAKE_CURRENT,
   RENDER,
 
   Sentinel /* this must be last for serialization purposes. */
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1217,16 +1217,41 @@ pub extern "C" fn wr_dp_push_clip(state:
 
 #[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_id();
 }
 
 #[no_mangle]
+pub extern "C" fn wr_dp_define_sticky_frame(state: &mut WrState,
+                                            content_rect: LayoutRect,
+                                            top_range: *const StickySideConstraint,
+                                            right_range: *const StickySideConstraint,
+                                            bottom_range: *const StickySideConstraint,
+                                            left_range: *const StickySideConstraint)
+                                            -> u64 {
+    assert!(unsafe { is_in_main_thread() });
+    let clip_id = state.frame_builder.dl_builder.define_sticky_frame(
+        None, content_rect, StickyFrameInfo::new(
+            unsafe { top_range.as_ref() }.cloned(),
+            unsafe { right_range.as_ref() }.cloned(),
+            unsafe { bottom_range.as_ref() }.cloned(),
+            unsafe { left_range.as_ref() }.cloned()));
+    match clip_id {
+        ClipId::Clip(id, nesting_index, pipeline_id) => {
+            assert!(pipeline_id == state.pipeline_id);
+            assert!(nesting_index == 0);
+            id
+        },
+        _ => panic!("Got unexpected clip id type"),
+    }
+}
+
+#[no_mangle]
 pub extern "C" fn wr_dp_define_scroll_layer(state: &mut WrState,
                                             scroll_id: u64,
                                             content_rect: LayoutRect,
                                             clip_rect: LayoutRect) {
     assert!(unsafe { is_in_main_thread() });
     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,
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -434,16 +434,26 @@ struct WrImageMask {
 
   bool operator==(const WrImageMask& aOther) const {
     return image == aOther.image &&
            rect == aOther.rect &&
            repeat == aOther.repeat;
   }
 };
 
+struct StickySideConstraint {
+  float margin;
+  float max_offset;
+
+  bool operator==(const StickySideConstraint& aOther) const {
+    return margin == aOther.margin &&
+           max_offset == aOther.max_offset;
+  }
+};
+
 struct BorderWidths {
   float left;
   float top;
   float right;
   float bottom;
 
   bool operator==(const BorderWidths& aOther) const {
     return left == aOther.left &&
@@ -854,16 +864,25 @@ WR_FUNC;
 WR_INLINE
 void wr_dp_define_scroll_layer(WrState *aState,
                                uint64_t aScrollId,
                                LayoutRect aContentRect,
                                LayoutRect aClipRect)
 WR_FUNC;
 
 WR_INLINE
+uint64_t wr_dp_define_sticky_frame(WrState *aState,
+                                   LayoutRect aContentRect,
+                                   const StickySideConstraint *aTopRange,
+                                   const StickySideConstraint *aRightRange,
+                                   const StickySideConstraint *aBottomRange,
+                                   const StickySideConstraint *aLeftRange)
+WR_FUNC;
+
+WR_INLINE
 void wr_dp_end(WrState *aState)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_pop_clip(WrState *aState)
 WR_FUNC;
 
 WR_INLINE