Bug 1451469 - Complete hooking up of the sampler thread. r=botond,nical
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 16 Apr 2018 17:39:26 -0400
changeset 414258 7ccbfd4a28d79aed59887b322af44ca0b80d2390
parent 414257 61724e1bb2ad7d0642d4d4cd7c05a396f44b7591
child 414259 da0dccbfc133dc4848d4fb9dd52b71036a3b7802
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)
reviewersbotond, nical
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 - Complete hooking up of the sampler thread. r=botond,nical This makes the APZ sampler thread be the render backend thread whenever webrender is being used (not just when async scene building is enabled). MozReview-Commit-ID: L9lmopd3pe7
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/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/webrender_bindings/src/bindings.rs
modules/libpref/init/all.js
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -15,16 +15,17 @@
 #include "nsTArray.h"
 #include "Units.h"
 
 namespace mozilla {
 
 class TimeStamp;
 
 namespace wr {
+struct Transaction;
 class TransactionWrapper;
 struct WrTransformProperty;
 struct WrWindowId;
 } // namespace wr
 
 namespace layers {
 
 class APZCTreeManager;
@@ -46,19 +47,21 @@ 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);
+  static void SampleForWebRender(const wr::WrWindowId& aWindowId,
+                                 wr::Transaction* aTxn);
 
   void SetSampleTime(const TimeStamp& aSampleTime);
-  bool PushStateToWR(wr::TransactionWrapper& aTxn);
+  void SampleForWebRender(wr::TransactionWrapper& aTxn);
 
   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
@@ -585,19 +585,19 @@ APZCTreeManager::UpdateHitTestingTree(La
                                       uint32_t aPaintSequenceNumber)
 {
   AssertOnUpdaterThread();
 
   UpdateHitTestingTreeImpl(aRootLayerTreeId, aScrollWrapper, aIsFirstPaint,
                            aOriginatingLayersId, aPaintSequenceNumber);
 }
 
-bool
-APZCTreeManager::PushStateToWR(wr::TransactionWrapper& aTxn,
-                               const TimeStamp& aSampleTime)
+void
+APZCTreeManager::SampleForWebRender(wr::TransactionWrapper& aTxn,
+                                    const TimeStamp& aSampleTime)
 {
   AssertOnSamplerThread();
   MutexAutoLock lock(mMapLock);
 
   bool activeAnimations = false;
   for (const auto& mapping : mApzcMap) {
     AsyncPanZoomController* apzc = mapping.second;
     ParentLayerPoint layerTranslation = apzc->GetCurrentAsyncTransform(
@@ -643,17 +643,26 @@ APZCTreeManager::PushStateToWR(wr::Trans
                 nullptr);
         });
     scrollbarTransforms.AppendElement(wr::ToWrTransformProperty(
         info.mThumbAnimationId,
         transform));
   }
   aTxn.AppendTransformProperties(scrollbarTransforms);
 
-  return activeAnimations;
+  if (activeAnimations) {
+    RefPtr<CompositorController> controller;
+    CompositorBridgeParent::CallWithIndirectShadowTree(mRootLayersId,
+      [&](LayerTreeState& aState) -> void {
+        controller = aState.GetCompositorController();
+      });
+    if (controller) {
+      controller->ScheduleRenderOnCompositorThread();
+    }
+  }
 }
 
 // Compute the clip region to be used for a layer with an APZC. This function
 // is only called for layers which actually have scrollable metrics and an APZC.
 template<class ScrollNode> static ParentLayerIntRegion
 ComputeClipRegion(const ScrollNode& aLayer)
 {
   ParentLayerIntRegion clipRegion;
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -210,27 +210,24 @@ public:
   void UpdateHitTestingTree(LayersId aRootLayerTreeId,
                             const WebRenderScrollDataWrapper& aScrollWrapper,
                             bool aIsFirstPaint,
                             LayersId aOriginatingLayersId,
                             uint32_t aPaintSequenceNumber);
 
   /**
    * Called when webrender is enabled, from the sampler thread. This function
-   * walks through the tree of APZC instances and tells webrender about the
-   * 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.
+   * populates the provided transaction with any async scroll offsets needed.
+   * It also advances APZ animations to the specified sample time, and requests
+   * another composite if there are still active animations.
+   * In effect it is the webrender equivalent of (part of) the code in
+   * AsyncCompositionManager.
    */
-  bool PushStateToWR(wr::TransactionWrapper& aTxn,
-                     const TimeStamp& aSampleTime);
+  void SampleForWebRender(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,41 +57,49 @@ 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());
   }
 }
 
+/*static*/ void
+APZSampler::SampleForWebRender(const wr::WrWindowId& aWindowId,
+                               wr::Transaction* aTransaction)
+{
+  if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) {
+    wr::TransactionWrapper txn(aTransaction);
+    sampler->SampleForWebRender(txn);
+  }
+}
+
 void
 APZSampler::SetSampleTime(const TimeStamp& aSampleTime)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   MutexAutoLock lock(mSampleTimeLock);
   mSampleTime = aSampleTime;
 }
 
-bool
-APZSampler::PushStateToWR(wr::TransactionWrapper& aTxn)
+void
+APZSampler::SampleForWebRender(wr::TransactionWrapper& aTxn)
 {
-  // This function will be removed eventually since we'll have WR pull
-  // the transforms from APZ instead.
   AssertOnSamplerThread();
   TimeStamp sampleTime;
   { // scope lock
     MutexAutoLock lock(mSampleTimeLock);
 
     // If mSampleTime is null we're in a startup phase where the
     // WebRenderBridgeParent hasn't yet provided us with a sample time.
     // If we're that early there probably aren't any APZ animations happening
     // anyway, so using Timestamp::Now() should be fine.
     sampleTime = mSampleTime.IsNull() ? TimeStamp::Now() : mSampleTime;
   }
-  return mApz->PushStateToWR(aTxn, sampleTime);
+  mApz->SampleForWebRender(aTxn, sampleTime);
 }
 
 bool
 APZSampler::SampleAnimations(const LayerMetricsWrapper& aLayer,
                              const TimeStamp& aSampleTime)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   AssertOnSamplerThread();
