Bug 1340301 - Ensure APZ functions are called from correct threads on Android with GPU process. r=botond

On Android the APZ controller thread is the android UI thread, rather
than the Gecko main thread as on other platforms. There some places
where the main thread requires to call IAPZCTreeManager functions that
must run on the controller thread. Currently we use the function
DispatchToControllerThread() prior to calling various IAPZCTreeManager
APIs to achieve this.

This works just fine for now, as there is no GPU process on
Android. However, once we do add a GPU process we will encounter
issues:

Firstly, there will now be a cross-process APZInputBridge rather than
using an in-process APZCTreeManager. The PAPZInputBridge protocol is
managed by PGPU, and therefore must run on the main thread in the
parent process. The input we require to send over the bridge, however,
originates from the UI thread.

To solve this we can convert PAPZInputBridge to a top-level protocol,
and bind it to the UI thread on Android. We can then send input
directly from the UI thread without issues.

Secondly, the PAPZCTreeManager protocol must also run from the main
thread in the parent process, as it is managed by
PCompositorBridge. Unlike PAPZInputBridge we cannot convert
PAPZCTreeManager in to a top level protocol, as it relies on the
ordering guarantees with PCompositorBridge.

We must therefore ensure that we only dispatch IAPZCTreeManager calls
to the controller thread when using an in-process
APZCTreeManager. Out-of-process calls, on the other hand, must be
dispatched to the main thread where we can send IPDL commands from. To
do this, we move the dispatch logic away from the callsites of
IAPZCTreeManager APIs, and in to the APZCTreeManager and
APZCTreeManagerChild implementations themselves.

Differential Revision: https://phabricator.services.mozilla.com/D131120
This commit is contained in:
Jamie Nicol 2021-11-20 09:49:14 +00:00
parent 7d875620dd
commit 8c1de22fbf
19 changed files with 242 additions and 99 deletions

View File

@ -219,11 +219,6 @@ void GPUParent::NotifyDeviceReset() {
Unused << SendNotifyDeviceReset(data);
}
already_AddRefed<PAPZInputBridgeParent> GPUParent::AllocPAPZInputBridgeParent(
const LayersId& aLayersId) {
return MakeAndAddRef<APZInputBridgeParent>(aLayersId);
}
mozilla::ipc::IPCResult GPUParent::RecvInit(
nsTArray<GfxVarUpdate>&& vars, const DevicePrefs& devicePrefs,
nsTArray<LayerTreeIdMapping>&& aMappings,
@ -413,6 +408,13 @@ mozilla::ipc::IPCResult GPUParent::RecvInitUiCompositorController(
return IPC_OK();
}
mozilla::ipc::IPCResult GPUParent::RecvInitAPZInputBridge(
const LayersId& aRootLayerTreeId,
Endpoint<PAPZInputBridgeParent>&& aEndpoint) {
APZInputBridgeParent::Create(aRootLayerTreeId, std::move(aEndpoint));
return IPC_OK();
}
mozilla::ipc::IPCResult GPUParent::RecvInitProfiler(
Endpoint<PProfilerChild>&& aEndpoint) {
mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));

View File

