Bug 1622360 - Remove UpdaterQueueSelector and update stuff that uses it. r=botond

This also downgrades a bunch of WRRootId parameters back down to LayersId
in APZUpdater since APZUpdater doesn't need the render root information any
more.

Changes to comments generally restore the text that was there prior to the
document-splitting patch landing.

Differential Revision: https://phabricator.services.mozilla.com/D68396

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kartikaya Gupta 2020-03-27 17:57:18 +00:00
parent 1330a33340
commit 6fed4c94d9
8 changed files with 154 additions and 277 deletions

View File

@ -58,29 +58,6 @@ struct WRRootId {
};
};
// This struct provides a way to select which APZUpdater queue a particular
// message is associated with. A layers subtree may have multiple render roots
// that are treated independently within WebRender, and each message that goes
// into the APZUpdater queue may deal with one or more of these render roots
// within a given layers subtree. This structure allows representing these
// relationships, and allows the APZUpdater to ensure that the ordering
// dependencies between messages are preserved and messages get processed in
// the correct order relative to each other.
struct UpdaterQueueSelector {
LayersId mLayersId;
wr::RenderRootSet mRenderRoots;
UpdaterQueueSelector() = default;
explicit UpdaterQueueSelector(LayersId aLayersId) : mLayersId(aLayersId) {}
UpdaterQueueSelector(LayersId aLayersId, wr::RenderRoot aRenderRoot)
: mLayersId(aLayersId), mRenderRoots(aRenderRoot) {}
explicit UpdaterQueueSelector(const WRRootId& aNodeId)
: mLayersId(aNodeId.mLayersId), mRenderRoots(aNodeId.mRenderRoot) {}
};
// This a simple structure that wraps a ScrollableLayerGuid and a RenderRoot.
// It is needed on codepaths shared with WebRender, where we need to propagate
// the RenderRoot information along with the ScrollableLayerGuid (as each

View File

