Bug 1039883 - Release Tiled layer's gralloc when an application is background. r=nical, a=2.0+
authorSotaro Ikeda <sikeda@mozilla.com>
Fri, 18 Jul 2014 20:00:00 -0400
changeset 209224 d0bb536942e27651a83d43cf2b251d39107815fe
parent 209223 f365749d72c9887111077fd1fb09b9953b69fff7
child 209225 4bd4b0ae7bbe709089afd8b4eded0ab74a9aec81
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical, 2
bugs1039883
milestone32.0a2
Bug 1039883 - Release Tiled layer's gralloc when an application is background. r=nical, a=2.0+
gfx/layers/client/ClientTiledThebesLayer.cpp
gfx/layers/client/TiledContentClient.cpp
gfx/layers/client/TiledContentClient.h
gfx/layers/composite/CompositableHost.h
gfx/layers/composite/TiledContentHost.cpp
gfx/layers/composite/TiledContentHost.h
gfx/layers/ipc/ISurfaceAllocator.cpp
gfx/layers/ipc/ISurfaceAllocator.h
gfx/layers/ipc/SharedBufferManagerChild.cpp
gfx/layers/ipc/SharedBufferManagerChild.h
gfx/layers/opengl/GrallocTextureClient.cpp
--- a/gfx/layers/client/ClientTiledThebesLayer.cpp
+++ b/gfx/layers/client/ClientTiledThebesLayer.cpp
@@ -47,16 +47,18 @@ ClientTiledThebesLayer::~ClientTiledTheb
 }
 
 void
 ClientTiledThebesLayer::ClearCachedResources()
 {
   if (mContentClient) {
     mContentClient->ClearCachedResources();
   }
+  mValidRegion.SetEmpty();
+  mContentClient = nullptr;
 }
 
 void
 ClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
 {
   aAttrs = ThebesLayerAttributes(GetValidRegion());
 }
 
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -101,18 +101,18 @@ TiledContentClient::TiledContentClient(C
                                                     &mSharedFrameMetricsHelper);
 
   mLowPrecisionTiledBuffer.SetResolution(gfxPrefs::LowPrecisionResolution());
 }
 
 void
 TiledContentClient::ClearCachedResources()
 {
-  mTiledBuffer.DiscardBackBuffers();
-  mLowPrecisionTiledBuffer.DiscardBackBuffers();
+  mTiledBuffer.DiscardBuffers();
+  mLowPrecisionTiledBuffer.DiscardBuffers();
 }
 
 void
 TiledContentClient::UseTiledLayerBuffer(TiledBufferType aType)
 {
   ClientTiledLayerBuffer* buffer = aType == LOW_PRECISION_TILED_BUFFER
     ? &mLowPrecisionTiledBuffer
     : &mTiledBuffer;
@@ -625,20 +625,21 @@ ClientTiledLayerBuffer::Release()
 {
   for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
     if (mRetainedTiles[i].IsPlaceholderTile()) continue;
     mRetainedTiles[i].Release();
   }
 }
 
 void
-ClientTiledLayerBuffer::DiscardBackBuffers()
+ClientTiledLayerBuffer::DiscardBuffers()
 {
   for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
     if (mRetainedTiles[i].IsPlaceholderTile()) continue;
+    mRetainedTiles[i].DiscardFrontBuffer();
     mRetainedTiles[i].DiscardBackBuffer();
   }
 }
 
 SurfaceDescriptorTiles
 ClientTiledLayerBuffer::GetSurfaceDescriptorTiles()
 {
   InfallibleTArray<TileDescriptor> tiles;
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -365,17 +365,17 @@ public:
                    void* aCallbackData);
 
   void ReadUnlock();
 
   void ReadLock();
 
   void Release();
 
