Bug 1253860 - Add machinery to update APZ's scroll offset without a main-thread paint. r?botond
MozReview-Commit-ID: ABnEJPzyJ5w
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -228,16 +228,22 @@ public:
void CopySmoothScrollInfoFrom(const FrameMetrics& aOther)
{
mSmoothScrollOffset = aOther.mSmoothScrollOffset;
mScrollGeneration = aOther.mScrollGeneration;
mDoSmoothScroll = aOther.mDoSmoothScroll;
}
+ void UpdateScrollInfo(uint32_t aScrollGeneration, const CSSPoint& aScrollOffset)
+ {
+ mScrollOffset = aScrollOffset;
+ mScrollGeneration = aScrollGeneration;
+ }
+
// Make a copy of this FrameMetrics object which does not have any pointers
// to heap-allocated memory (i.e. is Plain Old Data, or 'POD'), and is
// therefore safe to be placed into shared memory.
FrameMetrics MakePODObject() const
{
FrameMetrics copy = *this;
copy.mContentDescription.Truncate();
return copy;
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3462,16 +3462,45 @@ void AsyncPanZoomController::NotifyLayer
if (needContentRepaint) {
RequestContentRepaint();
}
UpdateSharedCompositorFrameMetrics();
}
void
+AsyncPanZoomController::UpdateScrollOffset(uint32_t aScrollGeneration,
+ const CSSPoint& aScrollOffset)
+{
+ APZThreadUtils::AssertOnCompositorThread();
+ ReentrantMonitorAutoEnter lock(mMonitor);
+
+ APZC_LOG("%p UpdateScrollOffset(%d, %s)\n", this, aScrollGeneration,
+ Stringify(aScrollOffset).c_str());
+
+ bool scrollOffsetUpdated = aScrollGeneration != mFrameMetrics.GetScrollGeneration();
+ if (!scrollOffsetUpdated) {
+ return;
+ }
+ APZC_LOG("%p updating scroll offset from %s to %s\n", this,
+ Stringify(mFrameMetrics.GetScrollOffset()).c_str(),
+ Stringify(aScrollOffset).c_str());
+
+ mFrameMetrics.UpdateScrollInfo(aScrollGeneration, aScrollOffset);
+ AcknowledgeScrollUpdate();
+ mExpectedGeckoMetrics.UpdateScrollInfo(aScrollGeneration, aScrollOffset);
+ CancelAnimation();
+ RequestContentRepaint();
+ UpdateSharedCompositorFrameMetrics();
+ // We don't call ScheduleComposite() here because that happens higher up
+ // in the call stack, when LayerTransactionParent handles this message.
+ // If we did it here it would incur an extra message posting unnecessarily.
+}
+
+void
AsyncPanZoomController::AcknowledgeScrollUpdate() const
{
// Once layout issues a scroll offset update, it becomes impervious to
// scroll offset updates from APZ until we acknowledge the update it sent.
// This prevents APZ updates from clobbering scroll updates from other
// more "legitimate" sources like content scripts.
RefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -183,16 +183,23 @@ public:
* |aIsFirstPaint| is a flag passed from the shadow
* layers code indicating that the frame metrics being sent with this call are
* the initial metrics and the initial paint of the frame has just happened.
*/
void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint,
bool aThisLayerTreeUpdated);
/**
+ * A lightweight version of NotifyLayersUpdated that allows just the scroll
+ * offset and scroll generation from the main thread to be propagated to APZ.
+ */
+ void UpdateScrollOffset(uint32_t aScrollGeneration,
+ const CSSPoint& aScrollOffset);
+
+ /**
* The platform implementation must set the compositor parent so that we can
* request composites.
*/
void SetCompositorParent(CompositorParent* aCompositorParent);
/**
* Inform this APZC that it will be sharing its FrameMetrics with a cross-process
* compositor so that the associated content process can access it. This is only
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -794,16 +794,35 @@ GetAPZCForViewID(Layer* aLayer, FrameMet
return c;
}
}
}
return nullptr;
}
bool
+LayerTransactionParent::RecvUpdateScrollOffset(
+ const FrameMetrics::ViewID& aScrollID,
+ const uint32_t& aScrollGeneration,
+ const CSSPoint& aScrollOffset)
+{
+ if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
+ return false;
+ }
+
+ AsyncPanZoomController* controller = GetAPZCForViewID(mRoot, aScrollID);
+ if (!controller) {
+ return false;
+ }
+ controller->UpdateScrollOffset(aScrollGeneration, aScrollOffset);
+ mShadowLayersManager->ForceComposite(this);
+ return true;
+}
+
+bool
LayerTransactionParent::RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aScrollID,
const float& aX, const float& aY)
{
if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
return false;
}
AsyncPanZoomController* controller = GetAPZCForViewID(mRoot, aScrollID);
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -123,16 +123,19 @@ protected:
virtual bool RecvForceComposite() override;
virtual bool RecvSetTestSampleTime(const TimeStamp& aTime) override;
virtual bool RecvLeaveTestMode() override;
virtual bool RecvGetOpacity(PLayerParent* aParent,
float* aOpacity) override;
virtual bool RecvGetAnimationTransform(PLayerParent* aParent,
MaybeTransform* aTransform)
override;
+ virtual bool RecvUpdateScrollOffset(const FrameMetrics::ViewID& aScrollId,
+ const uint32_t& aScrollGeneration,
+ const CSSPoint& aScrollOffset) override;
virtual bool RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aId,
const float& aX, const float& aY) override;
virtual bool RecvSetAsyncZoom(const FrameMetrics::ViewID& aId,
const float& aValue) override;
virtual bool RecvFlushApzRepaints() override;
virtual bool RecvGetAPZTestData(APZTestData* aOutData) override;
virtual bool RecvRequestProperty(const nsString& aProperty, float* aValue) override;
virtual bool RecvSetConfirmedTargetAPZC(const uint64_t& aBlockId,
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -17,16 +17,17 @@ include "mozilla/GfxMessageUtils.h";
using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
+using mozilla::CSSPoint from "Units.h";
/**
* The layers protocol is spoken between thread contexts that manage
* layer (sub)trees. The protocol comprises atomically publishing
* layer subtrees to a "shadow" thread context (which grafts the
* subtree into its own tree), and atomically updating a published
* subtree. ("Atomic" in this sense is wrt painting.)
*/
@@ -84,16 +85,20 @@ parent:
// Returns the value of the transform applied to the layer by animation after
// factoring out translation components introduced to account for the offset
// of the corresponding frame and transform origin and after converting to CSS
// pixels. If the layer is not transformed by animation, the return value will
// be void_t.
sync GetAnimationTransform(PLayer layer) returns (MaybeTransform transform);
+ // Updates the scroll offset and generation counter on the APZC for the
+ // given scroll id.
+ sync UpdateScrollOffset(ViewID id, uint32_t generation, CSSPoint offset);
+
// The next time the layer tree is composited, add this async scroll offset in
// CSS pixels for the given ViewID.
// Useful for testing rendering of async scrolling.
sync SetAsyncScrollOffset(ViewID id, float x, float y);
// The next time the layer tree is composited, include this async zoom in
// for the given ViewID.
// Useful for testing rendering of async zooming.