@ -60,7 +60,7 @@ class APZUpdater {
void ClearTree(LayersId aRootLayersId);
void UpdateFocusState(LayersId aRootLayerTreeId,
WRRootId aOriginatingWrRootId,
LayersId aOriginatingLayersId,
const FocusTarget& aFocusTarget);
void UpdateHitTestingTree(Layer* aRoot, bool aIsFirstPaint,
LayersId aOriginatingLayersId,
@ -73,8 +73,8 @@ class APZUpdater {
* This function will store the new scroll data and update the focus state and
* hit-testing tree.
*/
void UpdateScrollDataAndTreeState(WRRootId aRootLayerTreeId,
WRRootId aOriginatingWrRootId,
void UpdateScrollDataAndTreeState(LayersId aRootLayerTreeId,
LayersId aOriginatingLayersId,
const wr::Epoch& aEpoch,
WebRenderScrollData&& aScrollData);
/**
@ -83,26 +83,26 @@ class APZUpdater {
* side). This function will update the stored scroll offsets and the
* hit-testing tree.
*/
void UpdateScrollOffsets(WRRootId aRootLayerTreeId,
WRRootId aOriginatingWrRootId,
void UpdateScrollOffsets(LayersId aRootLayerTreeId,
LayersId aOriginatingLayersId,
ScrollUpdatesMap&& aUpdates,
uint32_t aPaintSequenceNumber);
void NotifyLayerTreeAdopted(WRRootId aWrRootId,
void NotifyLayerTreeAdopted(LayersId aLayersId,
const RefPtr<APZUpdater>& aOldUpdater);
void NotifyLayerTreeRemoved(WRRootId aWrRootId);
void NotifyLayerTreeRemoved(LayersId aLayersId);
bool GetAPZTestData(WRRootId aWrRootId, APZTestData* aOutData);
bool GetAPZTestData(LayersId aLayersId, APZTestData* aOutData);
void SetTestAsyncScrollOffset(WRRootId aWrRootId,
void SetTestAsyncScrollOffset(LayersId aLayersId,
const ScrollableLayerGuid::ViewID& aScrollId,
const CSSPoint& aOffset);
void SetTestAsyncZoom(WRRootId aWrRootId,
void SetTestAsyncZoom(LayersId aLayersId,
const ScrollableLayerGuid::ViewID& aScrollId,
const LayerToParentLayerScale& aZoom);
// This can only be called on the updater thread.
const WebRenderScrollData* GetScrollData(WRRootId aWrRootId) const;
const WebRenderScrollData* GetScrollData(LayersId aLayersId) const;
/**
* This can be used to assert that the current thread is the
@ -116,19 +116,12 @@ class APZUpdater {
* this function is called from the updater thread itself then the task is
* run immediately without getting queued.
*
* Conceptually each (layers tree, render root) tuple has a separate task
* queue. (In the case where WebRender is disabled, the render root is
* always the default render root). This makes it so that even if one
* (layers tree, render root) is blocked waiting for a scene build in
* WebRender, other tasks can still be processed. However, there may be
* tasks that are tied to multiple render roots within a given layers tree,
* and which would therefore block on all the associated (layers tree,
* render root) queues. The aSelector argument allows expressing the set of
* render roots the task is tied to so that this ordering dependency can be
* respected.
* The layers id argument should be the id of the layer tree that is
* requesting this task to be run. Conceptually each layer tree has a separate
* task queue, so that if one layer tree is blocked waiting for a scene build
* then tasks for the other layer trees can still be processed.
*/
void RunOnUpdaterThread(UpdaterQueueSelector aSelector,
already_AddRefed<Runnable> aTask);
void RunOnUpdaterThread(LayersId aLayersId, already_AddRefed<Runnable> aTask);
/**
* Returns true if currently on the APZUpdater's "updater thread".
@ -143,9 +136,9 @@ class APZUpdater {
* directly on the updater thread), that is when the task gets dispatched to
* the controller thread. The controller thread then actually runs the task.
*
* See the RunOnUpdaterThread method for details on the aSelector argument.
* See the RunOnUpdaterThread method for details on the layers id argument.
*/
void RunOnControllerThread(UpdaterQueueSelector aSelector,
void RunOnControllerThread(LayersId aLayersId,
already_AddRefed<Runnable> aTask);
void MarkAsDetached(LayersId aLayersId);
@ -164,41 +157,40 @@ class APZUpdater {
bool mDestroyed;
bool mIsUsingWebRender;
// Map from WRRoot id to WebRenderScrollData. This can only be touched on
// Map from layers id to WebRenderScrollData. This can only be touched on
// the updater thread.
std::unordered_map<WRRootId, WebRenderScrollData, WRRootId::HashFn>
std::unordered_map<LayersId, WebRenderScrollData, LayersId::HashFn>
mScrollData;
// Stores epoch state for a particular WRRoot id. This structure is only
// Stores epoch state for a particular layers id. This structure is only
// accessed on the updater thread.
struct EpochState {
// The epoch for the most recent scroll data sent from the content side.
wr::Epoch mRequired;
// The epoch for the most recent scene built and swapped in on the WR side.
Maybe<wr::Epoch> mBuilt;
// True if and only if the WRRoot id is the root WRRoot id for the
// True if and only if the layers id is the root layers id for the
// compositor
bool mIsRoot;
EpochState();
// Whether or not the state for this WRRoot id is such that it blocks
// processing of tasks. This happens if the root tree or a "visible"
// render root has scroll data for an epoch newer than what has been
// built. A "visible" render root is one that is attached to the full
// Whether or not the state for this layers id is such that it blocks
// processing of tasks for the layer tree. This happens if the root layers
// id or a "visible" layers id has scroll data for an epoch newer than what
// has been built. A "visible" layers id is one that is attached to the full
// layer tree (i.e. there is a chain of reflayer items from the root layer
// tree to the relevant layer subtree) on a WR document whose scene has
// been built. This is not always the case; for instance a content process
// may send the compositor layers for a document before the chrome has
// attached the remote iframe to the root UI document. Since WR only
// builds pipelines for "visible" render roots, |mBuilt| being populated
// means that the render root is "visible".
// tree to the relevant layer subtree). This is not always the case; for
// instance a content process may send the compositor layers for a document
// before the chrome has attached the remote iframe to the root document.
// Since WR only builds pipelines for "visible" layers ids, |mBuilt| being
// populated means that the layers id is "visible".
bool IsBlocked() const;
};
// Map from WRRoot id to epoch state.
// Map from layers id to epoch state.
// This data structure can only be touched on the updater thread.
std::unordered_map<WRRootId, EpochState, WRRootId::HashFn> mEpochData;
std::unordered_map<LayersId, EpochState, LayersId::HashFn> mEpochData;
// Used to manage the mapping from a WR window id to APZUpdater. These are
// only used if WebRender is enabled. Both sWindowIdMap and mWindowId should
@ -219,28 +211,22 @@ class APZUpdater {
// care about the contents.
Maybe<PlatformThreadId> mUpdaterThreadId;
// Helper struct that pairs each queued runnable with the layers id and render
// roots that it is associated with. This allows us to easily implement the
// conceptual separation of mUpdaterQueue into independent queues per (layers
// id, render root) pair. Note that when the UpdaterQueueSelector has multiple
// render roots, the task blocks on *all* of the queues for the (layers
// id, render root) pairs.
// Helper struct that pairs each queued runnable with the layers id that it is
// associated with. This allows us to easily implement the conceptual
// separation of mUpdaterQueue into independent queues per layers id.
struct QueuedTask {
UpdaterQueueSelector mSelector;
LayersId mLayersId;
RefPtr<Runnable> mRunnable;
};
// Lock used to protect mUpdaterQueue
Mutex mQueueLock;
// Holds a queue of tasks to be run on the updater thread, when the updater
// thread is a WebRender thread, since it is conceptually separated into
// multiple ones, one per (layers id, render root). Tasks for a given
// conceptual queue will always run in FIFO order, and tasks that are tied
// to multiple queues (by virtue of having multiple render roots in their
// UpdaterQueueSelector) can cause one queue to be blocked on another in
// order to preserve FIFO ordering. In the common case, though, where there
// is exactly one render root per task, there is no guaranteed ordering for
// tasks with different render roots.
// thread is a WebRender thread, since it won't have a message loop we can
// dispatch to. Note that although this is a single queue it is conceptually
// separated into multiple ones, one per layers id. Tasks for a given layers
// id will always run in FIFO order, but there is no guaranteed ordering for
// tasks with different layers ids.
std::deque<QueuedTask> mUpdaterQueue;
};

View File

@ -2451,7 +2451,7 @@ void APZCTreeManager::UpdateZoomConstraints(
// enabled, since the call will go over PAPZCTreeManager and arrive on the
// compositor thread in the GPU process.
GetUpdater()->RunOnUpdaterThread(
UpdaterQueueSelector(aGuid.GetWRRootId()),
aGuid.mScrollableLayerGuid.mLayersId,
NewRunnableMethod<SLGuidAndRenderRoot, Maybe<ZoomConstraints>>(
"APZCTreeManager::UpdateZoomConstraints", this,
&APZCTreeManager::UpdateZoomConstraints, aGuid, aConstraints));

View File

@ -90,8 +90,7 @@ void APZUpdater::CompleteSceneSwap(const wr::WrWindowId& aWindowId,
}
for (const auto& removedPipeline : aInfo.removed_pipelines) {
WRRootId layersId =
WRRootId(removedPipeline.pipeline_id, removedPipeline.document_id);
LayersId layersId = wr::AsLayersId(removedPipeline.pipeline_id);
updater->mEpochData.erase(layersId);
}
// Reset the built info for all pipelines, then put it back for the ones
@ -100,7 +99,7 @@ void APZUpdater::CompleteSceneSwap(const wr::WrWindowId& aWindowId,
i.second.mBuilt = Nothing();
}
for (const auto& epoch : aInfo.epochs) {
WRRootId layersId = WRRootId(epoch.pipeline_id, epoch.document_id);
LayersId layersId = wr::AsLayersId(epoch.pipeline_id);
updater->mEpochData[layersId].mBuilt = Some(epoch.epoch);
}
@ -133,47 +132,33 @@ void APZUpdater::ProcessPendingTasks(const wr::WrWindowId& aWindowId) {
void APZUpdater::ClearTree(LayersId aRootLayersId) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<APZUpdater> self = this;
RunOnUpdaterThread(
UpdaterQueueSelector(aRootLayersId, wr::RenderRoot::Default),
NS_NewRunnableFunction("APZUpdater::ClearTree", [=]() {
self->mApz->ClearTree();
self->mDestroyed = true;
RunOnUpdaterThread(aRootLayersId,
NS_NewRunnableFunction("APZUpdater::ClearTree", [=]() {
self->mApz->ClearTree();
self->mDestroyed = true;
// Once ClearTree is called on the APZCTreeManager, we
// are in a shutdown phase. After this point it's ok if
// WebRender cannot get a hold of the updater via the
// window id, and it's a good point to remove the mapping
// and avoid leaving a dangling pointer to this object.
StaticMutexAutoLock lock(sWindowIdLock);
if (self->mWindowId) {
MOZ_ASSERT(sWindowIdMap);
sWindowIdMap->erase(wr::AsUint64(*(self->mWindowId)));
}
}));
// Once ClearTree is called on the APZCTreeManager, we
// are in a shutdown phase. After this point it's ok if
// WebRender cannot get a hold of the updater via the
// window id, and it's a good point to remove the mapping
// and avoid leaving a dangling pointer to this object.
StaticMutexAutoLock lock(sWindowIdLock);
if (self->mWindowId) {
MOZ_ASSERT(sWindowIdMap);
sWindowIdMap->erase(wr::AsUint64(*(self->mWindowId)));
}
}));
}
void APZUpdater::UpdateFocusState(LayersId aRootLayerTreeId,
WRRootId aOriginatingWrRootId,
LayersId aOriginatingLayersId,
const FocusTarget& aFocusTarget) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
UpdaterQueueSelector selector(aOriginatingWrRootId.mLayersId);
if (aFocusTarget.mData.is<FocusTarget::ScrollTargets>()) {
const FocusTarget::ScrollTargets& targets =
aFocusTarget.mData.as<FocusTarget::ScrollTargets>();
if (targets.mHorizontalRenderRoot) {
selector.mRenderRoots += *targets.mHorizontalRenderRoot;
}
if (targets.mVerticalRenderRoot) {
selector.mRenderRoots += *targets.mVerticalRenderRoot;
}
} else {
selector.mRenderRoots += aOriginatingWrRootId.mRenderRoot;
}
RunOnUpdaterThread(selector,
RunOnUpdaterThread(aOriginatingLayersId,
NewRunnableMethod<LayersId, LayersId, FocusTarget>(
"APZUpdater::UpdateFocusState", mApz,
&APZCTreeManager::UpdateFocusState, aRootLayerTreeId,
aOriginatingWrRootId.mLayersId, aFocusTarget));
aOriginatingLayersId, aFocusTarget));
}
void APZUpdater::UpdateHitTestingTree(Layer* aRoot, bool aIsFirstPaint,
@ -186,7 +171,7 @@ void APZUpdater::UpdateHitTestingTree(Layer* aRoot, bool aIsFirstPaint,
}
void APZUpdater::UpdateScrollDataAndTreeState(
WRRootId aRootLayerTreeId, WRRootId aOriginatingWrRootId,
LayersId aRootLayerTreeId, LayersId aOriginatingLayersId,
const wr::Epoch& aEpoch, WebRenderScrollData&& aScrollData) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<APZUpdater> self = this;
@ -196,92 +181,88 @@ void APZUpdater::UpdateScrollDataAndTreeState(
// UpdateHitTestingTree call below needs to wait until the epoch requirement
// is satisfied, which is why it is a separate task in the queue.
RunOnUpdaterThread(
UpdaterQueueSelector(aOriginatingWrRootId),
aOriginatingLayersId,
NS_NewRunnableFunction("APZUpdater::UpdateEpochRequirement", [=]() {
if (aRootLayerTreeId == aOriginatingWrRootId) {
self->mEpochData[aOriginatingWrRootId].mIsRoot = true;
if (aRootLayerTreeId == aOriginatingLayersId) {
self->mEpochData[aOriginatingLayersId].mIsRoot = true;
}
self->mEpochData[aOriginatingWrRootId].mRequired = aEpoch;
self->mEpochData[aOriginatingLayersId].mRequired = aEpoch;
}));
RunOnUpdaterThread(
UpdaterQueueSelector(aOriginatingWrRootId),
aOriginatingLayersId,
NS_NewRunnableFunction(
"APZUpdater::UpdateHitTestingTree",
[=, aScrollData = std::move(aScrollData)]() mutable {
auto isFirstPaint = aScrollData.IsFirstPaint();
auto paintSequenceNumber = aScrollData.GetPaintSequenceNumber();
self->mScrollData[aOriginatingWrRootId] = std::move(aScrollData);
self->mScrollData[aOriginatingLayersId] = std::move(aScrollData);
auto root = self->mScrollData.find(aRootLayerTreeId);
if (root == self->mScrollData.end()) {
return;
}
self->mApz->UpdateHitTestingTree(
WebRenderScrollDataWrapper(*self, &(root->second)),
isFirstPaint, aOriginatingWrRootId.mLayersId,
paintSequenceNumber);
isFirstPaint, aOriginatingLayersId, paintSequenceNumber);
}));
}
void APZUpdater::UpdateScrollOffsets(WRRootId aRootLayerTreeId,
WRRootId aOriginatingWrRootId,
void APZUpdater::UpdateScrollOffsets(LayersId aRootLayerTreeId,
LayersId aOriginatingLayersId,
ScrollUpdatesMap&& aUpdates,
uint32_t aPaintSequenceNumber) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<APZUpdater> self = this;
RunOnUpdaterThread(UpdaterQueueSelector(aOriginatingWrRootId),
NS_NewRunnableFunction(
"APZUpdater::UpdateScrollOffsets",
[=, updates = std::move(aUpdates)]() mutable {
self->mScrollData[aOriginatingWrRootId].ApplyUpdates(
updates, aPaintSequenceNumber);
auto root = self->mScrollData.find(aRootLayerTreeId);
if (root == self->mScrollData.end()) {
return;
}
self->mApz->UpdateHitTestingTree(
WebRenderScrollDataWrapper(*self,
&(root->second)),
/*isFirstPaint*/ false,
aOriginatingWrRootId.mLayersId,
aPaintSequenceNumber);
}));
RunOnUpdaterThread(
aOriginatingLayersId,
NS_NewRunnableFunction(
"APZUpdater::UpdateScrollOffsets",
[=, updates = std::move(aUpdates)]() mutable {
self->mScrollData[aOriginatingLayersId].ApplyUpdates(
updates, aPaintSequenceNumber);
auto root = self->mScrollData.find(aRootLayerTreeId);
if (root == self->mScrollData.end()) {
return;
}
self->mApz->UpdateHitTestingTree(
WebRenderScrollDataWrapper(*self, &(root->second)),
/*isFirstPaint*/ false, aOriginatingLayersId,
aPaintSequenceNumber);
}));
}
void APZUpdater::NotifyLayerTreeAdopted(WRRootId aWrRootId,
void APZUpdater::NotifyLayerTreeAdopted(LayersId aLayersId,
const RefPtr<APZUpdater>& aOldUpdater) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RunOnUpdaterThread(
UpdaterQueueSelector(aWrRootId),
NewRunnableMethod<LayersId, RefPtr<APZCTreeManager>>(
"APZUpdater::NotifyLayerTreeAdopted", mApz,
&APZCTreeManager::NotifyLayerTreeAdopted, aWrRootId.mLayersId,
aOldUpdater ? aOldUpdater->mApz : nullptr));
RunOnUpdaterThread(aLayersId,
NewRunnableMethod<LayersId, RefPtr<APZCTreeManager>>(
"APZUpdater::NotifyLayerTreeAdopted", mApz,
&APZCTreeManager::NotifyLayerTreeAdopted, aLayersId,
aOldUpdater ? aOldUpdater->mApz : nullptr));
}
void APZUpdater::NotifyLayerTreeRemoved(WRRootId aWrRootId) {
void APZUpdater::NotifyLayerTreeRemoved(LayersId aLayersId) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<APZUpdater> self = this;
RunOnUpdaterThread(
UpdaterQueueSelector(aWrRootId),
aLayersId,
NS_NewRunnableFunction("APZUpdater::NotifyLayerTreeRemoved", [=]() {
self->mEpochData.erase(aWrRootId);
self->mScrollData.erase(aWrRootId);
self->mApz->NotifyLayerTreeRemoved(aWrRootId.mLayersId);
self->mEpochData.erase(aLayersId);
self->mScrollData.erase(aLayersId);
self->mApz->NotifyLayerTreeRemoved(aLayersId);
}));
}
bool APZUpdater::GetAPZTestData(WRRootId aWrRootId, APZTestData* aOutData) {
bool APZUpdater::GetAPZTestData(LayersId aLayersId, APZTestData* aOutData) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<APZCTreeManager> apz = mApz;
bool ret = false;
SynchronousTask waiter("APZUpdater::GetAPZTestData");
RunOnUpdaterThread(
UpdaterQueueSelector(aWrRootId),
NS_NewRunnableFunction("APZUpdater::GetAPZTestData", [&]() {
aLayersId, NS_NewRunnableFunction("APZUpdater::GetAPZTestData", [&]() {
AutoCompleteTask notifier(&waiter);
ret = apz->GetAPZTestData(aWrRootId.mLayersId, aOutData);
ret = apz->GetAPZTestData(aLayersId, aOutData);
}));
// Wait until the task posted above has run and populated aOutData and ret
@ -291,15 +272,15 @@ bool APZUpdater::GetAPZTestData(WRRootId aWrRootId, APZTestData* aOutData) {
}
void APZUpdater::SetTestAsyncScrollOffset(
WRRootId aWrRootId, const ScrollableLayerGuid::ViewID& aScrollId,
LayersId aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
const CSSPoint& aOffset) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<APZCTreeManager> apz = mApz;
RunOnUpdaterThread(
UpdaterQueueSelector(aWrRootId),
aLayersId,
NS_NewRunnableFunction("APZUpdater::SetTestAsyncScrollOffset", [=]() {
RefPtr<AsyncPanZoomController> apzc =
apz->GetTargetAPZC(aWrRootId.mLayersId, aScrollId);
apz->GetTargetAPZC(aLayersId, aScrollId);
if (apzc) {
apzc->SetTestAsyncScrollOffset(aOffset);
} else {
@ -308,16 +289,15 @@ void APZUpdater::SetTestAsyncScrollOffset(
}));
}
void APZUpdater::SetTestAsyncZoom(WRRootId aWrRootId,
void APZUpdater::SetTestAsyncZoom(LayersId aLayersId,
const ScrollableLayerGuid::ViewID& aScrollId,
const LayerToParentLayerScale& aZoom) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<APZCTreeManager> apz = mApz;
RunOnUpdaterThread(
UpdaterQueueSelector(aWrRootId),
NS_NewRunnableFunction("APZUpdater::SetTestAsyncZoom", [=]() {
aLayersId, NS_NewRunnableFunction("APZUpdater::SetTestAsyncZoom", [=]() {
RefPtr<AsyncPanZoomController> apzc =
apz->GetTargetAPZC(aWrRootId.mLayersId, aScrollId);
apz->GetTargetAPZC(aLayersId, aScrollId);
if (apzc) {
apzc->SetTestAsyncZoom(aZoom);
} else {
@ -326,9 +306,9 @@ void APZUpdater::SetTestAsyncZoom(WRRootId aWrRootId,
}));
}
const WebRenderScrollData* APZUpdater::GetScrollData(WRRootId aWrRootId) const {
const WebRenderScrollData* APZUpdater::GetScrollData(LayersId aLayersId) const {
AssertOnUpdaterThread();
auto it = mScrollData.find(aWrRootId);
auto it = mScrollData.find(aLayersId);
return (it == mScrollData.end() ? nullptr : &(it->second));
}
@ -338,7 +318,7 @@ void APZUpdater::AssertOnUpdaterThread() const {
}
}
void APZUpdater::RunOnUpdaterThread(UpdaterQueueSelector aSelector,
void APZUpdater::RunOnUpdaterThread(LayersId aLayersId,
already_AddRefed<Runnable> aTask) {
RefPtr<Runnable> task = aTask;
@ -363,59 +343,21 @@ void APZUpdater::RunOnUpdaterThread(UpdaterQueueSelector aSelector,
bool sendWakeMessage = true;
{ // scope lock
MutexAutoLock lock(mQueueLock);
wr::RenderRootSet alreadyWoken;
// What we're doing here is trying to avoid sending redundant
// WakeSceneBuilder messages. If another task exists with our
// layersId/renderRoots combination, then we know that either that message
// is going to be processed soon, or it's blocked on an epoch update, and
// in both of those cases sending a WakeSceneBuilder message won't do
// anything, and our message is destined to be blocked behind it. However,
// imagine the following queue (assume everything as the same layersId):
//
// q[0] (A)
// q[1] (A,B)
// q[2] -> (B,C) // This is what we want to put in the queue
//
// We could go two routes in this case: (I) elide the WakeSceneBuilder
// message if *any* of our renderRoots are already present in q, since we
// won't go until they're all unblocked, or (II) elide it only if *all* of
// our renderRoots are already present in q.
//
// If we go with (I), then if A needs an epoch update, adding (B,C)
// wouldn't send a WakeSceneBuilder message because (A,B) is in the queue
// (intersecting on B). But since (A,B) is only blocked on an epoch update
// for A, (B,C) *could* run if we sent a wake message. Thus, (I) means:
// - Fewer spurious WakeSceneBuilder messages
// - Potential for unnecessarily blocking certain messages
//
// If we went with (II), then (B,C) would run as early as possible, but we
// would send WakeSceneBuilder messages for all three items in the queue.
// Thus, (II) means:
// - More spurious WakeSceneBuilderMessages
// - Potential for violating people's ordering assumptions (i.e., that
// q[2] would run
// after q[1])
//
// We're electing to go with option (II), but we might revisit it if/when
// we have more than two documents. (Because it doesn't matter much before
// then.)
for (const auto& queuedTask : mUpdaterQueue) {
if (queuedTask.mSelector.mLayersId == aSelector.mLayersId) {
alreadyWoken +=
(queuedTask.mSelector.mRenderRoots & aSelector.mRenderRoots);
if (queuedTask.mLayersId == aLayersId) {
// If there's already a task in the queue with this layers id, then
// we must have previously sent a WakeSceneBuilder message (when
// adding the first task with this layers id to the queue). Either
// that hasn't been fully processed yet, or the layers id is blocked
// waiting for an epoch - in either case there's no point in sending
// another WakeSceneBuilder message.
sendWakeMessage = false;
break;
}
}
if (alreadyWoken == aSelector.mRenderRoots) {
sendWakeMessage = false;
}
mUpdaterQueue.push_back(QueuedTask{aSelector, task});
mUpdaterQueue.push_back(QueuedTask{aLayersId, task});
}
if (sendWakeMessage) {
// All the RenderRoots share a single scene builder thread, so we can
// just send the message to the default RenderRoot's API instead of
// sending one for each unwoken RenderRoot.
RefPtr<wr::WebRenderAPI> api =
mApz->GetWebRenderAPI(wr::RenderRoot::Default);
if (api) {
@ -452,13 +394,13 @@ bool APZUpdater::IsUpdaterThread() const {
return CompositorThreadHolder::IsInCompositorThread();
}
void APZUpdater::RunOnControllerThread(UpdaterQueueSelector aSelector,
void APZUpdater::RunOnControllerThread(LayersId aLayersId,
already_AddRefed<Runnable> aTask) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<Runnable> task = aTask;
RunOnUpdaterThread(aSelector,
RunOnUpdaterThread(aLayersId,
NewRunnableFunction("APZUpdater::RunOnControllerThread",
&APZThreadUtils::RunOnControllerThread,
std::move(task)));
@ -509,22 +451,14 @@ void APZUpdater::ProcessQueue() {
}
// We check the task to see if it is blocked. Note that while this
// ProcessQueue function is executing, a particular WRRoot id cannot go
// ProcessQueue function is executing, a particular layers id cannot go
// from blocked to unblocked, because only CompleteSceneSwap can unblock
// a WRRoot id, and that also runs on the updater thread. If somehow
// a WRRoot id gets unblocked while we're processing the queue, then it
// a layers id, and that also runs on the updater thread. If somehow
// a layers id gets unblocked while we're processing the queue, then it
// might result in tasks getting executed out of order.
bool blocked = false;
for (wr::RenderRoot root : task.mSelector.mRenderRoots) {
WRRootId selector = WRRootId(task.mSelector.mLayersId, root);
auto it = mEpochData.find(selector);
if (it != mEpochData.end() && it->second.IsBlocked()) {
blocked = true;
break;
}
}
if (blocked) {
auto it = mEpochData.find(task.mLayersId);
if (it != mEpochData.end() && it->second.IsBlocked()) {
// If this task is blocked, put it into the blockedTasks queue that
// we will replace mUpdaterQueue with
blockedTasks.push_back(task);

View File

@ -38,7 +38,7 @@ void APZCTreeManagerParent::ChildAdopted(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetKeyboardMap(
const KeyboardMap& aKeyboardMap) {
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(mWrRootId),
mWrRootId.mLayersId,
NewRunnableMethod<KeyboardMap>(
"layers::IAPZCTreeManager::SetKeyboardMap", mTreeManager,
&IAPZCTreeManager::SetKeyboardMap, aKeyboardMap));
@ -54,7 +54,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvZoomToRect(
}
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(aGuid.GetWRRootId()),
aGuid.mScrollableLayerGuid.mLayersId,
NewRunnableMethod<SLGuidAndRenderRoot, CSSRect, uint32_t>(
"layers::IAPZCTreeManager::ZoomToRect", mTreeManager,
&IAPZCTreeManager::ZoomToRect, aGuid, aRect, aFlags));
@ -64,7 +64,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvZoomToRect(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvContentReceivedInputBlock(
const uint64_t& aInputBlockId, const bool& aPreventDefault) {
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(mWrRootId),
mWrRootId.mLayersId,
NewRunnableMethod<uint64_t, bool>(
"layers::IAPZCTreeManager::ContentReceivedInputBlock", mTreeManager,
&IAPZCTreeManager::ContentReceivedInputBlock, aInputBlockId,
@ -75,15 +75,8 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvContentReceivedInputBlock(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetTargetAPZC(
const uint64_t& aInputBlockId, nsTArray<SLGuidAndRenderRoot>&& aTargets) {
UpdaterQueueSelector selector(mWrRootId.mLayersId);
for (size_t i = 0; i < aTargets.Length(); i++) {
if (!IsGuidValid(aTargets[i])) {
return IPC_FAIL_NO_REASON(this);
}
selector.mRenderRoots += aTargets[i].mRenderRoot;
}
mUpdater->RunOnControllerThread(
selector,
mWrRootId.mLayersId,
NewRunnableMethod<uint64_t,
StoreCopyPassByRRef<nsTArray<SLGuidAndRenderRoot>>>(
"layers::IAPZCTreeManager::SetTargetAPZC", mTreeManager,
@ -106,7 +99,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvUpdateZoomConstraints(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetDPI(
const float& aDpiValue) {
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(mWrRootId),
mWrRootId.mLayersId,
NewRunnableMethod<float>("layers::IAPZCTreeManager::SetDPI", mTreeManager,
&IAPZCTreeManager::SetDPI, aDpiValue));
return IPC_OK();
@ -115,7 +108,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetDPI(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetAllowedTouchBehavior(
const uint64_t& aInputBlockId, nsTArray<TouchBehaviorFlags>&& aValues) {
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(mWrRootId),
mWrRootId.mLayersId,
NewRunnableMethod<uint64_t,
StoreCopyPassByRRef<nsTArray<TouchBehaviorFlags>>>(
"layers::IAPZCTreeManager::SetAllowedTouchBehavior", mTreeManager,
@ -132,7 +125,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvStartScrollbarDrag(
}
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(aGuid.GetWRRootId()),
aGuid.mScrollableLayerGuid.mLayersId,
NewRunnableMethod<SLGuidAndRenderRoot, AsyncDragMetrics>(
"layers::IAPZCTreeManager::StartScrollbarDrag", mTreeManager,
&IAPZCTreeManager::StartScrollbarDrag, aGuid, aDragMetrics));
@ -150,7 +143,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvStartAutoscroll(
// sending the child process's layers id).
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(mWrRootId.mLayersId, aGuid.mRenderRoot),
mWrRootId.mLayersId,
NewRunnableMethod<SLGuidAndRenderRoot, ScreenPoint>(
"layers::IAPZCTreeManager::StartAutoscroll", mTreeManager,
&IAPZCTreeManager::StartAutoscroll, aGuid, aAnchorLocation));
@ -163,7 +156,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvStopAutoscroll(
// See RecvStartAutoscroll() for why we don't check the layers id.
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(mWrRootId.mLayersId, aGuid.mRenderRoot),
mWrRootId.mLayersId,
NewRunnableMethod<SLGuidAndRenderRoot>(
"layers::IAPZCTreeManager::StopAutoscroll", mTreeManager,
&IAPZCTreeManager::StopAutoscroll, aGuid));
@ -174,7 +167,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvStopAutoscroll(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetLongTapEnabled(
const bool& aLongTapEnabled) {
mUpdater->RunOnControllerThread(
UpdaterQueueSelector(mWrRootId),
mWrRootId.mLayersId,
NewRunnableMethod<bool>(
"layers::IAPZCTreeManager::SetLongTapEnabled", mTreeManager,
&IAPZCTreeManager::SetLongTapEnabled, aLongTapEnabled));

View File

@ -884,8 +884,7 @@ void CompositorBridgeParent::NotifyShadowTreeTransaction(
#endif
if (mApzUpdater) {
mApzUpdater->UpdateFocusState(mRootLayerTreeID,
WRRootId::NonWebRender(aId), aFocusTarget);
mApzUpdater->UpdateFocusState(mRootLayerTreeID, aId, aFocusTarget);
if (aHitTestUpdate) {
mApzUpdater->UpdateHitTestingTree(
mLayerManager->GetRoot(), aIsFirstPaint, aId, aPaintSequenceNumber);
@ -1271,8 +1270,7 @@ void CompositorBridgeParent::ShadowLayersUpdated(
mLayerManager->SetRoot(root);
if (mApzUpdater && !aInfo.isRepeatTransaction()) {
mApzUpdater->UpdateFocusState(mRootLayerTreeID,
WRRootId::NonWebRender(mRootLayerTreeID),
mApzUpdater->UpdateFocusState(mRootLayerTreeID, mRootLayerTreeID,
aInfo.focusTarget());
if (aHitTestUpdate) {
@ -1399,7 +1397,8 @@ void CompositorBridgeParent::SetTestAsyncScrollOffset(
const CSSPoint& aPoint) {
if (mApzUpdater) {
MOZ_ASSERT(aWrRootId.IsValid());
mApzUpdater->SetTestAsyncScrollOffset(aWrRootId, aScrollId, aPoint);
mApzUpdater->SetTestAsyncScrollOffset(aWrRootId.mLayersId, aScrollId,
aPoint);
}
}
@ -1408,7 +1407,7 @@ void CompositorBridgeParent::SetTestAsyncZoom(
const LayerToParentLayerScale& aZoom) {
if (mApzUpdater) {
MOZ_ASSERT(aWrRootId.IsValid());
mApzUpdater->SetTestAsyncZoom(aWrRootId, aScrollId, aZoom);
mApzUpdater->SetTestAsyncZoom(aWrRootId.mLayersId, aScrollId, aZoom);
}
}
@ -1416,7 +1415,7 @@ void CompositorBridgeParent::FlushApzRepaints(const WRRootId& aWrRootId) {
MOZ_ASSERT(mApzUpdater);
MOZ_ASSERT(aWrRootId.IsValid());
mApzUpdater->RunOnControllerThread(
UpdaterQueueSelector(aWrRootId),
aWrRootId.mLayersId,
NS_NewRunnableFunction(
"layers::CompositorBridgeParent::FlushApzRepaints",
[=]() { APZCTreeManager::FlushApzRepaints(aWrRootId.mLayersId); }));
@ -1426,7 +1425,7 @@ void CompositorBridgeParent::GetAPZTestData(const WRRootId& aWrRootId,
APZTestData* aOutData) {
if (mApzUpdater) {
MOZ_ASSERT(aWrRootId.IsValid());
mApzUpdater->GetAPZTestData(aWrRootId, aOutData);
mApzUpdater->GetAPZTestData(aWrRootId.mLayersId, aOutData);
}
}
@ -1444,11 +1443,7 @@ void CompositorBridgeParent::SetConfirmedTargetAPZC(
uint64_t, StoreCopyPassByConstLRef<nsTArray<SLGuidAndRenderRoot>>>(
"layers::CompositorBridgeParent::SetConfirmedTargetAPZC",
mApzcTreeManager.get(), setTargetApzcFunc, aInputBlockId, aTargets);
UpdaterQueueSelector selector(aLayersId);
for (size_t i = 0; i < aTargets.Length(); i++) {
selector.mRenderRoots += aTargets[i].mRenderRoot;
}
mApzUpdater->RunOnControllerThread(selector, task.forget());
mApzUpdater->RunOnControllerThread(aLayersId, task.forget());
}
void CompositorBridgeParent::SetFixedLayerMargins(ScreenIntCoord aTop,
@ -1879,8 +1874,7 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
MOZ_ASSERT(mApzcTreeManager);
parent->ChildAdopted(mApzcTreeManager, mApzUpdater);
}
mApzUpdater->NotifyLayerTreeAdopted(
WRRootId(child, gfxUtils::GetContentRenderRoot()), oldApzUpdater);
mApzUpdater->NotifyLayerTreeAdopted(child, oldApzUpdater);
}
if (apzEnablementChanged) {
Unused << SendCompositorOptionsChanged(child, mOptions);
@ -2116,8 +2110,7 @@ void EraseLayerState(LayersId aId) {
}
if (apz) {
apz->NotifyLayerTreeRemoved(
WRRootId(aId, gfxUtils::GetContentRenderRoot()));
apz->NotifyLayerTreeRemoved(aId);
}
}

View File

@ -1104,8 +1104,7 @@ void WebRenderBridgeParent::UpdateAPZFocusState(const FocusTarget& aFocus) {
}
LayersId rootLayersId = cbp->RootLayerTreeId();
if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
apz->UpdateFocusState(rootLayersId, WRRootId(GetLayersId(), *mRenderRoot),
aFocus);
apz->UpdateFocusState(rootLayersId, GetLayersId(), aFocus);
}
}
@ -1118,10 +1117,8 @@ void WebRenderBridgeParent::UpdateAPZScrollData(const wr::Epoch& aEpoch,
}
LayersId rootLayersId = cbp->RootLayerTreeId();
if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
apz->UpdateScrollDataAndTreeState(
WRRootId(rootLayersId, wr::RenderRoot::Default),
WRRootId(GetLayersId(), RenderRootForExternal(aRenderRoot)), aEpoch,
std::move(aData));
apz->UpdateScrollDataAndTreeState(rootLayersId, GetLayersId(), aEpoch,
std::move(aData));
}
}
@ -1134,10 +1131,8 @@ void WebRenderBridgeParent::UpdateAPZScrollOffsets(
}
LayersId rootLayersId = cbp->RootLayerTreeId();
if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
apz->UpdateScrollOffsets(
WRRootId(rootLayersId, wr::RenderRoot::Default),
WRRootId(GetLayersId(), RenderRootForExternal(aRenderRoot)),
std::move(aUpdates), aPaintSequenceNumber);
apz->UpdateScrollOffsets(rootLayersId, GetLayersId(), std::move(aUpdates),
aPaintSequenceNumber);
}
}

View File

@ -160,8 +160,7 @@ class MOZ_STACK_CLASS WebRenderScrollDataWrapper final {
// tree.
if (mLayer->GetReferentId()) {
return WebRenderScrollDataWrapper(
*mUpdater, mUpdater->GetScrollData(WRRootId(
*mLayer->GetReferentId(), wr::RenderRoot::Default)));
*mUpdater, mUpdater->GetScrollData(*mLayer->GetReferentId()));
}
return WebRenderScrollDataWrapper(*mUpdater);