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 "platform/graphics/paint/PaintController.h" | 5 #include "platform/graphics/paint/PaintController.h" |
6 | 6 |
7 #include "platform/TraceEvent.h" | 7 #include "platform/TraceEvent.h" |
8 #include "platform/graphics/GraphicsLayer.h" | 8 #include "platform/graphics/GraphicsLayer.h" |
9 #include "platform/graphics/paint/DrawingDisplayItem.h" | 9 #include "platform/graphics/paint/DrawingDisplayItem.h" |
10 #include "third_party/skia/include/core/SkPictureAnalyzer.h" | 10 #include "third_party/skia/include/core/SkPictureAnalyzer.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client
, DisplayItem::Type type) | 27 bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client
, DisplayItem::Type type) |
28 { | 28 { |
29 DCHECK(DisplayItem::isDrawingType(type)); | 29 DCHECK(DisplayItem::isDrawingType(type)); |
30 | 30 |
31 if (displayItemConstructionIsDisabled()) | 31 if (displayItemConstructionIsDisabled()) |
32 return false; | 32 return false; |
33 | 33 |
34 if (!clientCacheIsValid(client)) | 34 if (!clientCacheIsValid(client)) |
35 return false; | 35 return false; |
36 | 36 |
37 #if DCHECK_IS_ON() | 37 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && isChe
ckingUnderInvalidation()) { |
38 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()
&& isCheckingUnderInvalidation()) { | |
39 // We are checking under-invalidation of a subsequence enclosing this di
splay item. | 38 // We are checking under-invalidation of a subsequence enclosing this di
splay item. |
40 // Let the client continue to actually paint the display item. | 39 // Let the client continue to actually paint the display item. |
41 return false; | 40 return false; |
42 } | 41 } |
43 #endif | |
44 | 42 |
45 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type)); | 43 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type)); |
46 if (cachedItem == kNotFound) { | 44 if (cachedItem == kNotFound) { |
47 NOTREACHED(); | 45 NOTREACHED(); |
48 return false; | 46 return false; |
49 } | 47 } |
50 | 48 |
51 ++m_numCachedNewItems; | 49 ++m_numCachedNewItems; |
52 ensureNewDisplayItemListInitialCapacity(); | 50 ensureNewDisplayItemListInitialCapacity(); |
53 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidati
onCheckingEnabled()) | 51 if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) |
54 processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifac
t.getDisplayItemList()[cachedItem]), FromCachedItem); | 52 processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifac
t.getDisplayItemList()[cachedItem]), FromCachedItem); |
55 | 53 |
56 m_nextItemToMatch = cachedItem + 1; | 54 m_nextItemToMatch = cachedItem + 1; |
57 // Items before m_nextItemToMatch have been copied so we don't need to index
them. | 55 // Items before m_nextItemToMatch have been copied so we don't need to index
them. |
58 if (m_nextItemToMatch > m_nextItemToIndex) | 56 if (m_nextItemToMatch > m_nextItemToIndex) |
59 m_nextItemToIndex = m_nextItemToMatch; | 57 m_nextItemToIndex = m_nextItemToMatch; |
60 | 58 |
61 #if DCHECK_IS_ON() | 59 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
62 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ | |
63 if (!isCheckingUnderInvalidation()) { | 60 if (!isCheckingUnderInvalidation()) { |
64 m_underInvalidationCheckingBegin = cachedItem; | 61 m_underInvalidationCheckingBegin = cachedItem; |
65 m_underInvalidationCheckingEnd = cachedItem + 1; | 62 m_underInvalidationCheckingEnd = cachedItem + 1; |
66 m_underInvalidationMessagePrefix = ""; | 63 m_underInvalidationMessagePrefix = ""; |
67 } | 64 } |
68 // Return false to let the painter actually paint, and we will check if
the new painting | 65 // Return false to let the painter actually paint, and we will check if
the new painting |
69 // is the same as the cached. | 66 // is the same as the cached. |
70 return false; | 67 return false; |
71 } | 68 } |
72 #endif | |
73 | 69 |
74 return true; | 70 return true; |
75 } | 71 } |
76 | 72 |
77 bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& cl
ient) | 73 bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& cl
ient) |
78 { | 74 { |
79 if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled()) | 75 if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled()) |
80 return false; | 76 return false; |
81 | 77 |
82 if (!clientCacheIsValid(client)) | 78 if (!clientCacheIsValid(client)) |
83 return false; | 79 return false; |
84 | 80 |
85 #if DCHECK_IS_ON() | 81 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && isChe
ckingUnderInvalidation()) { |
86 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()
&& isCheckingUnderInvalidation()) { | |
87 // We are checking under-invalidation of an ancestor subsequence enclosi
ng this one. | 82 // We are checking under-invalidation of an ancestor subsequence enclosi
ng this one. |
88 // The ancestor subsequence is supposed to have already "copied", so we
should let the | 83 // The ancestor subsequence is supposed to have already "copied", so we
should let the |
89 // client continue to actually paint the descendant subsequences without
"copying". | 84 // client continue to actually paint the descendant subsequences without
"copying". |
90 return false; | 85 return false; |
91 } | 86 } |
92 #endif | |
93 | 87 |
94 size_t cachedItem = findCachedItem(DisplayItem::Id(client, DisplayItem::kSub
sequence)); | 88 size_t cachedItem = findCachedItem(DisplayItem::Id(client, DisplayItem::kSub
sequence)); |
95 if (cachedItem == kNotFound) { | 89 if (cachedItem == kNotFound) { |
96 NOTREACHED(); | 90 NOTREACHED(); |
97 return false; | 91 return false; |
98 } | 92 } |
99 | 93 |
100 // |cachedItem| will point to the first item after the subsequence or end of
the current list. | 94 // |cachedItem| will point to the first item after the subsequence or end of
the current list. |
101 ensureNewDisplayItemListInitialCapacity(); | 95 ensureNewDisplayItemListInitialCapacity(); |
102 copyCachedSubsequence(cachedItem); | 96 copyCachedSubsequence(cachedItem); |
103 | 97 |
104 m_nextItemToMatch = cachedItem; | 98 m_nextItemToMatch = cachedItem; |
105 // Items before |cachedItem| have been copied so we don't need to index them
. | 99 // Items before |cachedItem| have been copied so we don't need to index them
. |
106 if (cachedItem > m_nextItemToIndex) | 100 if (cachedItem > m_nextItemToIndex) |
107 m_nextItemToIndex = cachedItem; | 101 m_nextItemToIndex = cachedItem; |
108 | 102 |
109 #if DCHECK_IS_ON() | 103 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
110 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ | |
111 // Return false to let the painter actually paint, and we will check if
the new painting | 104 // Return false to let the painter actually paint, and we will check if
the new painting |
112 // is the same as the cached. | 105 // is the same as the cached. |
113 return false; | 106 return false; |
114 } | 107 } |
115 #endif | |
116 | 108 |
117 return true; | 109 return true; |
118 } | 110 } |
119 | 111 |
120 bool PaintController::lastDisplayItemIsNoopBegin() const | 112 bool PaintController::lastDisplayItemIsNoopBegin() const |
121 { | 113 { |
122 if (m_newDisplayItemList.isEmpty()) | 114 if (m_newDisplayItemList.isEmpty()) |
123 return false; | 115 return false; |
124 | 116 |
125 const auto& lastDisplayItem = m_newDisplayItemList.last(); | 117 const auto& lastDisplayItem = m_newDisplayItemList.last(); |
126 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); | 118 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); |
127 } | 119 } |
128 | 120 |
129 void PaintController::removeLastDisplayItem() | 121 void PaintController::removeLastDisplayItem() |
130 { | 122 { |
131 if (m_newDisplayItemList.isEmpty()) | 123 if (m_newDisplayItemList.isEmpty()) |
132 return; | 124 return; |
133 | 125 |
134 #if DCHECK_IS_ON() | 126 #if DCHECK_IS_ON() |
135 // Also remove the index pointing to the removed display item. | 127 // Also remove the index pointing to the removed display item. |
136 IndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient.find(&m_ne
wDisplayItemList.last().client()); | 128 IndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient.find(&m_ne
wDisplayItemList.last().client()); |
137 if (it != m_newDisplayItemIndicesByClient.end()) { | 129 if (it != m_newDisplayItemIndicesByClient.end()) { |
138 Vector<size_t>& indices = it->value; | 130 Vector<size_t>& indices = it->value; |
139 if (!indices.isEmpty() && indices.last() == (m_newDisplayItemList.size()
- 1)) | 131 if (!indices.isEmpty() && indices.last() == (m_newDisplayItemList.size()
- 1)) |
140 indices.removeLast(); | 132 indices.removeLast(); |
141 } | 133 } |
| 134 #endif |
142 | 135 |
143 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()
&& isCheckingUnderInvalidation()) { | 136 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && isChe
ckingUnderInvalidation()) { |
144 if (m_skippedProbableUnderInvalidationCount) { | 137 if (m_skippedProbableUnderInvalidationCount) { |
145 --m_skippedProbableUnderInvalidationCount; | 138 --m_skippedProbableUnderInvalidationCount; |
146 } else { | 139 } else { |
147 DCHECK(m_underInvalidationCheckingBegin); | 140 DCHECK(m_underInvalidationCheckingBegin); |
148 --m_underInvalidationCheckingBegin; | 141 --m_underInvalidationCheckingBegin; |
149 } | 142 } |
150 } | 143 } |
151 #endif | |
152 m_newDisplayItemList.removeLast(); | 144 m_newDisplayItemList.removeLast(); |
153 | 145 |
154 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 146 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
155 m_newPaintChunks.decrementDisplayItemIndex(); | 147 m_newPaintChunks.decrementDisplayItemIndex(); |
156 } | 148 } |
157 | 149 |
158 const DisplayItem* PaintController::lastDisplayItem(unsigned offset) | 150 const DisplayItem* PaintController::lastDisplayItem(unsigned offset) |
159 { | 151 { |
160 if (offset < m_newDisplayItemList.size()) | 152 if (offset < m_newDisplayItemList.size()) |
161 return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1]; | 153 return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1]; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt
emIndicesByClient, m_newDisplayItemList); | 210 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt
emIndicesByClient, m_newDisplayItemList); |
219 if (index != kNotFound) { | 211 if (index != kNotFound) { |
220 #ifndef NDEBUG | 212 #ifndef NDEBUG |
221 showDebugData(); | 213 showDebugData(); |
222 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%
d)\n", | 214 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%
d)\n", |
223 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde
x].asDebugString().utf8().data(), static_cast<int>(index)); | 215 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde
x].asDebugString().utf8().data(), static_cast<int>(index)); |
224 #endif | 216 #endif |
225 NOTREACHED(); | 217 NOTREACHED(); |
226 } | 218 } |
227 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi
splayItemIndicesByClient); | 219 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi
splayItemIndicesByClient); |
| 220 #endif // DCHECK_IS_ON() |
228 | 221 |
229 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 222 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) |
230 checkUnderInvalidation(); | 223 checkUnderInvalidation(); |
231 #endif // DCHECK_IS_ON() | |
232 } | 224 } |
233 | 225 |
234 void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id
, const PaintChunkProperties& newProperties) | 226 void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id
, const PaintChunkProperties& newProperties) |
235 { | 227 { |
236 m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties); | 228 m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties); |
237 } | 229 } |
238 | 230 |
239 const PaintChunkProperties& PaintController::currentPaintChunkProperties() const | 231 const PaintChunkProperties& PaintController::currentPaintChunkProperties() const |
240 { | 232 { |
241 return m_newPaintChunks.currentPaintChunkProperties(); | 233 return m_newPaintChunks.currentPaintChunkProperties(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 DCHECK(clientCacheIsValid(id.client)); | 284 DCHECK(clientCacheIsValid(id.client)); |
293 | 285 |
294 // Try to find the item sequentially first. This is fast if the current list
and the new list are in | 286 // Try to find the item sequentially first. This is fast if the current list
and the new list are in |
295 // the same order around the new item. If found, we don't need to update and
lookup the index. | 287 // the same order around the new item. If found, we don't need to update and
lookup the index. |
296 for (size_t i = m_nextItemToMatch; i < m_currentPaintArtifact.getDisplayItem
List().size(); ++i) { | 288 for (size_t i = m_nextItemToMatch; i < m_currentPaintArtifact.getDisplayItem
List().size(); ++i) { |
297 // We encounter an item that has already been copied which indicates we
can't do sequential matching. | 289 // We encounter an item that has already been copied which indicates we
can't do sequential matching. |
298 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i]
; | 290 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i]
; |
299 if (!item.hasValidClient()) | 291 if (!item.hasValidClient()) |
300 break; | 292 break; |
301 if (id == item.getId()) { | 293 if (id == item.getId()) { |
302 #if DCHECK_IS_ON() | 294 #ifndef NDEBUG |
303 ++m_numSequentialMatches; | 295 ++m_numSequentialMatches; |
304 #endif | 296 #endif |
305 return i; | 297 return i; |
306 } | 298 } |
307 // We encounter a different cacheable item which also indicates we can't
do sequential matching. | 299 // We encounter a different cacheable item which also indicates we can't
do sequential matching. |
308 if (item.isCacheable()) | 300 if (item.isCacheable()) |
309 break; | 301 break; |
310 } | 302 } |
311 | 303 |
312 size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m
_currentPaintArtifact.getDisplayItemList()); | 304 size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m
_currentPaintArtifact.getDisplayItemList()); |
313 if (foundIndex != kNotFound) { | 305 if (foundIndex != kNotFound) { |
314 #if DCHECK_IS_ON() | 306 #ifndef NDEBUG |
315 ++m_numOutOfOrderMatches; | 307 ++m_numOutOfOrderMatches; |
316 #endif | 308 #endif |
317 return foundIndex; | 309 return foundIndex; |
318 } | 310 } |
319 | 311 |
320 return findOutOfOrderCachedItemForward(id); | 312 return findOutOfOrderCachedItemForward(id); |
321 } | 313 } |
322 | 314 |
323 // Find forward for the item and index all skipped indexable items. | 315 // Find forward for the item and index all skipped indexable items. |
324 size_t PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& i
d) | 316 size_t PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& i
d) |
325 { | 317 { |
326 for (size_t i = m_nextItemToIndex; i < m_currentPaintArtifact.getDisplayItem
List().size(); ++i) { | 318 for (size_t i = m_nextItemToIndex; i < m_currentPaintArtifact.getDisplayItem
List().size(); ++i) { |
327 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i]
; | 319 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i]
; |
328 DCHECK(item.hasValidClient()); | 320 DCHECK(item.hasValidClient()); |
329 if (id == item.getId()) { | 321 if (id == item.getId()) { |
330 #if DCHECK_IS_ON() | 322 #ifndef NDEBUG |
331 ++m_numSequentialMatches; | 323 ++m_numSequentialMatches; |
332 #endif | 324 #endif |
333 return i; | 325 return i; |
334 } | 326 } |
335 if (item.isCacheable()) { | 327 if (item.isCacheable()) { |
336 #if DCHECK_IS_ON() | 328 #ifndef NDEBUG |
337 ++m_numIndexedItems; | 329 ++m_numIndexedItems; |
338 #endif | 330 #endif |
339 addItemToIndexIfNeeded(item, i, m_outOfOrderItemIndices); | 331 addItemToIndexIfNeeded(item, i, m_outOfOrderItemIndices); |
340 } | 332 } |
341 } | 333 } |
342 | 334 |
343 #ifndef NDEBUG | 335 #ifndef NDEBUG |
344 showDebugData(); | 336 showDebugData(); |
345 LOG(ERROR) << id.client.debugName() << ":" << DisplayItem::typeAsDebugString
(id.type); | 337 LOG(ERROR) << id.client.debugName() << ":" << DisplayItem::typeAsDebugString
(id.type); |
346 #endif | 338 #endif |
347 NOTREACHED() << "Can't find cached display item"; | 339 |
| 340 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) |
| 341 CHECK(false) << "Can't find cached display item"; |
| 342 |
348 // We did not find the cached display item. This should be impossible, but m
ay occur if there is a bug | 343 // We did not find the cached display item. This should be impossible, but m
ay occur if there is a bug |
349 // in the system, such as under-invalidation, incorrect cache checking or du
plicate display ids. | 344 // in the system, such as under-invalidation, incorrect cache checking or du
plicate display ids. |
350 // In this case, the caller should fall back to repaint the display item. | 345 // In this case, the caller should fall back to repaint the display item. |
351 return kNotFound; | 346 return kNotFound; |
352 } | 347 } |
353 | 348 |
354 // Copies a cached subsequence from current list to the new list. On return, | 349 // Copies a cached subsequence from current list to the new list. On return, |
355 // |cachedItemIndex| points to the item after the EndSubsequence item of the sub
sequence. | 350 // |cachedItemIndex| points to the item after the EndSubsequence item of the sub
sequence. |
356 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs
equence, | 351 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs
equence, |
357 // but mark the begin and end of the subsequence for under-invalidation checking
. | 352 // but mark the begin and end of the subsequence for under-invalidation checking
. |
358 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) | 353 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) |
359 { | 354 { |
360 DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cache
dItemIndex]; | 355 DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cache
dItemIndex]; |
361 #if DCHECK_IS_ON() | |
362 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); | 356 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); |
363 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ | 357 |
| 358 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
364 DCHECK(!isCheckingUnderInvalidation()); | 359 DCHECK(!isCheckingUnderInvalidation()); |
365 m_underInvalidationCheckingBegin = cachedItemIndex; | 360 m_underInvalidationCheckingBegin = cachedItemIndex; |
366 m_underInvalidationMessagePrefix = "(In cached subsequence of " + cached
Item->client().debugName() + ")"; | 361 m_underInvalidationMessagePrefix = "(In cached subsequence of " + cached
Item->client().debugName() + ")"; |
367 } | 362 } |
368 #endif | |
369 | 363 |
370 DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubs
equence); | 364 DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubs
equence); |
371 Vector<PaintChunk>::const_iterator cachedChunk; | 365 Vector<PaintChunk>::const_iterator cachedChunk; |
372 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 366 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
373 cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedI
temIndex); | 367 cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedI
temIndex); |
374 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id :
nullptr, cachedChunk->properties); | 368 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id :
nullptr, cachedChunk->properties); |
375 } else { | 369 } else { |
376 // This is to avoid compilation error about uninitialized variable on Wi
ndows. | 370 // This is to avoid compilation error about uninitialized variable on Wi
ndows. |
377 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); | 371 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); |
378 } | 372 } |
379 | 373 |
380 while (true) { | 374 while (true) { |
381 DCHECK(cachedItem->hasValidClient()); | 375 DCHECK(cachedItem->hasValidClient()); |
382 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 376 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
383 CHECK(cachedItem->client().isAlive()); | 377 CHECK(cachedItem->client().isAlive()); |
384 #endif | 378 #endif |
385 ++m_numCachedNewItems; | 379 ++m_numCachedNewItems; |
386 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; | 380 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; |
387 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali
dationCheckingEnabled()) { | 381 if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
388 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn
dex == cachedChunk->endIndex) { | 382 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn
dex == cachedChunk->endIndex) { |
389 ++cachedChunk; | 383 ++cachedChunk; |
390 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun
k->id : nullptr, cachedChunk->properties); | 384 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun
k->id : nullptr, cachedChunk->properties); |
391 } | 385 } |
392 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro
mCachedSubsequence); | 386 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro
mCachedSubsequence); |
393 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 387 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
394 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) ||
m_newPaintChunks.lastChunk().matches(*cachedChunk)); | 388 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) ||
m_newPaintChunks.lastChunk().matches(*cachedChunk)); |
395 } | 389 } |
396 | 390 |
397 ++cachedItemIndex; | 391 ++cachedItemIndex; |
398 if (metEndSubsequence) | 392 if (metEndSubsequence) |
399 break; | 393 break; |
400 | 394 |
401 // We should always be able to find the EndSubsequence display item. | 395 // We should always be able to find the EndSubsequence display item. |
402 DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().siz
e()); | 396 DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().siz
e()); |
403 cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cachedItemInde
x]; | 397 cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cachedItemInde
x]; |
404 } | 398 } |
405 | 399 |
406 #if DCHECK_IS_ON() | 400 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
407 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ | |
408 m_underInvalidationCheckingEnd = cachedItemIndex; | 401 m_underInvalidationCheckingEnd = cachedItemIndex; |
409 DCHECK(isCheckingUnderInvalidation()); | 402 DCHECK(isCheckingUnderInvalidation()); |
410 } | 403 } |
411 #endif | |
412 } | 404 } |
413 | 405 |
414 static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const La
youtSize& offsetFromLayoutObject) | 406 static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const La
youtSize& offsetFromLayoutObject) |
415 { | 407 { |
416 LayoutRect visualRect = displayItem.client().visualRect(); | 408 LayoutRect visualRect = displayItem.client().visualRect(); |
417 visualRect.move(-offsetFromLayoutObject); | 409 visualRect.move(-offsetFromLayoutObject); |
418 return enclosingIntRect(visualRect); | 410 return enclosingIntRect(visualRect); |
419 } | 411 } |
420 | 412 |
421 void PaintController::resetCurrentListIndices() | 413 void PaintController::resetCurrentListIndices() |
422 { | 414 { |
423 m_nextItemToMatch = 0; | 415 m_nextItemToMatch = 0; |
424 m_nextItemToIndex = 0; | 416 m_nextItemToIndex = 0; |
425 m_nextChunkToMatch = 0; | 417 m_nextChunkToMatch = 0; |
426 #if DCHECK_IS_ON() | |
427 m_underInvalidationCheckingBegin = 0; | 418 m_underInvalidationCheckingBegin = 0; |
428 m_underInvalidationCheckingEnd = 0; | 419 m_underInvalidationCheckingEnd = 0; |
429 m_skippedProbableUnderInvalidationCount = 0; | 420 m_skippedProbableUnderInvalidationCount = 0; |
430 #endif | |
431 } | 421 } |
432 | 422 |
433 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
ject) | 423 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
ject) |
434 { | 424 { |
435 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", | 425 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", |
436 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL
ist().size(), | 426 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL
ist().size(), |
437 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach
edNewItems); | 427 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach
edNewItems); |
438 m_numCachedNewItems = 0; | 428 m_numCachedNewItems = 0; |
439 | 429 |
440 // These data structures are used during painting only. | 430 // These data structures are used during painting only. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 } | 476 } |
487 | 477 |
488 // We'll allocate the initial buffer when we start the next paint. | 478 // We'll allocate the initial buffer when we start the next paint. |
489 m_newDisplayItemList = DisplayItemList(0); | 479 m_newDisplayItemList = DisplayItemList(0); |
490 | 480 |
491 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 481 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
492 CHECK(m_currentSubsequenceClients.isEmpty()); | 482 CHECK(m_currentSubsequenceClients.isEmpty()); |
493 DisplayItemClient::endShouldKeepAliveAllClients(this); | 483 DisplayItemClient::endShouldKeepAliveAllClients(this); |
494 #endif | 484 #endif |
495 | 485 |
496 #if DCHECK_IS_ON() | 486 #ifndef NDEBUG |
497 m_numSequentialMatches = 0; | 487 m_numSequentialMatches = 0; |
498 m_numOutOfOrderMatches = 0; | 488 m_numOutOfOrderMatches = 0; |
499 m_numIndexedItems = 0; | 489 m_numIndexedItems = 0; |
500 #endif | 490 #endif |
501 } | 491 } |
502 | 492 |
503 size_t PaintController::approximateUnsharedMemoryUsage() const | 493 size_t PaintController::approximateUnsharedMemoryUsage() const |
504 { | 494 { |
505 size_t memoryUsage = sizeof(*this); | 495 size_t memoryUsage = sizeof(*this); |
506 | 496 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 if (newChunkClients.add(&newItem.client()).isNewEntry) | 597 if (newChunkClients.add(&newItem.client()).isNewEntry) |
608 newChunk.rasterInvalidationRects.append(newItem.client().vis
ualRect()); | 598 newChunk.rasterInvalidationRects.append(newItem.client().vis
ualRect()); |
609 } else { | 599 } else { |
610 // The cached item was moved from the old chunk which should not
contain any item of the client now. | 600 // The cached item was moved from the old chunk which should not
contain any item of the client now. |
611 DCHECK(!oldChunkClients.contains(&newItem.client())); | 601 DCHECK(!oldChunkClients.contains(&newItem.client())); |
612 } | 602 } |
613 } | 603 } |
614 } | 604 } |
615 } | 605 } |
616 | 606 |
617 #if DCHECK_IS_ON() | |
618 | |
619 void PaintController::showUnderInvalidationError(const char* reason, const Displ
ayItem& newItem, const DisplayItem* oldItem) const | 607 void PaintController::showUnderInvalidationError(const char* reason, const Displ
ayItem& newItem, const DisplayItem* oldItem) const |
620 { | 608 { |
621 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; | 609 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; |
622 #ifndef NDEBUG | 610 #ifndef NDEBUG |
623 LOG(ERROR) << "New display item: " << newItem.asDebugString(); | 611 LOG(ERROR) << "New display item: " << newItem.asDebugString(); |
624 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() :
"None"); | 612 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() :
"None"); |
625 #else | 613 #else |
626 LOG(ERROR) << "Run debug build to get more details."; | 614 LOG(ERROR) << "Run debug build to get more details."; |
627 #endif | 615 #endif |
628 LOG(ERROR) << "See http://crbug.com/619103."; | 616 LOG(ERROR) << "See http://crbug.com/619103."; |
629 | 617 |
630 #ifndef NDEBUG | 618 #ifndef NDEBUG |
631 const SkPicture* newPicture = newItem.isDrawing() ? static_cast<const Drawin
gDisplayItem&>(newItem).picture() : nullptr; | 619 const SkPicture* newPicture = newItem.isDrawing() ? static_cast<const Drawin
gDisplayItem&>(newItem).picture() : nullptr; |
632 const SkPicture* oldPicture = oldItem && oldItem->isDrawing() ? static_cast<
const DrawingDisplayItem*>(oldItem)->picture() : nullptr; | 620 const SkPicture* oldPicture = oldItem && oldItem->isDrawing() ? static_cast<
const DrawingDisplayItem*>(oldItem)->picture() : nullptr; |
633 LOG(INFO) << "new picture:\n" << (newPicture ? pictureAsDebugString(newPictu
re) : "None"); | 621 LOG(INFO) << "new picture:\n" << (newPicture ? pictureAsDebugString(newPictu
re) : "None"); |
634 LOG(INFO) << "old picture:\n" << (oldPicture ? pictureAsDebugString(oldPictu
re) : "None"); | 622 LOG(INFO) << "old picture:\n" << (oldPicture ? pictureAsDebugString(oldPictu
re) : "None"); |
635 | 623 |
636 showDebugData(); | 624 showDebugData(); |
637 #endif // NDEBUG | 625 #endif // NDEBUG |
638 } | 626 } |
639 | 627 |
640 void PaintController::checkUnderInvalidation() | 628 void PaintController::checkUnderInvalidation() |
641 { | 629 { |
642 DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 630 DCHECK(RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()); |
643 | 631 |
644 if (!isCheckingUnderInvalidation()) | 632 if (!isCheckingUnderInvalidation()) |
645 return; | 633 return; |
646 | 634 |
647 const DisplayItem& newItem = m_newDisplayItemList.last(); | 635 const DisplayItem& newItem = m_newDisplayItemList.last(); |
648 size_t oldItemIndex = m_underInvalidationCheckingBegin + m_skippedProbableUn
derInvalidationCount; | 636 size_t oldItemIndex = m_underInvalidationCheckingBegin + m_skippedProbableUn
derInvalidationCount; |
649 DisplayItem* oldItem = oldItemIndex < m_currentPaintArtifact.getDisplayItemL
ist().size() ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] : null
ptr; | 637 DisplayItem* oldItem = oldItemIndex < m_currentPaintArtifact.getDisplayItemL
ist().size() ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] : null
ptr; |
650 | 638 |
651 bool oldAndNewEqual = oldItem && newItem.equals(*oldItem); | 639 bool oldAndNewEqual = oldItem && newItem.equals(*oldItem); |
652 if (!oldAndNewEqual) { | 640 if (!oldAndNewEqual) { |
(...skipping 11 matching lines...) Expand all Loading... |
664 return; | 652 return; |
665 } | 653 } |
666 } | 654 } |
667 } | 655 } |
668 | 656 |
669 if (m_skippedProbableUnderInvalidationCount || !oldAndNewEqual) { | 657 if (m_skippedProbableUnderInvalidationCount || !oldAndNewEqual) { |
670 // If we ever skipped reporting any under-invalidations, report the earl
iest one. | 658 // If we ever skipped reporting any under-invalidations, report the earl
iest one. |
671 showUnderInvalidationError("under-invalidation: display item changed", | 659 showUnderInvalidationError("under-invalidation: display item changed", |
672 m_newDisplayItemList[m_newDisplayItemList.size() - m_skippedProbable
UnderInvalidationCount - 1], | 660 m_newDisplayItemList[m_newDisplayItemList.size() - m_skippedProbable
UnderInvalidationCount - 1], |
673 &m_currentPaintArtifact.getDisplayItemList()[m_underInvalidationChec
kingBegin]); | 661 &m_currentPaintArtifact.getDisplayItemList()[m_underInvalidationChec
kingBegin]); |
674 NOTREACHED(); | 662 CHECK(false); |
675 } | 663 } |
676 | 664 |
677 // Discard the forced repainted display item and move the cached item into m
_newDisplayItemList. | 665 // Discard the forced repainted display item and move the cached item into m
_newDisplayItemList. |
678 // This is to align with the non-under-invalidation-checking path to empty t
he original cached slot, | 666 // This is to align with the non-under-invalidation-checking path to empty t
he original cached slot, |
679 // leaving only disappeared or invalidated display items in the old list aft
er painting. | 667 // leaving only disappeared or invalidated display items in the old list aft
er painting. |
680 m_newDisplayItemList.removeLast(); | 668 m_newDisplayItemList.removeLast(); |
681 m_newDisplayItemList.appendByMoving(*oldItem); | 669 m_newDisplayItemList.appendByMoving(*oldItem); |
682 | 670 |
683 ++m_underInvalidationCheckingBegin; | 671 ++m_underInvalidationCheckingBegin; |
684 } | 672 } |
685 | 673 |
686 #endif // DCHECK_IS_ON() | |
687 | |
688 String PaintController::displayItemListAsDebugString(const DisplayItemList& list
) const | 674 String PaintController::displayItemListAsDebugString(const DisplayItemList& list
) const |
689 { | 675 { |
690 StringBuilder stringBuilder; | 676 StringBuilder stringBuilder; |
691 size_t i = 0; | 677 size_t i = 0; |
692 for (auto it = list.begin(); it != list.end(); ++it, ++i) { | 678 for (auto it = list.begin(); it != list.end(); ++it, ++i) { |
693 const DisplayItem& displayItem = *it; | 679 const DisplayItem& displayItem = *it; |
694 if (i) | 680 if (i) |
695 stringBuilder.append(",\n"); | 681 stringBuilder.append(",\n"); |
696 stringBuilder.append(String::format("{index: %d, ", (int)i)); | 682 stringBuilder.append(String::format("{index: %d, ", (int)i)); |
697 #ifndef NDEBUG | 683 #ifndef NDEBUG |
(...skipping 24 matching lines...) Expand all Loading... |
722 return stringBuilder.toString(); | 708 return stringBuilder.toString(); |
723 } | 709 } |
724 | 710 |
725 void PaintController::showDebugData() const | 711 void PaintController::showDebugData() const |
726 { | 712 { |
727 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri
ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); | 713 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri
ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); |
728 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m
_newDisplayItemList).utf8().data()); | 714 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m
_newDisplayItemList).utf8().data()); |
729 } | 715 } |
730 | 716 |
731 } // namespace blink | 717 } // namespace blink |
OLD | NEW |