-  void DiscardBackBuffers();
+  void DiscardBuffers();
 
   const CSSToParentLayerScale& GetFrameResolution() { return mFrameResolution; }
 
   void SetFrameResolution(const CSSToParentLayerScale& aResolution) { mFrameResolution = aResolution; }
 
   bool HasFormatChanged() const;
 
   /**
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -229,17 +229,17 @@ public:
   // Detach this compositable host from its layer.
   // If we are used for async video, then it is not safe to blindly detach since
   // we might be re-attached to a different layer. aLayer is the layer which the
   // caller expects us to be attached to, we will only detach if we are in fact
   // attached to that layer. If we are part of a normal layer, then we will be
   // detached in any case. if aLayer is null, then we will only detach if we are
   // not async.
   // Only force detach if the IPDL tree is being shutdown.
-  void Detach(Layer* aLayer = nullptr, AttachFlags aFlags = NO_FLAGS)
+  virtual void Detach(Layer* aLayer = nullptr, AttachFlags aFlags = NO_FLAGS)
   {
     if (!mKeepAttached ||
         aLayer == mLayer ||
         aFlags & FORCE_DETACH) {
       SetLayer(nullptr);
       mAttached = false;
       mKeepAttached = false;
       if (mBackendData) {
--- a/gfx/layers/composite/TiledContentHost.cpp
+++ b/gfx/layers/composite/TiledContentHost.cpp
@@ -233,16 +233,52 @@ TiledContentHost::Attach(Layer* aLayer,
                          Compositor* aCompositor,
                          AttachFlags aFlags /* = NO_FLAGS */)
 {
   CompositableHost::Attach(aLayer, aCompositor, aFlags);
   static_cast<ThebesLayerComposite*>(aLayer)->EnsureTiled();
 }
 
 void
+TiledContentHost::Detach(Layer* aLayer,
+                         AttachFlags aFlags /* = NO_FLAGS */)
+{
+  if (!mKeepAttached || aLayer == mLayer || aFlags & FORCE_DETACH) {
+
+    // Unlock any buffers that may still be locked. If we have a pending upload,
+    // we will need to unlock the buffer that was about to be uploaded.
+    // If a buffer that was being composited had double-buffered tiles, we will
+    // need to unlock that buffer too.
+    if (mPendingUpload) {
+      mTiledBuffer.ReadUnlock();
+      if (mOldTiledBuffer.HasDoubleBufferedTiles()) {
+        mOldTiledBuffer.ReadUnlock();
+      }
+    } else if (mTiledBuffer.HasDoubleBufferedTiles()) {
+      mTiledBuffer.ReadUnlock();
+    }
+
+    if (mPendingLowPrecisionUpload) {
+      mLowPrecisionTiledBuffer.ReadUnlock();
+      if (mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
+        mOldLowPrecisionTiledBuffer.ReadUnlock();
+      }
+    } else if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
+      mLowPrecisionTiledBuffer.ReadUnlock();
+    }
+
+    mTiledBuffer = TiledLayerBufferComposite();
+    mLowPrecisionTiledBuffer = TiledLayerBufferComposite();
+    mOldTiledBuffer = TiledLayerBufferComposite();
+    mOldLowPrecisionTiledBuffer = TiledLayerBufferComposite();
+  }
+  CompositableHost::Detach(aLayer,aFlags);
+}
+
+void
 TiledContentHost::UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
                                       const SurfaceDescriptorTiles& aTiledDescriptor)
 {
   if (aTiledDescriptor.resolution() < 1) {
     if (mPendingLowPrecisionUpload) {
       mLowPrecisionTiledBuffer.ReadUnlock();
     } else {
       mPendingLowPrecisionUpload = true;
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -222,16 +222,19 @@ public:
   virtual CompositableType GetType() { return CompositableType::BUFFER_TILED; }
 
   virtual TiledLayerComposer* AsTiledLayerComposer() MOZ_OVERRIDE { return this; }
 
   virtual void Attach(Layer* aLayer,
                       Compositor* aCompositor,
                       AttachFlags aFlags = NO_FLAGS) MOZ_OVERRIDE;
 
+  virtual void Detach(Layer* aLayer = nullptr,
+                      AttachFlags aFlags = NO_FLAGS) MOZ_OVERRIDE;
+
 #ifdef MOZ_DUMP_PAINTING
   virtual void Dump(FILE* aFile=nullptr,
                     const char* aPrefix="",
                     bool aDumpHtml=false) MOZ_OVERRIDE;
 #endif
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
--- a/gfx/layers/ipc/ISurfaceAllocator.cpp
+++ b/gfx/layers/ipc/ISurfaceAllocator.cpp
@@ -319,10 +319,16 @@ ISurfaceAllocator::AllocGrallocBuffer(co
 }
 
 void
 ISurfaceAllocator::DeallocGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle)
 {
   SharedBufferManagerChild::GetSingleton()->DeallocGrallocBuffer(*aHandle);
 }
 
+void
+ISurfaceAllocator::DropGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle)
+{
+  SharedBufferManagerChild::GetSingleton()->DropGrallocBuffer(*aHandle);
+}
+
 } // namespace
 } // namespace
