Bug 1415994 - 4. Use LayerSession in native code; r=snorp draft
authorJim Chen <nchen@mozilla.com>
Tue, 14 Nov 2017 18:18:35 -0500
changeset 697878 040442539fd7cc1af8e13e4be1d9ebfb1625f778
parent 697877 eaf42122db1238c99b0da1e689bc365180a2835f
child 697879 ee4ae96e974d15c8cb9ad569ea9abf0ace4d0fa5
push id89133
push userbmo:nchen@mozilla.com
push dateTue, 14 Nov 2017 23:19:10 +0000
reviewerssnorp
bugs1415994
milestone59.0a1
Bug 1415994 - 4. Use LayerSession in native code; r=snorp Make native code use LayerSession::Compositor instead of LayerView::Compositor. Also, make some callbacks happen on the UI thread to make the Java code cleaner. MozReview-Commit-ID: KhuHel7Zfdn
widget/android/nsWindow.cpp
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -771,22 +771,22 @@ nsWindow::AndroidView::GetSettings(JSCon
     return widget::EventDispatcher::UnboxBundle(aCx, mSettings, aOut);
 }
 
 /**
  * Compositor has some unique requirements for its native calls, so make it
  * separate from GeckoViewSupport.
  */
 class nsWindow::LayerViewSupport final
-    : public LayerView::Compositor::Natives<LayerViewSupport>
+    : public LayerSession::Compositor::Natives<LayerViewSupport>
 {
     using LockedWindowPtr = WindowPtr<LayerViewSupport>::Locked;
 
     WindowPtr<LayerViewSupport> mWindow;
-    LayerView::Compositor::GlobalRef mCompositor;
+    LayerSession::Compositor::GlobalRef mCompositor;
     GeckoLayerClient::GlobalRef mLayerClient;
     Atomic<bool, ReleaseAcquire> mCompositorPaused;
     jni::Object::GlobalRef mSurface;
 
     // In order to use Event::HasSameTypeAs in PostTo(), we cannot make
     // LayerViewEvent a template because each template instantiation is
     // a different type. So implement LayerViewEvent as a ProxyEvent.
     class LayerViewEvent final : public nsAppShell::ProxyEvent
@@ -815,55 +815,62 @@ class nsWindow::LayerViewSupport final
                 event->setPrevious(this);
             } else {
                 queue.insertBack(this);
             }
         }
     };
 
 public:
-    typedef LayerView::Compositor::Natives<LayerViewSupport> Base;
+    typedef LayerSession::Compositor::Natives<LayerViewSupport> Base;
 
     template<class Functor>
     static void OnNativeCall(Functor&& aCall)
     {
         if (aCall.IsTarget(&LayerViewSupport::CreateCompositor)) {
             // This call is blocking.
             nsAppShell::SyncRunEvent(nsAppShell::LambdaEvent<Functor>(
                     mozilla::Move(aCall)), &LayerViewEvent::MakeEvent);
             return;
         }
 
         MOZ_CRASH("Unexpected call");
     }
 
     static LayerViewSupport*
-    FromNative(const LayerView::Compositor::LocalRef& instance)
+    FromNative(const LayerSession::Compositor::LocalRef& instance)
     {
         return GetNative(instance);
     }
 
     LayerViewSupport(NativePtr<LayerViewSupport>* aPtr, nsWindow* aWindow,
-                     const LayerView::Compositor::LocalRef& aInstance)
+                     const LayerSession::Compositor::LocalRef& aInstance)
         : mWindow(aPtr, aWindow)
         , mCompositor(aInstance)
         , mCompositorPaused(true)
     {
         MOZ_ASSERT(mWindow);
     }
 
     ~LayerViewSupport()
     {}
 
     using Base::AttachNative;
     using Base::DisposeNative;
 
     void OnDetach()
     {
-        mCompositor->Destroy();
+        if (RefPtr<nsThread> uiThread = GetAndroidUiThread()) {
+            LayerSession::Compositor::GlobalRef compositor(mCompositor);
+            uiThread->Dispatch(NS_NewRunnableFunction(
+                    "LayerViewSupport::OnDetach",
+                    [compositor] {
+                        compositor->OnCompositorDetached();
+                    }));
+        }
     }
 
     const GeckoLayerClient::Ref& GetLayerClient() const
     {
         return mLayerClient;
     }
 
     bool CompositorPaused() const
@@ -872,30 +879,23 @@ public:
     }
 
     jni::Object::Param GetSurface()
     {
         return mSurface;
     }
 
 private:
