// 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 "platform/graphics/paint/PaintController.h"

#include "platform/TraceEvent.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/graphics/paint/DrawingDisplayItem.h"
#include "third_party/skia/include/core/SkPictureAnalyzer.h"
#include "wtf/text/StringBuilder.h"

#ifndef NDEBUG
#include "platform/graphics/LoggingCanvas.h"
#include <stdio.h>
#endif

namespace blink {

const PaintArtifact& PaintController::paintArtifact() const
{
    DCHECK(m_newDisplayItemList.isEmpty());
    DCHECK(m_newPaintChunks.isInInitialState());
    return m_currentPaintArtifact;
}

bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client, DisplayItem::Type type)
{
    DCHECK(DisplayItem::isDrawingType(type));

    if (displayItemConstructionIsDisabled())
        return false;

    if (!clientCacheIsValid(client))
        return false;

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && 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;
    }

    size_t cachedItem = findCachedItem(DisplayItem::Id(client, type));
    if (cachedItem == kNotFound) {
        NOTREACHED();
        return false;
    }

    ++m_numCachedNewItems;
    ensureNewDisplayItemListInitialCapacity();
    if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled())
        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.
    if (m_nextItemToMatch > m_nextItemToIndex)
        m_nextItemToIndex = m_nextItemToMatch;

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
        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;
    }

    return true;
}

bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& client)
{
    if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled())
        return false;

    if (!clientCacheIsValid(client))
        return false;

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && 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;
    }

    size_t cachedItem = findCachedItem(DisplayItem::Id(client, DisplayItem::kSubsequence));
    if (cachedItem == kNotFound) {
        NOTREACHED();
        return false;
    }

    // |cachedItem| will point to the first item after the subsequence or end of the current list.
    ensureNewDisplayItemListInitialCapacity();
    copyCachedSubsequence(cachedItem);

    m_nextItemToMatch = cachedItem;
    // Items before |cachedItem| have been copied so we don't need to index them.
    if (cachedItem > m_nextItemToIndex)
        m_nextItemToIndex = cachedItem;

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
        // Return false to let the painter actually paint, and we will check if the new painting
        // is the same as the cached.
        return false;
    }

    return true;
}

bool PaintController::lastDisplayItemIsNoopBegin() const
{
    if (m_newDisplayItemList.isEmpty())
        return false;

    const auto& lastDisplayItem = m_newDisplayItemList.last();
    return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent();
}

void PaintController::removeLastDisplayItem()
{
    if (m_newDisplayItemList.isEmpty())
        return;

#if DCHECK_IS_ON()
    // Also remove the index pointing to the removed display item.
    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))
            indices.removeLast();
    }
#endif

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && isCheckingUnderInvalidation()) {
        if (m_skippedProbableUnderInvalidationCount) {
            --m_skippedProbableUnderInvalidationCount;
        } else {
            DCHECK(m_underInvalidationCheckingBegin);
            --m_underInvalidationCheckingBegin;
        }
    }
    m_newDisplayItemList.removeLast();

    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
        m_newPaintChunks.decrementDisplayItemIndex();
}

const DisplayItem* PaintController::lastDisplayItem(unsigned offset)
{
    if (offset < m_newDisplayItemList.size())
        return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1];
    return nullptr;
}

void PaintController::processNewItem(DisplayItem& displayItem, NewItemSource newItemSource)
{
    DCHECK(!m_constructionDisabled);

#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
    if (!isSkippingCache()) {
        if (displayItem.isCacheable()) {
            // Mark the client shouldKeepAlive under this PaintController.
            // The status will end after the new display items are committed.
            displayItem.client().beginShouldKeepAlive(this);

            if (!m_currentSubsequenceClients.isEmpty()) {
                // Mark the client shouldKeepAlive under the current subsequence.
                // The status will end when the subsequence owner is invalidated or deleted.
                displayItem.client().beginShouldKeepAlive(m_currentSubsequenceClients.last());
            }
        }

        if (displayItem.getType() == DisplayItem::kSubsequence) {
            m_currentSubsequenceClients.append(&displayItem.client());
        } else if (displayItem.getType() == DisplayItem::kEndSubsequence) {
            CHECK(m_currentSubsequenceClients.last() == &displayItem.client());
            m_currentSubsequenceClients.removeLast();
        }
    }
#endif

    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.
    if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) {
        const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList.size() - 2];
        if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayItem::kSubsequence && !beginDisplayItem.drawsContent())
            DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType()));
    }

    size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayItemIndicesByClient, m_newDisplayItemList);
    if (index != kNotFound) {
#ifndef NDEBUG
        showDebugData();
        WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%d)\n",
            displayItem.asDebugString().utf8().data(), m_newDisplayItemList[index].asDebugString().utf8().data(), static_cast<int>(index));
