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
--- 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,