Bug 1447299 - Bounce PAPZCTreeManager controller messages through the sampler thread. r?botond
The methods on PAPZCTreeManagerParent are always invoked on the
compositor thread, which currently is always the same as the sampler
thread. When it does RunOnControllerThread calls, there is an implicit
ordering with respect to the sampler thread, because the controller
thread messages are always dispatched *from* the sampler thread. When we
move the sampler thread to be the render backend thread, we have to
preseve this implicit ordering, but we have to make it more explicit.
This patch accomplishes that by introducing a method on APZSampler.
MozReview-Commit-ID: 9eYwkNpVkZ1
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -2,16 +2,17 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_layers_APZSampler_h
#define mozilla_layers_APZSampler_h
+#include "base/message_loop.h"
#include "LayersTypes.h"
#include "mozilla/layers/APZTestData.h"
#include "mozilla/layers/AsyncCompositionManager.h" // for AsyncTransform
#include "mozilla/Maybe.h"
#include "nsTArray.h"
#include "Units.h"
namespace mozilla {
@@ -120,16 +121,26 @@ public:
*/
void RunOnSamplerThread(already_AddRefed<Runnable> aTask);
/**
* Returns true if currently on the APZSampler's "sampler thread".
*/
bool IsSamplerThread();
+ /**
+ * Dispatches the given task to the APZ "controller thread", but does it *from*
+ * the sampler thread. That is, if the thread on which this function is called
+ * is not the sampler thread, the task is first dispatched to the sampler thread.
+ * When the sampler thread runs it (or if this is called directly on the sampler
+ * thread), that is when the task gets dispatched to the controller thread.
+ * The controller thread then actually runs the task.
+ */
+ void RunOnControllerThread(already_AddRefed<Runnable> aTask);
+
protected:
virtual ~APZSampler();
private:
RefPtr<APZCTreeManager> mApz;
};
} // namespace layers
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -247,10 +247,21 @@ APZSampler::RunOnSamplerThread(already_A
}
bool
APZSampler::IsSamplerThread()
{
return CompositorThreadHolder::IsInCompositorThread();
}
+void
+APZSampler::RunOnControllerThread(already_AddRefed<Runnable> aTask)
+{
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+
+ RunOnSamplerThread(NewRunnableFunction(
+ "APZSampler::RunOnControllerThread",
+ &APZThreadUtils::RunOnControllerThread,
+ Move(aTask)));
+}
+
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/ipc/APZCTreeManagerParent.cpp
+++ b/gfx/layers/ipc/APZCTreeManagerParent.cpp
@@ -38,17 +38,17 @@ APZCTreeManagerParent::ChildAdopted(RefP
MOZ_ASSERT(aAPZSampler->HasTreeManager(aAPZCTreeManager));
mTreeManager = aAPZCTreeManager;
mSampler = aAPZSampler;
}
mozilla::ipc::IPCResult
APZCTreeManagerParent::RecvSetKeyboardMap(const KeyboardMap& aKeyboardMap)
{
- APZThreadUtils::RunOnControllerThread(NewRunnableMethod<KeyboardMap>(
+ mSampler->RunOnControllerThread(NewRunnableMethod<KeyboardMap>(
"layers::IAPZCTreeManager::SetKeyboardMap",
mTreeManager,
&IAPZCTreeManager::SetKeyboardMap,
aKeyboardMap));
return IPC_OK();
}
@@ -59,31 +59,31 @@ APZCTreeManagerParent::RecvZoomToRect(
const uint32_t& aFlags)
{
if (aGuid.mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in RecvZoomToRect; dropping message...");
return IPC_FAIL_NO_REASON(this);
}
- APZThreadUtils::RunOnControllerThread(
+ mSampler->RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid, CSSRect, uint32_t>(
"layers::IAPZCTreeManager::ZoomToRect",
mTreeManager,
&IAPZCTreeManager::ZoomToRect,
aGuid, aRect, aFlags));
return IPC_OK();
}
mozilla::ipc::IPCResult
APZCTreeManagerParent::RecvContentReceivedInputBlock(
const uint64_t& aInputBlockId,
const bool& aPreventDefault)
{
- APZThreadUtils::RunOnControllerThread(NewRunnableMethod<uint64_t, bool>(
+ mSampler->RunOnControllerThread(NewRunnableMethod<uint64_t, bool>(
"layers::IAPZCTreeManager::ContentReceivedInputBlock",
mTreeManager,
&IAPZCTreeManager::ContentReceivedInputBlock,
aInputBlockId,
aPreventDefault));
return IPC_OK();
}
@@ -95,17 +95,17 @@ APZCTreeManagerParent::RecvSetTargetAPZC
{
for (size_t i = 0; i < aTargets.Length(); i++) {
if (aTargets[i].mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in RecvSetTargetAPZC; dropping message...");
return IPC_FAIL_NO_REASON(this);
}
}
- APZThreadUtils::RunOnControllerThread(
+ mSampler->RunOnControllerThread(
NewRunnableMethod<uint64_t,
StoreCopyPassByRRef<nsTArray<ScrollableLayerGuid>>>(
"layers::IAPZCTreeManager::SetTargetAPZC",
mTreeManager,
&IAPZCTreeManager::SetTargetAPZC,
aInputBlockId,
aTargets));
@@ -125,30 +125,30 @@ APZCTreeManagerParent::RecvUpdateZoomCon
mTreeManager->UpdateZoomConstraints(aGuid, aConstraints);
return IPC_OK();
}
mozilla::ipc::IPCResult
APZCTreeManagerParent::RecvSetDPI(const float& aDpiValue)
{
- APZThreadUtils::RunOnControllerThread(NewRunnableMethod<float>(
+ mSampler->RunOnControllerThread(NewRunnableMethod<float>(
"layers::IAPZCTreeManager::SetDPI",
mTreeManager,
&IAPZCTreeManager::SetDPI,
aDpiValue));
return IPC_OK();
}
mozilla::ipc::IPCResult
APZCTreeManagerParent::RecvSetAllowedTouchBehavior(
const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aValues)
{
- APZThreadUtils::RunOnControllerThread(
+ mSampler->RunOnControllerThread(
NewRunnableMethod<uint64_t,
StoreCopyPassByRRef<nsTArray<TouchBehaviorFlags>>>(
"layers::IAPZCTreeManager::SetAllowedTouchBehavior",
mTreeManager,
&IAPZCTreeManager::SetAllowedTouchBehavior,
aInputBlockId,
Move(aValues)));
@@ -161,17 +161,17 @@ APZCTreeManagerParent::RecvStartScrollba
const AsyncDragMetrics& aDragMetrics)
{
if (aGuid.mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in RecvStartScrollbarDrag; dropping message...");
return IPC_FAIL_NO_REASON(this);
}
- APZThreadUtils::RunOnControllerThread(
+ mSampler->RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid, AsyncDragMetrics>(
"layers::IAPZCTreeManager::StartScrollbarDrag",
mTreeManager,
&IAPZCTreeManager::StartScrollbarDrag,
aGuid,
aDragMetrics));
return IPC_OK();
@@ -184,45 +184,45 @@ APZCTreeManagerParent::RecvStartAutoscro
{
// Unlike RecvStartScrollbarDrag(), this message comes from the parent
// process (via nsBaseWidget::mAPZC) rather than from the child process
// (via TabChild::mApzcTreeManager), so there is no need to check the
// layers id against mLayersId (and in any case, it wouldn't match, because
// mLayersId stores the parent process's layers id, while nsBaseWidget is
// sending the child process's layers id).
- APZThreadUtils::RunOnControllerThread(
+ mSampler->RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid, ScreenPoint>(
"layers::IAPZCTreeManager::StartAutoscroll",
mTreeManager,
&IAPZCTreeManager::StartAutoscroll,
aGuid, aAnchorLocation));
return IPC_OK();
}
mozilla::ipc::IPCResult
APZCTreeManagerParent::RecvStopAutoscroll(const ScrollableLayerGuid& aGuid)
{
// See RecvStartAutoscroll() for why we don't check the layers id.
- APZThreadUtils::RunOnControllerThread(
+ mSampler->RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid>(
"layers::IAPZCTreeManager::StopAutoscroll",
mTreeManager,
&IAPZCTreeManager::StopAutoscroll,
aGuid));
return IPC_OK();
}
mozilla::ipc::IPCResult
APZCTreeManagerParent::RecvSetLongTapEnabled(const bool& aLongTapEnabled)
{
- APZThreadUtils::RunOnControllerThread(
+ mSampler->RunOnControllerThread(
NewRunnableMethod<bool>(
"layers::IAPZCTreeManager::SetLongTapEnabled",
mTreeManager,
&IAPZCTreeManager::SetLongTapEnabled,
aLongTapEnabled));
return IPC_OK();
}