Bug 1335895 - part 6: Update UiCompositorControllerChild to support added methods and to be instanced per session instead of a singleton r=dvander draft
authorRandall Barker <rbarker@mozilla.com>
Wed, 05 Apr 2017 15:51:55 -0700
changeset 561572 fbeed45da118f6ee4f777b7dd5f8d3679c1ce5d4
parent 561571 2468afd6f2122bf15a143a912f0b38a07818226d
child 561573 1faf3a944b36d0e1b05a8b819d9f38b41c45bd05
push id53787
push userbmo:rbarker@mozilla.com
push dateWed, 12 Apr 2017 22:56:58 +0000
reviewersdvander
bugs1335895
milestone55.0a1
Bug 1335895 - part 6: Update UiCompositorControllerChild to support added methods and to be instanced per session instead of a singleton r=dvander
gfx/layers/ipc/UiCompositorControllerChild.cpp
gfx/layers/ipc/UiCompositorControllerChild.h
--- a/gfx/layers/ipc/UiCompositorControllerChild.cpp
+++ b/gfx/layers/ipc/UiCompositorControllerChild.cpp
@@ -3,240 +3,385 @@
 /* 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/. */
 
 #include "UiCompositorControllerChild.h"
 #include "UiCompositorControllerParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/layers/CompositorThread.h"
+#include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/StaticPtr.h"
+#include "nsBaseWidget.h"
 #include "nsThreadUtils.h"
-#include "mozilla/gfx/GPUProcessManager.h"
+#if defined(MOZ_WIDGET_ANDROID)
+#include "mozilla/widget/AndroidUiThread.h"
+
+static RefPtr<nsThread>
+GetUiThread()
+{
+  return mozilla::GetAndroidUiThread();
+}
+#else
+static RefPtr<nsThread>
+GetUiThread()
+{
+  MOZ_CRASH("Platform does not support UiCompositorController");
+  return nullptr;
+}
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+namespace {
+static const int32_t COMPOSITOR_CONTROLLER_OPEN = 20;
+}
+
+static bool
+IsOnUiThread()
+{
+  return NS_GetCurrentThread() == GetUiThread();
+}
+
+using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
-using namespace gfx;
 
