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 28 matching lines...) Expand all Loading... |
39 DCHECK(DisplayItem::isDrawingType(type)); | 39 DCHECK(DisplayItem::isDrawingType(type)); |
40 | 40 |
41 if (displayItemConstructionIsDisabled()) | 41 if (displayItemConstructionIsDisabled()) |
42 return false; | 42 return false; |
43 | 43 |
44 if (!clientCacheIsValid(client)) | 44 if (!clientCacheIsValid(client)) |
45 return false; | 45 return false; |
46 | 46 |
47 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && | 47 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && |
48 isCheckingUnderInvalidation()) { | 48 isCheckingUnderInvalidation()) { |
49 // We are checking under-invalidation of a subsequence enclosing this displa
y item. | 49 // We are checking under-invalidation of a subsequence enclosing this |
50 // Let the client continue to actually paint the display item. | 50 // display item. Let the client continue to actually paint the display item. |
51 return false; | 51 return false; |
52 } | 52 } |
53 | 53 |
54 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type)); | 54 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type)); |
55 if (cachedItem == kNotFound) { | 55 if (cachedItem == kNotFound) { |
56 NOTREACHED(); | 56 NOTREACHED(); |
57 return false; | 57 return false; |
58 } | 58 } |
59 | 59 |
60 ++m_numCachedNewItems; | 60 ++m_numCachedNewItems; |
61 ensureNewDisplayItemListInitialCapacity(); | 61 ensureNewDisplayItemListInitialCapacity(); |
62 if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) | 62 if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) |
63 processNewItem(moveItemFromCurrentListToNewList(cachedItem)); | 63 processNewItem(moveItemFromCurrentListToNewList(cachedItem)); |
64 | 64 |
65 m_nextItemToMatch = cachedItem + 1; | 65 m_nextItemToMatch = cachedItem + 1; |
66 // Items before m_nextItemToMatch have been copied so we don't need to index t
hem. | 66 // Items before m_nextItemToMatch have been copied so we don't need to index |
| 67 // them. |
67 if (m_nextItemToMatch > m_nextItemToIndex) | 68 if (m_nextItemToMatch > m_nextItemToIndex) |
68 m_nextItemToIndex = m_nextItemToMatch; | 69 m_nextItemToIndex = m_nextItemToMatch; |
69 | 70 |
70 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { | 71 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
71 if (!isCheckingUnderInvalidation()) { | 72 if (!isCheckingUnderInvalidation()) { |
72 m_underInvalidationCheckingBegin = cachedItem; | 73 m_underInvalidationCheckingBegin = cachedItem; |
73 m_underInvalidationCheckingEnd = cachedItem + 1; | 74 m_underInvalidationCheckingEnd = cachedItem + 1; |
74 m_underInvalidationMessagePrefix = ""; | 75 m_underInvalidationMessagePrefix = ""; |
75 } | 76 } |
76 // Return false to let the painter actually paint, and we will check if the
new painting | 77 // Return false to let the painter actually paint. We will check if the new |
77 // is the same as the cached. | 78 // painting is the same as the cached one. |
78 return false; | 79 return false; |
79 } | 80 } |
80 | 81 |
81 return true; | 82 return true; |
82 } | 83 } |
83 | 84 |
84 bool PaintController::useCachedSubsequenceIfPossible( | 85 bool PaintController::useCachedSubsequenceIfPossible( |
85 const DisplayItemClient& client) { | 86 const DisplayItemClient& client) { |
86 if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled()) | 87 if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled()) |
87 return false; | 88 return false; |
88 | 89 |
89 if (!clientCacheIsValid(client)) | 90 if (!clientCacheIsValid(client)) |
90 return false; | 91 return false; |
91 | 92 |
92 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && | 93 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && |
93 isCheckingUnderInvalidation()) { | 94 isCheckingUnderInvalidation()) { |
94 // We are checking under-invalidation of an ancestor subsequence enclosing t
his one. | 95 // We are checking under-invalidation of an ancestor subsequence enclosing |
95 // The ancestor subsequence is supposed to have already "copied", so we shou
ld let the | 96 // this one. The ancestor subsequence is supposed to have already "copied", |
96 // client continue to actually paint the descendant subsequences without "co
pying". | 97 // so we should let the client continue to actually paint the descendant |
| 98 // subsequences without "copying". |
97 return false; | 99 return false; |
98 } | 100 } |
99 | 101 |
100 size_t cachedItem = | 102 size_t cachedItem = |
101 findCachedItem(DisplayItem::Id(client, DisplayItem::kSubsequence)); | 103 findCachedItem(DisplayItem::Id(client, DisplayItem::kSubsequence)); |
102 if (cachedItem == kNotFound) { | 104 if (cachedItem == kNotFound) { |
103 NOTREACHED(); | 105 NOTREACHED(); |
104 return false; | 106 return false; |
105 } | 107 } |
106 | 108 |
107 // |cachedItem| will point to the first item after the subsequence or end of t
he current list. | 109 // |cachedItem| will point to the first item after the subsequence or end of |
| 110 // the current list. |
108 ensureNewDisplayItemListInitialCapacity(); | 111 ensureNewDisplayItemListInitialCapacity(); |
109 copyCachedSubsequence(cachedItem); | 112 copyCachedSubsequence(cachedItem); |
110 | 113 |
111 m_nextItemToMatch = cachedItem; | 114 m_nextItemToMatch = cachedItem; |
112 // Items before |cachedItem| have been copied so we don't need to index them. | 115 // Items before |cachedItem| have been copied so we don't need to index them. |
113 if (cachedItem > m_nextItemToIndex) | 116 if (cachedItem > m_nextItemToIndex) |
114 m_nextItemToIndex = cachedItem; | 117 m_nextItemToIndex = cachedItem; |
115 | 118 |
116 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { | 119 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
117 // Return false to let the painter actually paint, and we will check if the
new painting | 120 // Return false to let the painter actually paint. We will check if the new |
118 // is the same as the cached. | 121 // painting is the same as the cached one. |
119 return false; | 122 return false; |
120 } | 123 } |
121 | 124 |
122 return true; | 125 return true; |
123 } | 126 } |
124 | 127 |
125 bool PaintController::lastDisplayItemIsNoopBegin() const { | 128 bool PaintController::lastDisplayItemIsNoopBegin() const { |
126 if (m_newDisplayItemList.isEmpty()) | 129 if (m_newDisplayItemList.isEmpty()) |
127 return false; | 130 return false; |
128 | 131 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 175 |
173 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 176 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
174 if (!isSkippingCache()) { | 177 if (!isSkippingCache()) { |
175 if (displayItem.isCacheable()) { | 178 if (displayItem.isCacheable()) { |
176 // Mark the client shouldKeepAlive under this PaintController. | 179 // Mark the client shouldKeepAlive under this PaintController. |
177 // The status will end after the new display items are committed. | 180 // The status will end after the new display items are committed. |
178 displayItem.client().beginShouldKeepAlive(this); | 181 displayItem.client().beginShouldKeepAlive(this); |
179 | 182 |
180 if (!m_currentSubsequenceClients.isEmpty()) { | 183 if (!m_currentSubsequenceClients.isEmpty()) { |
181 // Mark the client shouldKeepAlive under the current subsequence. | 184 // Mark the client shouldKeepAlive under the current subsequence. |
182 // The status will end when the subsequence owner is invalidated or dele
ted. | 185 // The status will end when the subsequence owner is invalidated or |
| 186 // deleted. |
183 displayItem.client().beginShouldKeepAlive( | 187 displayItem.client().beginShouldKeepAlive( |
184 m_currentSubsequenceClients.last()); | 188 m_currentSubsequenceClients.last()); |
185 } | 189 } |
186 } | 190 } |
187 | 191 |
188 if (displayItem.getType() == DisplayItem::kSubsequence) { | 192 if (displayItem.getType() == DisplayItem::kSubsequence) { |
189 m_currentSubsequenceClients.append(&displayItem.client()); | 193 m_currentSubsequenceClients.append(&displayItem.client()); |
190 } else if (displayItem.getType() == DisplayItem::kEndSubsequence) { | 194 } else if (displayItem.getType() == DisplayItem::kEndSubsequence) { |
191 CHECK(m_currentSubsequenceClients.last() == &displayItem.client()); | 195 CHECK(m_currentSubsequenceClients.last() == &displayItem.client()); |
192 m_currentSubsequenceClients.removeLast(); | 196 m_currentSubsequenceClients.removeLast(); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 ? displayItemIndicesByClient | 315 ? displayItemIndicesByClient |
312 .add(&displayItem.client(), Vector<size_t>()) | 316 .add(&displayItem.client(), Vector<size_t>()) |
313 .storedValue->value | 317 .storedValue->value |
314 : it->value; | 318 : it->value; |
315 indices.append(index); | 319 indices.append(index); |
316 } | 320 } |
317 | 321 |
318 size_t PaintController::findCachedItem(const DisplayItem::Id& id) { | 322 size_t PaintController::findCachedItem(const DisplayItem::Id& id) { |
319 DCHECK(clientCacheIsValid(id.client)); | 323 DCHECK(clientCacheIsValid(id.client)); |
320 | 324 |
321 // Try to find the item sequentially first. This is fast if the current list a
nd the new list are in | 325 // Try to find the item sequentially first. This is fast if the current list |
322 // the same order around the new item. If found, we don't need to update and l
ookup the index. | 326 // and the new list are in the same order around the new item. If found, we |
| 327 // don't need to update and lookup the index. |
323 for (size_t i = m_nextItemToMatch; | 328 for (size_t i = m_nextItemToMatch; |
324 i < m_currentPaintArtifact.getDisplayItemList().size(); ++i) { | 329 i < m_currentPaintArtifact.getDisplayItemList().size(); ++i) { |
325 // We encounter an item that has already been copied which indicates we can'
t do sequential matching. | 330 // We encounter an item that has already been copied which indicates we |
| 331 // can't do sequential matching. |
326 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i]; | 332 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i]; |
327 if (!item.hasValidClient()) | 333 if (!item.hasValidClient()) |
328 break; | 334 break; |
329 if (id == item.getId()) { | 335 if (id == item.getId()) { |
330 #ifndef NDEBUG | 336 #ifndef NDEBUG |
331 ++m_numSequentialMatches; | 337 ++m_numSequentialMatches; |
332 #endif | 338 #endif |
333 return i; | 339 return i; |
334 } | 340 } |
335 // We encounter a different cacheable item which also indicates we can't do
sequential matching. | 341 // We encounter a different cacheable item which also indicates we can't do |
| 342 // sequential matching. |
336 if (item.isCacheable()) | 343 if (item.isCacheable()) |
337 break; | 344 break; |
338 } | 345 } |
339 | 346 |
340 size_t foundIndex = findMatchingItemFromIndex( | 347 size_t foundIndex = findMatchingItemFromIndex( |
341 id, m_outOfOrderItemIndices, m_currentPaintArtifact.getDisplayItemList()); | 348 id, m_outOfOrderItemIndices, m_currentPaintArtifact.getDisplayItemList()); |
342 if (foundIndex != kNotFound) { | 349 if (foundIndex != kNotFound) { |
343 #ifndef NDEBUG | 350 #ifndef NDEBUG |
344 ++m_numOutOfOrderMatches; | 351 ++m_numOutOfOrderMatches; |
345 #endif | 352 #endif |
(...skipping 26 matching lines...) Expand all Loading... |
372 | 379 |
373 #ifndef NDEBUG | 380 #ifndef NDEBUG |
374 showDebugData(); | 381 showDebugData(); |
375 LOG(ERROR) << id.client.debugName() << ":" | 382 LOG(ERROR) << id.client.debugName() << ":" |
376 << DisplayItem::typeAsDebugString(id.type); | 383 << DisplayItem::typeAsDebugString(id.type); |
377 #endif | 384 #endif |
378 | 385 |
379 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) | 386 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) |
380 CHECK(false) << "Can't find cached display item"; | 387 CHECK(false) << "Can't find cached display item"; |
381 | 388 |
382 // We did not find the cached display item. This should be impossible, but may
occur if there is a bug | 389 // We did not find the cached display item. This should be impossible, but may |
383 // in the system, such as under-invalidation, incorrect cache checking or dupl
icate display ids. | 390 // occur if there is a bug in the system, such as under-invalidation, |
384 // In this case, the caller should fall back to repaint the display item. | 391 // incorrect cache checking or duplicate display ids. In this case, the caller |
| 392 // should fall back to repaint the display item. |
385 return kNotFound; | 393 return kNotFound; |
386 } | 394 } |
387 | 395 |
388 // Copies a cached subsequence from current list to the new list. On return, | 396 // Copies a cached subsequence from current list to the new list. On return, |
389 // |cachedItemIndex| points to the item after the EndSubsequence item of the sub
sequence. | 397 // |cachedItemIndex| points to the item after the EndSubsequence item of the |
390 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs
equence, | 398 // subsequence. When paintUnderInvaldiationCheckingEnabled() we'll not actually |
391 // but mark the begin and end of the subsequence for under-invalidation checking
. | 399 // copy the subsequence, but mark the begin and end of the subsequence for |
| 400 // under-invalidation checking. |
392 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) { | 401 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) { |
393 AutoReset<size_t> subsequenceBeginIndex( | 402 AutoReset<size_t> subsequenceBeginIndex( |
394 &m_currentCachedSubsequenceBeginIndexInNewList, | 403 &m_currentCachedSubsequenceBeginIndexInNewList, |
395 m_newDisplayItemList.size()); | 404 m_newDisplayItemList.size()); |
396 DisplayItem* cachedItem = | 405 DisplayItem* cachedItem = |
397 &m_currentPaintArtifact.getDisplayItemList()[cachedItemIndex]; | 406 &m_currentPaintArtifact.getDisplayItemList()[cachedItemIndex]; |
398 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); | 407 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); |
399 | 408 |
400 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { | 409 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
401 DCHECK(!isCheckingUnderInvalidation()); | 410 DCHECK(!isCheckingUnderInvalidation()); |
402 m_underInvalidationCheckingBegin = cachedItemIndex; | 411 m_underInvalidationCheckingBegin = cachedItemIndex; |
403 m_underInvalidationMessagePrefix = | 412 m_underInvalidationMessagePrefix = |
404 "(In cached subsequence of " + cachedItem->client().debugName() + ")"; | 413 "(In cached subsequence of " + cachedItem->client().debugName() + ")"; |
405 } | 414 } |
406 | 415 |
407 DisplayItem::Id endSubsequenceId(cachedItem->client(), | 416 DisplayItem::Id endSubsequenceId(cachedItem->client(), |
408 DisplayItem::kEndSubsequence); | 417 DisplayItem::kEndSubsequence); |
409 Vector<PaintChunk>::const_iterator cachedChunk; | 418 Vector<PaintChunk>::const_iterator cachedChunk; |
410 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 419 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
411 cachedChunk = | 420 cachedChunk = |
412 m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedItemIndex); | 421 m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedItemIndex); |
413 DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end()); | 422 DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end()); |
414 updateCurrentPaintChunkProperties( | 423 updateCurrentPaintChunkProperties( |
415 cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); | 424 cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); |
416 } else { | 425 } else { |
417 // This is to avoid compilation error about uninitialized variable on Window
s. | 426 // Avoid uninitialized variable error on Windows. |
418 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); | 427 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); |
419 } | 428 } |
420 | 429 |
421 while (true) { | 430 while (true) { |
422 DCHECK(cachedItem->hasValidClient()); | 431 DCHECK(cachedItem->hasValidClient()); |
423 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 432 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
424 CHECK(cachedItem->client().isAlive()); | 433 CHECK(cachedItem->client().isAlive()); |
425 #endif | 434 #endif |
426 ++m_numCachedNewItems; | 435 ++m_numCachedNewItems; |
427 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; | 436 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 ++oldIndex) { | 685 ++oldIndex) { |
677 const DisplayItem& oldItem = | 686 const DisplayItem& oldItem = |
678 m_currentPaintArtifact.getDisplayItemList()[oldIndex]; | 687 m_currentPaintArtifact.getDisplayItemList()[oldIndex]; |
679 const DisplayItemClient* clientToInvalidate = nullptr; | 688 const DisplayItemClient* clientToInvalidate = nullptr; |
680 bool isPotentiallyInvalidClient = false; | 689 bool isPotentiallyInvalidClient = false; |
681 if (!oldItem.hasValidClient()) { | 690 if (!oldItem.hasValidClient()) { |
682 size_t movedToIndex = m_itemsMovedIntoNewList[oldIndex]; | 691 size_t movedToIndex = m_itemsMovedIntoNewList[oldIndex]; |
683 if (m_newDisplayItemList[movedToIndex].drawsContent()) { | 692 if (m_newDisplayItemList[movedToIndex].drawsContent()) { |
684 if (movedToIndex < newChunk.beginIndex || | 693 if (movedToIndex < newChunk.beginIndex || |
685 movedToIndex >= newChunk.endIndex) { | 694 movedToIndex >= newChunk.endIndex) { |
686 // The item has been moved into another chunk, so need to invalidate i
t in the old chunk. | 695 // The item has been moved into another chunk, so need to invalidate |
| 696 // it in the old chunk. |
687 clientToInvalidate = &m_newDisplayItemList[movedToIndex].client(); | 697 clientToInvalidate = &m_newDisplayItemList[movedToIndex].client(); |
688 // And invalidate in the new chunk into which the item was moved. | 698 // And invalidate in the new chunk into which the item was moved. |
689 PaintChunk& movedToChunk = | 699 PaintChunk& movedToChunk = |
690 m_newPaintChunks.findChunkByDisplayItemIndex(movedToIndex); | 700 m_newPaintChunks.findChunkByDisplayItemIndex(movedToIndex); |
691 addRasterInvalidationInfo( | 701 addRasterInvalidationInfo( |
692 clientToInvalidate, movedToChunk, | 702 clientToInvalidate, movedToChunk, |
693 FloatRect(clientToInvalidate->visualRect())); | 703 FloatRect(clientToInvalidate->visualRect())); |
694 } else if (movedToIndex < highestMovedToIndex) { | 704 } else if (movedToIndex < highestMovedToIndex) { |
695 // The item has been moved behind other cached items, so need to inval
idate the area | 705 // The item has been moved behind other cached items, so need to |
696 // that is probably exposed by the item moved earlier. | 706 // invalidate the area that is probably exposed by the item moved |
| 707 // earlier. |
697 clientToInvalidate = &m_newDisplayItemList[movedToIndex].client(); | 708 clientToInvalidate = &m_newDisplayItemList[movedToIndex].client(); |
698 } else { | 709 } else { |
699 highestMovedToIndex = movedToIndex; | 710 highestMovedToIndex = movedToIndex; |
700 } | 711 } |
701 } | 712 } |
702 } else if (oldItem.drawsContent()) { | 713 } else if (oldItem.drawsContent()) { |
703 isPotentiallyInvalidClient = true; | 714 isPotentiallyInvalidClient = true; |
704 clientToInvalidate = &oldItem.client(); | 715 clientToInvalidate = &oldItem.client(); |
705 } | 716 } |
706 if (clientToInvalidate && | 717 if (clientToInvalidate && |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 size_t oldItemIndex = m_underInvalidationCheckingBegin + | 777 size_t oldItemIndex = m_underInvalidationCheckingBegin + |
767 m_skippedProbableUnderInvalidationCount; | 778 m_skippedProbableUnderInvalidationCount; |
768 DisplayItem* oldItem = | 779 DisplayItem* oldItem = |
769 oldItemIndex < m_currentPaintArtifact.getDisplayItemList().size() | 780 oldItemIndex < m_currentPaintArtifact.getDisplayItemList().size() |
770 ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] | 781 ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] |
771 : nullptr; | 782 : nullptr; |
772 | 783 |
773 bool oldAndNewEqual = oldItem && newItem.equals(*oldItem); | 784 bool oldAndNewEqual = oldItem && newItem.equals(*oldItem); |
774 if (!oldAndNewEqual) { | 785 if (!oldAndNewEqual) { |
775 if (newItem.isBegin()) { | 786 if (newItem.isBegin()) { |
776 // Temporarily skip mismatching begin display item which may be removed wh
en we remove a no-op pair. | 787 // Temporarily skip mismatching begin display item which may be removed |
| 788 // when we remove a no-op pair. |
777 ++m_skippedProbableUnderInvalidationCount; | 789 ++m_skippedProbableUnderInvalidationCount; |
778 return; | 790 return; |
779 } | 791 } |
780 if (newItem.isDrawing() && m_skippedProbableUnderInvalidationCount == 1) { | 792 if (newItem.isDrawing() && m_skippedProbableUnderInvalidationCount == 1) { |
781 DCHECK_GE(m_newDisplayItemList.size(), 2u); | 793 DCHECK_GE(m_newDisplayItemList.size(), 2u); |
782 if (m_newDisplayItemList[m_newDisplayItemList.size() - 2].getType() == | 794 if (m_newDisplayItemList[m_newDisplayItemList.size() - 2].getType() == |
783 DisplayItem::kBeginCompositing) { | 795 DisplayItem::kBeginCompositing) { |
784 // This might be a drawing item between a pair of begin/end compositing
display items that will be folded | 796 // This might be a drawing item between a pair of begin/end compositing |
785 // into a single drawing display item. | 797 // display items that will be folded into a single drawing display item. |
786 ++m_skippedProbableUnderInvalidationCount; | 798 ++m_skippedProbableUnderInvalidationCount; |
787 return; | 799 return; |
788 } | 800 } |
789 } | 801 } |
790 } | 802 } |
791 | 803 |
792 if (m_skippedProbableUnderInvalidationCount || !oldAndNewEqual) { | 804 if (m_skippedProbableUnderInvalidationCount || !oldAndNewEqual) { |
793 // If we ever skipped reporting any under-invalidations, report the earliest
one. | 805 // If we ever skipped reporting any under-invalidations, report the earliest |
| 806 // one. |
794 showUnderInvalidationError( | 807 showUnderInvalidationError( |
795 "under-invalidation: display item changed", | 808 "under-invalidation: display item changed", |
796 m_newDisplayItemList[m_newDisplayItemList.size() - | 809 m_newDisplayItemList[m_newDisplayItemList.size() - |
797 m_skippedProbableUnderInvalidationCount - 1], | 810 m_skippedProbableUnderInvalidationCount - 1], |
798 &m_currentPaintArtifact | 811 &m_currentPaintArtifact |
799 .getDisplayItemList()[m_underInvalidationCheckingBegin]); | 812 .getDisplayItemList()[m_underInvalidationCheckingBegin]); |
800 CHECK(false); | 813 CHECK(false); |
801 } | 814 } |
802 | 815 |
803 // Discard the forced repainted display item and move the cached item into m_n
ewDisplayItemList. | 816 // Discard the forced repainted display item and move the cached item into |
804 // This is to align with the non-under-invalidation-checking path to empty the
original cached slot, | 817 // m_newDisplayItemList. This is to align with the |
805 // leaving only disappeared or invalidated display items in the old list after
painting. | 818 // non-under-invalidation-checking path to empty the original cached slot, |
| 819 // leaving only disappeared or invalidated display items in the old list after |
| 820 // painting. |
806 m_newDisplayItemList.removeLast(); | 821 m_newDisplayItemList.removeLast(); |
807 moveItemFromCurrentListToNewList(oldItemIndex); | 822 moveItemFromCurrentListToNewList(oldItemIndex); |
808 | 823 |
809 ++m_underInvalidationCheckingBegin; | 824 ++m_underInvalidationCheckingBegin; |
810 } | 825 } |
811 | 826 |
812 String PaintController::displayItemListAsDebugString( | 827 String PaintController::displayItemListAsDebugString( |
813 const DisplayItemList& list, | 828 const DisplayItemList& list, |
814 bool showPictures) const { | 829 bool showPictures) const { |
815 StringBuilder stringBuilder; | 830 StringBuilder stringBuilder; |
816 size_t i = 0; | 831 size_t i = 0; |
817 for (auto it = list.begin(); it != list.end(); ++it, ++i) { | 832 for (auto it = list.begin(); it != list.end(); ++it, ++i) { |
818 const DisplayItem& displayItem = *it; | 833 const DisplayItem& displayItem = *it; |
819 if (i) | 834 if (i) |
820 stringBuilder.append(",\n"); | 835 stringBuilder.append(",\n"); |
821 stringBuilder.append(String::format("{index: %zu, ", i)); | 836 stringBuilder.append(String::format("{index: %zu, ", i)); |
822 #ifndef NDEBUG | 837 #ifndef NDEBUG |
823 displayItem.dumpPropertiesAsDebugString(stringBuilder); | 838 displayItem.dumpPropertiesAsDebugString(stringBuilder); |
824 #endif | 839 #endif |
825 | 840 |
826 if (displayItem.hasValidClient()) { | 841 if (displayItem.hasValidClient()) { |
827 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 842 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
828 if (!displayItem.client().isAlive()) { | 843 if (!displayItem.client().isAlive()) { |
829 stringBuilder.append(", clientIsAlive: false"); | 844 stringBuilder.append(", clientIsAlive: false"); |
830 } else { | 845 } else { |
831 #else | 846 #else |
832 // debugName() and clientCacheIsValid() can only be called on alive client
, so only output it for | 847 // debugName() and clientCacheIsValid() can only be called on a live |
833 // m_newDisplayItemList in which we are sure the clients are all alive. | 848 // client, so only output it for m_newDisplayItemList, in which we are |
| 849 // sure the clients are all alive. |
834 if (&list == &m_newDisplayItemList) { | 850 if (&list == &m_newDisplayItemList) { |
835 #endif | 851 #endif |
836 #ifdef NDEBUG | 852 #ifdef NDEBUG |
837 stringBuilder.append( | 853 stringBuilder.append( |
838 String::format("clientDebugName: \"%s\"", | 854 String::format("clientDebugName: \"%s\"", |
839 displayItem.client().debugName().ascii().data())); | 855 displayItem.client().debugName().ascii().data())); |
840 #endif | 856 #endif |
841 stringBuilder.append(", cacheIsValid: "); | 857 stringBuilder.append(", cacheIsValid: "); |
842 stringBuilder.append( | 858 stringBuilder.append( |
843 clientCacheIsValid(displayItem.client()) ? "true" : "false"); | 859 clientCacheIsValid(displayItem.client()) ? "true" : "false"); |
(...skipping 25 matching lines...) Expand all Loading... |
869 m_currentPaintArtifact.getDisplayItemList(), showPictures) | 885 m_currentPaintArtifact.getDisplayItemList(), showPictures) |
870 .utf8() | 886 .utf8() |
871 .data()); | 887 .data()); |
872 WTFLogAlways("new display item list: [%s]\n", | 888 WTFLogAlways("new display item list: [%s]\n", |
873 displayItemListAsDebugString(m_newDisplayItemList, showPictures) | 889 displayItemListAsDebugString(m_newDisplayItemList, showPictures) |
874 .utf8() | 890 .utf8() |
875 .data()); | 891 .data()); |
876 } | 892 } |
877 | 893 |
878 } // namespace blink | 894 } // namespace blink |
OLD | NEW |