Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Unified Diff: third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp

Issue 2277443003: [SPv2] Rasterization invalidation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: - Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..7b8214512cfd3b7b47438c8861e83e1857d0e817 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)
+ generateChunkRasterInvalidationRects(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())
+ generateChunkRasterInvalidationRects(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,86 @@ void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& dis
m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDisplayItem(displayItem, offsetFromLayoutObject));
}
+void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk)
+{
+ DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
+ if (m_currentChunkIsFromCachedSubsequence)
+ return;
+
+ if (!newChunk.id) {
+ 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)) {
+ generateChunkRasterInvalidationRectsComparingOldChunk(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])) {
+ generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, oldChunks[i]);
+ return;
+ }
+ }
+ }
+
+ // We reach here because the chunk is new.
+ newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRect()));
+}
+
+void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(PaintChunk& newChunk, const PaintChunk& oldChunk)
+{
+ DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
+
+ // TODO(wangxianzhu): Support raster invalidation for reordered display items without invalidating
+ // display item clients. Currently we invalidate display item clients ensuring raster invalidation.
+ // TODO(wangxianzhu): Handle PaintInvalidationIncremental.
+ // TODO(wangxianzhu): Optimize paint offset change.
+
+ // 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];
+ // oldItem.hasValidClient() indicates that the item has not been copied as a cached item into
+ // m_newDislayItemList, so the item either disappeared or changed, and needs raster invalidation.
+ if (oldItem.hasValidClient() && oldItem.drawsContent() && oldChunkClients.add(&oldItem.client(), i).isNewEntry)
+ newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDisplayItemList().visualRect(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 (!clientCacheIsValid(newItem.client())) {
+ if (newChunkClients.add(&newItem.client()).isNewEntry)
+ newChunk.rasterInvalidationRects.append(newItem.client().visualRect());
+ } else {
+ // The cached item was moved from the old chunk which should not contain any item of the client now.
+ DCHECK(!oldChunkClients.contains(&newItem.client()));
+ }
+ }
+ }
+}
+
#if DCHECK_IS_ON()
void PaintController::showUnderInvalidationError(const char* reason, const DisplayItem& newItem, const DisplayItem* oldItem) const
@@ -549,7 +646,7 @@ void PaintController::checkUnderInvalidation()
const DisplayItem& newItem = m_newDisplayItemList.last();
size_t oldItemIndex = m_underInvalidationCheckingBegin + m_skippedProbableUnderInvalidationCount;
- const DisplayItem* oldItem = oldItemIndex < m_currentPaintArtifact.getDisplayItemList().size() ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] : nullptr;
+ DisplayItem* oldItem = oldItemIndex < m_currentPaintArtifact.getDisplayItemList().size() ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] : nullptr;
bool oldAndNewEqual = oldItem && newItem.equals(*oldItem);
if (!oldAndNewEqual) {
@@ -577,6 +674,12 @@ void PaintController::checkUnderInvalidation()
NOTREACHED();
}
+ // Discard the forced repainted display item and move the cached item into m_newDisplayItemList.
+ // This is to align with the non-under-invalidation-checking path to empty the original cached slot,
+ // leaving only disappeared or invalidated display items in the old list after painting.
+ m_newDisplayItemList.removeLast();
+ m_newDisplayItemList.appendByMoving(*oldItem);
+
++m_underInvalidationCheckingBegin;
}
@@ -597,8 +700,16 @@ String PaintController::displayItemListAsDebugString(const DisplayItemList& list
stringBuilder.append(String::format("clientDebugName: %s", displayItem.client().debugName().ascii().data()));
#endif
if (displayItem.hasValidClient()) {
- stringBuilder.append(", cacheIsValid: ");
- stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false");
+ do {
+#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
+ if (!displayItem.client().isAlive()) {
+ stringBuilder.append(", clientIsAlive: false");
+ break;
+ }
+#endif
+ stringBuilder.append(", cacheIsValid: ");
+ stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false");
+ } while (false);
}
if (list.hasVisualRect(i)) {
IntRect visualRect = list.visualRect(i);

Powered by Google App Engine
This is Rietveld 408576698