-static bool sInitialized = false;
-static StaticRefPtr<UiCompositorControllerChild> sChild;
-static StaticRefPtr<UiCompositorControllerParent> sParent;
-
-namespace {
-
-struct SurfaceResizeCache {
-  int32_t mSurfaceWidth;
-  int32_t mSurfaceHeight;
-
-  SurfaceResizeCache(int32_t aWidth, int32_t aHeight) :
-    mSurfaceWidth(aWidth),
-    mSurfaceHeight(aHeight) {}
-
-  SurfaceResizeCache(const SurfaceResizeCache& value)
-  {
-    *this = value;
-  }
 
-  SurfaceResizeCache& operator=(const SurfaceResizeCache& value)
-  {
-    mSurfaceWidth = value.mSurfaceWidth;
-    mSurfaceHeight = value.mSurfaceHeight;
-    return *this;
-  }
-
-  SurfaceResizeCache() :
-    mSurfaceWidth(0),
-    mSurfaceHeight(0) {}
-};
-
-static std::map<int64_t, SurfaceResizeCache> sResizeCache;
-
-static void
-DoCachedResize()
+// public:
+/* static */ RefPtr<UiCompositorControllerChild>
+UiCompositorControllerChild::CreateForSameProcess(const int64_t& aRootLayerTreeId)
 {
-  MOZ_ASSERT(sChild);
-  MOZ_ASSERT(sChild->IsOnUiThread());
-
-  for (auto& cache : sResizeCache) {
-    sChild->SendResumeAndResize(cache.first, cache.second.mSurfaceWidth, cache.second.mSurfaceHeight);
-  }
-
-  sResizeCache.clear();
+  RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(0);
+  child->mParent = new UiCompositorControllerParent(aRootLayerTreeId);
+  GetUiThread()->Dispatch(NewRunnableMethod(child, &UiCompositorControllerChild::OpenForSameProcess), nsIThread::DISPATCH_NORMAL);
+  return child;
 }
 
-} // namespace
-
-UiCompositorControllerChild::UiCompositorControllerChild(RefPtr<nsThread> aThread, const uint64_t& aProcessToken)
- : mUiThread(aThread),
-   mProcessToken(aProcessToken)
-{
-}
-
-UiCompositorControllerChild::~UiCompositorControllerChild()
-{
-}
-
-/* static */ UiCompositorControllerChild*
-UiCompositorControllerChild::Get()
-{
-  return sChild;
-}
-
-/* static */ bool
-UiCompositorControllerChild::IsInitialized()
-{
-  return sInitialized;
-}
-
-/* static */ void
-UiCompositorControllerChild::Shutdown()
+/* static */ RefPtr<UiCompositorControllerChild>
+UiCompositorControllerChild::CreateForGPUProcess(const uint64_t& aProcessToken,
+                                                 Endpoint<PUiCompositorControllerChild>&& aEndpoint)
 {
-  RefPtr<UiCompositorControllerChild> child = sChild;
-  if (child) {
-    child->Close();
-    sInitialized = false;
-  }
-}
-
-/* static */ void
-UiCompositorControllerChild::InitSameProcess(RefPtr<nsThread> aThread)
-{
-  MOZ_ASSERT(!sChild);
-  MOZ_ASSERT(!sParent);
-  MOZ_ASSERT(aThread);
-  MOZ_ASSERT(!sInitialized);
-
-  sInitialized = true;
-  RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(aThread, 0);
-  sParent = new UiCompositorControllerParent();
-  aThread->Dispatch(NewRunnableMethod(child, &UiCompositorControllerChild::OpenForSameProcess), nsIThread::DISPATCH_NORMAL);
-}
-
-/* static */ void
-UiCompositorControllerChild::InitWithGPUProcess(RefPtr<nsThread> aThread,
-                                                const uint64_t& aProcessToken,
-                                                Endpoint<PUiCompositorControllerChild>&& aEndpoint)
-{
-  MOZ_ASSERT(!sChild);
-  MOZ_ASSERT(!sParent);
-  MOZ_ASSERT(aThread);
-  MOZ_ASSERT(!sInitialized);
-
-  sInitialized = true;
-  RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(aThread, aProcessToken);
+  RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(aProcessToken);
 
   RefPtr<nsIRunnable> task = NewRunnableMethod<Endpoint<PUiCompositorControllerChild>&&>(
     child, &UiCompositorControllerChild::OpenForGPUProcess, Move(aEndpoint));
 
-  aThread->Dispatch(task.forget(), nsIThread::DISPATCH_NORMAL);
+  GetUiThread()->Dispatch(task.forget(), nsIThread::DISPATCH_NORMAL);
+  return child;
+}
+
+bool
+UiCompositorControllerChild::Pause()
+{
+  if (!mIsOpen) {
+    return false;
+  }
+  return SendPause();
+}
+
+bool
+UiCompositorControllerChild::Resume()
+{
+  if (!mIsOpen) {
+    return false;
+  }
+  return SendResume();
 }
 