#endif
        NOTREACHED();
    }
    addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDisplayItemIndicesByClient);
#endif // DCHECK_IS_ON()

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled())
        checkUnderInvalidation();
}

void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id, const PaintChunkProperties& newProperties)
{
    m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties);
}

const PaintChunkProperties& PaintController::currentPaintChunkProperties() const
{
    return m_newPaintChunks.currentPaintChunkProperties();
}

void PaintController::invalidateAll()
{
    // Can only be called during layout/paintInvalidation, not during painting.
    DCHECK(m_newDisplayItemList.isEmpty());
    m_currentPaintArtifact.reset();
    m_currentCacheGeneration.invalidate();
}

bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const
{
#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
    CHECK(client.isAlive());
#endif
    if (isSkippingCache())
        return false;
    return client.displayItemsAreCached(m_currentCacheGeneration);
}

size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, const IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list)
{
    IndicesByClientMap::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];
        DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.client);
        if (id == existingItem.getId())
            return index;
    }

    return kNotFound;
}

void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, size_t index, IndicesByClientMap& displayItemIndicesByClient)
{
    if (!displayItem.isCacheable())
        return;

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

size_t PaintController::findCachedItem(const DisplayItem::Id& id)
{
    DCHECK(clientCacheIsValid(id.client));

    // Try to find the item sequentially first. This is fast if the current list and the new list are in
    // the same order around the new item. If found, we don't need to update and lookup the index.
    for (size_t i = m_nextItemToMatch; i < m_currentPaintArtifact.getDisplayItemList().size(); ++i) {
        // We encounter an item that has already been copied which indicates we can't do sequential matching.
        const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i];
        if (!item.hasValidClient())
            break;
        if (id == item.getId()) {
#ifndef NDEBUG
            ++m_numSequentialMatches;
#endif
            return i;
        }
        // We encounter a different cacheable item which also indicates we can't do sequential matching.
        if (item.isCacheable())
            break;
    }

    size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m_currentPaintArtifact.getDisplayItemList());
    if (foundIndex != kNotFound) {
#ifndef NDEBUG
        ++m_numOutOfOrderMatches;
#endif
        return foundIndex;
    }

    return findOutOfOrderCachedItemForward(id);
}

// Find forward for the item and index all skipped indexable items.
size_t PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& id)
{
    for (size_t i = m_nextItemToIndex; i < m_currentPaintArtifact.getDisplayItemList().size(); ++i) {
        const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i];
        DCHECK(item.hasValidClient());
        if (id == item.getId()) {
#ifndef NDEBUG
            ++m_numSequentialMatches;
#endif
            return i;
        }
        if (item.isCacheable()) {
#ifndef NDEBUG
            ++m_numIndexedItems;
#endif
            addItemToIndexIfNeeded(item, i, m_outOfOrderItemIndices);
        }
    }

#ifndef NDEBUG
    showDebugData();
    LOG(ERROR) << id.client.debugName() << ":" << DisplayItem::typeAsDebugString(id.type);
#endif

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled())
        CHECK(false) << "Can't find cached display item";

    // 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, the caller should fall back to repaint the display item.
    return kNotFound;
}

