| Index: third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
|
| diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
|
| deleted file mode 100644
|
| index 03fb94474e5424677a297040288a8cf687d8ea35..0000000000000000000000000000000000000000
|
| --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
|
| +++ /dev/null
|
| @@ -1,565 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "config.h"
|
| -#include "platform/graphics/paint/DisplayItemList.h"
|
| -
|
| -#include "platform/NotImplemented.h"
|
| -#include "platform/TraceEvent.h"
|
| -#include "platform/graphics/GraphicsLayer.h"
|
| -#include "platform/graphics/paint/DrawingDisplayItem.h"
|
| -
|
| -#ifndef NDEBUG
|
| -#include "platform/graphics/LoggingCanvas.h"
|
| -#include "wtf/text/StringBuilder.h"
|
| -#include <stdio.h>
|
| -#endif
|
| -
|
| -namespace blink {
|
| -
|
| -const PaintArtifact& DisplayItemList::paintArtifact() const
|
| -{
|
| - ASSERT(m_newDisplayItems.isEmpty());
|
| - ASSERT(m_newPaintChunks.isInInitialState());
|
| - return m_currentPaintArtifact;
|
| -}
|
| -
|
| -bool DisplayItemList::lastDisplayItemIsNoopBegin() const
|
| -{
|
| - if (m_newDisplayItems.isEmpty())
|
| - return false;
|
| -
|
| - const auto& lastDisplayItem = m_newDisplayItems.last();
|
| - return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent();
|
| -}
|
| -
|
| -void DisplayItemList::removeLastDisplayItem()
|
| -{
|
| - if (m_newDisplayItems.isEmpty())
|
| - return;
|
| -
|
| -#if ENABLE(ASSERT)
|
| - // Also remove the index pointing to the removed display item.
|
| - DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient.find(m_newDisplayItems.last().client());
|
| - if (it != m_newDisplayItemIndicesByClient.end()) {
|
| - Vector<size_t>& indices = it->value;
|
| - if (!indices.isEmpty() && indices.last() == (m_newDisplayItems.size() - 1))
|
| - indices.removeLast();
|
| - }
|
| -#endif
|
| - m_newDisplayItems.removeLast();
|
| -
|
| - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
|
| - m_newPaintChunks.decrementDisplayItemIndex();
|
| -}
|
| -
|
| -void DisplayItemList::processNewItem(DisplayItem& displayItem)
|
| -{
|
| - ASSERT(!m_constructionDisabled);
|
| - ASSERT(!skippingCache() || !displayItem.isCached());
|
| -
|
| - if (displayItem.isCached())
|
| - ++m_numCachedItems;
|
| -
|
| -#if ENABLE(ASSERT)
|
| - // Verify noop begin/end pairs have been removed.
|
| - if (m_newDisplayItems.size() >= 2 && displayItem.isEnd()) {
|
| - const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size() - 2];
|
| - if (beginDisplayItem.isBegin() && !beginDisplayItem.isSubsequence() && !beginDisplayItem.drawsContent())
|
| - ASSERT(!displayItem.isEndAndPairedWith(beginDisplayItem.type()));
|
| - }
|
| -#endif
|
| -
|
| - if (!m_scopeStack.isEmpty())
|
| - displayItem.setScope(m_scopeStack.last());
|
| -
|
| -#if ENABLE(ASSERT)
|
| - size_t index = findMatchingItemFromIndex(displayItem.nonCachedId(), m_newDisplayItemIndicesByClient, m_newDisplayItems);
|
| - if (index != kNotFound) {
|
| -#ifndef NDEBUG
|
| - showDebugData();
|
| - WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%d)\n",
|
| - displayItem.asDebugString().utf8().data(), m_newDisplayItems[index].asDebugString().utf8().data(), static_cast<int>(index));
|
| -#endif
|
| - ASSERT_NOT_REACHED();
|
| - }
|
| - addItemToIndexIfNeeded(displayItem, m_newDisplayItems.size() - 1, m_newDisplayItemIndicesByClient);
|
| -#endif // ENABLE(ASSERT)
|
| -
|
| - if (skippingCache())
|
| - displayItem.setSkippedCache();
|
| -
|
| - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
|
| - m_newPaintChunks.incrementDisplayItemIndex();
|
| -}
|
| -
|
| -void DisplayItemList::updateCurrentPaintChunkProperties(const PaintChunkProperties& newProperties)
|
| -{
|
| - m_newPaintChunks.updateCurrentPaintChunkProperties(newProperties);
|
| -}
|
| -
|
| -void DisplayItemList::beginScope()
|
| -{
|
| - ASSERT_WITH_SECURITY_IMPLICATION(m_nextScope < UINT_MAX);
|
| - m_scopeStack.append(m_nextScope++);
|
| - beginSkippingCache();
|
| -}
|
| -
|
| -void DisplayItemList::endScope()
|
| -{
|
| - m_scopeStack.removeLast();
|
| - endSkippingCache();
|
| -}
|
| -
|
| -void DisplayItemList::invalidate(const DisplayItemClientWrapper& client, PaintInvalidationReason paintInvalidationReason, const IntRect& previousPaintInvalidationRect, const IntRect& newPaintInvalidationRect)
|
| -{
|
| - invalidateClient(client);
|
| -
|
| - if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) {
|
| - Invalidation invalidation = { previousPaintInvalidationRect, paintInvalidationReason };
|
| - if (!previousPaintInvalidationRect.isEmpty())
|
| - m_invalidations.append(invalidation);
|
| - if (newPaintInvalidationRect != previousPaintInvalidationRect && !newPaintInvalidationRect.isEmpty()) {
|
| - invalidation.rect = newPaintInvalidationRect;
|
| - m_invalidations.append(invalidation);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DisplayItemList::invalidateClient(const DisplayItemClientWrapper& client)
|
| -{
|
| - invalidateUntracked(client.displayItemClient());
|
| - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvalidationObjects)
|
| - m_trackedPaintInvalidationObjects->append(client.debugName());
|
| -}
|
| -
|
| -void DisplayItemList::invalidateUntracked(DisplayItemClient client)
|
| -{
|
| - // This can be called during painting, but we can't invalidate already painted clients.
|
| - ASSERT(!m_newDisplayItemIndicesByClient.contains(client));
|
| - updateValidlyCachedClientsIfNeeded();
|
| - m_validlyCachedClients.remove(client);
|
| -}
|
| -
|
| -void DisplayItemList::invalidateAll()
|
| -{
|
| - // Can only be called during layout/paintInvalidation, not during painting.
|
| - ASSERT(m_newDisplayItems.isEmpty());
|
| - m_currentPaintArtifact.reset();
|
| - m_validlyCachedClients.clear();
|
| - m_validlyCachedClientsDirty = false;
|
| -
|
| - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvalidationObjects)
|
| - m_trackedPaintInvalidationObjects->append("##ALL##");
|
| -}
|
| -
|
| -bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const
|
| -{
|
| - if (skippingCache())
|
| - return false;
|
| - updateValidlyCachedClientsIfNeeded();
|
| - return m_validlyCachedClients.contains(client);
|
| -}
|
| -
|
| -void DisplayItemList::invalidatePaintOffset(const DisplayItemClientWrapper& client)
|
| -{
|
| - ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled());
|
| - invalidateClient(client);
|
| -
|
| -#if ENABLE(ASSERT)
|
| - ASSERT(!paintOffsetWasInvalidated(client.displayItemClient()));
|
| - m_clientsWithPaintOffsetInvalidations.add(client.displayItemClient());
|
| -#endif
|
| -}
|
| -
|
| -#if ENABLE(ASSERT)
|
| -bool DisplayItemList::paintOffsetWasInvalidated(DisplayItemClient client) const
|
| -{
|
| - ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled());
|
| - return m_clientsWithPaintOffsetInvalidations.contains(client);
|
| -}
|
| -#endif
|
| -
|
| -size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, const DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItems& list)
|
| -{
|
| - DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(id.client);
|
| - if (it == displayItemIndicesByClient.end())
|
| - return kNotFound;
|
| -
|
| - const Vector<size_t>& indices = it->value;
|
| - for (size_t index : indices) {
|
| - const DisplayItem& existingItem = list[index];
|
| - ASSERT(!existingItem.isValid() || existingItem.client() == id.client);
|
| - if (existingItem.isValid() && id.matches(existingItem))
|
| - return index;
|
| - }
|
| -
|
| - return kNotFound;
|
| -}
|
| -
|
| -void DisplayItemList::addItemToIndexIfNeeded(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);
|
| -}
|
| -
|
| -struct DisplayItemList::OutOfOrderIndexContext {
|
| - OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin) { }
|
| -
|
| - DisplayItems::iterator nextItemToIndex;
|
| - DisplayItemIndicesByClientMap displayItemIndicesByClient;
|
| -};
|
| -
|
| -DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(const DisplayItem::Id& id, OutOfOrderIndexContext& context)
|
| -{
|
| - ASSERT(clientCacheIsValid(id.client));
|
| -
|
| - size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndicesByClient, m_currentPaintArtifact.displayItems());
|
| - if (foundIndex != kNotFound)
|
| - return m_currentPaintArtifact.displayItems().begin() + foundIndex;
|
| -
|
| - return findOutOfOrderCachedItemForward(id, context);
|
| -}
|
| -
|
| -// Find forward for the item and index all skipped indexable items.
|
| -DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const DisplayItem::Id& id, OutOfOrderIndexContext& context)
|
| -{
|
| - DisplayItems::iterator currentEnd = m_currentPaintArtifact.displayItems().end();
|
| - for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) {
|
| - const DisplayItem& item = *context.nextItemToIndex;
|
| - ASSERT(item.isValid());
|
| - if (item.isCacheable() && clientCacheIsValid(item.client())) {
|
| - if (id.matches(item))
|
| - return context.nextItemToIndex++;
|
| -
|
| - addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPaintArtifact.displayItems().begin(), context.displayItemIndicesByClient);
|
| - }
|
| - }
|
| - return currentEnd;
|
| -}
|
| -
|
| -void DisplayItemList::copyCachedSubsequence(DisplayItems::iterator& currentIt, DisplayItems& updatedList)
|
| -{
|
| - ASSERT(currentIt->isSubsequence());
|
| - ASSERT(!currentIt->scope());
|
| - DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::subsequenceTypeToEndSubsequenceType(currentIt->type()), 0);
|
| - do {
|
| - // We should always find the EndSubsequence display item.
|
| - ASSERT(currentIt != m_currentPaintArtifact.displayItems().end());
|
| - ASSERT(currentIt->isValid());
|
| - updatedList.appendByMoving(*currentIt);
|
| - ++currentIt;
|
| - } while (!endSubsequenceId.matches(updatedList.last()));
|
| -}
|
| -
|
| -// Update the existing display items by removing invalidated entries, updating
|
| -// repainted ones, and appending new items.
|
| -// - For cached drawing display item, copy the corresponding cached DrawingDisplayItem;
|
| -// - For cached subsequence display item, copy the cached display items between the
|
| -// corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.);
|
| -// - Otherwise, copy the new display item.
|
| -//
|
| -// The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|).
|
| -// Coefficients are related to the ratio of out-of-order CachedDisplayItems
|
| -// and the average number of (Drawing|Subsequence)DisplayItems per client.
|
| -//
|
| -void DisplayItemList::commitNewDisplayItems(GraphicsLayer* graphicsLayer)
|
| -{
|
| - TRACE_EVENT2("blink,benchmark", "DisplayItemList::commitNewDisplayItems",
|
| - "current_display_list_size", (int)m_currentPaintArtifact.displayItems().size(),
|
| - "num_non_cached_new_items", (int)m_newDisplayItems.size() - m_numCachedItems);
|
| -
|
| - if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) {
|
| - for (const auto& invalidation : m_invalidations)
|
| - graphicsLayer->setNeedsDisplayInRect(invalidation.rect, invalidation.invalidationReason);
|
| - m_invalidations.clear();
|
| - m_clientsCheckedPaintInvalidation.clear();
|
| - }
|
| -
|
| - // These data structures are used during painting only.
|
| - ASSERT(m_scopeStack.isEmpty());
|
| - m_scopeStack.clear();
|
| - m_nextScope = 1;
|
| - ASSERT(!skippingCache());
|
| -#if ENABLE(ASSERT)
|
| - m_newDisplayItemIndicesByClient.clear();
|
| - m_clientsWithPaintOffsetInvalidations.clear();
|
| -#endif
|
| -
|
| - if (m_currentPaintArtifact.isEmpty()) {
|
| -#if ENABLE(ASSERT)
|
| - for (const auto& item : m_newDisplayItems)
|
| - ASSERT(!item.isCached());
|
| -#endif
|
| - m_currentPaintArtifact.displayItems().swap(m_newDisplayItems);
|
| - m_currentPaintArtifact.paintChunks() = m_newPaintChunks.releasePaintChunks();
|
| - m_validlyCachedClientsDirty = true;
|
| - m_numCachedItems = 0;
|
| - return;
|
| - }
|
| -
|
| - updateValidlyCachedClientsIfNeeded();
|
| -
|
| - // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched
|
| - // by CachedDisplayItems during synchronized matching. The indexed items will be matched
|
| - // by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensures that when
|
| - // 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_currentPaintArtifact.displayItems().begin());
|
| -
|
| - // TODO(jbroman): Consider revisiting this heuristic.
|
| - DisplayItems updatedList(std::max(m_currentPaintArtifact.displayItems().usedCapacityInBytes(), m_newDisplayItems.usedCapacityInBytes()));
|
| - Vector<PaintChunk> updatedPaintChunks;
|
| - DisplayItems::iterator currentIt = m_currentPaintArtifact.displayItems().begin();
|
| - DisplayItems::iterator currentEnd = m_currentPaintArtifact.displayItems().end();
|
| - for (DisplayItems::iterator newIt = m_newDisplayItems.begin(); newIt != m_newDisplayItems.end(); ++newIt) {
|
| - const DisplayItem& newDisplayItem = *newIt;
|
| - const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId();
|
| - bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayItemId.type;
|
| -
|
| - bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matches(*currentIt);
|
| -
|
| - if (newDisplayItemHasCachedType) {
|
| - ASSERT(newDisplayItem.isCached());
|
| - ASSERT(clientCacheIsValid(newDisplayItem.client()) || (RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && !paintOffsetWasInvalidated(newDisplayItem.client())));
|
| - if (!isSynchronized) {
|
| - currentIt = findOutOfOrderCachedItem(newDisplayItemId, outOfOrderIndexContext);
|
| -
|
| - if (currentIt == currentEnd) {
|
| -#ifndef NDEBUG
|
| - showDebugData();
|
| - WTFLogAlways("%s not found in m_currentDisplayItems\n", newDisplayItem.asDebugString().utf8().data());
|
| -#endif
|
| - ASSERT_NOT_REACHED();
|
| - // 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;
|
| - }
|
| - }
|
| -#if ENABLE(ASSERT)
|
| - if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
|
| - DisplayItems::iterator temp = currentIt;
|
| - checkUnderInvalidation(newIt, temp);
|
| - }
|
| -#endif
|
| - if (newDisplayItem.isCachedDrawing()) {
|
| - updatedList.appendByMoving(*currentIt);
|
| - ++currentIt;
|
| - } else {
|
| - ASSERT(newDisplayItem.isCachedSubsequence());
|
| - copyCachedSubsequence(currentIt, updatedList);
|
| - ASSERT(updatedList.last().isEndSubsequence());
|
| - }
|
| - } else {
|
| - ASSERT(!newDisplayItem.isDrawing()
|
| - || newDisplayItem.skippedCache()
|
| - || !clientCacheIsValid(newDisplayItem.client())
|
| - || (RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && paintOffsetWasInvalidated(newDisplayItem.client())));
|
| -
|
| - updatedList.appendByMoving(*newIt);
|
| -
|
| - if (isSynchronized)
|
| - ++currentIt;
|
| - }
|
| - // Items before currentIt should have been copied so we don't need to index them.
|
| - if (currentIt - outOfOrderIndexContext.nextItemToIndex > 0)
|
| - outOfOrderIndexContext.nextItemToIndex = currentIt;
|
| - }
|
| -
|
| -#if ENABLE(ASSERT)
|
| - if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
|
| - checkNoRemainingCachedDisplayItems();
|
| -#endif // ENABLE(ASSERT)
|
| -
|
| -
|
| - // TODO(jbroman): When subsequence caching applies to SPv2, we'll need to
|
| - // merge the paint chunks as well.
|
| - m_currentPaintArtifact.displayItems().swap(updatedList);
|
| - m_currentPaintArtifact.paintChunks() = m_newPaintChunks.releasePaintChunks();
|
| -
|
| - m_newDisplayItems.clear();
|
| - m_validlyCachedClientsDirty = true;
|
| - m_numCachedItems = 0;
|
| -}
|
| -
|
| -size_t DisplayItemList::approximateUnsharedMemoryUsage() const
|
| -{
|
| - size_t memoryUsage = sizeof(*this);
|
| -
|
| - // Memory outside this class due to m_currentPaintArtifact.
|
| - memoryUsage += m_currentPaintArtifact.approximateUnsharedMemoryUsage() - sizeof(m_currentPaintArtifact);
|
| -
|
| - // TODO(jbroman): If display items begin to have significant external memory
|
| - // usage that's not shared with the embedder, we should account for it here.
|
| - //
|
| - // External objects, shared with the embedder, such as SkPicture, should be
|
| - // excluded to avoid double counting. It is the embedder's responsibility to
|
| - // count such objects.
|
| - //
|
| - // At time of writing, the only known case of unshared external memory was
|
| - // the rounded clips vector in ClipDisplayItem, which is not expected to
|
| - // contribute significantly to memory usage.
|
| -
|
| - // Memory outside this class due to m_newDisplayItems.
|
| - ASSERT(m_newDisplayItems.isEmpty());
|
| - memoryUsage += m_newDisplayItems.memoryUsageInBytes();
|
| -
|
| - return memoryUsage;
|
| -}
|
| -
|
| -void DisplayItemList::updateValidlyCachedClientsIfNeeded() const
|
| -{
|
| - if (!m_validlyCachedClientsDirty)
|
| - return;
|
| -
|
| - m_validlyCachedClients.clear();
|
| - m_validlyCachedClientsDirty = false;
|
| -
|
| - DisplayItemClient lastAddedClient = nullptr;
|
| - for (const DisplayItem& displayItem : m_currentPaintArtifact.displayItems()) {
|
| - if (displayItem.client() == lastAddedClient)
|
| - continue;
|
| - if (displayItem.isCacheable()) {
|
| - lastAddedClient = displayItem.client();
|
| - m_validlyCachedClients.add(lastAddedClient);
|
| - }
|
| - }
|
| -}
|
| -
|
| -#if ENABLE(ASSERT)
|
| -
|
| -void DisplayItemList::checkUnderInvalidation(DisplayItems::iterator& newIt, DisplayItems::iterator& currentIt)
|
| -{
|
| - ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled());
|
| - ASSERT(newIt->isCached());
|
| -
|
| - // When under-invalidation-checking is enabled, the forced painting is following the cached display item.
|
| - DisplayItem::Type nextItemType = DisplayItem::nonCachedType(newIt->type());
|
| - ++newIt;
|
| - ASSERT(newIt->type() == nextItemType);
|
| -
|
| - if (newIt->isDrawing()) {
|
| - checkCachedDisplayItemIsUnchanged("", *newIt, *currentIt);
|
| - return;
|
| - }
|
| -
|
| - ASSERT(newIt->isSubsequence());
|
| -
|
| -#ifndef NDEBUG
|
| - CString messagePrefix = String::format("(In CachedSubsequence of %s)", newIt->clientDebugString().utf8().data()).utf8();
|
| -#else
|
| - CString messagePrefix = "(In CachedSubsequence)";
|
| -#endif
|
| -
|
| - DisplayItem::Id endSubsequenceId(newIt->client(), DisplayItem::subsequenceTypeToEndSubsequenceType(newIt->type()), 0);
|
| - while (true) {
|
| - ASSERT(newIt != m_newDisplayItems.end());
|
| - if (newIt->isCached())
|
| - checkUnderInvalidation(newIt, currentIt);
|
| - else
|
| - checkCachedDisplayItemIsUnchanged(messagePrefix.data(), *newIt, *currentIt);
|
| -
|
| - if (endSubsequenceId.matches(*newIt))
|
| - break;
|
| -
|
| - ++newIt;
|
| - ++currentIt;
|
| - }
|
| -}
|
| -
|
| -static void showUnderInvalidationError(const char* messagePrefix, const char* reason, const DisplayItem* newItem, const DisplayItem* oldItem)
|
| -{
|
| -#ifndef NDEBUG
|
| - WTFLogAlways("%s %s:\nNew display item: %s\nOld display item: %s\nSee http://crbug.com/450725.", messagePrefix, reason,
|
| - newItem ? newItem->asDebugString().utf8().data() : "None",
|
| - oldItem ? oldItem->asDebugString().utf8().data() : "None");
|
| -#else
|
| - WTFLogAlways("%s %s. Run debug build to get more details\nSee http://crbug.com/450725.", messagePrefix, reason);
|
| -#endif // NDEBUG
|
| -}
|
| -
|
| -void DisplayItemList::checkCachedDisplayItemIsUnchanged(const char* messagePrefix, const DisplayItem& newItem, const DisplayItem& oldItem)
|
| -{
|
| - ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled());
|
| - ASSERT(!newItem.isCached());
|
| - ASSERT(!oldItem.isCached());
|
| -
|
| - if (newItem.skippedCache()) {
|
| - showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: skipped-cache in cached subsequence", &newItem, &oldItem);
|
| - ASSERT_NOT_REACHED();
|
| - }
|
| -
|
| - if (newItem.isCacheable() && !m_validlyCachedClients.contains(newItem.client())) {
|
| - showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: invalidated in cached subsequence", &newItem, &oldItem);
|
| - ASSERT_NOT_REACHED();
|
| - }
|
| -
|
| - if (newItem.equals(oldItem))
|
| - return;
|
| -
|
| - showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: display item changed", &newItem, &oldItem);
|
| -
|
| -#ifndef NDEBUG
|
| - if (newItem.isDrawing()) {
|
| - RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayItem&>(newItem).picture();
|
| - RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayItem&>(oldItem).picture();
|
| - String oldPictureDebugString = oldPicture ? pictureAsDebugString(oldPicture.get()) : "None";
|
| - String newPictureDebugString = newPicture ? pictureAsDebugString(newPicture.get()) : "None";
|
| - WTFLogAlways("old picture:\n%s\n", oldPictureDebugString.utf8().data());
|
| - WTFLogAlways("new picture:\n%s\n", newPictureDebugString.utf8().data());
|
| - }
|
| -#endif // NDEBUG
|
| -
|
| - ASSERT_NOT_REACHED();
|
| -}
|
| -
|
| -void DisplayItemList::checkNoRemainingCachedDisplayItems()
|
| -{
|
| - ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled());
|
| -
|
| - for (const auto& displayItem : m_currentPaintArtifact.displayItems()) {
|
| - if (!displayItem.isValid() || !displayItem.isCacheable() || !clientCacheIsValid(displayItem.client()))
|
| - continue;
|
| - showUnderInvalidationError("", "May be under-invalidation: no new display item", nullptr, &displayItem);
|
| - }
|
| -}
|
| -
|
| -#endif // ENABLE(ASSERT)
|
| -
|
| -#ifndef NDEBUG
|
| -
|
| -WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list) const
|
| -{
|
| - StringBuilder stringBuilder;
|
| - size_t i = 0;
|
| - for (auto it = list.begin(); it != list.end(); ++it, ++i) {
|
| - const DisplayItem& displayItem = *it;
|
| - if (i)
|
| - stringBuilder.append(",\n");
|
| - stringBuilder.append(String::format("{index: %d, ", (int)i));
|
| - displayItem.dumpPropertiesAsDebugString(stringBuilder);
|
| - if (displayItem.isValid()) {
|
| - stringBuilder.append(", cacheIsValid: ");
|
| - stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false");
|
| - }
|
| - stringBuilder.append('}');
|
| - }
|
| - return stringBuilder.toString();
|
| -}
|
| -
|
| -void DisplayItemList::showDebugData() const
|
| -{
|
| - WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_currentPaintArtifact.displayItems()).utf8().data());
|
| - WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDisplayItems).utf8().data());
|
| -}
|
| -
|
| -#endif // ifndef NDEBUG
|
| -
|
| -} // namespace blink
|
|
|