| 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 24e041f2dfa42c8fd87ee2decc2415e96c99bd86..0b991a0f1a9d607a2138e4eb964405306ab9d636 100644
|
| --- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
|
| +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
|
| @@ -41,11 +41,12 @@ bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client
|
| if (!clientCacheIsValid(client))
|
| return false;
|
|
|
| -#if ENABLE(ASSERT)
|
| - // When under-invalidation checking is enabled, we output CachedDrawing display item
|
| - // followed by the display item containing forced painting.
|
| - if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
|
| +#if DCHECK_IS_ON()
|
| + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled() && isCheckingUnderInvalidation()) {
|
| + // We are checking under-invalidation of a subsequence enclosing this display item.
|
| + // Let the client continue to actually paint the display item.
|
| return false;
|
| + }
|
| #endif
|
|
|
| DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client, type));
|
| @@ -56,13 +57,27 @@ bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client
|
|
|
| ++m_numCachedNewItems;
|
| ensureNewDisplayItemListInitialCapacity();
|
| - processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem));
|
| + if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
|
| + processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem));
|
|
|
| m_nextItemToMatch = cachedItem + 1;
|
| // Items before m_nextItemToMatch have been copied so we don't need to index them.
|
| if (m_nextItemToMatch - m_nextItemToIndex > 0)
|
| m_nextItemToIndex = m_nextItemToMatch;
|
|
|
| +#if DCHECK_IS_ON()
|
| + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
|
| + if (!isCheckingUnderInvalidation()) {
|
| + m_underInvalidationCheckingBegin = cachedItem;
|
| + m_underInvalidationCheckingEnd = cachedItem + 1;
|
| + m_underInvalidationMessagePrefix = "";
|
| + }
|
| + // Return false to let the painter actually paint, and we will check if the new painting
|
| + // is the same as the cached.
|
| + return false;
|
| + }
|
| +#endif
|
| +
|
| return true;
|
| }
|
|
|
| @@ -81,11 +96,13 @@ bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& cl
|
| if (!clientCacheIsValid(client))
|
| return false;
|
|
|
| -#if ENABLE(ASSERT)
|
| - // When under-invalidation checking is enabled, we output CachedDrawing display item
|
| - // followed by the display item containing forced painting.
|
| - if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
|
| +#if DCHECK_IS_ON()
|
| + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled() && isCheckingUnderInvalidation()) {
|
| + // We are checking under-invalidation of an ancestor subsequence enclosing this one.
|
| + // The ancestor subsequence is supposed to have already "copied", so we should let the
|
| + // client continue to actually paint the descendant subsequences without "copying".
|
| return false;
|
| + }
|
| #endif
|
|
|
| DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client, DisplayItem::Subsequence));
|
| @@ -103,6 +120,14 @@ bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& cl
|
| if (cachedItem - m_nextItemToIndex > 0)
|
| m_nextItemToIndex = cachedItem;
|
|
|
| +#if DCHECK_IS_ON()
|
| + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
|
| + // Return false to let the painter actually paint, and we will check if the new painting
|
| + // is the same as the cached.
|
| + return false;
|
| + }
|
| +#endif
|
| +
|
| return true;
|
| }
|
|
|
| @@ -185,6 +210,9 @@ void PaintController::processNewItem(DisplayItem& displayItem)
|
| NOTREACHED();
|
| }
|
| addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDisplayItemIndicesByClient);
|
| +
|
| + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
|
| + checkUnderInvalidation();
|
| #endif // DCHECK_IS_ON()
|
|
|
| if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
|
| @@ -313,11 +341,27 @@ DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const
|
| return end;
|
| }
|
|
|
| +// Copies a cached subsequence from current list to the new list.
|
| // On return, |it| points to the item after the EndSubsequence item of the subsequence.
|
| +// When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subsequence,
|
| +// but mark the begin and end of the subsequence for under-invalidation checking.
|
| void PaintController::copyCachedSubsequence(DisplayItemList::iterator& it)
|
| {
|
| +#if DCHECK_IS_ON()
|
| DCHECK(it->getType() == DisplayItem::Subsequence);
|
| + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
|
| + DCHECK(!isCheckingUnderInvalidation());
|
| + m_underInvalidationCheckingBegin = it;
|
| +#ifndef NDEBUG
|
| + m_underInvalidationMessagePrefix = "(In CachedSubsequence of " + it->clientDebugString() + ")";
|
| +#else
|
| + m_underInvalidationMessagePrefix = "(In CachedSubsequence)";
|
| +#endif
|
| + }
|
| +#endif
|
| +
|
| DisplayItem::Id endSubsequenceId(it->client(), DisplayItem::EndSubsequence);
|
| + bool metEndSubsequence = false;
|
| do {
|
| // We should always find the EndSubsequence display item.
|
| DCHECK(it != m_currentPaintArtifact.getDisplayItemList().end());
|
| @@ -326,9 +370,19 @@ void PaintController::copyCachedSubsequence(DisplayItemList::iterator& it)
|
| CHECK(it->client().isAlive());
|
| #endif
|
| ++m_numCachedNewItems;
|
| - processNewItem(m_newDisplayItemList.appendByMoving(*it));
|
| + if (it->getId() == endSubsequenceId)
|
| + metEndSubsequence = true;
|
| + if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
|
| + processNewItem(m_newDisplayItemList.appendByMoving(*it));
|
| ++it;
|
| - } while (endSubsequenceId != m_newDisplayItemList.last().getId());
|
| + } while (!metEndSubsequence);
|
| +
|
| +#if DCHECK_IS_ON()
|
| + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
|
| + m_underInvalidationCheckingEnd = it;
|
| + DCHECK(isCheckingUnderInvalidation());
|
| + }
|
| +#endif
|
| }
|
|
|
| static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const LayoutSize& offsetFromLayoutObject)
|
| @@ -342,6 +396,10 @@ void PaintController::resetCurrentListIterators()
|
| {
|
| m_nextItemToMatch = m_currentPaintArtifact.getDisplayItemList().begin();
|
| m_nextItemToIndex = m_nextItemToMatch;
|
| +#if DCHECK_IS_ON()
|
| + m_underInvalidationCheckingBegin = m_currentPaintArtifact.getDisplayItemList().end();
|
| + m_underInvalidationCheckingEnd = m_currentPaintArtifact.getDisplayItemList().begin();
|
| +#endif
|
| }
|
|
|
| void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutObject)
|
| @@ -428,91 +486,47 @@ void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& dis
|
| resetCurrentListIterators();
|
| }
|
|
|
| -#if 0 // DCHECK_IS_ON()
|
| -// TODO(wangxianzhu): Fix under-invalidation checking for the new caching method.
|
| +#if DCHECK_IS_ON()
|
|
|
| -void PaintController::checkUnderInvalidation(DisplayItemList::iterator& newIt, DisplayItemList::iterator& currentIt)
|
| +void PaintController::showUnderInvalidationError(const char* reason, const DisplayItem& newItem, const DisplayItem& oldItem) const
|
| {
|
| - DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled());
|
| -
|
| - // When under-invalidation-checking is enabled, the forced painting is following the cached display item.
|
| - DisplayItem::Type nextItemType = DisplayItem::nonCachedType(newIt->getType());
|
| - ++newIt;
|
| - DCHECK(newIt->getType() == nextItemType);
|
| -
|
| - if (newIt->isDrawing()) {
|
| - checkCachedDisplayItemIsUnchanged("", *newIt, *currentIt);
|
| - return;
|
| - }
|
| -
|
| - DCHECK(newIt->getType() == DisplayItem::Subsequence);
|
| -
|
| + LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason;
|
| #ifndef NDEBUG
|
| - CString messagePrefix = String::format("(In CachedSubsequence of %s)", newIt->clientDebugString().utf8().data()).utf8();
|
| + LOG(ERROR) << "New display item: " << newItem.asDebugString();
|
| + LOG(ERROR) << "Old display item: " << oldItem.asDebugString();
|
| #else
|
| - CString messagePrefix = "(In CachedSubsequence)";
|
| + LOG(ERROR) << "Run debug build to get more details.";
|
| #endif
|
| + LOG(ERROR) << "See http://crbug.com/619103.";
|
|
|
| - DisplayItem::Id endSubsequenceId(newIt->client(), DisplayItem::EndSubsequence);
|
| - while (true) {
|
| - DCHECK(newIt != m_newDisplayItemList.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);
|
| + if (newItem.isDrawing()) {
|
| + RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayItem&>(newItem).picture();
|
| + RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayItem&>(oldItem).picture();
|
| + LOG(INFO) << "new picture:\n" << (newPicture ? pictureAsDebugString(newPicture.get()) : "None");
|
| + LOG(INFO) << "old picture:\n" << (oldPicture ? pictureAsDebugString(oldPicture.get()) : "None");
|
| + }
|
| #endif // NDEBUG
|
| }
|
|
|
| -void PaintController::checkCachedDisplayItemIsUnchanged(const char* messagePrefix, const DisplayItem& newItem, const DisplayItem& oldItem)
|
| +void PaintController::checkUnderInvalidation()
|
| {
|
| DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled());
|
| - DCHECK(!newItem.isCached());
|
| - DCHECK(!oldItem.isCached());
|
|
|
| - if (newItem.skippedCache()) {
|
| - showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: skipped-cache in cached subsequence", &newItem, &oldItem);
|
| - NOTREACHED();
|
| - }
|
| + if (!isCheckingUnderInvalidation())
|
| + return;
|
| +
|
| + const DisplayItem& newItem = m_newDisplayItemList.last();
|
| + const DisplayItem& oldItem = *m_underInvalidationCheckingBegin++;
|
|
|
| if (newItem.isCacheable() && !clientCacheIsValid(newItem.client())) {
|
| - showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: invalidated in cached subsequence", &newItem, &oldItem);
|
| + showUnderInvalidationError("under-invalidation of PaintLayer: invalidated in cached subsequence", newItem, oldItem);
|
| NOTREACHED();
|
| }
|
| -
|
| - 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());
|
| + if (!newItem.equals(oldItem)) {
|
| + showUnderInvalidationError("under-invalidation: display item changed", newItem, oldItem);
|
| + NOTREACHED();
|
| }
|
| -#endif // NDEBUG
|
| -
|
| - NOTREACHED();
|
| }
|
|
|
| #endif // DCHECK_IS_ON()
|
| @@ -533,10 +547,12 @@ String PaintController::displayItemListAsDebugString(const DisplayItemList& list
|
| stringBuilder.append(", cacheIsValid: ");
|
| stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false");
|
| }
|
| - IntRect visualRect = list.visualRect(i);
|
| - stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]",
|
| - visualRect.x(), visualRect.y(),
|
| - visualRect.width(), visualRect.height()));
|
| + if (list.hasVisualRect(i)) {
|
| + IntRect visualRect = list.visualRect(i);
|
| + stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]",
|
| + visualRect.x(), visualRect.y(),
|
| + visualRect.width(), visualRect.height()));
|
| + }
|
| stringBuilder.append('}');
|
| }
|
| return stringBuilder.toString();
|
|
|