-/* static */ void
-UiCompositorControllerChild::CacheSurfaceResize(int64_t aId, int32_t aWidth, int32_t aHeight)
+bool
+UiCompositorControllerChild::ResumeAndResize(const int32_t& aWidth, const int32_t& aHeight)
+{
+  if (!mIsOpen) {
+    mResizeCached = true;
+    mResizeWidth = aWidth;
+    mResizeHeight = aHeight;
+    // Since we are caching these values, pretend the call succeeded.
+    return true;
+  }
+  return SendResumeAndResize(aWidth, aHeight);
+}
+
+bool
+UiCompositorControllerChild::InvalidateAndRender()
 {
-  // This should only be called if the sChild has not been set yet.
-  // It should also only be called from the UI thread but since the sChild hasn't been set
-  // yet, there isn't a good way to verify this.
-  MOZ_ASSERT(!sChild);
-  sResizeCache[aId] = SurfaceResizeCache{aWidth, aHeight};
+  if (!mIsOpen) {
+    return false;
+  }
+  return SendInvalidateAndRender();
+}
+
+bool
+UiCompositorControllerChild::SetMaxToolbarHeight(const int32_t& aHeight)
+{
+  if (!mIsOpen) {
+    mMaxToolbarHeightCached = true;
+    mMaxToolbarHeight = aHeight;
+    // Since we are caching this value, pretend the call succeeded.
+    return true;
+  }
+  return SendMaxToolbarHeight(aHeight);
 }
 
-void
-UiCompositorControllerChild::OpenForSameProcess()
+bool
+UiCompositorControllerChild::SetPinned(const bool& aPinned, const int32_t& aReason)
+{
+  if (!mIsOpen) {
+    return false;
+  }
+  return SendPinned(aPinned, aReason);
+}
+
+bool
+UiCompositorControllerChild::ToolbarAnimatorMessageFromUI(const int32_t& aMessage)
 {
-  MOZ_ASSERT(sParent);
-  MOZ_ASSERT(!sChild);
-  MOZ_ASSERT(IsOnUiThread());
+  if (!mIsOpen) {
+    return false;
+  }
+
+  return SendToolbarAnimatorMessageFromUI(aMessage);
+}
 