// Copies a cached subsequence from current list to the new list. On return,
// |cachedItemIndex| 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(size_t& cachedItemIndex)
{
    DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cachedItemIndex];
    DCHECK(cachedItem->getType() == DisplayItem::kSubsequence);

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
        DCHECK(!isCheckingUnderInvalidation());
        m_underInvalidationCheckingBegin = cachedItemIndex;
        m_underInvalidationMessagePrefix = "(In cached subsequence of " + cachedItem->client().debugName() + ")";
    }

    DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubsequence);
    Vector<PaintChunk>::const_iterator cachedChunk;
    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
        cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedItemIndex);
        updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties);
    } else {
        // This is to avoid compilation error about uninitialized variable on Windows.
        cachedChunk = m_currentPaintArtifact.paintChunks().begin();
    }

    while (true) {
        DCHECK(cachedItem->hasValidClient());
#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
        CHECK(cachedItem->client().isAlive());
#endif
        ++m_numCachedNewItems;
        bool metEndSubsequence = cachedItem->getId() == endSubsequenceId;
        if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
            if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIndex == cachedChunk->endIndex) {
                ++cachedChunk;
                updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties);
            }
            processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), FromCachedSubsequence);
            if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
                DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk));
        }

        ++cachedItemIndex;
        if (metEndSubsequence)
            break;

        // We should always be able to find the EndSubsequence display item.
        DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().size());
        cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cachedItemIndex];
    }

    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
        m_underInvalidationCheckingEnd = cachedItemIndex;
        DCHECK(isCheckingUnderInvalidation());
    }
}

static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const LayoutSize& offsetFromLayoutObject)
{
    LayoutRect visualRect = displayItem.client().visualRect();
    visualRect.move(-offsetFromLayoutObject);
    return enclosingIntRect(visualRect);
}

void PaintController::resetCurrentListIndices()
{
    m_nextItemToMatch = 0;
    m_nextItemToIndex = 0;
    m_nextChunkToMatch = 0;
    m_underInvalidationCheckingBegin = 0;
    m_underInvalidationCheckingEnd = 0;
    m_skippedProbableUnderInvalidationCount = 0;
}

void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutObject)
{
    TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems",
        "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemList().size(),
        "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCachedNewItems);
    m_numCachedNewItems = 0;

    // These data structures are used during painting only.
    DCHECK(!isSkippingCache());
#if DCHECK_IS_ON()
    m_newDisplayItemIndicesByClient.clear();
#endif

    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && !m_newDisplayItemList.isEmpty())
        generateChunkRasterInvalidationRects(m_newPaintChunks.lastChunk());

    SkPictureGpuAnalyzer gpuAnalyzer;

    m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationReason::next();
    Vector<const DisplayItemClient*> skippedCacheClients;
    for (const auto& item : m_newDisplayItemList) {
        // No reason to continue the analysis once we have a veto.
        if (gpuAnalyzer.suitableForGpuRasterization())
            item.analyzeForGpuRasterization(gpuAnalyzer);

        // TODO(wkorman): Only compute and append visual rect for drawings.
        m_newDisplayItemList.appendVisualRect(visualRectForDisplayItem(item, offsetFromLayoutObject));

        if (item.isCacheable()) {
            item.client().setDisplayItemsCached(m_currentCacheGeneration);
        } else {
            if (item.client().isJustCreated())
                item.client().clearIsJustCreated();
            if (item.skippedCache())
                skippedCacheClients.append(&item.client());
        }
    }

    for (auto* client : skippedCacheClients)
        client->setDisplayItemsUncached();

    // The new list will not be appended to again so we can release unused memory.
    m_newDisplayItemList.shrinkToFit();
    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()) {
            if (chunk.id && chunk.id->client.isJustCreated())
                chunk.id->client.clearIsJustCreated();
        }
    }

    // We'll allocate the initial buffer when we start the next paint.
    m_newDisplayItemList = DisplayItemList(0);

#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
    CHECK(m_currentSubsequenceClients.isEmpty());
    DisplayItemClient::endShouldKeepAliveAllClients(this);
#endif

#ifndef NDEBUG
    m_numSequentialMatches = 0;
    m_numOutOfOrderMatches = 0;
    m_numIndexedItems = 0;
#endif
}