@ -40,9 +40,6 @@ class GPUParent final : public PGPUParent {
mozilla::ipc::ScopedPort aPort);
void NotifyDeviceReset();
already_AddRefed<PAPZInputBridgeParent> AllocPAPZInputBridgeParent(
const LayersId& aLayersId);
mozilla::ipc::IPCResult RecvInit(nsTArray<GfxVarUpdate>&& vars,
const DevicePrefs& devicePrefs,
nsTArray<LayerTreeIdMapping>&& mappings,
@ -61,6 +58,9 @@ class GPUParent final : public PGPUParent {
mozilla::ipc::IPCResult RecvInitUiCompositorController(
const LayersId& aRootLayerTreeId,
Endpoint<PUiCompositorControllerParent>&& aEndpoint);
mozilla::ipc::IPCResult RecvInitAPZInputBridge(
const LayersId& aRootLayerTreeId,
Endpoint<PAPZInputBridgeParent>&& aEndpoint);
mozilla::ipc::IPCResult RecvInitProfiler(
Endpoint<PProfilerChild>&& aEndpoint);
mozilla::ipc::IPCResult RecvUpdateVar(const GfxVarUpdate& pref);

View File

@ -933,11 +933,23 @@ RefPtr<CompositorSession> GPUProcessManager::CreateRemoteSession(
}
apz = static_cast<APZCTreeManagerChild*>(papz);
RefPtr<APZInputBridgeChild> pinput = new APZInputBridgeChild();
if (!mGPUChild->SendPAPZInputBridgeConstructor(pinput, aRootLayerTreeId)) {
ipc::Endpoint<PAPZInputBridgeParent> parentPipe;
ipc::Endpoint<PAPZInputBridgeChild> childPipe;
nsresult rv = PAPZInputBridge::CreateEndpoints(mGPUChild->OtherPid(),
base::GetCurrentProcId(),
&parentPipe, &childPipe);
if (NS_FAILED(rv)) {
return nullptr;
}
apz->SetInputBridge(pinput);
mGPUChild->SendInitAPZInputBridge(aRootLayerTreeId, std::move(parentPipe));
RefPtr<APZInputBridgeChild> inputBridge =
APZInputBridgeChild::Create(mProcessToken, std::move(childPipe));
if (!inputBridge) {
return nullptr;
}
apz->SetInputBridge(inputBridge);
}
return new RemoteCompositorSession(aWidget, child, widget, apz,

View File

@ -50,13 +50,7 @@ struct LayerTreeIdMapping {
// the GPU process and the GPUChild living on the main thread of the UI process.
sync protocol PGPU
{
manages PAPZInputBridge;
parent:
// Sent from the UI process to initialize a new APZ input bridge when a new
// top-level compositor is created.
async PAPZInputBridge(LayersId aLayersId);
// Sent by the UI process to initiate core settings.
async Init(GfxVarUpdate[] vars,
DevicePrefs devicePrefs,
@ -69,6 +63,8 @@ parent:
async InitVideoBridge(Endpoint<PVideoBridgeParent> endpoint);
async InitVRManager(Endpoint<PVRManagerParent> endpoint);
async InitUiCompositorController(LayersId rootLayerTreeId, Endpoint<PUiCompositorControllerParent> endpoint);
async InitAPZInputBridge(LayersId layersId,
Endpoint<PAPZInputBridgeParent> endpoint);
async InitProfiler(Endpoint<PProfilerChild> endpoint);
// Forward GPU process its endpoints to the VR process.
async InitVR(Endpoint<PVRGPUChild> endpoint);

View File

@ -366,6 +366,16 @@ SampleTime APZCTreeManager::GetFrameTime() {
void APZCTreeManager::SetAllowedTouchBehavior(
uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aValues) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<uint64_t,
StoreCopyPassByLRef<nsTArray<TouchBehaviorFlags>>>(
"layers::APZCTreeManager::SetAllowedTouchBehavior", this,
&APZCTreeManager::SetAllowedTouchBehavior, aInputBlockId,
aValues.Clone()));
return;
}
APZThreadUtils::AssertOnControllerThread();
mInputQueue->SetAllowedTouchBehavior(aInputBlockId, aValues);
@ -1014,6 +1024,14 @@ already_AddRefed<HitTestingTreeNode> APZCTreeManager::RecycleOrCreateNode(
void APZCTreeManager::StartScrollbarDrag(const ScrollableLayerGuid& aGuid,
const AsyncDragMetrics& aDragMetrics) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid, AsyncDragMetrics>(
"layers::APZCTreeManager::StartScrollbarDrag", this,
&APZCTreeManager::StartScrollbarDrag, aGuid, aDragMetrics));
return;
}
APZThreadUtils::AssertOnControllerThread();
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
@ -2305,6 +2323,13 @@ void APZCTreeManager::ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
}
void APZCTreeManager::SetKeyboardMap(const KeyboardMap& aKeyboardMap) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod<KeyboardMap>(
"layers::APZCTreeManager::SetKeyboardMap", this,
&APZCTreeManager::SetKeyboardMap, aKeyboardMap));
return;
}
APZThreadUtils::AssertOnControllerThread();
mKeyboardMap = aKeyboardMap;
@ -2313,6 +2338,14 @@ void APZCTreeManager::SetKeyboardMap(const KeyboardMap& aKeyboardMap) {
void APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
const ZoomTarget& aZoomTarget,
const uint32_t aFlags) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid, ZoomTarget, uint32_t>(
"layers::APZCTreeManager::ZoomToRect", this,
&APZCTreeManager::ZoomToRect, aGuid, aZoomTarget, aFlags));
return;
}
// We could probably move this to run on the updater thread if needed, but
// either way we should restrict it to a single thread. For now let's use the
// controller thread.
@ -2326,6 +2359,14 @@ void APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
void APZCTreeManager::ContentReceivedInputBlock(uint64_t aInputBlockId,
bool aPreventDefault) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod<uint64_t, bool>(
"layers::APZCTreeManager::ContentReceivedInputBlock", this,
&APZCTreeManager::ContentReceivedInputBlock, aInputBlockId,
aPreventDefault));
return;
}
APZThreadUtils::AssertOnControllerThread();
mInputQueue->ContentReceivedInputBlock(aInputBlockId, aPreventDefault);
@ -2333,7 +2374,15 @@ void APZCTreeManager::ContentReceivedInputBlock(uint64_t aInputBlockId,
void APZCTreeManager::SetTargetAPZC(
uint64_t aInputBlockId, const nsTArray<ScrollableLayerGuid>& aTargets) {
APZThreadUtils::AssertOnControllerThread();
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<uint64_t,
StoreCopyPassByRRef<nsTArray<ScrollableLayerGuid>>>(
"layers::APZCTreeManager::SetTargetAPZC", this,
&layers::APZCTreeManager::SetTargetAPZC, aInputBlockId,
aTargets.Clone()));
return;
}
RefPtr<AsyncPanZoomController> target = nullptr;
if (aTargets.Length() > 0) {
@ -2828,12 +2877,20 @@ APZCTreeManager::BuildOverscrollHandoffChain(
}
void APZCTreeManager::SetLongTapEnabled(bool aLongTapEnabled) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod<bool>(
"layers::APZCTreeManager::SetLongTapEnabled", this,
&APZCTreeManager::SetLongTapEnabled, aLongTapEnabled));
return;
}
APZThreadUtils::AssertOnControllerThread();
GestureEventListener::SetLongTapEnabled(aLongTapEnabled);
}
void APZCTreeManager::AddInputBlockCallback(uint64_t aInputBlockId,
InputBlockCallback&& aCallback) {
APZThreadUtils::AssertOnControllerThread();
mInputQueue->AddInputBlockCallback(aInputBlockId, std::move(aCallback));
}
@ -3568,6 +3625,13 @@ void APZCTreeManager::UnlockTree() {
}
void APZCTreeManager::SetDPI(float aDpiValue) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<float>("layers::APZCTreeManager::SetDPI", this,
&APZCTreeManager::SetDPI, aDpiValue));
return;
}
APZThreadUtils::AssertOnControllerThread();
mDPI = aDpiValue;
}

