Index: Source/platform/graphics/paint/DisplayItemList.cpp |
diff --git a/Source/platform/graphics/paint/DisplayItemList.cpp b/Source/platform/graphics/paint/DisplayItemList.cpp |
index 2947afd84b91892ae388df0b67a981c1e7c63d68..3a79ddbddea3313b57ec5bba534ed5f6175a9211 100644 |
--- a/Source/platform/graphics/paint/DisplayItemList.cpp |
+++ b/Source/platform/graphics/paint/DisplayItemList.cpp |
@@ -91,7 +91,9 @@ void DisplayItemList::processNewItem(DisplayItem* displayItem) |
#endif |
ASSERT_NOT_REACHED(); |
} |
- addItemToIndexIfNeeded(*displayItem, m_newDisplayItems.size() - 1, m_newDisplayItemIndicesByClient); |
+ // TODO: Do we need to check duplicated ids for other types? |
+ if (displayItem->isCached() || displayItem->isCacheable()) |
+ addItemToIndex(*displayItem, m_newDisplayItems.size() - 1, m_newDisplayItemIndicesByClient); |
#endif // ENABLE(ASSERT) |
ASSERT(!displayItem->skippedCache()); // Only DisplayItemList can set the flag. |
@@ -119,6 +121,7 @@ void DisplayItemList::invalidate(DisplayItemClient client) |
ASSERT(m_newDisplayItems.isEmpty()); |
updateValidlyCachedClientsIfNeeded(); |
m_validlyCachedClients.remove(client); |
+ m_subtreeIndicesByClient.remove(client); |
} |
void DisplayItemList::invalidateAll() |
@@ -129,6 +132,8 @@ void DisplayItemList::invalidateAll() |
m_currentDisplayItems.clear(); |
m_validlyCachedClients.clear(); |
m_validlyCachedClientsDirty = false; |
+ m_subtreeIndicesByClient.clear(); |
+ m_subtreeIndicesByClientDirty = false; |
} |
bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const |
@@ -139,6 +144,15 @@ bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const |
return m_validlyCachedClients.contains(client); |
} |
+bool DisplayItemList::subtreeCacheIsValid(DisplayItemClient client, DisplayItem::Type type) const |
+{ |
+ ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
+ if (skippingCache()) |
+ return false; |
+ updateSubtreeIndicesByClientIfNeeded(); |
+ return findMatchingItemFromIndex(DisplayItem::Id(client, type, 0), m_subtreeIndicesByClient, m_currentDisplayItems) != kNotFound; |
+} |
+ |
size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, const DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItems& list) |
{ |
DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(id.client); |
@@ -157,15 +171,9 @@ size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, con |
return kNotFound; |
} |
-void DisplayItemList::addItemToIndexIfNeeded(const DisplayItem& displayItem, size_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
+void DisplayItemList::addItemToIndex(const DisplayItem& displayItem, size_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
{ |
- if (!displayItem.isCacheable()) |
- return; |
- |
- DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find(displayItem.client()); |
- Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? |
- displayItemIndicesByClient.add(displayItem.client(), Vector<size_t>()).storedValue->value : it->value; |
- indices.append(index); |
+ displayItemIndicesByClient.add(displayItem.client(), Vector<size_t>()).storedValue->value.append(index); |
} |
struct DisplayItemList::OutOfOrderIndexContext { |
@@ -187,6 +195,10 @@ DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::i |
if (foundIndex != kNotFound) |
return m_currentDisplayItems.begin() + foundIndex; |
+ // We have indexed all BeginSubtree display items, so don't need to find forward. |
+ if (DisplayItem::isBeginSubtreeType(id.type)) |
+ return m_currentDisplayItems.end(); |
+ |
return findOutOfOrderCachedItemForward(id, context); |
} |
@@ -201,7 +213,8 @@ DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const Di |
if (id.matches(item)) |
return context.nextItemToIndex++; |
- addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentDisplayItems.begin(), context.displayItemIndicesByClient); |
+ if (item.isDrawing() && !item.skippedCache()) |
+ addItemToIndex(item, context.nextItemToIndex - m_currentDisplayItems.begin(), context.displayItemIndicesByClient); |
} |
} |
return currentEnd; |
@@ -254,6 +267,7 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
#endif |
m_currentDisplayItems.swap(m_newDisplayItems); |
m_validlyCachedClientsDirty = true; |
+ m_subtreeIndicesByClientDirty = true; |
m_numCachedItems = 0; |
return; |
} |
@@ -266,13 +280,14 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
// 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. |
OutOfOrderIndexContext outOfOrderIndexContext(m_currentDisplayItems.begin()); |
+ outOfOrderIndexContext.displayItemIndicesByClient.swap(m_subtreeIndicesByClient); |
#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, outOfOrderIndexContext.displayItemIndicesByClient); |
+ addItemToIndex(item, i, outOfOrderIndexContext.displayItemIndicesByClient); |
++i; |
} |
} |
@@ -296,23 +311,18 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
ASSERT(newDisplayItem.isCached()); |
ASSERT(clientCacheIsValid(newDisplayItem.client())); |
if (!isSynchronized) { |
- DisplayItems::iterator foundIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId, outOfOrderIndexContext); |
- |
- if (foundIt == currentEnd) { |
+ currentIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId, outOfOrderIndexContext); |
+ if (currentIt == currentEnd) { |
#ifndef NDEBUG |
showDebugData(); |
WTFLogAlways("%s not found in m_currentDisplayItems\n", newDisplayItem.asDebugString().utf8().data()); |
#endif |
ASSERT_NOT_REACHED(); |
- |
- // If foundIt == currentEnd, it means that we did not find the cached display item. This should be impossible, but may occur |
- // if there is a bug in the system, such as under-invalidation, incorrect cache checking or duplicate display ids. In this case, |
+ // We did not find the cached display item. This should be impossible, but may occur if there is a bug in |
+ // the system, such as under-invalidation, incorrect cache checking or duplicate display ids. In this case, |
// 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()) { |
@@ -344,6 +354,7 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
m_newDisplayItems.clear(); |
m_validlyCachedClientsDirty = true; |
pdr.
2015/08/20 22:45:06
Are we still planning on removing m_validlyCachedC
Xianzhu
2015/08/21 00:31:38
I'm thinking of this, but not sure for now about:
|
+ m_subtreeIndicesByClientDirty = true; |
m_currentDisplayItems.swap(updatedList); |
m_numCachedItems = 0; |
} |
@@ -391,6 +402,20 @@ void DisplayItemList::updateValidlyCachedClientsIfNeeded() const |
} |
} |
+void DisplayItemList::updateSubtreeIndicesByClientIfNeeded() const |
+{ |
+ if (!m_subtreeIndicesByClientDirty) |
+ return; |
+ |
+ m_subtreeIndicesByClient.clear(); |
+ m_subtreeIndicesByClientDirty = false; |
+ |
+ for (DisplayItems::const_iterator it = m_currentDisplayItems.begin(); it != m_currentDisplayItems.end(); ++it) { |
+ if (it->isBeginSubtree() && !it->skippedCache()) |
+ addItemToIndex(*it, it - m_currentDisplayItems.begin(), m_subtreeIndicesByClient); |
+ } |
+} |
+ |
void DisplayItemList::appendToWebDisplayItemList(WebDisplayItemList* list) |
{ |
for (const DisplayItem& item : m_currentDisplayItems) |