| 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 |