Bug 1451469 - Add a TransactionWrapper class. r=nical
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 16 Apr 2018 17:39:26 -0400
changeset 414256 82ed4ba5a5e8dcf3e2adeb7e053eb516b2b8cd2a
parent 414255 4ed9f2bddf7fe354ec5d8ac89292add263d56d4b
child 414257 61724e1bb2ad7d0642d4d4cd7c05a396f44b7591
push id33862
push userdluca@mozilla.com
push dateWed, 18 Apr 2018 16:55:46 +0000
treeherdermozilla-central@697d0f7076eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1451469
milestone61.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 1451469 - Add a TransactionWrapper class. r=nical The TransactionBuilder class comes with a bunch of baggage (it automatically allocates/deallocates a transaction under the hood) which we will want to avoid for the RB callbacks into APZ. This patch adds a lightweight TransactionWrapper class that APZ can use to provide the async transform info and that will be simpler to use in the callback from rust code. MozReview-Commit-ID: 1ywhx4TIzGd
gfx/layers/apz/public/APZSampler.h
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
gfx/layers/apz/src/APZSampler.cpp
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -15,17 +15,17 @@
 #include "nsTArray.h"
 #include "Units.h"
 
 namespace mozilla {
 
 class TimeStamp;
 
 namespace wr {
-class TransactionBuilder;
+class TransactionWrapper;
 struct WrTransformProperty;
 struct WrWindowId;
 } // namespace wr
 
 namespace layers {
 
 class APZCTreeManager;
 class LayerMetricsWrapper;
@@ -47,17 +47,17 @@ public:
   /**
    * This function is invoked from rust on the render backend thread when it
    * is created. It effectively tells the APZSampler "the current thread is
    * the sampler thread for this window id" and allows APZSampler to remember
    * which thread it is.
    */
   static void SetSamplerThread(const wr::WrWindowId& aWindowId);
 
-  bool PushStateToWR(wr::TransactionBuilder& aTxn,
+  bool PushStateToWR(wr::TransactionWrapper& aTxn,
                      const TimeStamp& aSampleTime);
 
   bool SampleAnimations(const LayerMetricsWrapper& aLayer,
                         const TimeStamp& aSampleTime);
 
   /**
    * Compute the updated shadow transform for a scroll thumb layer that
    * reflects async scrolling of the associated scroll frame.
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -586,17 +586,17 @@ APZCTreeManager::UpdateHitTestingTree(La
 {
   AssertOnUpdaterThread();
 
   UpdateHitTestingTreeImpl(aRootLayerTreeId, aScrollWrapper, aIsFirstPaint,
                            aOriginatingLayersId, aPaintSequenceNumber);
 }
 
 bool
-APZCTreeManager::PushStateToWR(wr::TransactionBuilder& aTxn,
+APZCTreeManager::PushStateToWR(wr::TransactionWrapper& aTxn,
                                const TimeStamp& aSampleTime)
 {
   AssertOnSamplerThread();
   MutexAutoLock lock(mMapLock);
 
   bool activeAnimations = false;
   for (const auto& mapping : mApzcMap) {
     AsyncPanZoomController* apzc = mapping.second;
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -30,17 +30,17 @@
 #if defined(MOZ_WIDGET_ANDROID)
 #include "mozilla/layers/AndroidDynamicToolbarAnimator.h"
 #endif // defined(MOZ_WIDGET_ANDROID)
 
 namespace mozilla {
 class MultiTouchInput;
 
 namespace wr {
-class TransactionBuilder;
+class TransactionWrapper;
 class WebRenderAPI;
 struct WrTransformProperty;
 }
 
 namespace layers {
 
 class Layer;
 class AsyncPanZoomController;
@@ -219,17 +219,17 @@ public:
    * async scroll position. It also advances APZ animations to the specified
    * sample time. In effect it is the webrender equivalent of (part of) the
    * code in AsyncCompositionManager. If scrollbar transforms need updating
    * to reflect the async scroll position, the updated transforms are appended
    * to the provided transaction as well.
    * Returns true if any APZ animations are in progress and we need to keep
    * compositing.
    */
-  bool PushStateToWR(wr::TransactionBuilder& aTxn,
+  bool PushStateToWR(wr::TransactionWrapper& aTxn,
                      const TimeStamp& aSampleTime);
 
   /**
    * Walk the tree of APZCs and flushes the repaint requests for all the APZCS
    * corresponding to the given layers id. Finally, sends a flush complete
    * notification to the GeckoContentController for the layers id.
    */
   void FlushApzRepaints(LayersId aLayersId);
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -57,17 +57,17 @@ APZSampler::SetSamplerThread(const wr::W
   if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) {
     // Ensure nobody tried to use the updater thread before this point.
     MOZ_ASSERT(!sampler->mSamplerThreadQueried);
     sampler->mSamplerThreadId = Some(PlatformThread::CurrentId());
   }
 }
 
 bool
-APZSampler::PushStateToWR(wr::TransactionBuilder& aTxn,
+APZSampler::PushStateToWR(wr::TransactionWrapper& aTxn,
                           const TimeStamp& aSampleTime)
 {
   // This function will be removed eventually since we'll have WR pull
   // the transforms from APZ instead.
   return mApz->PushStateToWR(aTxn, aSampleTime);
 }
 
 bool
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3568,22 +3568,24 @@ AsyncPanZoomController::RequestContentRe
   mLastPaintRequestMetrics = aFrameMetrics;
 }
 
 bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
                                              nsTArray<RefPtr<Runnable>>* aOutDeferredTasks)
 {
   AssertOnSamplerThread();
 
-  // This function may get called multiple with the same sample time, because
-  // there may be multiple layers with this APZC, and each layer invokes this
-  // function during composition. However we only want to do one animation step
-  // per composition so we need to deduplicate these calls first.
+  // This function may get called multiple with the same sample time, for two
+  // reasons: (1) there may be multiple layers with this APZC, and each layer
+  // invokes this function during composition, and (2) we might composite
+  // multiple times at the same timestamp.
+  // However we only want to do one animation step per composition so we need
+  // to deduplicate these calls first.
   if (mLastSampleTime == aSampleTime) {
-    return false;
+    return (mAnimation != nullptr);
   }
 
   // Sample the composited async transform once per composite. Note that we
   // call this after the |mLastSampleTime == aSampleTime| check, to ensure
   // it's only called once per APZC on each composite.
   bool needComposite = SampleCompositedAsyncTransform();
 
   TimeDuration sampleTimeDelta = aSampleTime - mLastSampleTime;
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -543,17 +543,21 @@ WebRenderBridgeParent::PushAPZStateToWR(
     TimeStamp animationTime = cbp->GetTestingTimeStamp().valueOr(
         mCompositorScheduler->GetLastComposeTime());
     TimeDuration frameInterval = cbp->GetVsyncInterval();
     // As with the non-webrender codepath in AsyncCompositionManager, we want to
     // use the timestamp for the next vsync when advancing animations.
     if (frameInterval != TimeDuration::Forever()) {
       animationTime += frameInterval;
     }
-    return apz->PushStateToWR(aTxn, animationTime);
+    // The TransactionWrapper shares the underlying transaction object with
+    // aTxn. When we exit this scope the TransactionWrapper is destroyed but
+    // the underlying transaction lives on in aTxn.
+    wr::TransactionWrapper txn(aTxn.Raw());
+    return apz->PushStateToWR(txn, animationTime);
   }
   return false;
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
                                           InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                           InfallibleTArray<OpDestroy>&& aToDestroy,
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -247,16 +247,37 @@ TransactionBuilder::SetWindowParameters(
 void
 TransactionBuilder::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
                                          const layers::FrameMetrics::ViewID& aScrollId,
                                          const wr::LayoutPoint& aScrollPosition)
 {
   wr_transaction_scroll_layer(mTxn, aPipelineId, aScrollId, aScrollPosition);
 }
 
+TransactionWrapper::TransactionWrapper(Transaction* aTxn)
+  : mTxn(aTxn)
+{
+}
+
+void
+TransactionWrapper::AppendTransformProperties(const nsTArray<wr::WrTransformProperty>& aTransformArray)
+{
+  wr_transaction_append_transform_properties(
+      mTxn,
+      aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(),
+      aTransformArray.Length());
+}
+
+void
+TransactionWrapper::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
+                                         const layers::FrameMetrics::ViewID& aScrollId,
+                                         const wr::LayoutPoint& aScrollPosition)
+{
+  wr_transaction_scroll_layer(mTxn, aPipelineId, aScrollId, aScrollPosition);
+}
 
 /*static*/ void
 WebRenderAPI::InitExternalLogHandler()
 {
   // Redirect the webrender's log to gecko's log system.
   // The current log level is "error".
   mozilla::wr::wr_init_external_log_handler(wr::WrLogLevelFilter::Error);
 }
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -142,16 +142,29 @@ public:
 
   Transaction* Raw() { return mTxn; }
   wr::ResourceUpdates* RawUpdates() { return mResourceUpdates; }
 protected:
   Transaction* mTxn;
   wr::ResourceUpdates* mResourceUpdates;
 };
 
+class TransactionWrapper
+{
+public:
+  explicit TransactionWrapper(Transaction* aTxn);
+
+  void AppendTransformProperties(const nsTArray<wr::WrTransformProperty>& aTransformArray);
+  void UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
+                            const layers::FrameMetrics::ViewID& aScrollId,
+                            const wr::LayoutPoint& aScrollPosition);
+private:
+  Transaction* mTxn;
+};
+
 class WebRenderAPI
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderAPI);
 
 public:
   /// This can be called on the compositor thread only.
   static already_AddRefed<WebRenderAPI> Create(layers::CompositorBridgeParent* aBridge,
                                                RefPtr<widget::CompositorWidget>&& aWidget,