@@ -242,20 +250,22 @@ APZSampler::GetSampler(const wr::WrWindo
 }
 
 } // namespace layers
 } // namespace mozilla
 
 void
 apz_register_sampler(mozilla::wr::WrWindowId aWindowId)
 {
+  mozilla::layers::APZSampler::SetSamplerThread(aWindowId);
 }
 
 void
 apz_sample_transforms(mozilla::wr::WrWindowId aWindowId,
                       mozilla::wr::Transaction *aTransaction)
 {
+  mozilla::layers::APZSampler::SampleForWebRender(aWindowId, aTransaction);
 }
 
 void
 apz_deregister_sampler(mozilla::wr::WrWindowId aWindowId)
 {
 }
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -527,40 +527,34 @@ WebRenderBridgeParent::UpdateAPZScrollDa
     return;
   }
   LayersId rootLayersId = cbp->RootLayerTreeId();
   if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
     apz->UpdateScrollDataAndTreeState(rootLayersId, GetLayersId(), aEpoch, Move(aData));
   }
 }
 
-bool
-WebRenderBridgeParent::PushAPZStateToWR(wr::TransactionBuilder& aTxn)
+void
+WebRenderBridgeParent::SetAPZSampleTime()
 {
   CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
   if (!cbp) {
-    return false;
+    return;
   }
   if (RefPtr<APZSampler> apz = cbp->GetAPZSampler()) {
     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;
     }
     apz->SetSampleTime(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);
   }
-  return false;
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
                                           InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                           InfallibleTArray<OpDestroy>&& aToDestroy,
                                           const uint64_t& aFwdTransactionId,
                                           const uint64_t& aTransactionId,
@@ -1243,25 +1237,20 @@ WebRenderBridgeParent::CompositeToTarget
   nsTArray<wr::WrOpacityProperty> opacityArray;
   nsTArray<wr::WrTransformProperty> transformArray;
 
   SampleAnimations(opacityArray, transformArray);
   if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
     ScheduleGenerateFrame();
   }
   // We do this even if the arrays are empty, because it will clear out any
-  // previous properties stored on the WR side, which is desirable. Also, we
-  // must do this before the PushAPZStateToWR call which will append more
-  // properties, If we did this after that call, this would clobber those
-  // properties.
+  // previous properties store on the WR side, which is desirable.
   txn.UpdateDynamicProperties(opacityArray, transformArray);
 
-  if (PushAPZStateToWR(txn)) {
-    ScheduleGenerateFrame();
-  }
+  SetAPZSampleTime();
 
   wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId());
 
 #if defined(ENABLE_FRAME_LATENCY_LOG)
   auto startTime = TimeStamp::Now();
   mApi->SetFrameStartTime(startTime);
 #endif
 
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -215,21 +215,18 @@ private:
   mozilla::ipc::IPCResult HandleShutdown();
 
   void AdvanceAnimations();
   void SampleAnimations(nsTArray<wr::WrOpacityProperty>& aOpacityArray,
                         nsTArray<wr::WrTransformProperty>& aTransformArray);
 
   CompositorBridgeParent* GetRootCompositorBridgeParent() const;
 
-  // Have APZ push the async scroll state to WR. Returns true if an APZ
-  // animation is in effect and we need to schedule another composition.
-  // If scrollbars need their transforms updated, the transaction builder
-  // is populated with the property update details via AppendTransformProperties
-  bool PushAPZStateToWR(wr::TransactionBuilder& aTxn);
+  // Tell APZ what the subsequent sampling's timestamp should be.
+  void SetAPZSampleTime();
 
   wr::Epoch GetNextWrEpoch();
 
 private:
   struct PendingTransactionId {
     PendingTransactionId(const wr::Epoch& aEpoch, uint64_t aId, const TimeStamp& aTxnStartTime, const TimeStamp& aFwdTime)
       : mEpoch(aEpoch)
       , mId(aId)
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1168,17 +1168,16 @@ pub extern "C" fn wr_transaction_append_
 
 #[no_mangle]
 pub extern "C" fn wr_transaction_scroll_layer(
     txn: &mut Transaction,
     pipeline_id: WrPipelineId,
     scroll_id: u64,
     new_scroll_origin: LayoutPoint
 ) {
-    assert!(unsafe { is_in_compositor_thread() });
     let scroll_id = ExternalScrollId(scroll_id, pipeline_id);
     txn.scroll_node_with_id(new_scroll_origin, scroll_id, ScrollClamping::NoClamping);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_add_image(
     resources: &mut ResourceUpdates,
     image_key: WrImageKey,
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -849,16 +849,17 @@ pref("gfx.webrender.dcomp-win.enabled", 
 pref("gfx.webrender.program-binary", true);
 #endif
 
 #ifdef XP_MACOSX
 pref("gfx.compositor.glcontext.opaque", false);
 #endif
 
 pref("gfx.webrender.highlight-painted-layers", false);
+pref("gfx.webrender.async-scene-build", false);
 pref("gfx.webrender.blob-images", 1);
 pref("gfx.webrender.blob.invalidation", true);
 pref("gfx.webrender.hit-test", true);
 
 // WebRender debugging utilities.
 pref("gfx.webrender.debug.texture-cache", false);
 pref("gfx.webrender.debug.render-targets", false);
 pref("gfx.webrender.debug.alpha-primitives", false);