Chromium Code Reviews| Index: Source/platform/graphics/Canvas2DLayerManager.cpp |
| diff --git a/Source/platform/graphics/Canvas2DLayerManager.cpp b/Source/platform/graphics/Canvas2DLayerManager.cpp |
| index 5d21312a0fe0d650bd4a30b23b0142bb8c5852b3..03ab299cc5fd5e38c4cde5eea7aeab68598f794c 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,12 @@ 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(); |
|
Stephen White
2014/01/24 18:52:35
Could you add a comment here explaining why we hav
|
| + currentLayer->limitPendingFrames(); |
| + } |
| } |
| void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) |
| @@ -92,8 +98,7 @@ void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) |
| m_layerList.remove(layer); |
| m_layerList.push(layer); // Set as MRU |
| } |
| - } else |
| - addLayerToList(layer); |
| + } |
| if (!m_taskObserverActive) { |
| m_taskObserverActive = true; |
| @@ -102,48 +107,42 @@ void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) |
| } |
| } |
| -void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer) |
| -{ |
| - ASSERT(!isInList(layer)); |
| - m_bytesAllocated += layer->bytesAllocated(); |
| - m_layerList.push(layer); // Set as MRU |
| -} |
| - |
| -void Canvas2DLayerManager::layerAllocatedStorageChanged(Canvas2DLayerBridge* layer, intptr_t deltaBytes) |
| +void Canvas2DLayerManager::layerTransientResourceAllocationChanged(Canvas2DLayerBridge* layer, intptr_t deltaBytes) |
| { |
| - if (!isInList(layer)) |
| - addLayerToList(layer); |
| - else { |
| - ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0); |
| - m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes; |
| + ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0); |
| + m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes; |
| + if (!isInList(layer) && layer->hasTransientResources()) { |
| + m_layerList.push(layer); |
| + } else if (isInList(layer) && !layer->hasTransientResources()) { |
| + m_layerList.remove(layer); |
| + layer->setNext(0); |
| + layer->setPrev(0); |
| } |
| + |
| if (deltaBytes > 0) |
| freeMemoryIfNecessary(); |
| } |
| -void Canvas2DLayerManager::layerToBeDestroyed(Canvas2DLayerBridge* layer) |
| -{ |
| - if (isInList(layer)) |
| - removeLayerFromList(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()); |
| } |
| } |
| } |
| @@ -151,13 +150,11 @@ void Canvas2DLayerManager::freeMemoryIfNecessary() |
| void Canvas2DLayerManager::removeLayerFromList(Canvas2DLayerBridge* layer) |
| { |
| ASSERT(isInList(layer)); |
| - m_bytesAllocated -= layer->bytesAllocated(); |
| - m_layerList.remove(layer); |
| - layer->setNext(0); |
| - layer->setPrev(0); |
| + ASSERT(!layer->hasTransientResources()); |
| + |
| } |
| -bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer) |
| +bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer) const |
| { |
| return layer->prev() || m_layerList.head() == layer; |
| } |