| 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);
|
|
|