-    void OnResumedCompositor()
+    already_AddRefed<UiCompositorControllerChild> GetUiCompositorControllerChild()
     {
-        MOZ_ASSERT(NS_IsMainThread());
-
-        // When we receive this, the compositor has already been told to
-        // resume. (It turns out that waiting till we reach here to tell
-        // the compositor to resume takes too long, resulting in a black
-        // flash.) This means it's now safe for layer updates to occur.
-        // Since we might have prevented one or more draw events from
-        // occurring while the compositor was paused, we need to schedule
-        // a draw event now.
-        if (!mCompositorPaused) {
-            mWindow->RedrawAll();
+        RefPtr<UiCompositorControllerChild> child;
+        if (LockedWindowPtr window{mWindow}) {
+            child = window->GetUiCompositorControllerChild();
         }
+        return child.forget();
     }
 
     /**
      * Compositor methods
      */
 public:
     void AttachToJava(jni::Object::Param aClient, jni::Object::Param aNPZC)
     {
@@ -907,17 +907,24 @@ public:
         mLayerClient = GeckoLayerClient::Ref::From(aClient);
 
         MOZ_ASSERT(aNPZC);
         auto npzc = NativePanZoomController::LocalRef(
                 jni::GetGeckoThreadEnv(),
                 NativePanZoomController::Ref::From(aNPZC));
         mWindow->mNPZCSupport.Attach(npzc, mWindow, npzc);
 
-        mLayerClient->OnGeckoReady();
+        if (RefPtr<nsThread> uiThread = GetAndroidUiThread()) {
+            LayerSession::Compositor::GlobalRef compositor(mCompositor);
+            uiThread->Dispatch(NS_NewRunnableFunction(
+                    "LayerViewSupport::AttachToJava",
+                    [compositor] {
+                        compositor->OnCompositorAttached();
+                    }));
+        }
 
         // Set the first-paint flag so that we (re-)link any new Java objects
         // to Gecko, co-ordinate viewports, etc.
         if (RefPtr<CompositorBridgeChild> bridge = mWindow->GetCompositorBridgeChild()) {
             bridge->SendForceIsFirstPaint();
         }
     }
 
@@ -942,17 +949,16 @@ public:
         if (!mWindow) {
             return; // Already shut down.
         }
 
         mSurface = aSurface;
         mWindow->CreateLayerManager(aWidth, aHeight);
 
         mCompositorPaused = false;
-        OnResumedCompositor();
     }
 
     void SyncPauseCompositor()
     {
         MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
 
         if (RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild()) {
           mCompositorPaused = true;
@@ -965,133 +971,136 @@ public:
         MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
 
         if (RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild()) {
           mCompositorPaused = false;
           child->Resume();
         }
     }
 
-    void SyncResumeResizeCompositor(const LayerView::Compositor::LocalRef& aObj,
+    void SyncResumeResizeCompositor(const LayerSession::Compositor::LocalRef& aObj,
                                     int32_t aWidth, int32_t aHeight,
                                     jni::Object::Param aSurface)
     {
         MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
 
         mSurface = aSurface;
 
         if (RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild()) {
             child->ResumeAndResize(aWidth, aHeight);
         }
 
         mCompositorPaused = false;
 
         class OnResumedEvent : public nsAppShell::Event
         {
-            LayerView::Compositor::GlobalRef mCompositor;
+            LayerSession::Compositor::GlobalRef mCompositor;
 
         public:
-            OnResumedEvent(LayerView::Compositor::GlobalRef&& aCompositor)
+            OnResumedEvent(LayerSession::Compositor::GlobalRef&& aCompositor)
                 : mCompositor(mozilla::Move(aCompositor))
             {}
 
             void Run() override
             {
                 MOZ_ASSERT(NS_IsMainThread());
 
                 JNIEnv* const env = jni::GetGeckoThreadEnv();
                 LayerViewSupport* const lvs = GetNative(
-                        LayerView::Compositor::LocalRef(env, mCompositor));
+                        LayerSession::Compositor::LocalRef(env, mCompositor));
 
                 if (!lvs || !lvs->mWindow) {
                     env->ExceptionClear();
                     return; // Already shut down.
                 }
 
-                lvs->OnResumedCompositor();
+                // When we get here, the compositor has already been told to
+                // resume. This means it's now safe for layer updates to occur.
+                // Since we might have prevented one or more draw events from
+                // occurring while the compositor was paused, we need to
+                // schedule a draw event now.
+                if (!lvs->mCompositorPaused) {
+                    lvs->mWindow->RedrawAll();
+                }
             }
         };
 
         // Use priority queue for timing-sensitive event.
         nsAppShell::PostEvent(MakeUnique<LayerViewEvent>(
                 MakeUnique<OnResumedEvent>(aObj)));
     }
 
     void SyncInvalidateAndScheduleComposite()
     {
         RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild();
         if (!child) {
             return;
         }
 
-        if (!AndroidBridge::IsJavaUiThread()) {
-            RefPtr<nsThread> uiThread = GetAndroidUiThread();
-            if (uiThread) {
-                uiThread->Dispatch(NewRunnableMethod("layers::UiCompositorControllerChild::InvalidateAndRender",
-                                                     child,
-                                                     &UiCompositorControllerChild::InvalidateAndRender),
-                                   nsIThread::DISPATCH_NORMAL);
-            }
+        if (AndroidBridge::IsJavaUiThread()) {
+            child->InvalidateAndRender();
             return;
         }
 
-        child->InvalidateAndRender();
+        if (RefPtr<nsThread> uiThread = GetAndroidUiThread()) {
+            uiThread->Dispatch(NewRunnableMethod<>(
+                    "LayerViewSupport::InvalidateAndRender",
+                    child, &UiCompositorControllerChild::InvalidateAndRender),
+                    nsIThread::DISPATCH_NORMAL);
+        }
     }
 
     void SetMaxToolbarHeight(int32_t aHeight)
     {
         MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
 
         if (RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild()) {
           child->SetMaxToolbarHeight(aHeight);
         }
     }
 
     void SetPinned(bool aPinned, int32_t aReason)
     {
         RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild();
         if (!child) {
-          return;
-        }
-
-        if (!AndroidBridge::IsJavaUiThread()) {
-            RefPtr<nsThread> uiThread = GetAndroidUiThread();
-            if (uiThread) {
-                uiThread->Dispatch(NewRunnableMethod<bool, int32_t>(
-                                       "layers::UiCompositorControllerChild::SetPinned",
-                                       child, &UiCompositorControllerChild::SetPinned, aPinned, aReason),
-                                   nsIThread::DISPATCH_NORMAL);
-            }
             return;
         }
 
-        child->SetPinned(aPinned, aReason);
+        if (AndroidBridge::IsJavaUiThread()) {
+            child->SetPinned(aPinned, aReason);
+            return;
+        }
+
+        if (RefPtr<nsThread> uiThread = GetAndroidUiThread()) {
+            uiThread->Dispatch(NewRunnableMethod<bool, int32_t>(
+                    "LayerViewSupport::SetPinned",
+                    child, &UiCompositorControllerChild::SetPinned,
+                    aPinned, aReason), nsIThread::DISPATCH_NORMAL);
+        }
     }
 
 
     void SendToolbarAnimatorMessage(int32_t aMessage)
     {
         RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild();
-
         if (!child) {
-          return;
-        }
-
-        if (!AndroidBridge::IsJavaUiThread()) {
-            RefPtr<nsThread> uiThread = GetAndroidUiThread();
-            if (uiThread) {
-                uiThread->Dispatch(NewRunnableMethod<int32_t>(
-                                       "layers::UiCompositorControllerChild::ToolbarAnimatorMessageFromUI",
-                                       child, &UiCompositorControllerChild::ToolbarAnimatorMessageFromUI, aMessage),
-                                   nsIThread::DISPATCH_NORMAL);
-            }
             return;
         }
 
-        child->ToolbarAnimatorMessageFromUI(aMessage);
+        if (AndroidBridge::IsJavaUiThread()) {
+            child->ToolbarAnimatorMessageFromUI(aMessage);
+            return;
+        }
+
+        if (RefPtr<nsThread> uiThread = GetAndroidUiThread()) {
+            uiThread->Dispatch(NewRunnableMethod<int32_t>(
+                    "LayerViewSupport::ToolbarAnimatorMessageFromUI",
+                    child, &UiCompositorControllerChild::ToolbarAnimatorMessageFromUI,
+                    aMessage), nsIThread::DISPATCH_NORMAL);
+        }
     }
 
     void RecvToolbarAnimatorMessage(int32_t aMessage)
     {
         mCompositor->RecvToolbarAnimatorMessage(aMessage);
     }
 
     void SetDefaultClearColor(int32_t aColor)
@@ -1139,43 +1148,33 @@ public:
            Shmem mem;
            child->AllocPixelBuffer(aPixels->Length() * sizeof(int32_t), &mem);
            aPixels->CopyTo(mem.get<int32_t>(), mem.Size<int32_t>());
            if (!child->ToolbarPixelsToCompositor(mem, ScreenIntSize(aWidth, aHeight))) {
                child->DeallocPixelBuffer(mem);
            }
         }
     }
