Bug 1451469 - Set the sample time on APZSampler. r?botond,nical draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 16 Apr 2018 17:39:26 -0400
changeset 783275 30400f44d009d2bf344c05b48523e2730c6899ab
parent 783274 8f190a76cf6b9a79e26b8f5ddce681ba772b6ee7
child 783276 f80456b38271cdce44ea29ad22da8a385fbf6c31
push id106651
push userkgupta@mozilla.com
push dateMon, 16 Apr 2018 21:40:40 +0000
reviewersbotond, nical
bugs1451469, 1453360
milestone61.0a1
Bug 1451469 - Set the sample time on APZSampler. r?botond,nical When sampling APZ transforms from rust code, we will need a timestamp at which to sample the transforms. It's not obvious what the right timestamp is to use here, and this will almost certainly be revisited when we are hooking up OMTA in bug 1453360. For now we just stash the most recent composite timestamp on the APZSampler and use that when sampling. This seems to work fine. MozReview-Commit-ID: KinsXO9tEJH
gfx/layers/apz/public/APZSampler.h
gfx/layers/apz/src/APZSampler.cpp
gfx/layers/wr/WebRenderBridgeParent.cpp
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -47,18 +47,18 @@ 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::TransactionWrapper& aTxn,
-                     const TimeStamp& aSampleTime);
+  void SetSampleTime(const TimeStamp& aSampleTime);
+  bool PushStateToWR(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.
    *
@@ -120,14 +120,17 @@ private:
   // without locking should be fine.
   Maybe<PlatformThreadId> mSamplerThreadId;
 #ifdef DEBUG
   // This flag is used to ensure that we don't ever try to do sampler-thread
   // stuff before the updater thread has been properly initialized.
   mutable bool mSamplerThreadQueried;
 #endif
 
+  Mutex mSampleTimeLock;
+  // Can only be accessed or modified while holding mSampleTimeLock.
+  TimeStamp mSampleTime;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_APZSampler_h
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -22,16 +22,17 @@ StaticMutex APZSampler::sWindowIdLock;
 std::unordered_map<uint64_t, APZSampler*> APZSampler::sWindowIdMap;
 
 
 APZSampler::APZSampler(const RefPtr<APZCTreeManager>& aApz)
   : mApz(aApz)
 #ifdef DEBUG
   , mSamplerThreadQueried(false)
 #endif
+  , mSampleTimeLock("APZSampler::mSampleTimeLock")
 {
   MOZ_ASSERT(aApz);
   mApz->SetSampler(this);
 }
 
 APZSampler::~APZSampler()
 {
   mApz->SetSampler(nullptr);
@@ -56,23 +57,41 @@ 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());
   }
 }
 
+void
+APZSampler::SetSampleTime(const TimeStamp& aSampleTime)
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  MutexAutoLock lock(mSampleTimeLock);
+  mSampleTime = aSampleTime;
+}
+
 bool
-APZSampler::PushStateToWR(wr::TransactionWrapper& aTxn,
-                          const TimeStamp& aSampleTime)
+APZSampler::PushStateToWR(wr::TransactionWrapper& aTxn)
 {
   // This function will be removed eventually since we'll have WR pull
   // the transforms from APZ instead.
-  return mApz->PushStateToWR(aTxn, aSampleTime);
+  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);
 }
 
 bool
 APZSampler::SampleAnimations(const LayerMetricsWrapper& aLayer,
                              const TimeStamp& aSampleTime)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   AssertOnSamplerThread();
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -543,21 +543,22 @@ 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;
     }
+    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, animationTime);
+    return apz->PushStateToWR(txn);
   }
   return false;
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
                                           InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                           InfallibleTArray<OpDestroy>&& aToDestroy,