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
--- 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
@@ -933,16 +933,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", false);
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);