Bug 1262328 - Add Add ClientLayer::HandleMemoryPressure() r=nical
authorSotaro Ikeda <sotaro.ikeda.g@gmail.com>
Wed, 06 Apr 2016 18:44:05 -0700
changeset 315771 ab62a777c115ca638278771925f27921675b9efd
parent 315770 dba6ae0abf3aea49900f24f239b9d2fc19b00685
child 315772 4f662b15f40b63818e4c0bf707c434f82321deb4
push id9480
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 17:12:58 +0000
treeherdermozilla-aurora@0d6a91c76a9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1262328
milestone48.0a1
Bug 1262328 - Add Add ClientLayer::HandleMemoryPressure() r=nical
gfx/layers/client/ClientCanvasLayer.h
gfx/layers/client/ClientImageLayer.cpp
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/ClientLayerManager.h
gfx/layers/client/ClientPaintedLayer.h
gfx/layers/client/ClientTiledPaintedLayer.h
gfx/layers/client/CompositableClient.cpp
gfx/layers/client/CompositableClient.h
gfx/layers/client/TextureClientRecycleAllocator.cpp
gfx/layers/client/TextureClientRecycleAllocator.h
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -57,16 +57,23 @@ public:
 
   virtual void ClearCachedResources() override
   {
     if (mCanvasClient) {
       mCanvasClient->Clear();
     }
   }
 
+  virtual void HandleMemoryPressure() override
+  {
+    if (mCanvasClient) {
+      mCanvasClient->HandleMemoryPressure();
+    }
+  }
+
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override
   {
     aAttrs = CanvasLayerAttributes(mFilter, mBounds);
   }
 
   virtual Layer* AsLayer()  override { return this; }
   virtual ShadowableLayer* AsShadowableLayer()  override { return this; }
 
--- a/gfx/layers/client/ClientImageLayer.cpp
+++ b/gfx/layers/client/ClientImageLayer.cpp
@@ -55,16 +55,23 @@ protected:
 
   virtual void RenderLayer() override;
   
   virtual void ClearCachedResources() override
   {
     DestroyBackBuffer();
   }
 
+  virtual void HandleMemoryPressure() override
+  {
+    if (mImageClient) {
+      mImageClient->HandleMemoryPressure();
+    }
+  }
+
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override
   {
     aAttrs = ImageLayerAttributes(mFilter, mScaleToSize, mScaleMode);
   }
 
   virtual Layer* AsLayer() override { return this; }
   virtual ShadowableLayer* AsShadowableLayer() override { return this; }
 
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -742,32 +742,46 @@ ClientLayerManager::ClearCachedResources
   for (size_t i = 0; i < mTexturePools.Length(); i++) {
     mTexturePools[i]->Clear();
   }
 }
 
 void
 ClientLayerManager::HandleMemoryPressure()
 {
+  if (mRoot) {
+    HandleMemoryPressureLayer(mRoot);
+  }
+
   for (size_t i = 0; i < mTexturePools.Length(); i++) {
     mTexturePools[i]->ShrinkToMinimumSize();
   }
 }
 
 void
 ClientLayerManager::ClearLayer(Layer* aLayer)
 {
   ClientLayer::ToClientLayer(aLayer)->ClearCachedResources();
   for (Layer* child = aLayer->GetFirstChild(); child;
        child = child->GetNextSibling()) {
     ClearLayer(child);
   }
 }
 
 void
