Index: third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp |
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp |
index ac49b8ada5618d180554bfaf35424a13018f422f..fa5209e751107c4f0f9f924bae93f7da4b670292 100644 |
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp |
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp |
@@ -99,28 +99,22 @@ |
return false; |
} |
- SubsequenceMarkers* markers = getSubsequenceMarkers(client); |
- if (!markers) { |
+ size_t cachedItem = |
+ findCachedItem(DisplayItem::Id(client, DisplayItem::kSubsequence)); |
+ if (cachedItem == kNotFound) { |
+ NOTREACHED(); |
return false; |
} |
// |cachedItem| will point to the first item after the subsequence or end of |
// the current list. |
ensureNewDisplayItemListInitialCapacity(); |
- |
- size_t sizeBeforeCopy = m_newDisplayItemList.size(); |
- copyCachedSubsequence(markers->start, markers->end); |
- |
- if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
- addCachedSubsequence(client, sizeBeforeCopy, |
- m_newDisplayItemList.size() - 1); |
- } |
- |
- m_nextItemToMatch = markers->end + 1; |
- // Items before |m_nextItemToMatch| have been copied so we don't need to index |
- // them. |
- if (m_nextItemToMatch > m_nextItemToIndex) |
- m_nextItemToIndex = m_nextItemToMatch; |
+ copyCachedSubsequence(cachedItem); |
+ |
+ m_nextItemToMatch = cachedItem; |
+ // Items before |cachedItem| have been copied so we don't need to index them. |
+ if (cachedItem > m_nextItemToIndex) |
+ m_nextItemToIndex = cachedItem; |
if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
// Return false to let the painter actually paint. We will check if the new |
@@ -129,40 +123,6 @@ |
} |
return true; |
-} |
- |
-PaintController::SubsequenceMarkers* PaintController::getSubsequenceMarkers( |
- const DisplayItemClient& client) { |
- auto result = m_currentCachedSubsequences.find(&client); |
- if (result == m_currentCachedSubsequences.end()) |
- return nullptr; |
- return &result->value; |
-} |
- |
-void PaintController::addCachedSubsequence(const DisplayItemClient& client, |
- unsigned start, |
- unsigned end) { |
- DCHECK(start <= end); |
- DCHECK(end < m_newDisplayItemList.size()); |
- if (isCheckingUnderInvalidation()) { |
- SubsequenceMarkers* markers = getSubsequenceMarkers(client); |
- if (!markers) { |
- showSequenceUnderInvalidationError( |
- "under-invalidation : unexpected subsequence", client, start, end); |
- DCHECK(false); |
- } |
- if (markers->end - markers->start != end - start) { |
- showSequenceUnderInvalidationError( |
- "under-invalidation: new subsequence wrong length", client, start, |
- end); |
- DCHECK(false); |
- } |
- } |
- |
- DCHECK(m_newCachedSubsequences.find(&client) == |
- m_newCachedSubsequences.end()); |
- |
- m_newCachedSubsequences.insert(&client, SubsequenceMarkers(start, end)); |
} |
bool PaintController::lastDisplayItemIsNoopBegin() const { |
@@ -210,29 +170,31 @@ |
return nullptr; |
} |
-#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
-void PaintController::beginShouldKeepAlive(const DisplayItemClient& client) { |
- if (!isSkippingCache()) { |
- // Mark the client shouldKeepAlive under this PaintController. |
- // The status will end after the new display items are committed. |
- client.beginShouldKeepAlive(this); |
- |
- if (!m_currentSubsequenceClients.isEmpty()) { |
- // Mark the client shouldKeepAlive under the current subsequence. |
- // The status will end when the subsequence owner is invalidated or |
- // deleted. |
- client.beginShouldKeepAlive(m_currentSubsequenceClients.back()); |
- } |
- } |
-} |
-#endif |
- |
void PaintController::processNewItem(DisplayItem& displayItem) { |
DCHECK(!m_constructionDisabled); |
#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
- if (displayItem.isCacheable()) { |
- beginShouldKeepAlive(displayItem.client()); |
+ if (!isSkippingCache()) { |
+ if (displayItem.isCacheable()) { |
+ // Mark the client shouldKeepAlive under this PaintController. |
+ // The status will end after the new display items are committed. |
+ displayItem.client().beginShouldKeepAlive(this); |
+ |
+ if (!m_currentSubsequenceClients.isEmpty()) { |
+ // Mark the client shouldKeepAlive under the current subsequence. |
+ // The status will end when the subsequence owner is invalidated or |
+ // deleted. |
+ displayItem.client().beginShouldKeepAlive( |
+ m_currentSubsequenceClients.back()); |
+ } |
+ } |
+ |
+ if (displayItem.getType() == DisplayItem::kSubsequence) { |
+ m_currentSubsequenceClients.push_back(&displayItem.client()); |
+ } else if (displayItem.getType() == DisplayItem::kEndSubsequence) { |
+ CHECK(m_currentSubsequenceClients.back() == &displayItem.client()); |
+ m_currentSubsequenceClients.pop_back(); |
+ } |
} |
#endif |
@@ -255,6 +217,7 @@ |
const auto& beginDisplayItem = |
m_newDisplayItemList[m_newDisplayItemList.size() - 2]; |
if (beginDisplayItem.isBegin() && |
+ beginDisplayItem.getType() != DisplayItem::kSubsequence && |
!beginDisplayItem.drawsContent()) |
DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); |
} |
@@ -430,29 +393,32 @@ |
return kNotFound; |
} |
-// Copies a cached subsequence from current list to the new list. |
-// When paintUnderInvaldiationCheckingEnabled() we'll not actually |
+// Copies a cached subsequence from current list to the new list. On return, |
+// |cachedItemIndex| points to the item after the EndSubsequence item of the |
+// subsequence. When paintUnderInvaldiationCheckingEnabled() we'll not actually |
// copy the subsequence, but mark the begin and end of the subsequence for |
// under-invalidation checking. |
-void PaintController::copyCachedSubsequence(size_t beginIndex, |
- size_t endIndex) { |
+void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) { |
AutoReset<size_t> subsequenceBeginIndex( |
&m_currentCachedSubsequenceBeginIndexInNewList, |
m_newDisplayItemList.size()); |
DisplayItem* cachedItem = |
- &m_currentPaintArtifact.getDisplayItemList()[beginIndex]; |
+ &m_currentPaintArtifact.getDisplayItemList()[cachedItemIndex]; |
+ DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); |
if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
DCHECK(!isCheckingUnderInvalidation()); |
- m_underInvalidationCheckingBegin = beginIndex; |
+ m_underInvalidationCheckingBegin = cachedItemIndex; |
m_underInvalidationMessagePrefix = |
"(In cached subsequence of " + cachedItem->client().debugName() + ")"; |
} |
+ DisplayItem::Id endSubsequenceId(cachedItem->client(), |
+ DisplayItem::kEndSubsequence); |
Vector<PaintChunk>::const_iterator cachedChunk; |
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
cachedChunk = |
- m_currentPaintArtifact.findChunkByDisplayItemIndex(beginIndex); |
+ m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedItemIndex); |
DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end()); |
updateCurrentPaintChunkProperties( |
cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); |
@@ -461,32 +427,40 @@ |
cachedChunk = m_currentPaintArtifact.paintChunks().begin(); |
} |
- for (size_t currentIndex = beginIndex; currentIndex <= endIndex; |
- ++currentIndex) { |
- cachedItem = &m_currentPaintArtifact.getDisplayItemList()[currentIndex]; |
+ while (true) { |
DCHECK(cachedItem->hasValidClient()); |
#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
CHECK(cachedItem->client().isAlive()); |
#endif |
++m_numCachedNewItems; |
+ bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; |
if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && |
- currentIndex == cachedChunk->endIndex) { |
+ cachedItemIndex == cachedChunk->endIndex) { |
++cachedChunk; |
DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end()); |
updateCurrentPaintChunkProperties( |
cachedChunk->id ? &*cachedChunk->id : nullptr, |
cachedChunk->properties); |
} |
- processNewItem(moveItemFromCurrentListToNewList(currentIndex)); |
+ processNewItem(moveItemFromCurrentListToNewList(cachedItemIndex)); |
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || |
m_newPaintChunks.lastChunk().matches(*cachedChunk)); |
} |
+ |
+ ++cachedItemIndex; |
+ if (metEndSubsequence) |
+ break; |
+ |
+ // We should always be able to find the EndSubsequence display item. |
+ DCHECK(cachedItemIndex < |
+ m_currentPaintArtifact.getDisplayItemList().size()); |
+ cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cachedItemIndex]; |
} |
if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
- m_underInvalidationCheckingEnd = endIndex + 1; |
+ m_underInvalidationCheckingEnd = cachedItemIndex; |
DCHECK(isCheckingUnderInvalidation()); |
} |
} |
@@ -518,6 +492,7 @@ |
"num_non_cached_new_items", |
(int)m_newDisplayItemList.size() - m_numCachedNewItems); |
m_numCachedNewItems = 0; |
+ |
// These data structures are used during painting only. |
DCHECK(!isSkippingCache()); |
#if DCHECK_IS_ON() |
@@ -532,16 +507,6 @@ |
m_currentCacheGeneration = |
DisplayItemClient::CacheGenerationOrInvalidationReason::next(); |
- |
- m_newCachedSubsequences.swap(m_currentCachedSubsequences); |
- m_newCachedSubsequences.clear(); |
- for (auto& item : m_currentCachedSubsequences) { |
- item.key->setDisplayItemsCached(m_currentCacheGeneration); |
-#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
- DisplayItemClient::endShouldKeepAliveAllClients(item.key); |
-#endif |
- } |
- |
Vector<const DisplayItemClient*> skippedCacheClients; |
for (const auto& item : m_newDisplayItemList) { |
// No reason to continue the analysis once we have a veto. |
@@ -601,6 +566,7 @@ |
m_newDisplayItemList = DisplayItemList(0); |
#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
+ CHECK(m_currentSubsequenceClients.isEmpty()); |
DisplayItemClient::endShouldKeepAliveAllClients(this); |
#endif |
@@ -819,21 +785,6 @@ |
#endif // NDEBUG |
} |
-void PaintController::showSequenceUnderInvalidationError( |
- const char* reason, |
- const DisplayItemClient& client, |
- int start, |
- int end) { |
- LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; |
- LOG(ERROR) << "Subsequence client: " << client.debugName(); |
-#ifndef NDEBUG |
-// showDebugData(); |
-#else |
- LOG(ERROR) << "Run debug build to get more details."; |
-#endif |
- LOG(ERROR) << "See http://crbug.com/619103."; |
-} |
- |
void PaintController::checkUnderInvalidation() { |
DCHECK(RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()); |