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 23 matching lines...) Expand all Loading... |
34 bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client
, DisplayItem::Type type) | 34 bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client
, DisplayItem::Type type) |
35 { | 35 { |
36 DCHECK(DisplayItem::isDrawingType(type)); | 36 DCHECK(DisplayItem::isDrawingType(type)); |
37 | 37 |
38 if (displayItemConstructionIsDisabled()) | 38 if (displayItemConstructionIsDisabled()) |
39 return false; | 39 return false; |
40 | 40 |
41 if (!clientCacheIsValid(client)) | 41 if (!clientCacheIsValid(client)) |
42 return false; | 42 return false; |
43 | 43 |
44 #if ENABLE(ASSERT) | 44 #if DCHECK_IS_ON() |
45 // When under-invalidation checking is enabled, we output CachedDrawing disp
lay item | 45 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()
&& isCheckingUnderInvalidation()) { |
46 // followed by the display item containing forced painting. | 46 // We are checking under-invalidation of a subsequence enclosing this di
splay item. |
47 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 47 // Let the client continue to actually paint the display item. |
48 return false; | 48 return false; |
| 49 } |
49 #endif | 50 #endif |
50 | 51 |
51 DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client
, type)); | 52 DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client
, type)); |
52 if (cachedItem == m_currentPaintArtifact.getDisplayItemList().end()) { | 53 if (cachedItem == m_currentPaintArtifact.getDisplayItemList().end()) { |
53 NOTREACHED(); | 54 NOTREACHED(); |
54 return false; | 55 return false; |
55 } | 56 } |
56 | 57 |
57 ++m_numCachedNewItems; | 58 ++m_numCachedNewItems; |
58 ensureNewDisplayItemListInitialCapacity(); | 59 ensureNewDisplayItemListInitialCapacity(); |
59 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem)); | 60 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidati
onCheckingEnabled()) |
| 61 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem)); |
60 | 62 |
61 m_nextItemToMatch = cachedItem + 1; | 63 m_nextItemToMatch = cachedItem + 1; |
62 // Items before m_nextItemToMatch have been copied so we don't need to index
them. | 64 // Items before m_nextItemToMatch have been copied so we don't need to index
them. |
63 if (m_nextItemToMatch - m_nextItemToIndex > 0) | 65 if (m_nextItemToMatch - m_nextItemToIndex > 0) |
64 m_nextItemToIndex = m_nextItemToMatch; | 66 m_nextItemToIndex = m_nextItemToMatch; |
65 | 67 |
| 68 #if DCHECK_IS_ON() |
| 69 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ |
| 70 if (!isCheckingUnderInvalidation()) { |
| 71 m_underInvalidationCheckingBegin = cachedItem; |
| 72 m_underInvalidationCheckingEnd = cachedItem + 1; |
| 73 m_underInvalidationMessagePrefix = ""; |
| 74 } |
| 75 // Return false to let the painter actually paint, and we will check if
the new painting |
| 76 // is the same as the cached. |
| 77 return false; |
| 78 } |
| 79 #endif |
| 80 |
66 return true; | 81 return true; |
67 } | 82 } |
68 | 83 |
69 bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& cl
ient) | 84 bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& cl
ient) |
70 { | 85 { |
71 // TODO(crbug.com/596983): Implement subsequence caching for spv2. | 86 // TODO(crbug.com/596983): Implement subsequence caching for spv2. |
72 // The problem is in copyCachedSubsequence() which fails to handle PaintChun
kProperties | 87 // The problem is in copyCachedSubsequence() which fails to handle PaintChun
kProperties |
73 // of chunks containing cached display items. We need to find the previous | 88 // of chunks containing cached display items. We need to find the previous |
74 // PaintChunkProperties and ensure they are valid in the current paint prope
rty tree. | 89 // PaintChunkProperties and ensure they are valid in the current paint prope
rty tree. |
75 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 90 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
76 return false; | 91 return false; |
77 | 92 |
78 if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled()) | 93 if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled()) |
79 return false; | 94 return false; |
80 | 95 |
81 if (!clientCacheIsValid(client)) | 96 if (!clientCacheIsValid(client)) |
82 return false; | 97 return false; |
83 | 98 |
84 #if ENABLE(ASSERT) | 99 #if DCHECK_IS_ON() |
85 // When under-invalidation checking is enabled, we output CachedDrawing disp
lay item | 100 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()
&& isCheckingUnderInvalidation()) { |
86 // followed by the display item containing forced painting. | 101 // We are checking under-invalidation of an ancestor subsequence enclosi
ng this one. |
87 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 102 // The ancestor subsequence is supposed to have already "copied", so we
should let the |
| 103 // client continue to actually paint the descendant subsequences without
"copying". |
88 return false; | 104 return false; |
| 105 } |
89 #endif | 106 #endif |
90 | 107 |
91 DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client
, DisplayItem::Subsequence)); | 108 DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client
, DisplayItem::Subsequence)); |
92 if (cachedItem == m_currentPaintArtifact.getDisplayItemList().end()) { | 109 if (cachedItem == m_currentPaintArtifact.getDisplayItemList().end()) { |
93 NOTREACHED(); | 110 NOTREACHED(); |
94 return false; | 111 return false; |
95 } | 112 } |
96 | 113 |
97 // |cachedItem| will point to the first item after the subsequence or end of
the current list. | 114 // |cachedItem| will point to the first item after the subsequence or end of
the current list. |
98 ensureNewDisplayItemListInitialCapacity(); | 115 ensureNewDisplayItemListInitialCapacity(); |
99 copyCachedSubsequence(cachedItem); | 116 copyCachedSubsequence(cachedItem); |
100 | 117 |
101 m_nextItemToMatch = cachedItem; | 118 m_nextItemToMatch = cachedItem; |
102 // Items before |cachedItem| have been copied so we don't need to index them
. | 119 // Items before |cachedItem| have been copied so we don't need to index them
. |
103 if (cachedItem - m_nextItemToIndex > 0) | 120 if (cachedItem - m_nextItemToIndex > 0) |
104 m_nextItemToIndex = cachedItem; | 121 m_nextItemToIndex = cachedItem; |
105 | 122 |
| 123 #if DCHECK_IS_ON() |
| 124 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ |
| 125 // Return false to let the painter actually paint, and we will check if
the new painting |
| 126 // is the same as the cached. |
| 127 return false; |
| 128 } |
| 129 #endif |
| 130 |
106 return true; | 131 return true; |
107 } | 132 } |
108 | 133 |
109 bool PaintController::lastDisplayItemIsNoopBegin() const | 134 bool PaintController::lastDisplayItemIsNoopBegin() const |
110 { | 135 { |
111 if (m_newDisplayItemList.isEmpty()) | 136 if (m_newDisplayItemList.isEmpty()) |
112 return false; | 137 return false; |
113 | 138 |
114 const auto& lastDisplayItem = m_newDisplayItemList.last(); | 139 const auto& lastDisplayItem = m_newDisplayItemList.last(); |
115 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); | 140 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt
emIndicesByClient, m_newDisplayItemList); | 203 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt
emIndicesByClient, m_newDisplayItemList); |
179 if (index != kNotFound) { | 204 if (index != kNotFound) { |
180 #ifndef NDEBUG | 205 #ifndef NDEBUG |
181 showDebugData(); | 206 showDebugData(); |
182 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%
d)\n", | 207 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%
d)\n", |
183 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde
x].asDebugString().utf8().data(), static_cast<int>(index)); | 208 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde
x].asDebugString().utf8().data(), static_cast<int>(index)); |
184 #endif | 209 #endif |
185 NOTREACHED(); | 210 NOTREACHED(); |
186 } | 211 } |
187 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi
splayItemIndicesByClient); | 212 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi
splayItemIndicesByClient); |
| 213 |
| 214 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
| 215 checkUnderInvalidation(); |
188 #endif // DCHECK_IS_ON() | 216 #endif // DCHECK_IS_ON() |
189 | 217 |
190 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 218 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
191 m_newPaintChunks.incrementDisplayItemIndex(behaviorOfItemType(displayIte
m.getType())); | 219 m_newPaintChunks.incrementDisplayItemIndex(behaviorOfItemType(displayIte
m.getType())); |
192 } | 220 } |
193 | 221 |
194 void PaintController::updateCurrentPaintChunkProperties(const PaintChunkProperti
es& newProperties) | 222 void PaintController::updateCurrentPaintChunkProperties(const PaintChunkProperti
es& newProperties) |
195 { | 223 { |
196 m_newPaintChunks.updateCurrentPaintChunkProperties(newProperties); | 224 m_newPaintChunks.updateCurrentPaintChunkProperties(newProperties); |
197 } | 225 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 showDebugData(); | 334 showDebugData(); |
307 LOG(ERROR) << id.client.debugName() << ":" << DisplayItem::typeAsDebugString
(id.type) << " not found in current display item list"; | 335 LOG(ERROR) << id.client.debugName() << ":" << DisplayItem::typeAsDebugString
(id.type) << " not found in current display item list"; |
308 #endif | 336 #endif |
309 NOTREACHED(); | 337 NOTREACHED(); |
310 // We did not find the cached display item. This should be impossible, but m
ay occur if there is a bug | 338 // We did not find the cached display item. This should be impossible, but m
ay occur if there is a bug |
311 // in the system, such as under-invalidation, incorrect cache checking or du
plicate display ids. | 339 // in the system, such as under-invalidation, incorrect cache checking or du
plicate display ids. |
312 // In this case, the caller should fall back to repaint the display item. | 340 // In this case, the caller should fall back to repaint the display item. |
313 return end; | 341 return end; |
314 } | 342 } |
315 | 343 |
| 344 // Copies a cached subsequence from current list to the new list. |
316 // On return, |it| points to the item after the EndSubsequence item of the subse
quence. | 345 // On return, |it| points to the item after the EndSubsequence item of the subse
quence. |
| 346 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs
equence, |
| 347 // but mark the begin and end of the subsequence for under-invalidation checking
. |
317 void PaintController::copyCachedSubsequence(DisplayItemList::iterator& it) | 348 void PaintController::copyCachedSubsequence(DisplayItemList::iterator& it) |
318 { | 349 { |
| 350 #if DCHECK_IS_ON() |
319 DCHECK(it->getType() == DisplayItem::Subsequence); | 351 DCHECK(it->getType() == DisplayItem::Subsequence); |
| 352 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ |
| 353 DCHECK(!isCheckingUnderInvalidation()); |
| 354 m_underInvalidationCheckingBegin = it; |
| 355 #ifndef NDEBUG |
| 356 m_underInvalidationMessagePrefix = "(In CachedSubsequence of " + it->cli
entDebugString() + ")"; |
| 357 #else |
| 358 m_underInvalidationMessagePrefix = "(In CachedSubsequence)"; |
| 359 #endif |
| 360 } |
| 361 #endif |
| 362 |
320 DisplayItem::Id endSubsequenceId(it->client(), DisplayItem::EndSubsequence); | 363 DisplayItem::Id endSubsequenceId(it->client(), DisplayItem::EndSubsequence); |
| 364 bool metEndSubsequence = false; |
321 do { | 365 do { |
322 // We should always find the EndSubsequence display item. | 366 // We should always find the EndSubsequence display item. |
323 DCHECK(it != m_currentPaintArtifact.getDisplayItemList().end()); | 367 DCHECK(it != m_currentPaintArtifact.getDisplayItemList().end()); |
324 DCHECK(it->hasValidClient()); | 368 DCHECK(it->hasValidClient()); |
325 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 369 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
326 CHECK(it->client().isAlive()); | 370 CHECK(it->client().isAlive()); |
327 #endif | 371 #endif |
328 ++m_numCachedNewItems; | 372 ++m_numCachedNewItems; |
329 processNewItem(m_newDisplayItemList.appendByMoving(*it)); | 373 if (it->getId() == endSubsequenceId) |
| 374 metEndSubsequence = true; |
| 375 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali
dationCheckingEnabled()) |
| 376 processNewItem(m_newDisplayItemList.appendByMoving(*it)); |
330 ++it; | 377 ++it; |
331 } while (endSubsequenceId != m_newDisplayItemList.last().getId()); | 378 } while (!metEndSubsequence); |
| 379 |
| 380 #if DCHECK_IS_ON() |
| 381 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ |
| 382 m_underInvalidationCheckingEnd = it; |
| 383 DCHECK(isCheckingUnderInvalidation()); |
| 384 } |
| 385 #endif |
332 } | 386 } |
333 | 387 |
334 static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const La
youtSize& offsetFromLayoutObject) | 388 static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const La
youtSize& offsetFromLayoutObject) |
335 { | 389 { |
336 LayoutRect visualRect = displayItem.client().visualRect(); | 390 LayoutRect visualRect = displayItem.client().visualRect(); |
337 visualRect.move(-offsetFromLayoutObject); | 391 visualRect.move(-offsetFromLayoutObject); |
338 return enclosingIntRect(visualRect); | 392 return enclosingIntRect(visualRect); |
339 } | 393 } |
340 | 394 |
341 void PaintController::resetCurrentListIterators() | 395 void PaintController::resetCurrentListIterators() |
342 { | 396 { |
343 m_nextItemToMatch = m_currentPaintArtifact.getDisplayItemList().begin(); | 397 m_nextItemToMatch = m_currentPaintArtifact.getDisplayItemList().begin(); |
344 m_nextItemToIndex = m_nextItemToMatch; | 398 m_nextItemToIndex = m_nextItemToMatch; |
| 399 #if DCHECK_IS_ON() |
| 400 m_underInvalidationCheckingBegin = m_currentPaintArtifact.getDisplayItemList
().end(); |
| 401 m_underInvalidationCheckingEnd = m_currentPaintArtifact.getDisplayItemList()
.begin(); |
| 402 #endif |
345 } | 403 } |
346 | 404 |
347 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
ject) | 405 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
ject) |
348 { | 406 { |
349 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", | 407 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", |
350 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL
ist().size(), | 408 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL
ist().size(), |
351 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach
edNewItems); | 409 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach
edNewItems); |
352 m_numCachedNewItems = 0; | 410 m_numCachedNewItems = 0; |
353 | 411 |
354 // These data structures are used during painting only. | 412 // These data structures are used during painting only. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 { | 479 { |
422 DCHECK(m_newDisplayItemList.isEmpty()); | 480 DCHECK(m_newDisplayItemList.isEmpty()); |
423 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList(
).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::Debug
Drawing, picture); | 481 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList(
).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::Debug
Drawing, picture); |
424 displayItem.setSkippedCache(); | 482 displayItem.setSkippedCache(); |
425 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi
splayItem(displayItem, offsetFromLayoutObject)); | 483 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi
splayItem(displayItem, offsetFromLayoutObject)); |
426 | 484 |
427 // Need to reset the iterators after mutation of the DisplayItemList. | 485 // Need to reset the iterators after mutation of the DisplayItemList. |
428 resetCurrentListIterators(); | 486 resetCurrentListIterators(); |
429 } | 487 } |
430 | 488 |
431 #if 0 // DCHECK_IS_ON() | 489 #if DCHECK_IS_ON() |
432 // TODO(wangxianzhu): Fix under-invalidation checking for the new caching method
. | |
433 | 490 |
434 void PaintController::checkUnderInvalidation(DisplayItemList::iterator& newIt, D
isplayItemList::iterator& currentIt) | 491 void PaintController::showUnderInvalidationError(const char* reason, const Displ
ayItem& newItem, const DisplayItem& oldItem) const |
435 { | 492 { |
436 DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 493 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; |
437 | |
438 // When under-invalidation-checking is enabled, the forced painting is follo
wing the cached display item. | |
439 DisplayItem::Type nextItemType = DisplayItem::nonCachedType(newIt->getType()
); | |
440 ++newIt; | |
441 DCHECK(newIt->getType() == nextItemType); | |
442 | |
443 if (newIt->isDrawing()) { | |
444 checkCachedDisplayItemIsUnchanged("", *newIt, *currentIt); | |
445 return; | |
446 } | |
447 | |
448 DCHECK(newIt->getType() == DisplayItem::Subsequence); | |
449 | |
450 #ifndef NDEBUG | 494 #ifndef NDEBUG |
451 CString messagePrefix = String::format("(In CachedSubsequence of %s)", newIt
->clientDebugString().utf8().data()).utf8(); | 495 LOG(ERROR) << "New display item: " << newItem.asDebugString(); |
| 496 LOG(ERROR) << "Old display item: " << oldItem.asDebugString(); |
452 #else | 497 #else |
453 CString messagePrefix = "(In CachedSubsequence)"; | 498 LOG(ERROR) << "Run debug build to get more details."; |
454 #endif | 499 #endif |
455 | 500 LOG(ERROR) << "See http://crbug.com/619103."; |
456 DisplayItem::Id endSubsequenceId(newIt->client(), DisplayItem::EndSubsequenc
e); | |
457 while (true) { | |
458 DCHECK(newIt != m_newDisplayItemList.end()); | |
459 if (newIt->isCached()) | |
460 checkUnderInvalidation(newIt, currentIt); | |
461 else | |
462 checkCachedDisplayItemIsUnchanged(messagePrefix.data(), *newIt, *cur
rentIt); | |
463 | |
464 if (endSubsequenceId.matches(*newIt)) | |
465 break; | |
466 | |
467 ++newIt; | |
468 ++currentIt; | |
469 } | |
470 } | |
471 | |
472 static void showUnderInvalidationError(const char* messagePrefix, const char* re
ason, const DisplayItem* newItem, const DisplayItem* oldItem) | |
473 { | |
474 #ifndef NDEBUG | |
475 WTFLogAlways("%s %s:\nNew display item: %s\nOld display item: %s\nSee http:/
/crbug.com/450725.", messagePrefix, reason, | |
476 newItem ? newItem->asDebugString().utf8().data() : "None", | |
477 oldItem ? oldItem->asDebugString().utf8().data() : "None"); | |
478 #else | |
479 WTFLogAlways("%s %s. Run debug build to get more details\nSee http://crbug.c
om/450725.", messagePrefix, reason); | |
480 #endif // NDEBUG | |
481 } | |
482 | |
483 void PaintController::checkCachedDisplayItemIsUnchanged(const char* messagePrefi
x, const DisplayItem& newItem, const DisplayItem& oldItem) | |
484 { | |
485 DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | |
486 DCHECK(!newItem.isCached()); | |
487 DCHECK(!oldItem.isCached()); | |
488 | |
489 if (newItem.skippedCache()) { | |
490 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: sk
ipped-cache in cached subsequence", &newItem, &oldItem); | |
491 NOTREACHED(); | |
492 } | |
493 | |
494 if (newItem.isCacheable() && !clientCacheIsValid(newItem.client())) { | |
495 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: in
validated in cached subsequence", &newItem, &oldItem); | |
496 NOTREACHED(); | |
497 } | |
498 | |
499 if (newItem.equals(oldItem)) | |
500 return; | |
501 | |
502 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: displa
y item changed", &newItem, &oldItem); | |
503 | 501 |
504 #ifndef NDEBUG | 502 #ifndef NDEBUG |
505 if (newItem.isDrawing()) { | 503 if (newItem.isDrawing()) { |
506 RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayIte
m&>(newItem).picture(); | 504 RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayIte
m&>(newItem).picture(); |
507 RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayIte
m&>(oldItem).picture(); | 505 RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayIte
m&>(oldItem).picture(); |
508 String oldPictureDebugString = oldPicture ? pictureAsDebugString(oldPict
ure.get()) : "None"; | 506 LOG(INFO) << "new picture:\n" << (newPicture ? pictureAsDebugString(newP
icture.get()) : "None"); |
509 String newPictureDebugString = newPicture ? pictureAsDebugString(newPict
ure.get()) : "None"; | 507 LOG(INFO) << "old picture:\n" << (oldPicture ? pictureAsDebugString(oldP
icture.get()) : "None"); |
510 WTFLogAlways("old picture:\n%s\n", oldPictureDebugString.utf8().data()); | |
511 WTFLogAlways("new picture:\n%s\n", newPictureDebugString.utf8().data()); | |
512 } | 508 } |
513 #endif // NDEBUG | 509 #endif // NDEBUG |
| 510 } |
514 | 511 |
515 NOTREACHED(); | 512 void PaintController::checkUnderInvalidation() |
| 513 { |
| 514 DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); |
| 515 |
| 516 if (!isCheckingUnderInvalidation()) |
| 517 return; |
| 518 |
| 519 const DisplayItem& newItem = m_newDisplayItemList.last(); |
| 520 const DisplayItem& oldItem = *m_underInvalidationCheckingBegin++; |
| 521 |
| 522 if (newItem.isCacheable() && !clientCacheIsValid(newItem.client())) { |
| 523 showUnderInvalidationError("under-invalidation of PaintLayer: invalidate
d in cached subsequence", newItem, oldItem); |
| 524 NOTREACHED(); |
| 525 } |
| 526 if (!newItem.equals(oldItem)) { |
| 527 showUnderInvalidationError("under-invalidation: display item changed", n
ewItem, oldItem); |
| 528 NOTREACHED(); |
| 529 } |
516 } | 530 } |
517 | 531 |
518 #endif // DCHECK_IS_ON() | 532 #endif // DCHECK_IS_ON() |
519 | 533 |
520 #ifndef NDEBUG | 534 #ifndef NDEBUG |
521 | 535 |
522 String PaintController::displayItemListAsDebugString(const DisplayItemList& list
) const | 536 String PaintController::displayItemListAsDebugString(const DisplayItemList& list
) const |
523 { | 537 { |
524 StringBuilder stringBuilder; | 538 StringBuilder stringBuilder; |
525 size_t i = 0; | 539 size_t i = 0; |
526 for (auto it = list.begin(); it != list.end(); ++it, ++i) { | 540 for (auto it = list.begin(); it != list.end(); ++it, ++i) { |
527 const DisplayItem& displayItem = *it; | 541 const DisplayItem& displayItem = *it; |
528 if (i) | 542 if (i) |
529 stringBuilder.append(",\n"); | 543 stringBuilder.append(",\n"); |
530 stringBuilder.append(String::format("{index: %d, ", (int)i)); | 544 stringBuilder.append(String::format("{index: %d, ", (int)i)); |
531 displayItem.dumpPropertiesAsDebugString(stringBuilder); | 545 displayItem.dumpPropertiesAsDebugString(stringBuilder); |
532 if (displayItem.hasValidClient()) { | 546 if (displayItem.hasValidClient()) { |
533 stringBuilder.append(", cacheIsValid: "); | 547 stringBuilder.append(", cacheIsValid: "); |
534 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "tru
e" : "false"); | 548 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "tru
e" : "false"); |
535 } | 549 } |
536 IntRect visualRect = list.visualRect(i); | 550 if (list.hasVisualRect(i)) { |
537 stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]", | 551 IntRect visualRect = list.visualRect(i); |
538 visualRect.x(), visualRect.y(), | 552 stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]", |
539 visualRect.width(), visualRect.height())); | 553 visualRect.x(), visualRect.y(), |
| 554 visualRect.width(), visualRect.height())); |
| 555 } |
540 stringBuilder.append('}'); | 556 stringBuilder.append('}'); |
541 } | 557 } |
542 return stringBuilder.toString(); | 558 return stringBuilder.toString(); |
543 } | 559 } |
544 | 560 |
545 void PaintController::showDebugData() const | 561 void PaintController::showDebugData() const |
546 { | 562 { |
547 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri
ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); | 563 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri
ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); |
548 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m
_newDisplayItemList).utf8().data()); | 564 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m
_newDisplayItemList).utf8().data()); |
549 } | 565 } |
550 | 566 |
551 #endif // ifndef NDEBUG | 567 #endif // ifndef NDEBUG |
552 | 568 |
553 } // namespace blink | 569 } // namespace blink |
OLD | NEW |