-  if (!Open(sParent->GetIPCChannel(),
-           mozilla::layers::CompositorThreadHolder::Loop(),
-           mozilla::ipc::ChildSide)) {
-    sParent = nullptr;
-    return;
+bool
+UiCompositorControllerChild::SetDefaultClearColor(const uint32_t& aColor)
+{
+  if (!mIsOpen) {
+    mDefaultClearColorCached = true;
+    mDefaultClearColor = aColor;
+    // Since we are caching this value, pretend the call succeeded.
+    return true;
   }
 
-  AddRef();
-  sChild = this;
-  DoCachedResize();
+  return SendDefaultClearColor(aColor);
+}
+
+bool
+UiCompositorControllerChild::RequestScreenPixels()
+{
+  if (!mIsOpen) {
+    return false;
+  }
+
+  return SendRequestScreenPixels();
+}
+
+bool
+UiCompositorControllerChild::EnableLayerUpdateNotifications(const bool& aEnable)
+{
+  if (!mIsOpen) {
+    mLayerUpdateCached = true;
+    mLayerUpdateEnabled = aEnable;
+    // Since we are caching this value, pretend the call succeeded.
+    return true;
+  }
+
+  return SendEnableLayerUpdateNotifications(aEnable);
+}
+
+bool
+UiCompositorControllerChild::ToolbarPixelsToCompositor(const int32_t& aWidth, const int32_t& aHeight, Shmem& aMem)
+{
+  if (!mIsOpen) {
+    return false;
+  }
+
+  return SendToolbarPixelsToCompositor(aWidth, aHeight, aMem);
 }
 
 void
-UiCompositorControllerChild::OpenForGPUProcess(Endpoint<PUiCompositorControllerChild>&& aEndpoint)
+UiCompositorControllerChild::Destroy()
 {
-  MOZ_ASSERT(!sChild);
-  MOZ_ASSERT(IsOnUiThread());
-
-  if (!aEndpoint.Bind(this)) {
-    // The GPU Process Manager might be gone if we receive ActorDestroy very
-    // late in shutdown.
-    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
-      gpm->NotifyRemoteActorDestroyed(mProcessToken);
-    }
+  if (!IsOnUiThread()) {
+    GetUiThread()->Dispatch(NewRunnableMethod(this, &UiCompositorControllerChild::Destroy), nsIThread::DISPATCH_NORMAL);
     return;
   }
 
-  AddRef();
-  sChild = this;
-  DoCachedResize();
+  if (mIsOpen) {
+    // Close the underlying IPC channel.
+    PUiCompositorControllerChild::Close();
+    mIsOpen = false;
+  }
 }
 
 void
-UiCompositorControllerChild::Close()
+UiCompositorControllerChild::SetBaseWidget(nsBaseWidget* aWidget)
 {
-  if (!IsOnUiThread()) {
-    mUiThread->Dispatch(NewRunnableMethod(this, &UiCompositorControllerChild::Close), nsIThread::DISPATCH_NORMAL);
-    return;
-  }
-
-  // We clear mProcessToken when the channel is closed.
-  if (!mProcessToken) {
-    return;
-  }
-
-  // Clear the process token so we don't notify the GPUProcessManager. It already
-  // knows we're closed since it manually called Close, and in fact the GPM could
-  // have already been destroyed during shutdown.
-  mProcessToken = 0;
-  if (this == sChild) {
-    sChild = nullptr;
-  }
-
-  // Close the underlying IPC channel.
-  PUiCompositorControllerChild::Close();
+  mWidget = aWidget;
 }
 
+bool
+UiCompositorControllerChild::AllocPixelBuffer(const int32_t aSize, Shmem* aMem)
+{
+  MOZ_ASSERT(aSize > 0);
+  return AllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC, aMem);
+}
+
+bool
+UiCompositorControllerChild::DeallocPixelBuffer(Shmem& aMem)
+{
+  return DeallocShmem(aMem);
+}
+
+// protected:
 void
 UiCompositorControllerChild::ActorDestroy(ActorDestroyReason aWhy)
 {
+  mIsOpen = false;
+  mParent = nullptr;
+
   if (mProcessToken) {
     GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken);
     mProcessToken = 0;
-    sParent = nullptr;
   }
 }
 
 void
 UiCompositorControllerChild::DeallocPUiCompositorControllerChild()
 {
+  if (mParent) {
+    mParent = nullptr;
+  }
   Release();
-  sInitialized = false;
 }
 
 void
 UiCompositorControllerChild::ProcessingError(Result aCode, const char* aReason)
 {
   MOZ_RELEASE_ASSERT(aCode == MsgDropped, "Processing error in UiCompositorControllerChild");
 }
 
 void
 UiCompositorControllerChild::HandleFatalError(const char* aName, const char* aMsg) const
 {
   dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
 }
 
