From 73a7b93fd06549b2c19ee161679045dbb23b0b0f Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 9 Mar 2016 22:57:14 -0500 Subject: [PATCH] Bug 1253860 - Add machinery to update APZ's scroll offset without a main-thread paint. r=botond MozReview-Commit-ID: Chy40f6VNIQ --- gfx/layers/FrameMetrics.h | 6 ++++ gfx/layers/apz/src/AsyncPanZoomController.cpp | 33 +++++++++++++++++-- gfx/layers/apz/src/AsyncPanZoomController.h | 7 ++++ gfx/layers/ipc/LayerTransactionParent.cpp | 19 +++++++++++ gfx/layers/ipc/LayerTransactionParent.h | 3 ++ gfx/layers/ipc/PLayerTransaction.ipdl | 5 +++ 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index d549f9c9f603..bf38c6acb0d2 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -233,6 +233,12 @@ public: 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. diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 583dfc5aa901..5229257683c0 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -3257,9 +3257,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri if (!aThisLayerTreeUpdated && !isDefault) { // No new information here, skip it. Note that this is not just an // optimization; it's correctness too. In the case where we get one of these - // stale aLayerMetrics *after* a call to UpdateScrollOffset, processing the + // stale aLayerMetrics *after* a call to NotifyScrollUpdated, processing the // stale aLayerMetrics would clobber the more up-to-date information from - // UpdateScrollOffset. + // NotifyScrollUpdated. MOZ_ASSERT(aLayerMetrics == mLastContentPaintMetrics); APZC_LOG("%p NotifyLayersUpdated short-circuit\n", this); return; @@ -3466,6 +3466,35 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri UpdateSharedCompositorFrameMetrics(); } +void +AsyncPanZoomController::NotifyScrollUpdated(uint32_t aScrollGeneration, + const CSSPoint& aScrollOffset) +{ + APZThreadUtils::AssertOnCompositorThread(); + ReentrantMonitorAutoEnter lock(mMonitor); + + APZC_LOG("%p NotifyScrollUpdated(%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 { diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 5f2d0af6e1b4..239648b32a3b 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -187,6 +187,13 @@ public: 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 NotifyScrollUpdated(uint32_t aScrollGeneration, + const CSSPoint& aScrollOffset); + /** * The platform implementation must set the compositor parent so that we can * request composites. diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index f2fee9facd64..6ec9b119e096 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -798,6 +798,25 @@ GetAPZCForViewID(Layer* aLayer, FrameMetrics::ViewID aScrollID) 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->NotifyScrollUpdated(aScrollGeneration, aScrollOffset); + mShadowLayersManager->ForceComposite(this); + return true; +} + bool LayerTransactionParent::RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aScrollID, const float& aX, const float& aY) diff --git a/gfx/layers/ipc/LayerTransactionParent.h b/gfx/layers/ipc/LayerTransactionParent.h index 5555d4e43b12..1cf77a707b11 100644 --- a/gfx/layers/ipc/LayerTransactionParent.h +++ b/gfx/layers/ipc/LayerTransactionParent.h @@ -128,6 +128,9 @@ protected: 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, diff --git a/gfx/layers/ipc/PLayerTransaction.ipdl b/gfx/layers/ipc/PLayerTransaction.ipdl index 0d110cecb038..7ddb884b6673 100644 --- a/gfx/layers/ipc/PLayerTransaction.ipdl +++ b/gfx/layers/ipc/PLayerTransaction.ipdl @@ -22,6 +22,7 @@ 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 @@ -89,6 +90,10 @@ parent: // 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.