Bug 1336929 - Have UiCompositorControllerChild cache surface resize when not yet initialized. r=jchen,dvander a=gchang
authorRandall Barker <rbarker@mozilla.com>
Tue, 07 Feb 2017 14:44:43 -0800
changeset 378486 16153c4e477e2fbb872e57f24d11e973f7ee7ff0
parent 378485 84ece89d7cc04e7bd8eb983ff5edf8ced8ea8b87
child 378487 7f305a9951d3fa7af72c49a705826deddfb68a30
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjchen, dvander, gchang
bugs1336929
milestone53.0a2
Bug 1336929 - Have UiCompositorControllerChild cache surface resize when not yet initialized. r=jchen,dvander a=gchang
gfx/layers/ipc/UiCompositorControllerChild.cpp
gfx/layers/ipc/UiCompositorControllerChild.h
widget/android/nsWindow.cpp
--- a/gfx/layers/ipc/UiCompositorControllerChild.cpp
+++ b/gfx/layers/ipc/UiCompositorControllerChild.cpp
@@ -13,16 +13,60 @@
 
 namespace mozilla {
 namespace layers {
 
 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()
+{
+  MOZ_ASSERT(sChild);
+  MOZ_ASSERT(sChild->IsOnUiThread());
+
+  for (auto& cache : sResizeCache) {
+    sChild->SendResumeAndResize(cache.first, cache.second.mSurfaceWidth, cache.second.mSurfaceHeight);
+  }
+
+  sResizeCache.empty();
+}
+
+} // namespace
+
 UiCompositorControllerChild::UiCompositorControllerChild(RefPtr<nsThread> aThread, const uint64_t& aProcessToken)
  : mUiThread(aThread),
    mProcessToken(aProcessToken)
 {
 }
 
 UiCompositorControllerChild::~UiCompositorControllerChild()
 {
@@ -78,32 +122,43 @@ UiCompositorControllerChild::InitWithGPU
   RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(aThread, aProcessToken);
 
   RefPtr<nsIRunnable> task = NewRunnableMethod<Endpoint<PUiCompositorControllerChild>&&>(
     child, &UiCompositorControllerChild::OpenForGPUProcess, Move(aEndpoint));
 
   aThread->Dispatch(task.forget(), nsIThread::DISPATCH_NORMAL);
 }
 
+/* static */ void
+UiCompositorControllerChild::CacheSurfaceResize(int64_t aId, int32_t aWidth, int32_t aHeight)
+{
+  // 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};
+}
+
 void
 UiCompositorControllerChild::OpenForSameProcess()
 {
   MOZ_ASSERT(sParent);
   MOZ_ASSERT(!sChild);
   MOZ_ASSERT(IsOnUiThread());
 
   if (!Open(sParent->GetIPCChannel(),
            mozilla::layers::CompositorThreadHolder::Loop(),
            mozilla::ipc::ChildSide)) {
     sParent = nullptr;
     return;
   }
 
   AddRef();
   sChild = this;
+  DoCachedResize();
 }
 
 void
 UiCompositorControllerChild::OpenForGPUProcess(Endpoint<PUiCompositorControllerChild>&& aEndpoint)
 {
   MOZ_ASSERT(!sChild);
   MOZ_ASSERT(IsOnUiThread());
 
@@ -113,16 +168,17 @@ UiCompositorControllerChild::OpenForGPUP
     if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
       gpm->NotifyRemoteActorDestroyed(mProcessToken);
     }
     return;
   }
 
   AddRef();
   sChild = this;
+  DoCachedResize();
 }
 
 void
 UiCompositorControllerChild::Close()
 {
   if (!IsOnUiThread()) {
     mUiThread->Dispatch(NewRunnableMethod(this, &UiCompositorControllerChild::Close), nsIThread::DISPATCH_NORMAL);
     return;
--- a/gfx/layers/ipc/UiCompositorControllerChild.h
+++ b/gfx/layers/ipc/UiCompositorControllerChild.h
@@ -21,30 +21,31 @@ public:
   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 void CacheSurfaceResize(int64_t aId, int32_t aWidth, int32_t aHeight);
   void Close();
 
   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;
 private:
   UiCompositorControllerChild(RefPtr<nsThread> aThread, const uint64_t& aProcessToken);
   ~UiCompositorControllerChild();
   void OpenForSameProcess();
   void OpenForGPUProcess(Endpoint<PUiCompositorControllerChild>&& aEndpoint);
-  bool IsOnUiThread() const;
 
   RefPtr<nsThread> mUiThread;
   uint64_t mProcessToken;
 };
 
 } // namespace layers
 } // namespace mozilla
 
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1171,21 +1171,23 @@ public:
 
         if (id == 0) {
             return;
         }
 
         RefPtr<UiCompositorControllerChild> child = UiCompositorControllerChild::Get();
 
         if (!child) {
-            return;
+            // When starting, sometimes the UiCompositorControllerChild is still initializing
+            // so cache the resized surface dimensions until it has initialized.
+            UiCompositorControllerChild::CacheSurfaceResize(id, aWidth, aHeight);
+        } else {
+            child->SendResumeAndResize(id, aWidth, aHeight);
         }
 
-        child->SendResumeAndResize(id, aWidth, aHeight);
-
         mCompositorPaused = false;
 
         class OnResumedEvent : public nsAppShell::Event
         {
             LayerView::Compositor::GlobalRef mCompositor;
 
         public:
             OnResumedEvent(LayerView::Compositor::GlobalRef&& aCompositor)