-bool
-UiCompositorControllerChild::IsOnUiThread() const
+mozilla::ipc::IPCResult
+UiCompositorControllerChild::RecvToolbarAnimatorMessageFromCompositor(const int32_t& aMessage)
+{
+#if defined(MOZ_WIDGET_ANDROID)
+  if (mWidget) {
+    mWidget->RecvToolbarAnimatorMessageFromCompositor(aMessage);
+  }
+#endif // defined(MOZ_WIDGET_ANDROID)
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+UiCompositorControllerChild::RecvRootFrameMetrics(const float& aScrollX, const float& aScrollY, const float& aZoom,
+                                                  const float& aCssPageLeft, const float& aCssPageTop,
+                                                  const float& aCssPageRight, const float& aCssPageBottom)
+{
+#if defined(MOZ_WIDGET_ANDROID)
+  if (mWidget) {
+    mWidget->UpdateRootFrameMetrics(aScrollX, aScrollY, aZoom,
+                                    aCssPageLeft, aCssPageTop,
+                                    aCssPageRight, aCssPageBottom);
+  }
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+UiCompositorControllerChild::RecvScreenPixels(const int32_t& aWidth, const int32_t& aHeight, ipc::Shmem&& aMem)
+{
+#if defined(MOZ_WIDGET_ANDROID)
+  if (mWidget) {
+    mWidget->RecvScreenPixels(aWidth, aHeight, aMem);
+  }
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+  return IPC_OK();
+}
+
+// private:
+UiCompositorControllerChild::UiCompositorControllerChild(const uint64_t& aProcessToken)
+ : mIsOpen(false),
+   mProcessToken(aProcessToken),
+   mResizeCached(false),
+   mResizeWidth(0),
+   mResizeHeight(0),
+   mMaxToolbarHeightCached(false),
+   mMaxToolbarHeight(0),
+   mDefaultClearColorCached(false),
+   mDefaultClearColor(0),
+   mLayerUpdateCached(false),
+   mLayerUpdateEnabled(false),
+   mWidget(nullptr)
+{
+}
+
+UiCompositorControllerChild::~UiCompositorControllerChild()
+{
+}
+
+void
+UiCompositorControllerChild::OpenForSameProcess()
 {
-  return NS_GetCurrentThread() == mUiThread;
+  MOZ_ASSERT(IsOnUiThread());
+
+  mIsOpen = Open(mParent->GetIPCChannel(),
+                 mozilla::layers::CompositorThreadHolder::Loop(),
+                 mozilla::ipc::ChildSide);
+
+  if (!mIsOpen) {
+    mParent = nullptr;
+    return;
+  }
+
+  mParent->InitializeForSameProcess();
+  AddRef();
+  SendCachedValues();
+  // Let Ui thread know the connection is open;
+  RecvToolbarAnimatorMessageFromCompositor(COMPOSITOR_CONTROLLER_OPEN);
+}
+
+void
+UiCompositorControllerChild::OpenForGPUProcess(Endpoint<PUiCompositorControllerChild>&& aEndpoint)
+{
+  MOZ_ASSERT(IsOnUiThread());
+
+  mIsOpen = aEndpoint.Bind(this);
+
+  if (!mIsOpen) {
+    // The GPU Process Manager might be gone if we receive ActorDestroy very
+    // late in shutdown.
+    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
+      gpm->NotifyRemoteActorDestroyed(mProcessToken);
+    }
+    return;
+  }
+
+  AddRef();
+  SendCachedValues();
+  // Let Ui thread know the connection is open;
+  RecvToolbarAnimatorMessageFromCompositor(COMPOSITOR_CONTROLLER_OPEN);
+}
+
+void
+UiCompositorControllerChild::SendCachedValues()
+{
+  MOZ_ASSERT(mIsOpen);
+  if (mResizeCached) {
+    SendResumeAndResize(mResizeWidth, mResizeHeight);
+    mResizeCached = false;
+    mResizeWidth = mResizeHeight = 0;
+  }
+  if (mMaxToolbarHeightCached) {
+    SendMaxToolbarHeight(mMaxToolbarHeight);
+    mMaxToolbarHeightCached = false;
+    mMaxToolbarHeight = 0;
+  }
+  if (mDefaultClearColorCached) {
+    SendDefaultClearColor(mDefaultClearColor);
+    mDefaultClearColorCached = false;
+    mDefaultClearColor = 0;
+  }
+  if (mLayerUpdateCached) {
+    SendEnableLayerUpdateNotifications(mLayerUpdateEnabled);
+    mLayerUpdateCached = false;
+    mLayerUpdateEnabled = false;
+  }
+
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/UiCompositorControllerChild.h
+++ b/gfx/layers/ipc/UiCompositorControllerChild.h
@@ -2,51 +2,82 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=99: */
 /* 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 include_gfx_ipc_UiCompositorControllerChild_h
 #define include_gfx_ipc_UiCompositorControllerChild_h
 
 #include "mozilla/layers/PUiCompositorControllerChild.h"
+#include "mozilla/layers/UiCompositorControllerParent.h"
 #include "mozilla/RefPtr.h"
-#include <nsThread.h>
+#include "nsThread.h"
+#include "mozilla/ipc/Shmem.h"
+
+class nsBaseWidget;
 
 namespace mozilla {
 namespace layers {
 
-class UiCompositorControllerChild final : public PUiCompositorControllerChild
+class UiCompositorControllerChild final : protected PUiCompositorControllerChild
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UiCompositorControllerChild)
 
-  static bool IsInitialized();
-  static void Shutdown();
-  static UiCompositorControllerChild* Get();
-  static void InitSameProcess(RefPtr<nsThread> aThread);
-  static void InitWithGPUProcess(RefPtr<nsThread> aThread,
-                                 const uint64_t& aProcessToken,
-                                 Endpoint<PUiCompositorControllerChild>&& aEndpoint);
+  static RefPtr<UiCompositorControllerChild> CreateForSameProcess(const int64_t& aRootLayerTreeId);
+  static RefPtr<UiCompositorControllerChild> CreateForGPUProcess(const uint64_t& aProcessToken,
+                                                                 Endpoint<PUiCompositorControllerChild>&& aEndpoint);
 
-  static void CacheSurfaceResize(int64_t aId, int32_t aWidth, int32_t aHeight);
-  void Close();
+  bool Pause();
+  bool Resume();
+  bool ResumeAndResize(const int32_t& aHeight, const int32_t& aWidth);
+  bool InvalidateAndRender();
+  bool SetMaxToolbarHeight(const int32_t& aHeight);
+  bool SetPinned(const bool& aPinned, const int32_t& aReason);
+  bool ToolbarAnimatorMessageFromUI(const int32_t& aMessage);
+  bool SetDefaultClearColor(const uint32_t& aColor);
+  bool RequestScreenPixels();
+  bool EnableLayerUpdateNotifications(const bool& aEnable);
+  bool ToolbarPixelsToCompositor(const int32_t& aWidth, const int32_t& aHeight, Shmem& aMem);
 
+  void Destroy();
+
+  void SetBaseWidget(nsBaseWidget* aWidget);
+  bool AllocPixelBuffer(const int32_t aSize, Shmem* aMem);
+  bool DeallocPixelBuffer(Shmem& aMem);
+
+protected:
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeallocPUiCompositorControllerChild() override;
   void ProcessingError(Result aCode, const char* aReason) override;
-
   virtual void HandleFatalError(const char* aName, const char* aMsg) const override;
-
-  bool IsOnUiThread() const;
+  mozilla::ipc::IPCResult RecvToolbarAnimatorMessageFromCompositor(const int32_t& aMessage) override;
+  mozilla::ipc::IPCResult RecvRootFrameMetrics(const float& aScrollX, const float& aScrollY, const float& aZoom,
+                                               const float& aCssPageLeft, const float& aCssPageTop,
+                                               const float& aCssPageRight, const float& aCssPageBottom) override;
+  mozilla::ipc::IPCResult RecvScreenPixels(const int32_t& aWidth, const int32_t& aHeight, ipc::Shmem&& aMem) override;
 private:
-  UiCompositorControllerChild(RefPtr<nsThread> aThread, const uint64_t& aProcessToken);
+  explicit UiCompositorControllerChild(const uint64_t& aProcessToken);
   ~UiCompositorControllerChild();
   void OpenForSameProcess();
   void OpenForGPUProcess(Endpoint<PUiCompositorControllerChild>&& aEndpoint);
+  void SendCachedValues();
 
-  RefPtr<nsThread> mUiThread;
+  bool mIsOpen;
   uint64_t mProcessToken;
+  bool mResizeCached;
+  int32_t mResizeWidth;
+  int32_t mResizeHeight;
+  bool mMaxToolbarHeightCached;
+  int32_t mMaxToolbarHeight;
+  bool mDefaultClearColorCached;
+  uint32_t mDefaultClearColor;
+  bool mLayerUpdateCached;
+  bool mLayerUpdateEnabled;
+  nsBaseWidget* mWidget;
+  // Should only be set when compositor is in process.
+  RefPtr<UiCompositorControllerParent> mParent;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // include_gfx_ipc_UiCompositorControllerChild_h