--- a/gfx/layers/ipc/ISurfaceAllocator.h
+++ b/gfx/layers/ipc/ISurfaceAllocator.h
@@ -158,16 +158,18 @@ public:
   // method that does the actual allocation work
   bool AllocGrallocBuffer(const gfx::IntSize& aSize,
                           uint32_t aFormat,
                           uint32_t aUsage,
                           MaybeMagicGrallocBufferHandle* aHandle);
 
   void DeallocGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle);
 
+  void DropGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle);
+
   virtual bool IPCOpen() const { return true; }
   virtual bool IsSameProcess() const = 0;
 
   virtual bool IsImageBridgeChild() const { return false; }
 
   virtual MessageLoop * GetMessageLoop() const
   {
     return mDefaultMessageLoop;
--- a/gfx/layers/ipc/SharedBufferManagerChild.cpp
+++ b/gfx/layers/ipc/SharedBufferManagerChild.cpp
@@ -312,28 +312,39 @@ SharedBufferManagerChild::DeallocGralloc
     mBuffers.erase(aBuffer.get_GrallocBufferRef().mKey);
   }
   SendDropGrallocBuffer(aBuffer);
 #else
   NS_RUNTIMEABORT("No GrallocBuffer for you");
 #endif
 }
 
-bool SharedBufferManagerChild::RecvDropGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& handle)
+void
+SharedBufferManagerChild::DropGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& aHandle)
 {
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
-  NS_ASSERTION(handle.type() == mozilla::layers::MaybeMagicGrallocBufferHandle::TGrallocBufferRef, "shouldn't go this way");
-  int64_t bufferKey = handle.get_GrallocBufferRef().mKey;
+  int64_t bufferKey = -1;
+  if (aHandle.type() == mozilla::layers::MaybeMagicGrallocBufferHandle::TMagicGrallocBufferHandle) {
+    bufferKey = aHandle.get_MagicGrallocBufferHandle().mRef.mKey;
+  } else if (aHandle.type() == mozilla::layers::MaybeMagicGrallocBufferHandle::TGrallocBufferRef) {
+    bufferKey = aHandle.get_GrallocBufferRef().mKey;
+  } else {
+    return;
+  }
 
   {
     MutexAutoLock lock(mBufferMutex);
-    NS_ASSERTION(mBuffers.count(bufferKey) != 0, "Not my buffer");
     mBuffers.erase(bufferKey);
   }
 #endif
+}
+
+bool SharedBufferManagerChild::RecvDropGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& aHandle)
+{
+  DropGrallocBuffer(aHandle);
   return true;
 }
 
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
 android::sp<android::GraphicBuffer>
 SharedBufferManagerChild::GetGraphicBuffer(int64_t key)
 {
   MutexAutoLock lock(mBufferMutex);
--- a/gfx/layers/ipc/SharedBufferManagerChild.h
+++ b/gfx/layers/ipc/SharedBufferManagerChild.h
@@ -99,17 +99,20 @@ public:
   /**
    * Deallocate a remotely allocated gralloc buffer.
    * As gralloc buffer life cycle controlled by sp, this just break the sharing status of the underlying buffer
    * and decrease the reference count on both side.
    */
   void
   DeallocGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& aBuffer);
 
-  virtual bool RecvDropGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& handle);
+  void
+  DropGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& aHandle);
+
+  virtual bool RecvDropGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& aHandle);
 
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   android::sp<android::GraphicBuffer> GetGraphicBuffer(int64_t key);
 #endif
 
   bool IsValidKey(int64_t key);
 
   base::Thread* GetThread() const;
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -42,19 +42,21 @@ GrallocTextureClientOGL::GrallocTextureC
 , mMediaBuffer(nullptr)
 {
   MOZ_COUNT_CTOR(GrallocTextureClientOGL);
 }
 
 GrallocTextureClientOGL::~GrallocTextureClientOGL()
 {
   MOZ_COUNT_DTOR(GrallocTextureClientOGL);
-    if (ShouldDeallocateInDestructor()) {
-    ISurfaceAllocator* allocator = GetAllocator();
+  ISurfaceAllocator* allocator = GetAllocator();
+  if (ShouldDeallocateInDestructor()) {
     allocator->DeallocGrallocBuffer(&mGrallocHandle);
+  } else {
+    allocator->DropGrallocBuffer(&mGrallocHandle);
   }
 }
 
 void
 GrallocTextureClientOGL::InitWith(MaybeMagicGrallocBufferHandle aHandle, gfx::IntSize aSize)
 {
   MOZ_ASSERT(!IsAllocated());
   MOZ_ASSERT(IsValid());