Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2311)

Unified Diff: Source/platform/graphics/Canvas2DLayerManager.cpp

Issue 117703004: Free temporary GPU and memory resources held by inactive or hidden 2D canvases (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: fixed upstream git branch Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/platform/graphics/Canvas2DLayerManager.cpp
diff --git a/Source/platform/graphics/Canvas2DLayerManager.cpp b/Source/platform/graphics/Canvas2DLayerManager.cpp
index 5d21312a0fe0d650bd4a30b23b0142bb8c5852b3..f020cafe4c7c7ec974bb37856781b890ea65d66a 100644
--- a/Source/platform/graphics/Canvas2DLayerManager.cpp
+++ b/Source/platform/graphics/Canvas2DLayerManager.cpp
@@ -31,11 +31,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using blink::WebThread;
namespace {
+
enum {
DefaultMaxBytesAllocated = 64*1024*1024,
DefaultTargetBytesAllocated = 16*1024*1024,
};
-}
+
+} // unnamed namespace
namespace WebCore {
@@ -81,8 +83,17 @@ void Canvas2DLayerManager::didProcessTask()
ASSERT(m_taskObserverActive);
blink::Platform::current()->currentThread()->removeTaskObserver(this);
m_taskObserverActive = false;
- for (Canvas2DLayerBridge* layer = m_layerList.head(); layer; layer = layer->next())
- layer->limitPendingFrames();
+ Canvas2DLayerBridge* layer = m_layerList.head();
+ while (layer) {
+ Canvas2DLayerBridge* currentLayer = layer;
+ layer = layer->next();
+ if (currentLayer->hidden()) {
+ currentLayer->freeTransientResources();
+ ASSERT(!isInList(currentLayer));
+ } else {
+ currentLayer->limitPendingFrames();
+ }
+ }
}
void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer)
@@ -102,6 +113,13 @@ void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer)
}
}
+void Canvas2DLayerManager::setLayerHasFreeableResources(Canvas2DLayerBridge* layer)
+{
+ if (!isInList(layer)) {
+ addLayerToList(layer);
+ }
+}
+
void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer)
{
ASSERT(!isInList(layer));
@@ -111,11 +129,14 @@ void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer)
void Canvas2DLayerManager::layerAllocatedStorageChanged(Canvas2DLayerBridge* layer, intptr_t deltaBytes)
{
- if (!isInList(layer))
+ if (!isInList(layer)) {
+ ASSERT(layer->hasTransientResources());
addLayerToList(layer);
- else {
+ } else {
ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0);
m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes;
+ if (!layer->hasTransientResources())
+ removeLayerFromList(layer);
}
if (deltaBytes > 0)
freeMemoryIfNecessary();
@@ -129,21 +150,41 @@ void Canvas2DLayerManager::layerToBeDestroyed(Canvas2DLayerBridge* layer)
void Canvas2DLayerManager::freeMemoryIfNecessary()
{
- if (m_bytesAllocated > m_maxBytesAllocated) {
+ if (m_bytesAllocated >= m_maxBytesAllocated) {
// Pass 1: Free memory from caches
Canvas2DLayerBridge* layer = m_layerList.tail(); // LRU
- while (m_bytesAllocated > m_targetBytesAllocated && layer) {
- layer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated);
+ while (layer && m_bytesAllocated > m_targetBytesAllocated) {
+ Canvas2DLayerBridge* currentLayer = layer;
layer = layer->prev();
+ currentLayer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated);
+ ASSERT(isInList(currentLayer) == currentLayer->hasTransientResources());
}
// Pass 2: Flush canvases
- Canvas2DLayerBridge* leastRecentlyUsedLayer = m_layerList.tail();
- while (m_bytesAllocated > m_targetBytesAllocated && leastRecentlyUsedLayer) {
- leastRecentlyUsedLayer->flush();
- leastRecentlyUsedLayer->freeMemoryIfPossible(~0);
- removeLayerFromList(leastRecentlyUsedLayer);
- leastRecentlyUsedLayer = m_layerList.tail();
+ layer = m_layerList.tail();
+ while (m_bytesAllocated > m_targetBytesAllocated && layer) {
+ Canvas2DLayerBridge* currentLayer = layer;
+ layer = layer->prev();
+ currentLayer->flush();
+ currentLayer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated);
+ ASSERT(isInList(currentLayer) == currentLayer->hasTransientResources());
+ }
+ }
+}
+
+void Canvas2DLayerManager::didHidePage()
+{
+ // A page that lives in this process just became hidden.
+ // Instead of traversing the page's DOMs to find its canvases,
+ // we traverse all live canvases to find those that are now hidden,
+ // which should almost always be more efficient than traversing DOMs.
+ Canvas2DLayerBridge* layer = m_layerList.head();
+ while (layer) {
+ Canvas2DLayerBridge* currentLayer = layer;
+ layer = layer->next();
+ if (currentLayer->hidden()) {
eseidel 2013/12/19 02:56:32 I'm surprised youw ant to check this "hidden" meth
+ currentLayer->freeTransientResources();
+ ASSERT(!isInList(currentLayer));
}
}
}
@@ -157,7 +198,7 @@ void Canvas2DLayerManager::removeLayerFromList(Canvas2DLayerBridge* layer)
layer->setPrev(0);
}
-bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer)
+bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer) const
{
return layer->prev() || m_layerList.head() == layer;
}

Powered by Google App Engine
This is Rietveld 408576698