size_t PaintController::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_newDisplayItemList.
    DCHECK(m_newDisplayItemList.isEmpty());
    memoryUsage += m_newDisplayItemList.memoryUsageInBytes();

    return memoryUsage;
}

void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& displayItemClient, sk_sp<SkPicture> picture, const LayoutSize& offsetFromLayoutObject)
{
    DCHECK(m_newDisplayItemList.isEmpty());
    DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList().allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::kDebugDrawing, std::move(picture));
    displayItem.setSkippedCache();
    // TODO(wkorman): Only compute and append visual rect for drawings.
    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()));
            }
        }
    }
}

void PaintController::showUnderInvalidationError(const char* reason, const DisplayItem& newItem, const DisplayItem* oldItem) const
{
    LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason;
#ifndef NDEBUG
    LOG(ERROR) << "New display item: " << newItem.asDebugString();
    LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() : "None");
#else
    LOG(ERROR) << "Run debug build to get more details.";
#endif
    LOG(ERROR) << "See http://crbug.com/619103.";

#ifndef NDEBUG
    const SkPicture* newPicture = newItem.isDrawing() ? static_cast<const DrawingDisplayItem&>(newItem).picture() : nullptr;
    const SkPicture* oldPicture = oldItem && oldItem->isDrawing() ? static_cast<const DrawingDisplayItem*>(oldItem)->picture() : nullptr;
    LOG(INFO) << "new picture:\n" << (newPicture ? pictureAsDebugString(newPicture) : "None");
    LOG(INFO) << "old picture:\n" << (oldPicture ? pictureAsDebugString(oldPicture) : "None");

    showDebugData();
#endif // NDEBUG
}

void PaintController::checkUnderInvalidation()
{
    DCHECK(RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled());

    if (!isCheckingUnderInvalidation())
        return;

    const DisplayItem& newItem = m_newDisplayItemList.last();
    size_t oldItemIndex = m_underInvalidationCheckingBegin + m_skippedProbableUnderInvalidationCount;
    DisplayItem* oldItem = oldItemIndex < m_currentPaintArtifact.getDisplayItemList().size() ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] : nullptr;

    bool oldAndNewEqual = oldItem && newItem.equals(*oldItem);
    if (!oldAndNewEqual) {
        if (newItem.isBegin()) {
            // Temporarily skip mismatching begin display item which may be removed when we remove a no-op pair.
            ++m_skippedProbableUnderInvalidationCount;
            return;
        }
        if (newItem.isDrawing() && m_skippedProbableUnderInvalidationCount == 1) {
            DCHECK_GE(m_newDisplayItemList.size(), 2u);
            if (m_newDisplayItemList[m_newDisplayItemList.size() - 2].getType() == DisplayItem::kBeginCompositing) {
                // This might be a drawing item between a pair of begin/end compositing display items that will be folded
                // into a single drawing display item.
                ++m_skippedProbableUnderInvalidationCount;
                return;
            }
        }
    }

    if (m_skippedProbableUnderInvalidationCount || !oldAndNewEqual) {
        // If we ever skipped reporting any under-invalidations, report the earliest one.
        showUnderInvalidationError("under-invalidation: display item changed",
            m_newDisplayItemList[m_newDisplayItemList.size() - m_skippedProbableUnderInvalidationCount - 1],
            &m_currentPaintArtifact.getDisplayItemList()[m_underInvalidationCheckingBegin]);
        CHECK(false);
    }

    // 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;
}

String PaintController::displayItemListAsDebugString(const DisplayItemList& 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));
#ifndef NDEBUG
        displayItem.dumpPropertiesAsDebugString(stringBuilder);
#else
        stringBuilder.append(String::format("clientDebugName: %s", displayItem.client().debugName().ascii().data()));
#endif
        if (displayItem.hasValidClient()) {
            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);
            stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]",
                visualRect.x(), visualRect.y(),
                visualRect.width(), visualRect.height()));
        }
        stringBuilder.append('}');
    }
    return stringBuilder.toString();
}

void PaintController::showDebugData() const
{
    WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugString(m_currentPaintArtifact.getDisplayItemList()).utf8().data());
    WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m_newDisplayItemList).utf8().data());
}

} // namespace blink
