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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 Copyright (C) 2012 Google Inc. All rights reserved. 2 Copyright (C) 2012 Google Inc. All rights reserved.
3 3
4 Redistribution and use in source and binary forms, with or without 4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions 5 modification, are permitted provided that the following conditions
6 are met: 6 are met:
7 1. Redistributions of source code must retain the above copyright 7 1. Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer. 8 notice, this list of conditions and the following disclaimer.
9 2. Redistributions in binary form must reproduce the above copyright 9 2. Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the 10 notice, this list of conditions and the following disclaimer in the
(...skipping 13 matching lines...) Expand all
24 #include "config.h" 24 #include "config.h"
25 25
26 #include "platform/graphics/Canvas2DLayerManager.h" 26 #include "platform/graphics/Canvas2DLayerManager.h"
27 27
28 #include "public/platform/Platform.h" 28 #include "public/platform/Platform.h"
29 #include "wtf/StdLibExtras.h" 29 #include "wtf/StdLibExtras.h"
30 30
31 using blink::WebThread; 31 using blink::WebThread;
32 32
33 namespace { 33 namespace {
34
34 enum { 35 enum {
35 DefaultMaxBytesAllocated = 64*1024*1024, 36 DefaultMaxBytesAllocated = 64*1024*1024,
36 DefaultTargetBytesAllocated = 16*1024*1024, 37 DefaultTargetBytesAllocated = 16*1024*1024,
37 }; 38 };
38 } 39
40 } // unnamed namespace
39 41
40 namespace WebCore { 42 namespace WebCore {
41 43
42 Canvas2DLayerManager::Canvas2DLayerManager() 44 Canvas2DLayerManager::Canvas2DLayerManager()
43 : m_bytesAllocated(0) 45 : m_bytesAllocated(0)
44 , m_maxBytesAllocated(DefaultMaxBytesAllocated) 46 , m_maxBytesAllocated(DefaultMaxBytesAllocated)
45 , m_targetBytesAllocated(DefaultTargetBytesAllocated) 47 , m_targetBytesAllocated(DefaultTargetBytesAllocated)
46 , m_taskObserverActive(false) 48 , m_taskObserverActive(false)
47 { 49 {
48 } 50 }
(...skipping 25 matching lines...) Expand all
74 void Canvas2DLayerManager::willProcessTask() 76 void Canvas2DLayerManager::willProcessTask()
75 { 77 {
76 } 78 }
77 79
78 void Canvas2DLayerManager::didProcessTask() 80 void Canvas2DLayerManager::didProcessTask()
79 { 81 {
80 // Called after the script action for the current frame has been processed. 82 // Called after the script action for the current frame has been processed.
81 ASSERT(m_taskObserverActive); 83 ASSERT(m_taskObserverActive);
82 blink::Platform::current()->currentThread()->removeTaskObserver(this); 84 blink::Platform::current()->currentThread()->removeTaskObserver(this);
83 m_taskObserverActive = false; 85 m_taskObserverActive = false;
84 for (Canvas2DLayerBridge* layer = m_layerList.head(); layer; layer = layer-> next()) 86 Canvas2DLayerBridge* layer = m_layerList.head();
85 layer->limitPendingFrames(); 87 while (layer) {
88 Canvas2DLayerBridge* currentLayer = layer;
89 layer = layer->next();
90 if (currentLayer->hidden()) {
91 currentLayer->freeTransientResources();
92 ASSERT(!isInList(currentLayer));
93 } else {
94 currentLayer->limitPendingFrames();
95 }
96 }
86 } 97 }
87 98
88 void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) 99 void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer)
89 { 100 {
90 if (isInList(layer)) { 101 if (isInList(layer)) {
91 if (layer != m_layerList.head()) { 102 if (layer != m_layerList.head()) {
92 m_layerList.remove(layer); 103 m_layerList.remove(layer);
93 m_layerList.push(layer); // Set as MRU 104 m_layerList.push(layer); // Set as MRU
94 } 105 }
95 } else 106 } else
96 addLayerToList(layer); 107 addLayerToList(layer);
97 108
98 if (!m_taskObserverActive) { 109 if (!m_taskObserverActive) {
99 m_taskObserverActive = true; 110 m_taskObserverActive = true;
100 // Schedule a call to didProcessTask() after completion of the current s cript task. 111 // Schedule a call to didProcessTask() after completion of the current s cript task.
101 blink::Platform::current()->currentThread()->addTaskObserver(this); 112 blink::Platform::current()->currentThread()->addTaskObserver(this);
102 } 113 }
103 } 114 }
104 115
116 void Canvas2DLayerManager::setLayerHasFreeableResources(Canvas2DLayerBridge* lay er)
117 {
118 if (!isInList(layer)) {
119 addLayerToList(layer);
120 }
121 }
122
105 void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer) 123 void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer)
106 { 124 {
107 ASSERT(!isInList(layer)); 125 ASSERT(!isInList(layer));
108 m_bytesAllocated += layer->bytesAllocated(); 126 m_bytesAllocated += layer->bytesAllocated();
109 m_layerList.push(layer); // Set as MRU 127 m_layerList.push(layer); // Set as MRU
110 } 128 }
111 129
112 void Canvas2DLayerManager::layerAllocatedStorageChanged(Canvas2DLayerBridge* lay er, intptr_t deltaBytes) 130 void Canvas2DLayerManager::layerAllocatedStorageChanged(Canvas2DLayerBridge* lay er, intptr_t deltaBytes)
113 { 131 {
114 if (!isInList(layer)) 132 if (!isInList(layer)) {
133 ASSERT(layer->hasTransientResources());
115 addLayerToList(layer); 134 addLayerToList(layer);
116 else { 135 } else {
117 ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0); 136 ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0);
118 m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes; 137 m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes;
138 if (!layer->hasTransientResources())
139 removeLayerFromList(layer);
119 } 140 }
120 if (deltaBytes > 0) 141 if (deltaBytes > 0)
121 freeMemoryIfNecessary(); 142 freeMemoryIfNecessary();
122 } 143 }
123 144
124 void Canvas2DLayerManager::layerToBeDestroyed(Canvas2DLayerBridge* layer) 145 void Canvas2DLayerManager::layerToBeDestroyed(Canvas2DLayerBridge* layer)
125 { 146 {
126 if (isInList(layer)) 147 if (isInList(layer))
127 removeLayerFromList(layer); 148 removeLayerFromList(layer);
128 } 149 }
129 150
130 void Canvas2DLayerManager::freeMemoryIfNecessary() 151 void Canvas2DLayerManager::freeMemoryIfNecessary()
131 { 152 {
132 if (m_bytesAllocated > m_maxBytesAllocated) { 153 if (m_bytesAllocated >= m_maxBytesAllocated) {
133 // Pass 1: Free memory from caches 154 // Pass 1: Free memory from caches
134 Canvas2DLayerBridge* layer = m_layerList.tail(); // LRU 155 Canvas2DLayerBridge* layer = m_layerList.tail(); // LRU
135 while (m_bytesAllocated > m_targetBytesAllocated && layer) { 156 while (layer && m_bytesAllocated > m_targetBytesAllocated) {
136 layer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocate d); 157 Canvas2DLayerBridge* currentLayer = layer;
137 layer = layer->prev(); 158 layer = layer->prev();
159 currentLayer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesA llocated);
160 ASSERT(isInList(currentLayer) == currentLayer->hasTransientResources ());
138 } 161 }
139 162
140 // Pass 2: Flush canvases 163 // Pass 2: Flush canvases
141 Canvas2DLayerBridge* leastRecentlyUsedLayer = m_layerList.tail(); 164 layer = m_layerList.tail();
142 while (m_bytesAllocated > m_targetBytesAllocated && leastRecentlyUsedLay er) { 165 while (m_bytesAllocated > m_targetBytesAllocated && layer) {
143 leastRecentlyUsedLayer->flush(); 166 Canvas2DLayerBridge* currentLayer = layer;
144 leastRecentlyUsedLayer->freeMemoryIfPossible(~0); 167 layer = layer->prev();
145 removeLayerFromList(leastRecentlyUsedLayer); 168 currentLayer->flush();
146 leastRecentlyUsedLayer = m_layerList.tail(); 169 currentLayer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesA llocated);
170 ASSERT(isInList(currentLayer) == currentLayer->hasTransientResources ());
147 } 171 }
148 } 172 }
149 } 173 }
174
175 void Canvas2DLayerManager::didHidePage()
176 {
177 // A page that lives in this process just became hidden.
178 // Instead of traversing the page's DOMs to find its canvases,
179 // we traverse all live canvases to find those that are now hidden,
180 // which should almost always be more efficient than traversing DOMs.
181 Canvas2DLayerBridge* layer = m_layerList.head();
182 while (layer) {
183 Canvas2DLayerBridge* currentLayer = layer;
184 layer = layer->next();
185 if (currentLayer->hidden()) {
eseidel 2013/12/19 02:56:32 I'm surprised youw ant to check this "hidden" meth
186 currentLayer->freeTransientResources();
187 ASSERT(!isInList(currentLayer));
188 }
189 }
190 }
150 191
151 void Canvas2DLayerManager::removeLayerFromList(Canvas2DLayerBridge* layer) 192 void Canvas2DLayerManager::removeLayerFromList(Canvas2DLayerBridge* layer)
152 { 193 {
153 ASSERT(isInList(layer)); 194 ASSERT(isInList(layer));
154 m_bytesAllocated -= layer->bytesAllocated(); 195 m_bytesAllocated -= layer->bytesAllocated();
155 m_layerList.remove(layer); 196 m_layerList.remove(layer);
156 layer->setNext(0); 197 layer->setNext(0);
157 layer->setPrev(0); 198 layer->setPrev(0);
158 } 199 }
159 200
160 bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer) 201 bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer) const
161 { 202 {
162 return layer->prev() || m_layerList.head() == layer; 203 return layer->prev() || m_layerList.head() == layer;
163 } 204 }
164 205
165 } 206 }
166 207
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698