Index: Source/platform/graphics/paint/DisplayItemList.cpp |
diff --git a/Source/platform/graphics/paint/DisplayItemList.cpp b/Source/platform/graphics/paint/DisplayItemList.cpp |
index 8a66d0c723c1491684403b72ab143d992878312c..2947afd84b91892ae388df0b67a981c1e7c63d68 100644 |
--- a/Source/platform/graphics/paint/DisplayItemList.cpp |
+++ b/Source/platform/graphics/paint/DisplayItemList.cpp |
@@ -149,8 +149,8 @@ size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, con |
for (size_t index : indices) { |
// TODO(pdr): elementAt is not cheap so this should be refactored (See crbug.com/505965). |
const DisplayItem& existingItem = list[index]; |
- ASSERT(existingItem.ignoreFromDisplayList() || existingItem.client() == id.client); |
- if (!existingItem.ignoreFromDisplayList() && id.matches(existingItem)) |
+ ASSERT(!existingItem.isValid() || existingItem.client() == id.client); |
+ if (existingItem.isValid() && id.matches(existingItem)) |
return index; |
} |
@@ -168,30 +168,40 @@ void DisplayItemList::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz |
indices.append(index); |
} |
-DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::iterator currentIt, const DisplayItem::Id& id, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
+struct DisplayItemList::OutOfOrderIndexContext { |
+ OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin) { } |
+ |
+ DisplayItems::iterator nextItemToIndex; |
+ DisplayItemIndicesByClientMap displayItemIndicesByClient; |
+}; |
+ |
+DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::iterator currentIt, const DisplayItem::Id& id, OutOfOrderIndexContext& context) |
{ |
ASSERT(clientCacheIsValid(id.client)); |
- size_t foundIndex = findMatchingItemFromIndex(id, displayItemIndicesByClient, m_currentDisplayItems); |
+ // Skip indexing of copied items. |
+ if (currentIt - context.nextItemToIndex > 0) |
+ context.nextItemToIndex = currentIt; |
+ |
+ size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndicesByClient, m_currentDisplayItems); |
if (foundIndex != kNotFound) |
return m_currentDisplayItems.begin() + foundIndex; |
- return findOutOfOrderCachedItemForward(currentIt, id, displayItemIndicesByClient); |
+ return findOutOfOrderCachedItemForward(id, context); |
} |
// Find forward for the item and index all skipped indexable items. |
-DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(DisplayItems::iterator currentIt, const DisplayItem::Id& id, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
+DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const DisplayItem::Id& id, OutOfOrderIndexContext& context) |
{ |
DisplayItems::iterator currentEnd = m_currentDisplayItems.end(); |
- for (; currentIt != currentEnd; ++currentIt) { |
- const DisplayItem& item = *currentIt; |
- if (!item.ignoreFromDisplayList() |
- && item.isCacheable() |
- && m_validlyCachedClients.contains(item.client())) { |
+ for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { |
+ const DisplayItem& item = *context.nextItemToIndex; |
+ ASSERT(item.isValid()); |
+ if (item.isCacheable() && clientCacheIsValid(item.client())) { |
if (id.matches(item)) |
- return currentIt; |
+ return context.nextItemToIndex++; |
- addItemToIndexIfNeeded(item, currentIt - m_currentDisplayItems.begin(), displayItemIndicesByClient); |
+ addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentDisplayItems.begin(), context.displayItemIndicesByClient); |
} |
} |
return currentEnd; |
@@ -203,14 +213,12 @@ void DisplayItemList::copyCachedSubtree(DisplayItems::iterator& currentIt, Displ |
ASSERT(currentIt->isBeginSubtree()); |
ASSERT(!currentIt->scope()); |
DisplayItem::Id endSubtreeId(currentIt->client(), DisplayItem::beginSubtreeTypeToEndSubtreeType(currentIt->type()), 0); |
- while (true) { |
- updatedList.appendByMoving(*currentIt, currentIt->derivedSize()); |
- if (endSubtreeId.matches(updatedList.last())) |
- break; |
- ++currentIt; |
+ do { |
// We should always find the EndSubtree display item. |
ASSERT(currentIt != m_currentDisplayItems.end()); |
- } |
+ updatedList.appendByMoving(*currentIt, currentIt->derivedSize()); |
+ ++currentIt; |
+ } while (!endSubtreeId.matches(updatedList.last())); |
} |
// Update the existing display items by removing invalidated entries, updating |
@@ -257,14 +265,14 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
// by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensures that when |
// out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems |
// looking for potential matches. Thus we can ensure that the algorithm runs in linear time. |
- DisplayItemIndicesByClientMap displayItemIndicesByClient; |
+ OutOfOrderIndexContext outOfOrderIndexContext(m_currentDisplayItems.begin()); |
#if ENABLE(ASSERT) |
if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { |
// Under-invalidation checking requires a full index of m_currentDisplayItems. |
size_t i = 0; |
for (const auto& item : m_currentDisplayItems) { |
- addItemToIndexIfNeeded(item, i, displayItemIndicesByClient); |
+ addItemToIndexIfNeeded(item, i, outOfOrderIndexContext.displayItemIndicesByClient); |
++i; |
} |
} |
@@ -281,17 +289,14 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); |
bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayItemId.type; |
- bool isSynchronized = currentIt != currentEnd |
- && !currentIt->ignoreFromDisplayList() |
- && newDisplayItemId.matches(*currentIt); |
+ bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matches(*currentIt); |
if (newDisplayItemHasCachedType) { |
ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()); |
ASSERT(newDisplayItem.isCached()); |
ASSERT(clientCacheIsValid(newDisplayItem.client())); |
if (!isSynchronized) { |
- DisplayItems::iterator foundIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId, displayItemIndicesByClient); |
- ASSERT(foundIt != currentIt); |
+ DisplayItems::iterator foundIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId, outOfOrderIndexContext); |
if (foundIt == currentEnd) { |
#ifndef NDEBUG |
@@ -305,11 +310,14 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
// attempt to recover rather than crashing or bailing on display of the rest of the display list. |
continue; |
} |
+ |
+ ASSERT(foundIt != currentIt); // because we are in 'if (!isSynchronized)' |
currentIt = foundIt; |
} |
if (newDisplayItem.isCachedDrawing()) { |
updatedList.appendByMoving(*currentIt, currentIt->derivedSize()); |
+ ++currentIt; |
} else { |
ASSERT(newDisplayItem.isCachedSubtree()); |
copyCachedSubtree(currentIt, updatedList); |
@@ -318,15 +326,15 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
} else { |
#if ENABLE(ASSERT) |
if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
- checkCachedDisplayItemIsUnchanged(newDisplayItem, displayItemIndicesByClient); |
+ checkCachedDisplayItemIsUnchanged(newDisplayItem, outOfOrderIndexContext.displayItemIndicesByClient); |
else |
ASSERT(!newDisplayItem.isDrawing() || newDisplayItem.skippedCache() || !clientCacheIsValid(newDisplayItem.client())); |
#endif // ENABLE(ASSERT) |
updatedList.appendByMoving(*newIt, newIt->derivedSize()); |
- } |
- if (isSynchronized) |
- ++currentIt; |
+ if (isSynchronized) |
+ ++currentIt; |
+ } |
} |
#if ENABLE(ASSERT) |
@@ -440,8 +448,8 @@ void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItem& displ |
DisplayItems::iterator foundItem = m_currentDisplayItems.begin() + index; |
RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayItem&>(displayItem).picture(); |
RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayItem&>(*foundItem).picture(); |
- // Mark the display item as ignored so that we can check if there are any remaining cached display items after merging. |
- foundItem->setIgnoredFromDisplayList(); |
+ // Invalidate the display item so that we can check if there are any remaining cached display items after merging. |
+ foundItem->clearClientForUnderInvalidationChecking(); |
if (!newPicture && !oldPicture) |
return; |
@@ -497,7 +505,7 @@ void DisplayItemList::checkNoRemainingCachedDisplayItems() |
ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()); |
for (const auto& displayItem : m_currentDisplayItems) { |
- if (displayItem.ignoreFromDisplayList() || !displayItem.isDrawing() || !clientCacheIsValid(displayItem.client())) |
+ if (!displayItem.isValid() || !displayItem.isDrawing() || !clientCacheIsValid(displayItem.client())) |
continue; |
showUnderInvalidationError("May be under-invalidation: no new display item", displayItem); |
} |
@@ -515,7 +523,7 @@ WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list) |
const DisplayItem& displayItem = *it; |
if (i) |
stringBuilder.append(",\n"); |
- if (displayItem.ignoreFromDisplayList()) { |
+ if (!displayItem.isValid()) { |
stringBuilder.append("null"); |
continue; |
} |