From 964162adc7c707d0999dfeb0b9c8505fb389e75b Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Wed, 29 Apr 2015 11:54:04 +0800 Subject: [PATCH] Bug 1154231 - Part 1. Reclaim cached resources when memory-pressure occurs. r=mattwoodrow --- widget/PuppetWidget.cpp | 41 +++++++++++++++++++++++++++++++++++++---- widget/PuppetWidget.h | 13 +++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index 38bb9106a098..43fdcc6d3482 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -118,6 +118,11 @@ PuppetWidget::Create(nsIWidget *aParent, else { Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false); } + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + mMemoryPressureObserver = new MemoryPressureObserver(this); + obs->AddObserver(mMemoryPressureObserver, "memory-pressure", false); + } return NS_OK; } @@ -153,6 +158,9 @@ PuppetWidget::Destroy() Base::OnDestroy(); Base::Destroy(); mPaintTask.Revoke(); + if (mMemoryPressureObserver) { + mMemoryPressureObserver->Remove(); + } mChild = nullptr; if (mLayerManager) { mLayerManager->Destroy(); @@ -175,10 +183,6 @@ PuppetWidget::Show(bool aState) mChild->mVisible = aState; } - if (!mVisible && mLayerManager) { - mLayerManager->ClearCachedResources(); - } - if (!wasVisible && mVisible) { Resize(mBounds.width, mBounds.height, false); Invalidate(mBounds); @@ -1037,6 +1041,35 @@ PuppetWidget::PaintTask::Run() return NS_OK; } +NS_IMPL_ISUPPORTS(PuppetWidget::MemoryPressureObserver, nsIObserver) + +NS_IMETHODIMP +PuppetWidget::MemoryPressureObserver::Observe(nsISupports* aSubject, + const char* aTopic, + const char16_t* aData) +{ + if (!mWidget) { + return NS_OK; + } + + if (strcmp("memory-pressure", aTopic) == 0) { + if (!mWidget->mVisible && mWidget->mLayerManager) { + mWidget->mLayerManager->ClearCachedResources(); + } + } + return NS_OK; +} + +void +PuppetWidget::MemoryPressureObserver::Remove() +{ + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + obs->RemoveObserver(this, "memory-pressure"); + } + mWidget = nullptr; +} + bool PuppetWidget::NeedsPaint() { diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index 0a052982afaf..3b4f8e1112e0 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -279,6 +279,18 @@ private: PuppetWidget* mWidget; }; + class MemoryPressureObserver : public nsIObserver { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + explicit MemoryPressureObserver(PuppetWidget* aWidget) : mWidget(aWidget) {} + void Remove(); + private: + virtual ~MemoryPressureObserver() {} + PuppetWidget* mWidget; + }; + friend class MemoryPressureObserver; + // TabChild normally holds a strong reference to this PuppetWidget // or its root ancestor, but each PuppetWidget also needs a // reference back to TabChild (e.g. to delegate nsIWidget IME calls @@ -291,6 +303,7 @@ private: nsRefPtr mChild; nsIntRegion mDirtyRegion; nsRevocableEventPtr mPaintTask; + nsRefPtr mMemoryPressureObserver; // XXX/cjones: keeping this around until we teach LayerManager to do // retained-content-only transactions mozilla::RefPtr mDrawTarget;