Bug 930939 - Add a function to encapsulate running things on the APZ controller thread. r=botond a=bajaj
--- a/gfx/layers/apz/util/APZThreadUtils.cpp
+++ b/gfx/layers/apz/util/APZThreadUtils.cpp
@@ -44,10 +44,28 @@ APZThreadUtils::AssertOnControllerThread
/*static*/ void
APZThreadUtils::AssertOnCompositorThread()
{
if (GetThreadAssertionsEnabled()) {
Compositor::AssertOnCompositorThread();
}
}
+/*static*/ void
+APZThreadUtils::RunOnControllerThread(Task* aTask)
+{
+#ifdef MOZ_WIDGET_GONK
+ // On B2G the controller thread is the compositor thread, and this function
+ // is always called from the libui thread or the main thread.
+ MessageLoop* loop = CompositorParent::CompositorLoop();
+ MOZ_ASSERT(MessageLoop::current() != loop);
+ loop->PostTask(FROM_HERE, aTask);
+#else
+ // On non-B2G platforms this is only ever called from the controller thread
+ // itself.
+ AssertOnControllerThread();
+ aTask->Run();
+ delete aTask;
+#endif
+}
+
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/apz/util/APZThreadUtils.h
+++ b/gfx/layers/apz/util/APZThreadUtils.h
@@ -1,16 +1,18 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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_APZThreadUtils_h
#define mozilla_layers_APZThreadUtils_h
+class Task;
+
namespace mozilla {
namespace layers {
class APZThreadUtils
{
public:
/**
* In the gtest environment everything runs on one thread, so we
@@ -28,14 +30,21 @@ public:
static void AssertOnControllerThread();
/**
* This can be used to assert that the current thread is the
* compositor thread (which applies the async transform).
* This does nothing if thread assertions are disabled.
*/
static void AssertOnCompositorThread();
+
+ /**
+ * Run the given task on the APZ "controller thread" for this platform. If
+ * this function is called from the controller thread itself then the task is
+ * run immediately without getting queued.
+ */
+ static void RunOnControllerThread(Task* aTask);
};
} // namespace layers
} // namespace mozilla
#endif /* mozilla_layers_APZThreadUtils_h */
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -11,16 +11,17 @@
#include "gfxPrefs.h"
#ifdef MOZ_ENABLE_D3D9_LAYER
# include "LayerManagerD3D9.h"
#endif //MOZ_ENABLE_D3D9_LAYER
#include "mozilla/BrowserElementParent.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/layers/APZCTreeManager.h"
+#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layers/LayerTransactionParent.h"
#include "nsContentUtils.h"
#include "nsFocusManager.h"
#include "nsFrameLoader.h"
#include "nsIObserver.h"
#include "nsSubDocumentFrame.h"
#include "nsView.h"
@@ -526,33 +527,40 @@ RenderFrameParent::ContentReceivedInputB
bool aPreventDefault)
{
if (aGuid.mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in ContentReceivedInputBlock; dropping message...");
return;
}
if (GetApzcTreeManager()) {
- GetApzcTreeManager()->ContentReceivedInputBlock(aInputBlockId, aPreventDefault);
+ APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
+ GetApzcTreeManager(), &APZCTreeManager::ContentReceivedInputBlock,
+ aInputBlockId, aPreventDefault));
}
}
void
RenderFrameParent::SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets)
{
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 SetTargetAPZC; dropping message...");
return;
}
}
if (GetApzcTreeManager()) {
- GetApzcTreeManager()->SetTargetAPZC(aInputBlockId, aTargets);
+ // need a local var to disambiguate between the SetTargetAPZC overloads.
+ void (APZCTreeManager::*setTargetApzcFunc)(uint64_t, const nsTArray<ScrollableLayerGuid>&)
+ = &APZCTreeManager::SetTargetAPZC;
+ APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
+ GetApzcTreeManager(), setTargetApzcFunc,
+ aInputBlockId, aTargets));
}
}
void
RenderFrameParent::UpdateZoomConstraints(uint32_t aPresShellId,
ViewID aViewId,
bool aIsRoot,
const ZoomConstraints& aConstraints)