| Index: Source/platform/graphics/Canvas2DLayerManager.cpp
|
| diff --git a/Source/platform/graphics/Canvas2DLayerManager.cpp b/Source/platform/graphics/Canvas2DLayerManager.cpp
|
| index 5d21312a0fe0d650bd4a30b23b0142bb8c5852b3..3e56351950b6caff5752262c4dd86ecd82eea3bd 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,14 @@ 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;
|
| + // must increment iterator before calling limitPendingFrames, which
|
| + // may result in the layer being removed from the list.
|
| + layer = layer->next();
|
| + currentLayer->limitPendingFrames();
|
| + }
|
| }
|
|
|
| void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer)
|
| @@ -92,8 +100,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 +109,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 +152,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;
|
| }
|
|
|