mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-23 19:09:49 +00:00
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:
parent
7d875620dd
commit
8c1de22fbf
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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".
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user