From 274c9d4c174a5c127776e7e4ab17a46237351f5e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 26 Mar 2015 14:23:02 -0700 Subject: [PATCH] Allow dispatching to the APZ controller thread from any thread. (bug 1147681 part 1, r=kats) --HG-- extra : rebase_source : ce0beebda151fdf5adf69e998465c684b193db75 --- gfx/layers/apz/util/APZThreadUtils.cpp | 44 +++++++++++--------------- gfx/layers/apz/util/APZThreadUtils.h | 5 +++ widget/gonk/nsWindow.cpp | 6 ++++ widget/gonk/nsWindow.h | 2 ++ widget/nsBaseWidget.cpp | 8 +++++ widget/nsBaseWidget.h | 1 + 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/gfx/layers/apz/util/APZThreadUtils.cpp b/gfx/layers/apz/util/APZThreadUtils.cpp index 1c9c5eb6e05f..9c4ddc35a2f3 100644 --- a/gfx/layers/apz/util/APZThreadUtils.cpp +++ b/gfx/layers/apz/util/APZThreadUtils.cpp @@ -11,7 +11,7 @@ namespace mozilla { namespace layers { static bool sThreadAssertionsEnabled = true; -static PRThread* sControllerThread; +static MessageLoop* sControllerThread; /*static*/ void APZThreadUtils::SetThreadAssertionsEnabled(bool aEnabled) { @@ -23,22 +23,22 @@ APZThreadUtils::GetThreadAssertionsEnabled() { return sThreadAssertionsEnabled; } +/*static*/ void +APZThreadUtils::SetControllerThread(MessageLoop* aLoop) +{ + // We must either be setting the initial controller thread, or removing it, + // or re-using an existing controller thread. + MOZ_ASSERT(!sControllerThread || !aLoop || sControllerThread == aLoop); + sControllerThread = aLoop; +} + /*static*/ void APZThreadUtils::AssertOnControllerThread() { if (!GetThreadAssertionsEnabled()) { return; } - static bool sControllerThreadDetermined = false; - if (!sControllerThreadDetermined) { - // Technically this may not actually pick up the correct controller thread, - // if the first call to this method happens from a non-controller thread. - // If the assertion below fires, it is possible that it is because - // sControllerThread is not actually the controller thread. - sControllerThread = PR_GetCurrentThread(); - sControllerThreadDetermined = true; - } - MOZ_ASSERT(sControllerThread == PR_GetCurrentThread()); + MOZ_ASSERT(sControllerThread == MessageLoop::current()); } /*static*/ void @@ -52,25 +52,19 @@ APZThreadUtils::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(); - if (!loop) { + if (!sControllerThread) { // Could happen on startup NS_WARNING("Dropping task posted to controller thread\n"); delete aTask; return; } - 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 + + if (sControllerThread == MessageLoop::current()) { + aTask->Run(); + delete aTask; + } else { + sControllerThread->PostTask(FROM_HERE, aTask); + } } } // namespace layers diff --git a/gfx/layers/apz/util/APZThreadUtils.h b/gfx/layers/apz/util/APZThreadUtils.h index 2bb37979e954..4b3ebc425455 100644 --- a/gfx/layers/apz/util/APZThreadUtils.h +++ b/gfx/layers/apz/util/APZThreadUtils.h @@ -22,6 +22,11 @@ public: static void SetThreadAssertionsEnabled(bool aEnabled); static bool GetThreadAssertionsEnabled(); + /** + * Set the controller thread. + */ + static void SetControllerThread(MessageLoop* aLoop); + /** * This can be used to assert that the current thread is the * controller/UI thread (on which input events are received). diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index e50a40184893..9d346d998842 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -227,6 +227,12 @@ nsWindow::DoDraw(void) } } +void +nsWindow::ConfigureAPZControllerThread() +{ + APZThreadUtils::SetControllerThread(CompositorParent::CompositorLoop()); +} + /*static*/ nsEventStatus nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent) { diff --git a/widget/gonk/nsWindow.h b/widget/gonk/nsWindow.h index 8b3b38e6a34a..7bd373b808f1 100644 --- a/widget/gonk/nsWindow.h +++ b/widget/gonk/nsWindow.h @@ -132,6 +132,8 @@ public: virtual Composer2D* GetComposer2D() override; + void ConfigureAPZControllerThread() override; + protected: nsWindow* mParent; bool mVisible; diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index bcd2ce14dde5..dbffe2ea34d0 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -978,6 +978,8 @@ void nsBaseWidget::ConfigureAPZCTreeManager() mAPZC = CompositorParent::GetAPZCTreeManager(rootLayerTreeId); MOZ_ASSERT(mAPZC); + ConfigureAPZControllerThread(); + mAPZC->SetDPI(GetDPI()); mAPZEventState = new APZEventState(this, new ChromeProcessContentReceivedInputBlockCallback(mAPZC)); @@ -990,6 +992,12 @@ void nsBaseWidget::ConfigureAPZCTreeManager() } } +void nsBaseWidget::ConfigureAPZControllerThread() +{ + // By default the controller thread is the main thread. + APZThreadUtils::SetControllerThread(MessageLoop::current()); +} + nsEventStatus nsBaseWidget::ProcessUntransformedAPZEvent(WidgetInputEvent* aEvent, const ScrollableLayerGuid& aGuid, diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 3a2a0000c298..269547d3a600 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -331,6 +331,7 @@ protected: nsWidgetInitData *aInitData); virtual void ConfigureAPZCTreeManager(); + virtual void ConfigureAPZControllerThread(); virtual already_AddRefed CreateRootContentController(); // Dispatch an event that has already been routed through APZ.