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

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..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

Powered by Google App Engine
This is Rietveld 408576698