View File

@ -230,8 +230,7 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
* When the event regions code is enabled, this function should be invoked to
* to confirm the target of the input block. This is only needed in cases
* where the initial input event of the block hit a dispatch-to-content region
* but is safe to call for all input blocks. This function should always be
* invoked on the controller thread.
* but is safe to call for all input blocks.
* The different elements in the array of targets correspond to the targets
* for the different touch points. In the case where the touch point has no
* target, or the target is not a scrollable frame, the target's |mScrollId|
@ -293,7 +292,6 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
* corresponds to the different touch point that is currently active.
* Must be called after receiving the TOUCH_START event that starts the
* touch-session.
* This must be called on the controller thread.
*/
void SetAllowedTouchBehavior(
uint64_t aInputBlockId,

View File

@ -390,10 +390,11 @@ void APZUpdater::RunOnControllerThread(LayersId aLayersId,
RefPtr<Runnable> task = aTask;
RunOnUpdaterThread(aLayersId,
NewRunnableFunction("APZUpdater::RunOnControllerThread",
&APZThreadUtils::RunOnControllerThread,
std::move(task)));
RunOnUpdaterThread(
aLayersId,
NewRunnableFunction("APZUpdater::RunOnControllerThread",
&APZThreadUtils::RunOnControllerThread,
std::move(task), nsIThread::DISPATCH_NORMAL));
}
bool APZUpdater::UsingWebRenderUpdaterThread() const {

View File

@ -58,7 +58,8 @@ void APZThreadUtils::AssertOnControllerThread() {
}
/*static*/
void APZThreadUtils::RunOnControllerThread(RefPtr<Runnable>&& aTask) {
void APZThreadUtils::RunOnControllerThread(RefPtr<Runnable>&& aTask,
uint32_t flags) {
RefPtr<nsISerialEventTarget> thread;
{
StaticMutexAutoLock lock(sControllerThreadMutex);
@ -76,7 +77,7 @@ void APZThreadUtils::RunOnControllerThread(RefPtr<Runnable>&& aTask) {
AUTO_PROFILE_FOLLOWING_RUNNABLE(task);
task->Run();
} else {
thread->Dispatch(task.forget());
thread->Dispatch(task.forget(), flags);
}
}

View File

@ -7,6 +7,7 @@
#ifndef mozilla_layers_APZThreadUtils_h
#define mozilla_layers_APZThreadUtils_h
#include "nsIEventTarget.h"
#include "nsINamed.h"
#include "nsITimer.h"
#include "nsString.h"
@ -46,7 +47,9 @@ class APZThreadUtils {
* this function is called from the controller thread itself then the task is
* run immediately without getting queued.
*/
static void RunOnControllerThread(RefPtr<Runnable>&& aTask);
static void RunOnControllerThread(
RefPtr<Runnable>&& aTask,
uint32_t flags = nsIEventTarget::DISPATCH_NORMAL);
/**
* Returns true if currently on APZ "controller thread".

View File

@ -144,12 +144,9 @@ void ChromeProcessController::HandleDoubleTap(
ScrollableLayerGuid::ViewID viewId;
if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
document->GetDocumentElement(), &presShellId, &viewId)) {
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid, ZoomTarget, uint32_t>(
"IAPZCTreeManager::ZoomToRect", mAPZCTreeManager,
&IAPZCTreeManager::ZoomToRect,
ScrollableLayerGuid(aGuid.mLayersId, presShellId, viewId),
zoomTarget, ZoomToRectBehavior::DEFAULT_BEHAVIOR));
mAPZCTreeManager->ZoomToRect(
ScrollableLayerGuid(aGuid.mLayersId, presShellId, viewId), zoomTarget,
ZoomToRectBehavior::DEFAULT_BEHAVIOR);
}
}

View File

@ -46,55 +46,68 @@ void APZCTreeManagerChild::Destroy() {
}
void APZCTreeManagerChild::SetKeyboardMap(const KeyboardMap& aKeyboardMap) {
MOZ_ASSERT(NS_IsMainThread());
SendSetKeyboardMap(aKeyboardMap);
}
void APZCTreeManagerChild::ZoomToRect(const ScrollableLayerGuid& aGuid,
const ZoomTarget& aZoomTarget,
const uint32_t aFlags) {
MOZ_ASSERT(NS_IsMainThread());
SendZoomToRect(aGuid, aZoomTarget, aFlags);
}
void APZCTreeManagerChild::ContentReceivedInputBlock(uint64_t aInputBlockId,
bool aPreventDefault) {
MOZ_ASSERT(NS_IsMainThread());
SendContentReceivedInputBlock(aInputBlockId, aPreventDefault);
}
void APZCTreeManagerChild::SetTargetAPZC(
uint64_t aInputBlockId, const nsTArray<ScrollableLayerGuid>& aTargets) {
MOZ_ASSERT(NS_IsMainThread());
SendSetTargetAPZC(aInputBlockId, aTargets);
}
void APZCTreeManagerChild::UpdateZoomConstraints(
const ScrollableLayerGuid& aGuid,
const Maybe<ZoomConstraints>& aConstraints) {
MOZ_ASSERT(NS_IsMainThread());
if (mIPCOpen) {
SendUpdateZoomConstraints(aGuid, aConstraints);
}
}
void APZCTreeManagerChild::SetDPI(float aDpiValue) { SendSetDPI(aDpiValue); }
void APZCTreeManagerChild::SetDPI(float aDpiValue) {
MOZ_ASSERT(NS_IsMainThread());
SendSetDPI(aDpiValue);
}
void APZCTreeManagerChild::SetAllowedTouchBehavior(
uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aValues) {
MOZ_ASSERT(NS_IsMainThread());
SendSetAllowedTouchBehavior(aInputBlockId, aValues);
}
void APZCTreeManagerChild::StartScrollbarDrag(
const ScrollableLayerGuid& aGuid, const AsyncDragMetrics& aDragMetrics) {
MOZ_ASSERT(NS_IsMainThread());
SendStartScrollbarDrag(aGuid, aDragMetrics);
}
bool APZCTreeManagerChild::StartAutoscroll(const ScrollableLayerGuid& aGuid,
const ScreenPoint& aAnchorLocation) {
MOZ_ASSERT(NS_IsMainThread());
return SendStartAutoscroll(aGuid, aAnchorLocation);
}
void APZCTreeManagerChild::StopAutoscroll(const ScrollableLayerGuid& aGuid) {
MOZ_ASSERT(NS_IsMainThread());
SendStopAutoscroll(aGuid);
}
void APZCTreeManagerChild::SetLongTapEnabled(bool aTapGestureEnabled) {
MOZ_ASSERT(NS_IsMainThread());
SendSetLongTapEnabled(aTapGestureEnabled);
}

View File

@ -37,7 +37,7 @@ void APZCTreeManagerParent::ChildAdopted(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetKeyboardMap(
const KeyboardMap& aKeyboardMap) {
mUpdater->RunOnControllerThread(
mUpdater->RunOnUpdaterThread(
mLayersId, NewRunnableMethod<KeyboardMap>(
"layers::IAPZCTreeManager::SetKeyboardMap", mTreeManager,
&IAPZCTreeManager::SetKeyboardMap, aKeyboardMap));
@ -52,7 +52,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvZoomToRect(
return IPC_FAIL_NO_REASON(this);
}
mUpdater->RunOnControllerThread(
mUpdater->RunOnUpdaterThread(
aGuid.mLayersId,
NewRunnableMethod<ScrollableLayerGuid, ZoomTarget, uint32_t>(
"layers::IAPZCTreeManager::ZoomToRect", mTreeManager,
@ -62,7 +62,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvZoomToRect(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvContentReceivedInputBlock(
const uint64_t& aInputBlockId, const bool& aPreventDefault) {
mUpdater->RunOnControllerThread(
mUpdater->RunOnUpdaterThread(
mLayersId, NewRunnableMethod<uint64_t, bool>(
"layers::IAPZCTreeManager::ContentReceivedInputBlock",
mTreeManager, &IAPZCTreeManager::ContentReceivedInputBlock,
@ -73,7 +73,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvContentReceivedInputBlock(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetTargetAPZC(
const uint64_t& aInputBlockId, nsTArray<ScrollableLayerGuid>&& aTargets) {
mUpdater->RunOnControllerThread(
mUpdater->RunOnUpdaterThread(
mLayersId,
NewRunnableMethod<uint64_t,
StoreCopyPassByRRef<nsTArray<ScrollableLayerGuid>>>(
@ -97,7 +97,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvUpdateZoomConstraints(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetDPI(
const float& aDpiValue) {
mUpdater->RunOnControllerThread(
mUpdater->RunOnUpdaterThread(
mLayersId,
NewRunnableMethod<float>("layers::IAPZCTreeManager::SetDPI", mTreeManager,
&IAPZCTreeManager::SetDPI, aDpiValue));
@ -106,7 +106,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetDPI(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetAllowedTouchBehavior(
const uint64_t& aInputBlockId, nsTArray<TouchBehaviorFlags>&& aValues) {
mUpdater->RunOnControllerThread(
mUpdater->RunOnUpdaterThread(
mLayersId,
NewRunnableMethod<uint64_t,
StoreCopyPassByRRef<nsTArray<TouchBehaviorFlags>>>(
@ -123,7 +123,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvStartScrollbarDrag(
return IPC_FAIL_NO_REASON(this);
}
mUpdater->RunOnControllerThread(
mUpdater->RunOnUpdaterThread(
aGuid.mLayersId,
NewRunnableMethod<ScrollableLayerGuid, AsyncDragMetrics>(
"layers::IAPZCTreeManager::StartScrollbarDrag", mTreeManager,
@ -164,7 +164,7 @@ mozilla::ipc::IPCResult APZCTreeManagerParent::RecvStopAutoscroll(
mozilla::ipc::IPCResult APZCTreeManagerParent::RecvSetLongTapEnabled(
const bool& aLongTapEnabled) {
mUpdater->RunOnControllerThread(
mUpdater->RunOnUpdaterThread(
mLayersId,
NewRunnableMethod<bool>(
"layers::IAPZCTreeManager::SetLongTapEnabled", mTreeManager,

View File

@ -7,34 +7,89 @@
#include "mozilla/layers/APZInputBridgeChild.h"
#include "InputData.h" // for InputData, etc
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/layers/APZThreadUtils.h"
namespace mozilla {
namespace layers {
APZInputBridgeChild::APZInputBridgeChild() : mDestroyed(false) {
/* static */
RefPtr<APZInputBridgeChild> APZInputBridgeChild::Create(
const uint64_t& aProcessToken, Endpoint<PAPZInputBridgeChild>&& aEndpoint) {
RefPtr<APZInputBridgeChild> child = new APZInputBridgeChild(aProcessToken);
MOZ_ASSERT(APZThreadUtils::IsControllerThreadAlive());
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<Endpoint<PAPZInputBridgeChild>&&>(
"layers::APZInputBridgeChild::Open", child,
&APZInputBridgeChild::Open, std::move(aEndpoint)));
return child;
}
APZInputBridgeChild::APZInputBridgeChild(const uint64_t& aProcessToken)
: mIsOpen(false), mProcessToken(aProcessToken) {
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
}
APZInputBridgeChild::~APZInputBridgeChild() = default;
void APZInputBridgeChild::Open(Endpoint<PAPZInputBridgeChild>&& aEndpoint) {
APZThreadUtils::AssertOnControllerThread();
mIsOpen = aEndpoint.Bind(this);
if (!mIsOpen) {
// The GPU Process Manager might be gone if we receive ActorDestroy very
// late in shutdown.
if (gfx::GPUProcessManager* gpm = gfx::GPUProcessManager::Get()) {
gpm->NotifyRemoteActorDestroyed(mProcessToken);
}
return;
}
}
void APZInputBridgeChild::Destroy() {
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (mDestroyed) {
// Destroy will get called from the main thread, so we must synchronously
// dispatch to the controller thread to close the bridge.
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod("layers::APZInputBridgeChild::Destroy", this,
&APZInputBridgeChild::Destroy),
nsIThread::DISPATCH_SYNC);
return;
}
Send__delete__(this);
mDestroyed = true;
APZThreadUtils::AssertOnControllerThread();
// Clear the process token so that we don't notify the GPUProcessManager
// about an abnormal shutdown, thereby tearing down the GPU process.
mProcessToken = 0;
if (mIsOpen) {
PAPZInputBridgeChild::Close();
mIsOpen = false;
}
}
void APZInputBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
mDestroyed = true;
mIsOpen = false;
if (mProcessToken) {
gfx::GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken);
mProcessToken = 0;
}
}
APZEventResult APZInputBridgeChild::ReceiveInputEvent(InputData& aEvent) {
MOZ_ASSERT(mIsOpen);
APZThreadUtils::AssertOnControllerThread();
APZEventResult res;
switch (aEvent.mInputType) {
case MULTITOUCH_INPUT: {
@ -111,6 +166,9 @@ APZEventResult APZInputBridgeChild::ReceiveInputEvent(InputData& aEvent) {
void APZInputBridgeChild::ProcessUnhandledEvent(
LayoutDeviceIntPoint* aRefPoint, ScrollableLayerGuid* aOutTargetGuid,
uint64_t* aOutFocusSequenceNumber, LayersId* aOutLayersId) {
MOZ_ASSERT(mIsOpen);
APZThreadUtils::AssertOnControllerThread();
SendProcessUnhandledEvent(*aRefPoint, aRefPoint, aOutTargetGuid,
aOutFocusSequenceNumber, aOutLayersId);
}
@ -118,6 +176,9 @@ void APZInputBridgeChild::ProcessUnhandledEvent(
void APZInputBridgeChild::UpdateWheelTransaction(
LayoutDeviceIntPoint aRefPoint, EventMessage aEventMessage,
const Maybe<ScrollableLayerGuid>& aTargetGuid) {
MOZ_ASSERT(mIsOpen);
APZThreadUtils::AssertOnControllerThread();
SendUpdateWheelTransaction(aRefPoint, aEventMessage, aTargetGuid);
}

View File

@ -14,10 +14,13 @@ namespace mozilla {
namespace layers {
class APZInputBridgeChild : public PAPZInputBridgeChild, public APZInputBridge {
NS_INLINE_DECL_REFCOUNTING(APZInputBridgeChild, final)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZInputBridgeChild, final)
public:
APZInputBridgeChild();
static RefPtr<APZInputBridgeChild> Create(
const uint64_t& aProcessToken,
Endpoint<PAPZInputBridgeChild>&& aEndpoint);
void Destroy();
APZEventResult ReceiveInputEvent(InputData& aEvent) override;
@ -33,10 +36,15 @@ class APZInputBridgeChild : public PAPZInputBridgeChild, public APZInputBridge {
const Maybe<ScrollableLayerGuid>& aTargetGuid) override;
void ActorDestroy(ActorDestroyReason aWhy) override;
explicit APZInputBridgeChild(const uint64_t& aProcessToken);
virtual ~APZInputBridgeChild();
private:
bool mDestroyed;
void Open(Endpoint<PAPZInputBridgeChild>&& aEndpoint);
bool mIsOpen;
uint64_t mProcessToken;
};
} // namespace layers

View File

@ -6,6 +6,7 @@
#include "mozilla/layers/APZInputBridgeParent.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/layers/APZInputBridge.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/IAPZCTreeManager.h"
@ -14,6 +15,18 @@
namespace mozilla {
namespace layers {
/* static */
RefPtr<APZInputBridgeParent> APZInputBridgeParent::Create(
const LayersId& aLayersId, Endpoint<PAPZInputBridgeParent>&& aEndpoint) {
RefPtr<APZInputBridgeParent> parent = new APZInputBridgeParent(aLayersId);
if (!aEndpoint.Bind(parent)) {
// We can't recover from this.
MOZ_CRASH("Failed to bind APZInputBridgeParent to endpoint");
}
return parent;
}
APZInputBridgeParent::APZInputBridgeParent(const LayersId& aLayersId) {
MOZ_ASSERT(XRE_IsGPUProcess());
MOZ_ASSERT(NS_IsMainThread());

View File

@ -18,7 +18,8 @@ class APZInputBridgeParent : public PAPZInputBridgeParent {
NS_INLINE_DECL_REFCOUNTING(APZInputBridgeParent, final)
public:
explicit APZInputBridgeParent(const LayersId& aLayersId);
static RefPtr<APZInputBridgeParent> Create(
const LayersId& aLayersId, Endpoint<PAPZInputBridgeParent>&& aEndpoint);
mozilla::ipc::IPCResult RecvReceiveMultiTouchInputEvent(
const MultiTouchInput& aEvent, APZEventResult* aOutResult,
@ -60,6 +61,7 @@ class APZInputBridgeParent : public PAPZInputBridgeParent {
void ActorDestroy(ActorDestroyReason aWhy) override;
protected:
explicit APZInputBridgeParent(const LayersId& aLayersId);
virtual ~APZInputBridgeParent();
private:

View File

@ -946,7 +946,7 @@ void CompositorBridgeParent::SetConfirmedTargetAPZC(
"layers::CompositorBridgeParent::SetConfirmedTargetAPZC",
mApzcTreeManager.get(), setTargetApzcFunc, aInputBlockId,
std::move(aTargets));
mApzUpdater->RunOnControllerThread(aLayersId, task.forget());
mApzUpdater->RunOnUpdaterThread(aLayersId, task.forget());
}
void CompositorBridgeParent::SetFixedLayerMargins(ScreenIntCoord aTop,

View File

@ -18,8 +18,6 @@ using class mozilla::KeyboardInput from "InputData.h";
using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
include protocol PGPU;
namespace mozilla {
namespace layers {
@ -27,14 +25,13 @@ namespace layers {
* This protocol is used to send input events from the UI process to the
* GPU process for handling by APZ. There is one instance per top-level
* compositor, or in other words, one instance per concrete APZCTreeManager
* instance. The child side lives on the main thread in the UI process,
* and the parent side lives on the main thread in the GPU process. If there
* is no GPU process, then this protocol is not instantiated.
* instance. The child side lives on the controller thread in the UI process,
* ie the main thread on most platforms, but the Android UI thread on Android.
* The parent side lives on the main thread in the GPU process. If there is no
* GPU process, then this protocol is not instantiated.
*/
[RefCounted] sync protocol PAPZInputBridge
{
manager PGPU;
parent:
// The following messages are used to
// implement the ReceiveInputEvent methods
@ -76,8 +73,6 @@ parent:
ScrollableLayerGuid aOutTargetGuid,
uint64_t aOutFocusSequenceNumber,
LayersId aOutLayersId);
async __delete__();
};
} // namespace gfx

View File

@ -835,20 +835,11 @@ void nsBaseWidget::ConfigureAPZCTreeManager() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mAPZC);
ConfigureAPZControllerThread();
float dpi = GetDPI();
// On Android the main thread is not the controller thread
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<float>("layers::IAPZCTreeManager::SetDPI", mAPZC,
&IAPZCTreeManager::SetDPI, dpi));
mAPZC->SetDPI(GetDPI());
if (StaticPrefs::apz_keyboard_enabled_AtStartup()) {
KeyboardMap map = RootWindowGlobalKeyListener::CollectKeyboardShortcuts();
// On Android the main thread is not the controller thread
APZThreadUtils::RunOnControllerThread(NewRunnableMethod<KeyboardMap>(
"layers::IAPZCTreeManager::SetKeyboardMap", mAPZC,
&IAPZCTreeManager::SetKeyboardMap, map));
mAPZC->SetKeyboardMap(map);
}
RefPtr<IAPZCTreeManager> treeManager = mAPZC; // for capture by the lambdas
@ -856,10 +847,7 @@ void nsBaseWidget::ConfigureAPZCTreeManager() {
ContentReceivedInputBlockCallback callback(
[treeManager](uint64_t aInputBlockId, bool aPreventDefault) {
MOZ_ASSERT(NS_IsMainThread());
APZThreadUtils::RunOnControllerThread(NewRunnableMethod<uint64_t, bool>(
"layers::IAPZCTreeManager::ContentReceivedInputBlock", treeManager,
&IAPZCTreeManager::ContentReceivedInputBlock, aInputBlockId,
aPreventDefault));
treeManager->ContentReceivedInputBlock(aInputBlockId, aPreventDefault);
});
mAPZEventState = new APZEventState(this, std::move(callback));
@ -867,12 +855,7 @@ void nsBaseWidget::ConfigureAPZCTreeManager() {
[treeManager](uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aFlags) {
MOZ_ASSERT(NS_IsMainThread());
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<
uint64_t, StoreCopyPassByLRef<nsTArray<TouchBehaviorFlags>>>(
"layers::IAPZCTreeManager::SetAllowedTouchBehavior",
treeManager, &IAPZCTreeManager::SetAllowedTouchBehavior,
aInputBlockId, aFlags.Clone()));
treeManager->SetAllowedTouchBehavior(aInputBlockId, aFlags);
};
mRootContentController = CreateRootContentController();
@ -896,11 +879,7 @@ void nsBaseWidget::ConfigureAPZControllerThread() {
void nsBaseWidget::SetConfirmedTargetAPZC(
uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const {
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<uint64_t,
StoreCopyPassByRRef<nsTArray<ScrollableLayerGuid>>>(
"layers::IAPZCTreeManager::SetTargetAPZC", mAPZC,
&IAPZCTreeManager::SetTargetAPZC, aInputBlockId, aTargets.Clone()));
mAPZC->SetTargetAPZC(aInputBlockId, aTargets);
}
void nsBaseWidget::UpdateZoomConstraints(
@ -1313,6 +1292,11 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) {
return;
}
// The controller thread must be configured before the compositor
// session is created, so that the input bridge runs on the right
// thread.
ConfigureAPZControllerThread();
CompositorOptions options;
RefPtr<WebRenderLayerManager> lm =
CreateCompositorSession(aWidth, aHeight, &options);
@ -1779,12 +1763,8 @@ void nsBaseWidget::ZoomToRect(const uint32_t& aPresShellId,
return;
}
LayersId layerId = mCompositorSession->RootLayerTreeId();
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid, ZoomTarget, uint32_t>(
"layers::IAPZCTreeManager::ZoomToRect", mAPZC,
&IAPZCTreeManager::ZoomToRect,
ScrollableLayerGuid(layerId, aPresShellId, aViewId),
ZoomTarget{aRect}, aFlags));
mAPZC->ZoomToRect(ScrollableLayerGuid(layerId, aPresShellId, aViewId),
ZoomTarget{aRect}, aFlags);
}
#ifdef ACCESSIBILITY
@ -1825,10 +1805,7 @@ void nsBaseWidget::StartAsyncScrollbarDrag(
ScrollableLayerGuid guid(layersId, aDragMetrics.mPresShellId,
aDragMetrics.mViewId);
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod<ScrollableLayerGuid, AsyncDragMetrics>(
"layers::IAPZCTreeManager::StartScrollbarDrag", mAPZC,
&IAPZCTreeManager::StartScrollbarDrag, guid, aDragMetrics));
mAPZC->StartScrollbarDrag(guid, aDragMetrics);
}
bool nsBaseWidget::StartAsyncAutoscroll(const ScreenPoint& aAnchorLocation,