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 cde9a3c99881117026576217ac7b733d00d121e9..0e06a6fe2d8e07c690e719268a74d07915a84cf3 100644 |
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp |
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp |
@@ -51,7 +51,7 @@ bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client |
++m_numCachedNewItems; |
ensureNewDisplayItemListInitialCapacity(); |
if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
- processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifact.getDisplayItemList()[cachedItem])); |
+ processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifact.getDisplayItemList()[cachedItem]), FromCachedItem); |
m_nextItemToMatch = cachedItem + 1; |
// Items before m_nextItemToMatch have been copied so we don't need to index them. |
@@ -133,7 +133,7 @@ void PaintController::removeLastDisplayItem() |
#if DCHECK_IS_ON() |
// Also remove the index pointing to the removed display item. |
- DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient.find(&m_newDisplayItemList.last().client()); |
+ IndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient.find(&m_newDisplayItemList.last().client()); |
if (it != m_newDisplayItemIndicesByClient.end()) { |
Vector<size_t>& indices = it->value; |
if (!indices.isEmpty() && indices.last() == (m_newDisplayItemList.size() - 1)) |
@@ -162,7 +162,7 @@ const DisplayItem* PaintController::lastDisplayItem(unsigned offset) |
return nullptr; |
} |
-void PaintController::processNewItem(DisplayItem& displayItem) |
+void PaintController::processNewItem(DisplayItem& displayItem, NewItemSource newItemSource) |
{ |
DCHECK(!m_constructionDisabled); |
@@ -189,8 +189,23 @@ void PaintController::processNewItem(DisplayItem& displayItem) |
} |
#endif |
- if (isSkippingCache()) |
+ if (isSkippingCache()) { |
+ DCHECK(newItemSource == NewPainting); |
displayItem.setSkippedCache(); |
+ } |
+ |
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
+ if (newItemSource != FromCachedSubsequence) |
+ m_currentChunkIsFromCachedSubsequence = false; |
+ |
+ size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex(); |
+ if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) { |
+ DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex()); |
+ if (lastChunkIndex != kNotFound) |
+ generateChunkRerasterizationRects(m_newPaintChunks.paintChunkAt(lastChunkIndex)); |
+ m_currentChunkIsFromCachedSubsequence = true; |
+ } |
+ } |
#if DCHECK_IS_ON() |
// Verify noop begin/end pairs have been removed. |
@@ -214,9 +229,6 @@ void PaintController::processNewItem(DisplayItem& displayItem) |
if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
checkUnderInvalidation(); |
#endif // DCHECK_IS_ON() |
- |
- if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
- m_newPaintChunks.incrementDisplayItemIndex(displayItem); |
} |
void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id, const PaintChunkProperties& newProperties) |
@@ -247,9 +259,9 @@ bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const |
return client.displayItemsAreCached(m_currentCacheGeneration); |
} |
-size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, const DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list) |
+size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, const IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list) |
{ |
- DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id.client); |
+ IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id.client); |
if (it == displayItemIndicesByClient.end()) |
return kNotFound; |
@@ -264,12 +276,12 @@ size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con |
return kNotFound; |
} |
-void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, size_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
+void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, size_t index, IndicesByClientMap& displayItemIndicesByClient) |
{ |
if (!displayItem.isCacheable()) |
return; |
- DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find(&displayItem.client()); |
+ IndicesByClientMap::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); |
@@ -377,7 +389,7 @@ void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) |
++cachedChunk; |
updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); |
} |
- processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem)); |
+ processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), FromCachedSubsequence); |
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); |
} |
@@ -410,6 +422,7 @@ void PaintController::resetCurrentListIndices() |
{ |
m_nextItemToMatch = 0; |
m_nextItemToIndex = 0; |
+ m_nextChunkToMatch = 0; |
#if DCHECK_IS_ON() |
m_underInvalidationCheckingBegin = 0; |
m_underInvalidationCheckingEnd = 0; |
@@ -430,6 +443,9 @@ void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb |
m_newDisplayItemIndicesByClient.clear(); |
#endif |
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && !m_newDisplayItemList.isEmpty()) |
+ generateChunkRerasterizationRects(m_newPaintChunks.lastChunk()); |
+ |
SkPictureGpuAnalyzer gpuAnalyzer; |
m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationReason::next(); |
@@ -460,6 +476,7 @@ void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb |
m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_newPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization()); |
resetCurrentListIndices(); |
m_outOfOrderItemIndices.clear(); |
+ m_outOfOrderChunkIndices.clear(); |
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
for (const auto& chunk : m_currentPaintArtifact.paintChunks()) { |
@@ -517,6 +534,85 @@ void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& dis |
m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDisplayItem(displayItem, offsetFromLayoutObject)); |
} |
+void PaintController::generateChunkRerasterizationRects(PaintChunk& newChunk) |
+{ |
+ DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
+ if (m_currentChunkIsFromCachedSubsequence) |
+ return; |
+ |
+ if (!newChunk.id) { |
chrishtr
2016/08/26 18:10:51
Why would there be no id?
Xianzhu
2016/08/26 18:39:23
Please see https://cs.chromium.org/chromium/src/th
|
+ newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRect())); |
+ return; |
+ } |
+ |
+ // Try to match old chunk sequentially first. |
+ const auto& oldChunks = m_currentPaintArtifact.paintChunks(); |
+ while (m_nextChunkToMatch < oldChunks.size()) { |
+ const PaintChunk& oldChunk = oldChunks[m_nextChunkToMatch]; |
+ if (newChunk.matches(oldChunk)) { |
+ generateChunkRerasterizationRectsComparingOldChunk(newChunk, oldChunk); |
+ ++m_nextChunkToMatch; |
+ return; |
+ } |
+ |
+ // Add skipped old chunks into the index. |
+ if (oldChunk.id) { |
+ auto it = m_outOfOrderChunkIndices.find(&oldChunk.id->client); |
+ Vector<size_t>& indices = it == m_outOfOrderChunkIndices.end() ? |
+ m_outOfOrderChunkIndices.add(&oldChunk.id->client, Vector<size_t>()).storedValue->value : it->value; |
+ indices.append(m_nextChunkToMatch); |
+ } |
+ ++m_nextChunkToMatch; |
+ } |
+ |
+ // Sequential matching reaches the end. Find from the out-of-order index. |
+ auto it = m_outOfOrderChunkIndices.find(&newChunk.id->client); |
+ if (it != m_outOfOrderChunkIndices.end()) { |
+ for (size_t i : it->value) { |
+ if (newChunk.matches(oldChunks[i])) { |
+ generateChunkRerasterizationRectsComparingOldChunk(newChunk, oldChunks[i]); |
+ return; |
+ } |
+ } |
+ } |
+ |
+ // We reach here because the chunk is new. |
+ newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRect())); |
+} |
+ |
+void PaintController::generateChunkRerasterizationRectsComparingOldChunk(PaintChunk& newChunk, const PaintChunk& oldChunk) |
+{ |
+ DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
+ |
+ // TODO(wangxianzhu): Support raster invalidation for recordered display items without invalidating |
chrishtr
2016/08/26 18:10:51
Do you mean "reordered"? What is an example where
Xianzhu
2016/08/26 18:39:23
Yes :) An example is z-index change: actually we d
|
+ // display item clients. Currently we invalidate display item clients ensuring raster invalidation. |
+ |
+ // Maps from each client to the index of the first drawing-content display item of the client. |
+ HashMap<const DisplayItemClient*, size_t> oldChunkClients; |
+ for (size_t i = oldChunk.beginIndex; i < oldChunk.endIndex; ++i) { |
+ const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList()[i]; |
+ if (oldItem.hasValidClient() && oldItem.drawsContent()) |
+ oldChunkClients.add(&oldItem.client(), i); |
+ } |
+ |
+ HashSet<const DisplayItemClient*> newChunkClients; |
+ for (size_t i = newChunk.beginIndex; i < newChunk.endIndex; ++i) { |
+ const DisplayItem& newItem = m_newDisplayItemList[i]; |
+ if (newItem.drawsContent()) { |
+ if (!newItem.client().isJustCreated() && newItem.client().getPaintInvalidationReason() == PaintInvalidationNone) |
chrishtr
2016/08/26 18:10:51
This is to check for cached items?
Xianzhu
2016/08/26 18:39:23
Yes. Changed to clientCacheIsValid(newItem.client(
|
+ oldChunkClients.remove(&newItem.client()); |
+ else |
+ newChunkClients.add(&newItem.client()); |
+ } |
+ } |
+ |
+ // TODO(wangxianzhu): Handle PaintInvalidationIncremental and optimize paint offset change. |
+ for (const DisplayItemClient* client : newChunkClients) |
+ newChunk.rasterInvalidationRects.append(client->visualRect()); |
+ for (const auto& oldChunkClientInfo : oldChunkClients) |
+ newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDisplayItemList().visualRect(oldChunkClientInfo.value)); |
+} |
+ |
#if DCHECK_IS_ON() |
void PaintController::showUnderInvalidationError(const char* reason, const DisplayItem& newItem, const DisplayItem* oldItem) const |