Bug 1399505 - Expose the API to add sticky frames to the WR display list. r?mstange
MozReview-Commit-ID: 1SEz6bqMoME
--- 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
@@ -117,16 +117,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
@@ -721,16 +721,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
@@ -224,16 +224,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
@@ -1210,16 +1210,41 @@ pub extern "C" fn wr_dp_push_clip(state:
#[no_mangle]
pub extern "C" fn wr_dp_pop_clip(state: &mut WrState) {
debug_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