+ClientLayerManager::HandleMemoryPressureLayer(Layer* aLayer)
+{
+  ClientLayer::ToClientLayer(aLayer)->HandleMemoryPressure();
+  for (Layer* child = aLayer->GetFirstChild(); child;
+       child = child->GetNextSibling()) {
+    HandleMemoryPressureLayer(child);
+  }
+}
+
+void
 ClientLayerManager::GetBackendName(nsAString& aName)
 {
   switch (mForwarder->GetCompositorBackendType()) {
     case LayersBackend::LAYERS_NONE: aName.AssignLiteral("None"); return;
     case LayersBackend::LAYERS_BASIC: aName.AssignLiteral("Basic"); return;
     case LayersBackend::LAYERS_OPENGL: aName.AssignLiteral("OpenGL"); return;
     case LayersBackend::LAYERS_D3D9: aName.AssignLiteral("Direct3D 9"); return;
     case LayersBackend::LAYERS_D3D11: {
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -294,16 +294,18 @@ private:
   /**
    * Take a snapshot of the parent context, and copy
    * it into mShadowTarget.
    */
   void MakeSnapshotIfRequired();
 
   void ClearLayer(Layer* aLayer);
 
+  void HandleMemoryPressureLayer(Layer* aLayer);
+
   bool EndTransactionInternal(DrawPaintedLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags);
 
   bool DependsOnStaleDevice() const;
 
   LayerRefArray mKeepAlive;
 
@@ -381,16 +383,20 @@ public:
     // automatically managed by IPDL, so we don't need to explicitly
     // free them here (it's hard to get that right on emergency
     // shutdown anyway).
     mShadow = nullptr;
   }
 
   virtual void ClearCachedResources() { }
 
+  // Shrink memory usage.
+  // Called when "memory-pressure" is observed.
+  virtual void HandleMemoryPressure() { }
+
   virtual void RenderLayer() = 0;
   virtual void RenderLayerWithReadback(ReadbackProcessor *aReadback) { RenderLayer(); }
 
   virtual ClientPaintedLayer* AsThebes() { return nullptr; }
 
   static inline ClientLayer *
   ToClientLayer(Layer* aLayer)
   {
--- a/gfx/layers/client/ClientPaintedLayer.h
+++ b/gfx/layers/client/ClientPaintedLayer.h
@@ -72,17 +72,24 @@ public:
   virtual void ClearCachedResources() override
   {
     if (mContentClient) {
       mContentClient->Clear();
     }
     mValidRegion.SetEmpty();
     DestroyBackBuffer();
   }
-  
+
+  virtual void HandleMemoryPressure() override
+  {
+    if (mContentClient) {
+      mContentClient->HandleMemoryPressure();
+    }
+  }
+
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override
   {
     aAttrs = PaintedLayerAttributes(GetValidRegion());
   }
   
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
--- a/gfx/layers/client/ClientTiledPaintedLayer.h
+++ b/gfx/layers/client/ClientTiledPaintedLayer.h
@@ -68,16 +68,23 @@ public:
   {
     ClientLayer::Disconnect();
   }
 
   virtual void RenderLayer() override;
 
   virtual void ClearCachedResources() override;
 
+  virtual void HandleMemoryPressure() override
+  {
+    if (mContentClient) {
+      mContentClient->HandleMemoryPressure();
+    }
+  }
+
   /**
    * Helper method to find the nearest ancestor layers which
    * scroll and have a displayport. The parameters are out-params
    * which hold the return values; the values passed in may be null.
    */
   void GetAncestorLayers(LayerMetricsWrapper* aOutScrollAncestor,
                          LayerMetricsWrapper* aOutDisplayPortAncestor,
                          bool* aOutHasTransformAnimation);
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -238,17 +238,25 @@ CompositableClient::AddTextureClient(Tex
   aClient->SetAddedToCompositableClient();
   return aClient->InitIPDLActor(mForwarder);
 }
 
 void
 CompositableClient::ClearCachedResources()
 {
   if (mTextureClientRecycler) {
-    mTextureClientRecycler = nullptr;
+    mTextureClientRecycler->ShrinkToMinimumSize();
+  }
+}
+
+void
+CompositableClient::HandleMemoryPressure()
+{
+  if (mTextureClientRecycler) {
+    mTextureClientRecycler->ShrinkToMinimumSize();
   }
 }
 
 void
 CompositableClient::RemoveTexture(TextureClient* aTexture)
 {
   mForwarder->RemoveTextureFromCompositable(this, aTexture);
 }
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -191,16 +191,22 @@ public:
 
   /**
    * Clear any resources that are not immediately necessary. This may be called
    * in low-memory conditions.
    */
   virtual void ClearCachedResources();
 
   /**
+   * Shrink memory usage.
+   * Called when "memory-pressure" is observed.
+   */
+  virtual void HandleMemoryPressure();
+
+  /**
    * Should be called when deataching a TextureClient from a Compositable, because
    * some platforms need to do some extra book keeping when this happens (for
    * example to properly keep track of fences on Gonk).
    *
    * See AutoRemoveTexture to automatically invoke this at the end of a scope.
    */
   virtual void RemoveTexture(TextureClient* aTexture);
 
--- a/gfx/layers/client/TextureClientRecycleAllocator.cpp
+++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp
@@ -190,16 +190,25 @@ TextureClientRecycleAllocator::Allocate(
                                         TextureFlags aTextureFlags,
                                         TextureAllocationFlags aAllocFlags)
 {
   return TextureClient::CreateForDrawing(mSurfaceAllocator, aFormat, aSize, aSelector,
                                          aTextureFlags, aAllocFlags);
 }
 
 void
+TextureClientRecycleAllocator::ShrinkToMinimumSize()
+{
+  MutexAutoLock lock(mLock);
+  while (!mPooledClients.empty()) {
+    mPooledClients.pop();
+  }
+}
+
+void
 TextureClientRecycleAllocator::RecycleTextureClient(TextureClient* aClient)
 {
   // Clearing the recycle allocator drops a reference, so make sure we stay alive
   // for the duration of this function.
   RefPtr<TextureClientRecycleAllocator> kungFuDeathGrip(this);
   aClient->SetRecycleAllocator(nullptr);
 
   RefPtr<TextureClientHolder> textureHolder;
--- a/gfx/layers/client/TextureClientRecycleAllocator.h
+++ b/gfx/layers/client/TextureClientRecycleAllocator.h
@@ -81,16 +81,18 @@ public:
                   gfx::IntSize aSize,
                   BackendSelector aSelector,
                   TextureFlags aTextureFlags,
                   TextureAllocationFlags flags = ALLOC_DEFAULT);
 
   already_AddRefed<TextureClient>
   CreateOrRecycle(ITextureClientAllocationHelper& aHelper);
 
+  void ShrinkToMinimumSize();
+
 protected:
   virtual already_AddRefed<TextureClient>
   Allocate(gfx::SurfaceFormat aFormat,
            gfx::IntSize aSize,
            BackendSelector aSelector,
            TextureFlags aTextureFlags,
            TextureAllocationFlags aAllocFlags);