diff --git a/gfx/layers/apz/public/APZSampler.h b/gfx/layers/apz/public/APZSampler.h index 46c2f9b2ff00..c2d25a4e6901 100644 --- a/gfx/layers/apz/public/APZSampler.h +++ b/gfx/layers/apz/public/APZSampler.h @@ -52,8 +52,8 @@ public: */ 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); @@ -125,6 +125,9 @@ private: mutable bool mSamplerThreadQueried; #endif + Mutex mSampleTimeLock; + // Can only be accessed or modified while holding mSampleTimeLock. + TimeStamp mSampleTime; }; } // namespace layers diff --git a/gfx/layers/apz/src/APZSampler.cpp b/gfx/layers/apz/src/APZSampler.cpp index 39c6cd406cd3..59416a3badda 100644 --- a/gfx/layers/apz/src/APZSampler.cpp +++ b/gfx/layers/apz/src/APZSampler.cpp @@ -27,6 +27,7 @@ APZSampler::APZSampler(const RefPtr& aApz) #ifdef DEBUG , mSamplerThreadQueried(false) #endif + , mSampleTimeLock("APZSampler::mSampleTimeLock") { MOZ_ASSERT(aApz); mApz->SetSampler(this); @@ -61,13 +62,31 @@ APZSampler::SetSamplerThread(const wr::WrWindowId& aWindowId) } } +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 diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 230b0798bbfd..ce7dfe17ec8b 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -548,11 +548,12 @@ WebRenderBridgeParent::PushAPZStateToWR(wr::TransactionBuilder& aTxn) 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; }