-
-    already_AddRefed<UiCompositorControllerChild> GetUiCompositorControllerChild()
-    {
-        RefPtr<UiCompositorControllerChild> child;
-        if (LockedWindowPtr window{mWindow}) {
-            child = window->GetUiCompositorControllerChild();
-        }
-        MOZ_ASSERT(child);
-        return child.forget();
-    }
 };
 
 template<> const char
 nsWindow::NativePtr<nsWindow::LayerViewSupport>::sName[] = "LayerViewSupport";
 
 /* PresentationMediaPlayerManager native calls access inner nsWindow functionality so PMPMSupport is a child class of nsWindow */
 class nsWindow::PMPMSupport final
     : public PresentationMediaPlayerManager::Natives<PMPMSupport>
 {
     PMPMSupport() = delete;
 
     static LayerViewSupport* GetLayerViewSupport(jni::Object::Param aView)
     {
         const auto& layerView = LayerView::Ref::From(aView);
 
-        LayerView::Compositor::LocalRef compositor = layerView->GetCompositor();
-        if (!layerView->IsCompositorReady() || !compositor) {
+        LayerSession::Compositor::LocalRef compositor = layerView->GetCompositor();
+        if (!compositor) {
             return nullptr;
         }
 
         LayerViewSupport* const lvs = LayerViewSupport::FromNative(compositor);
         if (!lvs) {
             // There is a pending exception whenever FromNative returns nullptr.
             compositor.Env()->ExceptionClear();
         }