OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "platform/graphics/paint/DisplayItemList.h" | 6 #include "platform/graphics/paint/PaintController.h" |
7 | 7 |
8 #include "platform/NotImplemented.h" | 8 #include "platform/NotImplemented.h" |
9 #include "platform/TraceEvent.h" | 9 #include "platform/TraceEvent.h" |
10 #include "platform/graphics/GraphicsLayer.h" | 10 #include "platform/graphics/GraphicsLayer.h" |
11 #include "platform/graphics/paint/DrawingDisplayItem.h" | 11 #include "platform/graphics/paint/DrawingDisplayItem.h" |
12 | 12 |
13 #ifndef NDEBUG | 13 #ifndef NDEBUG |
14 #include "platform/graphics/LoggingCanvas.h" | 14 #include "platform/graphics/LoggingCanvas.h" |
15 #include "wtf/text/StringBuilder.h" | 15 #include "wtf/text/StringBuilder.h" |
16 #include <stdio.h> | 16 #include <stdio.h> |
17 #endif | 17 #endif |
18 | 18 |
19 namespace blink { | 19 namespace blink { |
20 | 20 |
21 const PaintArtifact& DisplayItemList::paintArtifact() const | 21 const PaintArtifact& PaintController::paintArtifact() const |
22 { | 22 { |
23 ASSERT(m_newDisplayItems.isEmpty()); | 23 ASSERT(m_newDisplayItems.isEmpty()); |
24 ASSERT(m_newPaintChunks.isInInitialState()); | 24 ASSERT(m_newPaintChunks.isInInitialState()); |
25 return m_currentPaintArtifact; | 25 return m_currentPaintArtifact; |
26 } | 26 } |
27 | 27 |
28 bool DisplayItemList::lastDisplayItemIsNoopBegin() const | 28 bool PaintController::lastDisplayItemIsNoopBegin() const |
29 { | 29 { |
30 if (m_newDisplayItems.isEmpty()) | 30 if (m_newDisplayItems.isEmpty()) |
31 return false; | 31 return false; |
32 | 32 |
33 const auto& lastDisplayItem = m_newDisplayItems.last(); | 33 const auto& lastDisplayItem = m_newDisplayItems.last(); |
34 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); | 34 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); |
35 } | 35 } |
36 | 36 |
37 void DisplayItemList::removeLastDisplayItem() | 37 void PaintController::removeLastDisplayItem() |
38 { | 38 { |
39 if (m_newDisplayItems.isEmpty()) | 39 if (m_newDisplayItems.isEmpty()) |
40 return; | 40 return; |
41 | 41 |
42 #if ENABLE(ASSERT) | 42 #if ENABLE(ASSERT) |
43 // Also remove the index pointing to the removed display item. | 43 // Also remove the index pointing to the removed display item. |
44 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient
.find(m_newDisplayItems.last().client()); | 44 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient
.find(m_newDisplayItems.last().client()); |
45 if (it != m_newDisplayItemIndicesByClient.end()) { | 45 if (it != m_newDisplayItemIndicesByClient.end()) { |
46 Vector<size_t>& indices = it->value; | 46 Vector<size_t>& indices = it->value; |
47 if (!indices.isEmpty() && indices.last() == (m_newDisplayItems.size() -
1)) | 47 if (!indices.isEmpty() && indices.last() == (m_newDisplayItems.size() -
1)) |
48 indices.removeLast(); | 48 indices.removeLast(); |
49 } | 49 } |
50 #endif | 50 #endif |
51 m_newDisplayItems.removeLast(); | 51 m_newDisplayItems.removeLast(); |
52 | 52 |
53 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 53 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
54 m_newPaintChunks.decrementDisplayItemIndex(); | 54 m_newPaintChunks.decrementDisplayItemIndex(); |
55 } | 55 } |
56 | 56 |
57 void DisplayItemList::processNewItem(DisplayItem& displayItem) | 57 void PaintController::processNewItem(DisplayItem& displayItem) |
58 { | 58 { |
59 ASSERT(!m_constructionDisabled); | 59 ASSERT(!m_constructionDisabled); |
60 ASSERT(!skippingCache() || !displayItem.isCached()); | 60 ASSERT(!skippingCache() || !displayItem.isCached()); |
61 | 61 |
62 if (displayItem.isCached()) | 62 if (displayItem.isCached()) |
63 ++m_numCachedItems; | 63 ++m_numCachedItems; |
64 | 64 |
65 #if ENABLE(ASSERT) | 65 #if ENABLE(ASSERT) |
66 // Verify noop begin/end pairs have been removed. | 66 // Verify noop begin/end pairs have been removed. |
67 if (m_newDisplayItems.size() >= 2 && displayItem.isEnd()) { | 67 if (m_newDisplayItems.size() >= 2 && displayItem.isEnd()) { |
(...skipping 19 matching lines...) Expand all Loading... |
87 addItemToIndexIfNeeded(displayItem, m_newDisplayItems.size() - 1, m_newDispl
ayItemIndicesByClient); | 87 addItemToIndexIfNeeded(displayItem, m_newDisplayItems.size() - 1, m_newDispl
ayItemIndicesByClient); |
88 #endif // ENABLE(ASSERT) | 88 #endif // ENABLE(ASSERT) |
89 | 89 |
90 if (skippingCache()) | 90 if (skippingCache()) |
91 displayItem.setSkippedCache(); | 91 displayItem.setSkippedCache(); |
92 | 92 |
93 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 93 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
94 m_newPaintChunks.incrementDisplayItemIndex(); | 94 m_newPaintChunks.incrementDisplayItemIndex(); |
95 } | 95 } |
96 | 96 |
97 void DisplayItemList::updateCurrentPaintChunkProperties(const PaintChunkProperti
es& newProperties) | 97 void PaintController::updateCurrentPaintChunkProperties(const PaintChunkProperti
es& newProperties) |
98 { | 98 { |
99 m_newPaintChunks.updateCurrentPaintChunkProperties(newProperties); | 99 m_newPaintChunks.updateCurrentPaintChunkProperties(newProperties); |
100 } | 100 } |
101 | 101 |
102 void DisplayItemList::beginScope() | 102 void PaintController::beginScope() |
103 { | 103 { |
104 ASSERT_WITH_SECURITY_IMPLICATION(m_nextScope < UINT_MAX); | 104 ASSERT_WITH_SECURITY_IMPLICATION(m_nextScope < UINT_MAX); |
105 m_scopeStack.append(m_nextScope++); | 105 m_scopeStack.append(m_nextScope++); |
106 beginSkippingCache(); | 106 beginSkippingCache(); |
107 } | 107 } |
108 | 108 |
109 void DisplayItemList::endScope() | 109 void PaintController::endScope() |
110 { | 110 { |
111 m_scopeStack.removeLast(); | 111 m_scopeStack.removeLast(); |
112 endSkippingCache(); | 112 endSkippingCache(); |
113 } | 113 } |
114 | 114 |
115 void DisplayItemList::invalidate(const DisplayItemClientWrapper& client, PaintIn
validationReason paintInvalidationReason, const IntRect& previousPaintInvalidati
onRect, const IntRect& newPaintInvalidationRect) | 115 void PaintController::invalidate(const DisplayItemClientWrapper& client, PaintIn
validationReason paintInvalidationReason, const IntRect& previousPaintInvalidati
onRect, const IntRect& newPaintInvalidationRect) |
116 { | 116 { |
117 invalidateClient(client); | 117 invalidateClient(client); |
118 | 118 |
119 if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) { | 119 if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) { |
120 Invalidation invalidation = { previousPaintInvalidationRect, paintInvali
dationReason }; | 120 Invalidation invalidation = { previousPaintInvalidationRect, paintInvali
dationReason }; |
121 if (!previousPaintInvalidationRect.isEmpty()) | 121 if (!previousPaintInvalidationRect.isEmpty()) |
122 m_invalidations.append(invalidation); | 122 m_invalidations.append(invalidation); |
123 if (newPaintInvalidationRect != previousPaintInvalidationRect && !newPai
ntInvalidationRect.isEmpty()) { | 123 if (newPaintInvalidationRect != previousPaintInvalidationRect && !newPai
ntInvalidationRect.isEmpty()) { |
124 invalidation.rect = newPaintInvalidationRect; | 124 invalidation.rect = newPaintInvalidationRect; |
125 m_invalidations.append(invalidation); | 125 m_invalidations.append(invalidation); |
126 } | 126 } |
127 } | 127 } |
128 } | 128 } |
129 | 129 |
130 void DisplayItemList::invalidateClient(const DisplayItemClientWrapper& client) | 130 void PaintController::invalidateClient(const DisplayItemClientWrapper& client) |
131 { | 131 { |
132 invalidateUntracked(client.displayItemClient()); | 132 invalidateUntracked(client.displayItemClient()); |
133 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali
dationObjects) | 133 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali
dationObjects) |
134 m_trackedPaintInvalidationObjects->append(client.debugName()); | 134 m_trackedPaintInvalidationObjects->append(client.debugName()); |
135 } | 135 } |
136 | 136 |
137 void DisplayItemList::invalidateUntracked(DisplayItemClient client) | 137 void PaintController::invalidateUntracked(DisplayItemClient client) |
138 { | 138 { |
139 // This can be called during painting, but we can't invalidate already paint
ed clients. | 139 // This can be called during painting, but we can't invalidate already paint
ed clients. |
140 ASSERT(!m_newDisplayItemIndicesByClient.contains(client)); | 140 ASSERT(!m_newDisplayItemIndicesByClient.contains(client)); |
141 updateValidlyCachedClientsIfNeeded(); | 141 updateValidlyCachedClientsIfNeeded(); |
142 m_validlyCachedClients.remove(client); | 142 m_validlyCachedClients.remove(client); |
143 } | 143 } |
144 | 144 |
145 void DisplayItemList::invalidateAll() | 145 void PaintController::invalidateAll() |
146 { | 146 { |
147 // Can only be called during layout/paintInvalidation, not during painting. | 147 // Can only be called during layout/paintInvalidation, not during painting. |
148 ASSERT(m_newDisplayItems.isEmpty()); | 148 ASSERT(m_newDisplayItems.isEmpty()); |
149 m_currentPaintArtifact.reset(); | 149 m_currentPaintArtifact.reset(); |
150 m_validlyCachedClients.clear(); | 150 m_validlyCachedClients.clear(); |
151 m_validlyCachedClientsDirty = false; | 151 m_validlyCachedClientsDirty = false; |
152 | 152 |
153 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali
dationObjects) | 153 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali
dationObjects) |
154 m_trackedPaintInvalidationObjects->append("##ALL##"); | 154 m_trackedPaintInvalidationObjects->append("##ALL##"); |
155 } | 155 } |
156 | 156 |
157 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const | 157 bool PaintController::clientCacheIsValid(DisplayItemClient client) const |
158 { | 158 { |
159 if (skippingCache()) | 159 if (skippingCache()) |
160 return false; | 160 return false; |
161 updateValidlyCachedClientsIfNeeded(); | 161 updateValidlyCachedClientsIfNeeded(); |
162 return m_validlyCachedClients.contains(client); | 162 return m_validlyCachedClients.contains(client); |
163 } | 163 } |
164 | 164 |
165 void DisplayItemList::invalidatePaintOffset(const DisplayItemClientWrapper& clie
nt) | 165 void PaintController::invalidatePaintOffset(const DisplayItemClientWrapper& clie
nt) |
166 { | 166 { |
167 ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled()); | 167 ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled()); |
168 invalidateClient(client); | 168 invalidateClient(client); |
169 | 169 |
170 #if ENABLE(ASSERT) | 170 #if ENABLE(ASSERT) |
171 ASSERT(!paintOffsetWasInvalidated(client.displayItemClient())); | 171 ASSERT(!paintOffsetWasInvalidated(client.displayItemClient())); |
172 m_clientsWithPaintOffsetInvalidations.add(client.displayItemClient()); | 172 m_clientsWithPaintOffsetInvalidations.add(client.displayItemClient()); |
173 #endif | 173 #endif |
174 } | 174 } |
175 | 175 |
176 #if ENABLE(ASSERT) | 176 #if ENABLE(ASSERT) |
177 bool DisplayItemList::paintOffsetWasInvalidated(DisplayItemClient client) const | 177 bool PaintController::paintOffsetWasInvalidated(DisplayItemClient client) const |
178 { | 178 { |
179 ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled()); | 179 ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled()); |
180 return m_clientsWithPaintOffsetInvalidations.contains(client); | 180 return m_clientsWithPaintOffsetInvalidations.contains(client); |
181 } | 181 } |
182 #endif | 182 #endif |
183 | 183 |
184 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, con
st DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItems
& list) | 184 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con
st DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItems
& list) |
185 { | 185 { |
186 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien
t.find(id.client); | 186 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien
t.find(id.client); |
187 if (it == displayItemIndicesByClient.end()) | 187 if (it == displayItemIndicesByClient.end()) |
188 return kNotFound; | 188 return kNotFound; |
189 | 189 |
190 const Vector<size_t>& indices = it->value; | 190 const Vector<size_t>& indices = it->value; |
191 for (size_t index : indices) { | 191 for (size_t index : indices) { |
192 const DisplayItem& existingItem = list[index]; | 192 const DisplayItem& existingItem = list[index]; |
193 ASSERT(!existingItem.isValid() || existingItem.client() == id.client); | 193 ASSERT(!existingItem.isValid() || existingItem.client() == id.client); |
194 if (existingItem.isValid() && id.matches(existingItem)) | 194 if (existingItem.isValid() && id.matches(existingItem)) |
195 return index; | 195 return index; |
196 } | 196 } |
197 | 197 |
198 return kNotFound; | 198 return kNotFound; |
199 } | 199 } |
200 | 200 |
201 void DisplayItemList::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz
e_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) | 201 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz
e_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
202 { | 202 { |
203 if (!displayItem.isCacheable()) | 203 if (!displayItem.isCacheable()) |
204 return; | 204 return; |
205 | 205 |
206 DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find
(displayItem.client()); | 206 DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find
(displayItem.client()); |
207 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? | 207 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? |
208 displayItemIndicesByClient.add(displayItem.client(), Vector<size_t>()).s
toredValue->value : it->value; | 208 displayItemIndicesByClient.add(displayItem.client(), Vector<size_t>()).s
toredValue->value : it->value; |
209 indices.append(index); | 209 indices.append(index); |
210 } | 210 } |
211 | 211 |
212 struct DisplayItemList::OutOfOrderIndexContext { | 212 struct PaintController::OutOfOrderIndexContext { |
213 OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin
) { } | 213 OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin
) { } |
214 | 214 |
215 DisplayItems::iterator nextItemToIndex; | 215 DisplayItems::iterator nextItemToIndex; |
216 DisplayItemIndicesByClientMap displayItemIndicesByClient; | 216 DisplayItemIndicesByClientMap displayItemIndicesByClient; |
217 }; | 217 }; |
218 | 218 |
219 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(const DisplayIt
em::Id& id, OutOfOrderIndexContext& context) | 219 DisplayItems::iterator PaintController::findOutOfOrderCachedItem(const DisplayIt
em::Id& id, OutOfOrderIndexContext& context) |
220 { | 220 { |
221 ASSERT(clientCacheIsValid(id.client)); | 221 ASSERT(clientCacheIsValid(id.client)); |
222 | 222 |
223 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices
ByClient, m_currentPaintArtifact.displayItems()); | 223 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices
ByClient, m_currentPaintArtifact.displayItems()); |
224 if (foundIndex != kNotFound) | 224 if (foundIndex != kNotFound) |
225 return m_currentPaintArtifact.displayItems().begin() + foundIndex; | 225 return m_currentPaintArtifact.displayItems().begin() + foundIndex; |
226 | 226 |
227 return findOutOfOrderCachedItemForward(id, context); | 227 return findOutOfOrderCachedItemForward(id, context); |
228 } | 228 } |
229 | 229 |
230 // Find forward for the item and index all skipped indexable items. | 230 // Find forward for the item and index all skipped indexable items. |
231 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const Di
splayItem::Id& id, OutOfOrderIndexContext& context) | 231 DisplayItems::iterator PaintController::findOutOfOrderCachedItemForward(const Di
splayItem::Id& id, OutOfOrderIndexContext& context) |
232 { | 232 { |
233 DisplayItems::iterator currentEnd = m_currentPaintArtifact.displayItems().en
d(); | 233 DisplayItems::iterator currentEnd = m_currentPaintArtifact.displayItems().en
d(); |
234 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { | 234 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { |
235 const DisplayItem& item = *context.nextItemToIndex; | 235 const DisplayItem& item = *context.nextItemToIndex; |
236 ASSERT(item.isValid()); | 236 ASSERT(item.isValid()); |
237 if (item.isCacheable() && clientCacheIsValid(item.client())) { | 237 if (item.isCacheable() && clientCacheIsValid(item.client())) { |
238 if (id.matches(item)) | 238 if (id.matches(item)) |
239 return context.nextItemToIndex++; | 239 return context.nextItemToIndex++; |
240 | 240 |
241 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPain
tArtifact.displayItems().begin(), context.displayItemIndicesByClient); | 241 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPain
tArtifact.displayItems().begin(), context.displayItemIndicesByClient); |
242 } | 242 } |
243 } | 243 } |
244 return currentEnd; | 244 return currentEnd; |
245 } | 245 } |
246 | 246 |
247 void DisplayItemList::copyCachedSubsequence(DisplayItems::iterator& currentIt, D
isplayItems& updatedList) | 247 void PaintController::copyCachedSubsequence(DisplayItems::iterator& currentIt, D
isplayItems& updatedList) |
248 { | 248 { |
249 ASSERT(currentIt->isSubsequence()); | 249 ASSERT(currentIt->isSubsequence()); |
250 ASSERT(!currentIt->scope()); | 250 ASSERT(!currentIt->scope()); |
251 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::subsequen
ceTypeToEndSubsequenceType(currentIt->type()), 0); | 251 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::subsequen
ceTypeToEndSubsequenceType(currentIt->type()), 0); |
252 do { | 252 do { |
253 // We should always find the EndSubsequence display item. | 253 // We should always find the EndSubsequence display item. |
254 ASSERT(currentIt != m_currentPaintArtifact.displayItems().end()); | 254 ASSERT(currentIt != m_currentPaintArtifact.displayItems().end()); |
255 ASSERT(currentIt->isValid()); | 255 ASSERT(currentIt->isValid()); |
256 updatedList.appendByMoving(*currentIt); | 256 updatedList.appendByMoving(*currentIt); |
257 ++currentIt; | 257 ++currentIt; |
258 } while (!endSubsequenceId.matches(updatedList.last())); | 258 } while (!endSubsequenceId.matches(updatedList.last())); |
259 } | 259 } |
260 | 260 |
261 // Update the existing display items by removing invalidated entries, updating | 261 // Update the existing display items by removing invalidated entries, updating |
262 // repainted ones, and appending new items. | 262 // repainted ones, and appending new items. |
263 // - For cached drawing display item, copy the corresponding cached DrawingDispl
ayItem; | 263 // - For cached drawing display item, copy the corresponding cached DrawingDispl
ayItem; |
264 // - For cached subsequence display item, copy the cached display items between
the | 264 // - For cached subsequence display item, copy the cached display items between
the |
265 // corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.); | 265 // corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.); |
266 // - Otherwise, copy the new display item. | 266 // - Otherwise, copy the new display item. |
267 // | 267 // |
268 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|). | 268 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|). |
269 // Coefficients are related to the ratio of out-of-order CachedDisplayItems | 269 // Coefficients are related to the ratio of out-of-order CachedDisplayItems |
270 // and the average number of (Drawing|Subsequence)DisplayItems per client. | 270 // and the average number of (Drawing|Subsequence)DisplayItems per client. |
271 // | 271 // |
272 void DisplayItemList::commitNewDisplayItems(GraphicsLayer* graphicsLayer) | 272 void PaintController::commitNewDisplayItems(GraphicsLayer* graphicsLayer) |
273 { | 273 { |
274 TRACE_EVENT2("blink,benchmark", "DisplayItemList::commitNewDisplayItems", | 274 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", |
275 "current_display_list_size", (int)m_currentPaintArtifact.displayItems().
size(), | 275 "current_display_list_size", (int)m_currentPaintArtifact.displayItems().
size(), |
276 "num_non_cached_new_items", (int)m_newDisplayItems.size() - m_numCachedI
tems); | 276 "num_non_cached_new_items", (int)m_newDisplayItems.size() - m_numCachedI
tems); |
277 | 277 |
278 if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) { | 278 if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) { |
279 for (const auto& invalidation : m_invalidations) | 279 for (const auto& invalidation : m_invalidations) |
280 graphicsLayer->setNeedsDisplayInRect(invalidation.rect, invalidation
.invalidationReason); | 280 graphicsLayer->setNeedsDisplayInRect(invalidation.rect, invalidation
.invalidationReason); |
281 m_invalidations.clear(); | 281 m_invalidations.clear(); |
282 m_clientsCheckedPaintInvalidation.clear(); | 282 m_clientsCheckedPaintInvalidation.clear(); |
283 } | 283 } |
284 | 284 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 // TODO(jbroman): When subsequence caching applies to SPv2, we'll need to | 382 // TODO(jbroman): When subsequence caching applies to SPv2, we'll need to |
383 // merge the paint chunks as well. | 383 // merge the paint chunks as well. |
384 m_currentPaintArtifact.displayItems().swap(updatedList); | 384 m_currentPaintArtifact.displayItems().swap(updatedList); |
385 m_currentPaintArtifact.paintChunks() = m_newPaintChunks.releasePaintChunks()
; | 385 m_currentPaintArtifact.paintChunks() = m_newPaintChunks.releasePaintChunks()
; |
386 | 386 |
387 m_newDisplayItems.clear(); | 387 m_newDisplayItems.clear(); |
388 m_validlyCachedClientsDirty = true; | 388 m_validlyCachedClientsDirty = true; |
389 m_numCachedItems = 0; | 389 m_numCachedItems = 0; |
390 } | 390 } |
391 | 391 |
392 size_t DisplayItemList::approximateUnsharedMemoryUsage() const | 392 size_t PaintController::approximateUnsharedMemoryUsage() const |
393 { | 393 { |
394 size_t memoryUsage = sizeof(*this); | 394 size_t memoryUsage = sizeof(*this); |
395 | 395 |
396 // Memory outside this class due to m_currentPaintArtifact. | 396 // Memory outside this class due to m_currentPaintArtifact. |
397 memoryUsage += m_currentPaintArtifact.approximateUnsharedMemoryUsage() - siz
eof(m_currentPaintArtifact); | 397 memoryUsage += m_currentPaintArtifact.approximateUnsharedMemoryUsage() - siz
eof(m_currentPaintArtifact); |
398 | 398 |
399 // TODO(jbroman): If display items begin to have significant external memory | 399 // TODO(jbroman): If display items begin to have significant external memory |
400 // usage that's not shared with the embedder, we should account for it here. | 400 // usage that's not shared with the embedder, we should account for it here. |
401 // | 401 // |
402 // External objects, shared with the embedder, such as SkPicture, should be | 402 // External objects, shared with the embedder, such as SkPicture, should be |
403 // excluded to avoid double counting. It is the embedder's responsibility to | 403 // excluded to avoid double counting. It is the embedder's responsibility to |
404 // count such objects. | 404 // count such objects. |
405 // | 405 // |
406 // At time of writing, the only known case of unshared external memory was | 406 // At time of writing, the only known case of unshared external memory was |
407 // the rounded clips vector in ClipDisplayItem, which is not expected to | 407 // the rounded clips vector in ClipDisplayItem, which is not expected to |
408 // contribute significantly to memory usage. | 408 // contribute significantly to memory usage. |
409 | 409 |
410 // Memory outside this class due to m_newDisplayItems. | 410 // Memory outside this class due to m_newDisplayItems. |
411 ASSERT(m_newDisplayItems.isEmpty()); | 411 ASSERT(m_newDisplayItems.isEmpty()); |
412 memoryUsage += m_newDisplayItems.memoryUsageInBytes(); | 412 memoryUsage += m_newDisplayItems.memoryUsageInBytes(); |
413 | 413 |
414 return memoryUsage; | 414 return memoryUsage; |
415 } | 415 } |
416 | 416 |
417 void DisplayItemList::updateValidlyCachedClientsIfNeeded() const | 417 void PaintController::updateValidlyCachedClientsIfNeeded() const |
418 { | 418 { |
419 if (!m_validlyCachedClientsDirty) | 419 if (!m_validlyCachedClientsDirty) |
420 return; | 420 return; |
421 | 421 |
422 m_validlyCachedClients.clear(); | 422 m_validlyCachedClients.clear(); |
423 m_validlyCachedClientsDirty = false; | 423 m_validlyCachedClientsDirty = false; |
424 | 424 |
425 DisplayItemClient lastAddedClient = nullptr; | 425 DisplayItemClient lastAddedClient = nullptr; |
426 for (const DisplayItem& displayItem : m_currentPaintArtifact.displayItems())
{ | 426 for (const DisplayItem& displayItem : m_currentPaintArtifact.displayItems())
{ |
427 if (displayItem.client() == lastAddedClient) | 427 if (displayItem.client() == lastAddedClient) |
428 continue; | 428 continue; |
429 if (displayItem.isCacheable()) { | 429 if (displayItem.isCacheable()) { |
430 lastAddedClient = displayItem.client(); | 430 lastAddedClient = displayItem.client(); |
431 m_validlyCachedClients.add(lastAddedClient); | 431 m_validlyCachedClients.add(lastAddedClient); |
432 } | 432 } |
433 } | 433 } |
434 } | 434 } |
435 | 435 |
436 #if ENABLE(ASSERT) | 436 #if ENABLE(ASSERT) |
437 | 437 |
438 void DisplayItemList::checkUnderInvalidation(DisplayItems::iterator& newIt, Disp
layItems::iterator& currentIt) | 438 void PaintController::checkUnderInvalidation(DisplayItems::iterator& newIt, Disp
layItems::iterator& currentIt) |
439 { | 439 { |
440 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 440 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); |
441 ASSERT(newIt->isCached()); | 441 ASSERT(newIt->isCached()); |
442 | 442 |
443 // When under-invalidation-checking is enabled, the forced painting is follo
wing the cached display item. | 443 // When under-invalidation-checking is enabled, the forced painting is follo
wing the cached display item. |
444 DisplayItem::Type nextItemType = DisplayItem::nonCachedType(newIt->type()); | 444 DisplayItem::Type nextItemType = DisplayItem::nonCachedType(newIt->type()); |
445 ++newIt; | 445 ++newIt; |
446 ASSERT(newIt->type() == nextItemType); | 446 ASSERT(newIt->type() == nextItemType); |
447 | 447 |
448 if (newIt->isDrawing()) { | 448 if (newIt->isDrawing()) { |
(...skipping 29 matching lines...) Expand all Loading... |
478 { | 478 { |
479 #ifndef NDEBUG | 479 #ifndef NDEBUG |
480 WTFLogAlways("%s %s:\nNew display item: %s\nOld display item: %s\nSee http:/
/crbug.com/450725.", messagePrefix, reason, | 480 WTFLogAlways("%s %s:\nNew display item: %s\nOld display item: %s\nSee http:/
/crbug.com/450725.", messagePrefix, reason, |
481 newItem ? newItem->asDebugString().utf8().data() : "None", | 481 newItem ? newItem->asDebugString().utf8().data() : "None", |
482 oldItem ? oldItem->asDebugString().utf8().data() : "None"); | 482 oldItem ? oldItem->asDebugString().utf8().data() : "None"); |
483 #else | 483 #else |
484 WTFLogAlways("%s %s. Run debug build to get more details\nSee http://crbug.c
om/450725.", messagePrefix, reason); | 484 WTFLogAlways("%s %s. Run debug build to get more details\nSee http://crbug.c
om/450725.", messagePrefix, reason); |
485 #endif // NDEBUG | 485 #endif // NDEBUG |
486 } | 486 } |
487 | 487 |
488 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const char* messagePrefi
x, const DisplayItem& newItem, const DisplayItem& oldItem) | 488 void PaintController::checkCachedDisplayItemIsUnchanged(const char* messagePrefi
x, const DisplayItem& newItem, const DisplayItem& oldItem) |
489 { | 489 { |
490 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 490 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); |
491 ASSERT(!newItem.isCached()); | 491 ASSERT(!newItem.isCached()); |
492 ASSERT(!oldItem.isCached()); | 492 ASSERT(!oldItem.isCached()); |
493 | 493 |
494 if (newItem.skippedCache()) { | 494 if (newItem.skippedCache()) { |
495 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: sk
ipped-cache in cached subsequence", &newItem, &oldItem); | 495 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: sk
ipped-cache in cached subsequence", &newItem, &oldItem); |
496 ASSERT_NOT_REACHED(); | 496 ASSERT_NOT_REACHED(); |
497 } | 497 } |
498 | 498 |
(...skipping 14 matching lines...) Expand all Loading... |
513 String oldPictureDebugString = oldPicture ? pictureAsDebugString(oldPict
ure.get()) : "None"; | 513 String oldPictureDebugString = oldPicture ? pictureAsDebugString(oldPict
ure.get()) : "None"; |
514 String newPictureDebugString = newPicture ? pictureAsDebugString(newPict
ure.get()) : "None"; | 514 String newPictureDebugString = newPicture ? pictureAsDebugString(newPict
ure.get()) : "None"; |
515 WTFLogAlways("old picture:\n%s\n", oldPictureDebugString.utf8().data()); | 515 WTFLogAlways("old picture:\n%s\n", oldPictureDebugString.utf8().data()); |
516 WTFLogAlways("new picture:\n%s\n", newPictureDebugString.utf8().data()); | 516 WTFLogAlways("new picture:\n%s\n", newPictureDebugString.utf8().data()); |
517 } | 517 } |
518 #endif // NDEBUG | 518 #endif // NDEBUG |
519 | 519 |
520 ASSERT_NOT_REACHED(); | 520 ASSERT_NOT_REACHED(); |
521 } | 521 } |
522 | 522 |
523 void DisplayItemList::checkNoRemainingCachedDisplayItems() | 523 void PaintController::checkNoRemainingCachedDisplayItems() |
524 { | 524 { |
525 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 525 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); |
526 | 526 |
527 for (const auto& displayItem : m_currentPaintArtifact.displayItems()) { | 527 for (const auto& displayItem : m_currentPaintArtifact.displayItems()) { |
528 if (!displayItem.isValid() || !displayItem.isCacheable() || !clientCache
IsValid(displayItem.client())) | 528 if (!displayItem.isValid() || !displayItem.isCacheable() || !clientCache
IsValid(displayItem.client())) |
529 continue; | 529 continue; |
530 showUnderInvalidationError("", "May be under-invalidation: no new displa
y item", nullptr, &displayItem); | 530 showUnderInvalidationError("", "May be under-invalidation: no new displa
y item", nullptr, &displayItem); |
531 } | 531 } |
532 } | 532 } |
533 | 533 |
534 #endif // ENABLE(ASSERT) | 534 #endif // ENABLE(ASSERT) |
535 | 535 |
536 #ifndef NDEBUG | 536 #ifndef NDEBUG |
537 | 537 |
538 WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list)
const | 538 WTF::String PaintController::displayItemsAsDebugString(const DisplayItems& list)
const |
539 { | 539 { |
540 StringBuilder stringBuilder; | 540 StringBuilder stringBuilder; |
541 size_t i = 0; | 541 size_t i = 0; |
542 for (auto it = list.begin(); it != list.end(); ++it, ++i) { | 542 for (auto it = list.begin(); it != list.end(); ++it, ++i) { |
543 const DisplayItem& displayItem = *it; | 543 const DisplayItem& displayItem = *it; |
544 if (i) | 544 if (i) |
545 stringBuilder.append(",\n"); | 545 stringBuilder.append(",\n"); |
546 stringBuilder.append(String::format("{index: %d, ", (int)i)); | 546 stringBuilder.append(String::format("{index: %d, ", (int)i)); |
547 displayItem.dumpPropertiesAsDebugString(stringBuilder); | 547 displayItem.dumpPropertiesAsDebugString(stringBuilder); |
548 if (displayItem.isValid()) { | 548 if (displayItem.isValid()) { |
549 stringBuilder.append(", cacheIsValid: "); | 549 stringBuilder.append(", cacheIsValid: "); |
550 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "tru
e" : "false"); | 550 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "tru
e" : "false"); |
551 } | 551 } |
552 stringBuilder.append('}'); | 552 stringBuilder.append('}'); |
553 } | 553 } |
554 return stringBuilder.toString(); | 554 return stringBuilder.toString(); |
555 } | 555 } |
556 | 556 |
557 void DisplayItemList::showDebugData() const | 557 void PaintController::showDebugData() const |
558 { | 558 { |
559 WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_cu
rrentPaintArtifact.displayItems()).utf8().data()); | 559 WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_cu
rrentPaintArtifact.displayItems()).utf8().data()); |
560 WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDis
playItems).utf8().data()); | 560 WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDis
playItems).utf8().data()); |
561 } | 561 } |
562 | 562 |
563 #endif // ifndef NDEBUG | 563 #endif // ifndef NDEBUG |
564 | 564 |
565 } // namespace blink | 565 } // namespace blink |
OLD | NEW |