/*
 * Copyright (C) 2011-2014 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if USE(CG)

#include "TileGrid.h"

#include "GraphicsContext.h"
#include "LayerPool.h"
#include "Logging.h"
#include "PlatformCALayer.h"
#include "TileController.h"
#include <wtf/MainThread.h>
#include <wtf/text/CString.h>
#include <wtf/text/TextStream.h>

#if PLATFORM(IOS_FAMILY)
#include "TileControllerMemoryHandlerIOS.h"
#endif

namespace WebCore {

#if !LOG_DISABLED

static String validationPolicyAsString(OptionSet<TileGrid::ValidationPolicyFlag> policy)
{
    return makeString('[',
        policy.contains(TileGrid::PruneSecondaryTiles) ? "prune secondary" : "",
        policy.containsAll({ TileGrid::PruneSecondaryTiles, TileGrid::UnparentAllTiles }) ? ", " : "",
        policy.contains(TileGrid::PruneSecondaryTiles) ? "unparent all" : "",
        ']');
}

#endif

TileGrid::TileGrid(TileController& controller)
    : m_controller(controller)
    , m_containerLayer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
    , m_cohortRemovalTimer(*this, &TileGrid::cohortRemovalTimerFired)
    , m_tileSize(kDefaultTileSize, kDefaultTileSize)
{
    m_containerLayer.get().setName(TileController::tileGridContainerLayerName());
    m_containerLayer.get().setContentsScale(m_controller.deviceScaleFactor());
}

TileGrid::~TileGrid()
{
    ASSERT(isMainThread());

    for (auto& tile : m_tiles.values())
        tile.layer->setOwner(nullptr);
}

void TileGrid::setIsZoomedOutTileGrid(bool isZoomedOutGrid)
{
    if (isZoomedOutGrid)
        m_containerLayer.get().setName(TileController::zoomedOutTileGridContainerLayerName());
    else
        m_containerLayer.get().setName(TileController::tileGridContainerLayerName());
}

void TileGrid::setScale(float scale)
{
    m_scale = scale;

    TransformationMatrix transform;
    transform.scale(1 / m_scale);
    m_containerLayer->setTransform(transform);

    m_controller.setNeedsRevalidateTiles();

    m_containerLayer.get().setContentsScale(m_controller.deviceScaleFactor());

    for (auto& tile : m_tiles.values())
        tile.layer->setContentsScale(m_controller.deviceScaleFactor());
}

void TileGrid::setNeedsDisplay()
{
    for (auto& entry : m_tiles) {
        TileInfo& tileInfo = entry.value;
        IntRect tileRect = rectForTileIndex(entry.key);

        if (tileRect.intersects(m_primaryTileCoverageRect) && tileInfo.layer->superlayer())
            tileInfo.layer->setNeedsDisplay();
        else
            tileInfo.hasStaleContent = true;
    }
}

void TileGrid::setNeedsDisplayInRect(const IntRect& rect)
{
    if (m_tiles.isEmpty())
        return;

    FloatRect scaledRect(rect);
    scaledRect.scale(m_scale);
    IntRect repaintRectInTileCoords(enclosingIntRect(scaledRect));

    IntSize tileSize = m_tileSize;

    // For small invalidations, lookup the covered tiles.
    if (repaintRectInTileCoords.height() < 2 * tileSize.height() && repaintRectInTileCoords.width() < 2 * tileSize.width()) {
        TileIndex topLeft;
        TileIndex bottomRight;
        if (getTileIndexRangeForRect(repaintRectInTileCoords, topLeft, bottomRight)) {
            for (int y = topLeft.y(); y <= bottomRight.y(); ++y) {
                for (int x = topLeft.x(); x <= bottomRight.x(); ++x) {
                    TileIndex tileIndex(x, y);
                    auto it = m_tiles.find(tileIndex);
                    if (it != m_tiles.end())
                        setTileNeedsDisplayInRect(tileIndex, it->value, repaintRectInTileCoords, m_primaryTileCoverageRect);
                }
            }
        }
        return;
    }

    for (auto& entry : m_tiles)
        setTileNeedsDisplayInRect(entry.key, entry.value, repaintRectInTileCoords, m_primaryTileCoverageRect);
}

void TileGrid::dropTilesInRect(const IntRect& rect)
{
    if (m_tiles.isEmpty())
        return;

    FloatRect scaledRect(rect);
    scaledRect.scale(m_scale);
    IntRect dropRectInTileCoords(enclosingIntRect(scaledRect));

    Vector<TileIndex> tilesToRemove;

    for (auto& index : m_tiles.keys()) {
        if (rectForTileIndex(index).intersects(dropRectInTileCoords))
            tilesToRemove.append(index);
    }

    removeTiles(tilesToRemove);
}

void TileGrid::setTileNeedsDisplayInRect(const TileIndex& tileIndex, TileInfo& tileInfo, const IntRect& repaintRectInTileCoords, const IntRect& coverageRectInTileCoords)
{
    PlatformCALayer* tileLayer = tileInfo.layer.get();

    IntRect tileRect = rectForTileIndex(tileIndex);
    FloatRect tileRepaintRect = tileRect;
    tileRepaintRect.intersect(repaintRectInTileCoords);
    if (tileRepaintRect.isEmpty())
        return;

    tileRepaintRect.moveBy(-tileRect.location());
    
    // We could test for intersection with the visible rect. This would reduce painting yet more,
    // but may make scrolling stale tiles into view more frequent.
    if (tileRect.intersects(coverageRectInTileCoords) && tileLayer->superlayer()) {
        tileLayer->setNeedsDisplayInRect(tileRepaintRect);

        if (m_controller.rootLayer().owner()->platformCALayerShowRepaintCounter(0)) {
            FloatRect indicatorRect(0, 0, 52, 27);
            tileLayer->setNeedsDisplayInRect(indicatorRect);
        }
    } else
        tileInfo.hasStaleContent = true;
}

void TileGrid::updateTileLayerProperties()
{
    bool acceleratesDrawing = m_controller.acceleratesDrawing();
    bool deepColor = m_controller.wantsDeepColorBackingStore();
    bool subpixelAntialiasedText = m_controller.supportsSubpixelAntialiasedText();
    bool opaque = m_controller.tilesAreOpaque();
    Color tileDebugBorderColor = m_controller.tileDebugBorderColor();
    float tileDebugBorderWidth = m_controller.tileDebugBorderWidth();
    for (auto& tileInfo : m_tiles.values()) {
        tileInfo.layer->setAcceleratesDrawing(acceleratesDrawing);
        tileInfo.layer->setWantsDeepColorBackingStore(deepColor);
        tileInfo.layer->setSupportsSubpixelAntialiasedText(subpixelAntialiasedText);
        tileInfo.layer->setOpaque(opaque);
        tileInfo.layer->setBorderColor(tileDebugBorderColor);
        tileInfo.layer->setBorderWidth(tileDebugBorderWidth);
    }
}

bool TileGrid::tilesWouldChangeForCoverageRect(const FloatRect& coverageRect) const
{
    if (coverageRect.isEmpty())
        return false;

    FloatRect scaledRect(coverageRect);
    scaledRect.scale(m_scale);
    IntRect currentCoverageRectInTileCoords(enclosingIntRect(scaledRect));

    IntRect tileCoverageRect;
    TileIndex topLeft;
    TileIndex bottomRight;
    if (getTileIndexRangeForRect(currentCoverageRectInTileCoords, topLeft, bottomRight)) {
        tileCoverageRect = rectForTileIndex(topLeft);
        tileCoverageRect.unite(rectForTileIndex(bottomRight));
    }

    return tileCoverageRect != m_primaryTileCoverageRect;
}

bool TileGrid::prepopulateRect(const FloatRect& rect)
{
    LOG_WITH_STREAM(Tiling, stream << "TileGrid " << this << " prepopulateRect: " << rect);

    IntRect enclosingCoverageRect = enclosingIntRect(rect);
    if (m_primaryTileCoverageRect.contains(enclosingCoverageRect))
        return false;

    m_secondaryTileCoverageRects.append(enclosingCoverageRect);
    return true;
}

IntRect TileGrid::rectForTileIndex(const TileIndex& tileIndex) const
{
    // FIXME: calculating the scaled size here should match with the rest of calculated sizes where we use the combination of
    // enclosingIntRect, expandedIntSize (floor vs ceil).
    // However enclosing this size could reveal gap on root layer's background. see RenderView::backgroundRect()
    IntSize tileSize = m_tileSize;
    IntRect rect(tileIndex.x() * tileSize.width(), tileIndex.y() * tileSize.height(), tileSize.width(), tileSize.height());
    IntRect scaledBounds(m_controller.bounds());
    scaledBounds.scale(m_scale);
    rect.intersect(scaledBounds);
    return rect;
}

bool TileGrid::getTileIndexRangeForRect(const IntRect& rect, TileIndex& topLeft, TileIndex& bottomRight) const
{
    IntRect clampedRect = m_controller.bounds();
    clampedRect.scale(m_scale);
    clampedRect.intersect(rect);
    
    if (clampedRect.isEmpty())
        return false;

    auto tileSize = m_tileSize;
    if (clampedRect.x() >= 0)
        topLeft.setX(clampedRect.x() / tileSize.width());
    else
        topLeft.setX(floorf((float)clampedRect.x() / tileSize.width()));

    if (clampedRect.y() >= 0)
        topLeft.setY(clampedRect.y() / tileSize.height());
    else
        topLeft.setY(floorf((float)clampedRect.y() / tileSize.height()));

    int bottomXRatio = ceil((float)clampedRect.maxX() / tileSize.width());
    bottomRight.setX(std::max(bottomXRatio - 1, 0));

    int bottomYRatio = ceil((float)clampedRect.maxY() / tileSize.height());
    bottomRight.setY(std::max(bottomYRatio - 1, 0));
    
    return true;
}

unsigned TileGrid::blankPixelCount() const
{
    PlatformLayerList tiles(m_tiles.size());
    for (auto& tile : m_tiles.values()) {
        if (auto layer = tile.layer->platformLayer())
            tiles.append(layer);
    }
    return TileController::blankPixelCountForTiles(tiles, m_controller.visibleRect(), IntPoint(0, 0));
}

void TileGrid::removeTiles(Vector<TileGrid::TileIndex>& toRemove)
{
    for (size_t i = 0; i < toRemove.size(); ++i) {
        TileInfo tileInfo = m_tiles.take(toRemove[i]);
        tileInfo.layer->removeFromSuperlayer();
        m_tileRepaintCounts.removeAll(tileInfo.layer.get());
        tileInfo.layer->moveToLayerPool();
    }
}

void TileGrid::removeAllTiles()
{
    Vector<TileIndex> tilesToRemove;
    tilesToRemove.reserveInitialCapacity(m_tiles.size());

    for (auto& entry : m_tiles)
        tilesToRemove.uncheckedAppend(entry.key);

    removeTiles(tilesToRemove);
}

void TileGrid::removeAllSecondaryTiles()
{
    Vector<TileIndex> tilesToRemove;

    for (auto& entry : m_tiles) {
        const TileInfo& tileInfo = entry.value;
        if (tileInfo.cohort == visibleTileCohort)
            continue;
        tilesToRemove.append(entry.key);
    }

    removeTiles(tilesToRemove);
}

void TileGrid::removeTilesInCohort(TileCohort cohort)
{
    ASSERT(cohort != visibleTileCohort);
    Vector<TileIndex> tilesToRemove;

    for (auto& entry : m_tiles) {
        const TileInfo& tileInfo = entry.value;
        if (tileInfo.cohort != cohort)
            continue;
        tilesToRemove.append(entry.key);
    }

    removeTiles(tilesToRemove);
}

void TileGrid::revalidateTiles(OptionSet<ValidationPolicyFlag> validationPolicy)
{
    FloatRect coverageRect = m_controller.coverageRect();
    IntRect bounds = m_controller.bounds();

    LOG_WITH_STREAM(Tiling, stream << "TileGrid " << this << " (controller " << &m_controller << ") revalidateTiles: bounds " << bounds << " coverageRect" << coverageRect << " validation: " << validationPolicyAsString(validationPolicy));

    FloatRect scaledRect(coverageRect);
    scaledRect.scale(m_scale);
    IntRect coverageRectInTileCoords(enclosingIntRect(scaledRect));

    TileCohort currCohort = nextTileCohort();
    unsigned tilesInCohort = 0;

    Seconds minimumRevalidationTimerDuration = Seconds::infinity();
    bool needsTileRevalidation = false;
    
    auto tileSize = m_controller.computeTileSize();
    if (tileSize != m_tileSize) {
        removeAllTiles();
        m_tileSize = tileSize;
    }

    // Move tiles newly outside the coverage rect into the cohort map.
    for (auto& entry : m_tiles) {
        TileInfo& tileInfo = entry.value;
        TileIndex tileIndex = entry.key;

        PlatformCALayer* tileLayer = tileInfo.layer.get();
        IntRect tileRect = rectForTileIndex(tileIndex);

        if (tileRect.intersects(coverageRectInTileCoords)) {
            tileInfo.cohort = visibleTileCohort;
            if (tileInfo.hasStaleContent) {
                // FIXME: store a dirty region per layer?
                tileLayer->setNeedsDisplay();
                tileInfo.hasStaleContent = false;
            }
        } else {
            // Add to the currentCohort if not already in one.
            if (tileInfo.cohort == visibleTileCohort) {
                tileInfo.cohort = currCohort;
                ++tilesInCohort;
                tileLayer->removeFromSuperlayer();
            } else if (m_controller.shouldAggressivelyRetainTiles() && tileLayer->superlayer()) {
                // Aggressive tile retention means we'll never remove cohorts, but we need to make sure they're unparented.
                // We can't immediately unparent cohorts comprised of secondary tiles that never touch the primary coverage rect,
                // because that would defeat the usefulness of prepopulateRect(); instead, age prepopulated tiles out as if they were being removed.
                for (auto& cohort : m_cohortList) {
                    if (cohort.cohort != tileInfo.cohort)
                        continue;
                    Seconds timeUntilCohortExpires = cohort.timeUntilExpiration();
                    if (timeUntilCohortExpires > 0_s) {
                        minimumRevalidationTimerDuration = std::min(minimumRevalidationTimerDuration, timeUntilCohortExpires);
                        needsTileRevalidation = true;
                    } else
                        tileLayer->removeFromSuperlayer();
                    break;
                }
            }
        }
    }

    if (needsTileRevalidation)
        m_controller.scheduleTileRevalidation(minimumRevalidationTimerDuration);

    if (!m_controller.shouldAggressivelyRetainTiles()) {
        if (m_controller.shouldTemporarilyRetainTileCohorts())
            scheduleCohortRemoval();
        else if (tilesInCohort) {
            removeTilesInCohort(currCohort);
            tilesInCohort = 0;
        }
    }

    if (tilesInCohort)
        startedNewCohort(currCohort);

    if (validationPolicy & PruneSecondaryTiles) {
        removeAllSecondaryTiles();
        m_cohortList.clear();
    }

    if (validationPolicy & UnparentAllTiles) {
        for (auto& tile : m_tiles.values())
            tile.layer->removeFromSuperlayer();
    }

    auto boundsAtLastRevalidate = m_controller.boundsAtLastRevalidate();
    if (boundsAtLastRevalidate != bounds) {
        // If there are margin tiles and the bounds have grown taller or wider, then the tiles that used to
        // be bottom or right margin tiles need to be invalidated.
        if (m_controller.hasMargins()) {
            if (bounds.width() > boundsAtLastRevalidate.width() || bounds.height() > boundsAtLastRevalidate.height()) {
                IntRect boundsWithoutMargin = m_controller.boundsWithoutMargin();
                IntRect oldBoundsWithoutMargin = m_controller.boundsAtLastRevalidateWithoutMargin();

                if (bounds.height() > boundsAtLastRevalidate.height()) {
                    IntRect formerBottomMarginRect = IntRect(oldBoundsWithoutMargin.x(), oldBoundsWithoutMargin.height(),
                        oldBoundsWithoutMargin.width(), boundsWithoutMargin.height() - oldBoundsWithoutMargin.height());
                    setNeedsDisplayInRect(formerBottomMarginRect);
                }

                if (bounds.width() > boundsAtLastRevalidate.width()) {
                    IntRect formerRightMarginRect = IntRect(oldBoundsWithoutMargin.width(), oldBoundsWithoutMargin.y(),
                        boundsWithoutMargin.width() - oldBoundsWithoutMargin.width(), oldBoundsWithoutMargin.height());
                    setNeedsDisplayInRect(formerRightMarginRect);
                }
            }
        }

        FloatRect scaledBounds(bounds);
        scaledBounds.scale(m_scale);
        IntRect boundsInTileCoords(enclosingIntRect(scaledBounds));

        TileIndex topLeftForBounds;
        TileIndex bottomRightForBounds;
        if (getTileIndexRangeForRect(boundsInTileCoords, topLeftForBounds, bottomRightForBounds)) {
            Vector<TileIndex> tilesToRemove;
            for (auto& index : m_tiles.keys()) {
                if (index.y() < topLeftForBounds.y() || index.y() > bottomRightForBounds.y() || index.x() < topLeftForBounds.x() || index.x() > bottomRightForBounds.x())
                    tilesToRemove.append(index);
            }
            removeTiles(tilesToRemove);
        }
    }

    // Ensure primary tile coverage tiles.
    m_primaryTileCoverageRect = ensureTilesForRect(coverageRect, CoverageType::PrimaryTiles);

    // Ensure secondary tiles (requested via prepopulateRect).
    if (!(validationPolicy & PruneSecondaryTiles)) {
        for (auto& secondaryCoverageRect : m_secondaryTileCoverageRects) {
            FloatRect secondaryRectInLayerCoordinates(secondaryCoverageRect);
            secondaryRectInLayerCoordinates.scale(1 / m_scale);
            ensureTilesForRect(secondaryRectInLayerCoordinates, CoverageType::SecondaryTiles);
        }
        m_secondaryTileCoverageRects.clear();
    }

    m_controller.didRevalidateTiles();
}

TileGrid::TileCohort TileGrid::nextTileCohort() const
{
    if (!m_cohortList.isEmpty())
        return m_cohortList.last().cohort + 1;

    return 1;
}

void TileGrid::startedNewCohort(TileCohort cohort)
{
    m_cohortList.append(TileCohortInfo(cohort, MonotonicTime::now()));
#if PLATFORM(IOS_FAMILY)
    if (!m_controller.isInWindow())
        tileControllerMemoryHandler().tileControllerGainedUnparentedTiles(&m_controller);
#endif
}

TileGrid::TileCohort TileGrid::newestTileCohort() const
{
    return m_cohortList.isEmpty() ? 0 : m_cohortList.last().cohort;
}

TileGrid::TileCohort TileGrid::oldestTileCohort() const
{
    return m_cohortList.isEmpty() ? 0 : m_cohortList.first().cohort;
}

void TileGrid::scheduleCohortRemoval()
{
    const Seconds cohortRemovalTimerSeconds { 1_s };

    // Start the timer, or reschedule the timer from now if it's already active.
    if (!m_cohortRemovalTimer.isActive())
        m_cohortRemovalTimer.startRepeating(cohortRemovalTimerSeconds);
}

Seconds TileGrid::TileCohortInfo::timeUntilExpiration()
{
    Seconds cohortLifeTimeSeconds = 2_s;
    MonotonicTime timeThreshold = MonotonicTime::now() - cohortLifeTimeSeconds;
    return creationTime - timeThreshold;
}

void TileGrid::cohortRemovalTimerFired()
{
    if (m_cohortList.isEmpty()) {
        m_cohortRemovalTimer.stop();
        return;
    }

    while (!m_cohortList.isEmpty() && m_cohortList.first().timeUntilExpiration() < 0_s) {
        TileCohortInfo firstCohort = m_cohortList.takeFirst();
        removeTilesInCohort(firstCohort.cohort);
    }

    m_controller.updateTileCoverageMap();
}

IntRect TileGrid::ensureTilesForRect(const FloatRect& rect, CoverageType newTileType)
{
    if (!m_controller.isInWindow())
        return IntRect();

    FloatRect scaledRect(rect);
    scaledRect.scale(m_scale);
    IntRect rectInTileCoords(enclosingIntRect(scaledRect));

    TileIndex topLeft;
    TileIndex bottomRight;
    if (!getTileIndexRangeForRect(rectInTileCoords, topLeft, bottomRight))
        return IntRect();

    TileCohort currCohort = nextTileCohort();
    unsigned tilesInCohort = 0;

    IntRect coverageRect;

    for (int y = topLeft.y(); y <= bottomRight.y(); ++y) {
        for (int x = topLeft.x(); x <= bottomRight.x(); ++x) {
            TileIndex tileIndex(x, y);

            IntRect tileRect = rectForTileIndex(tileIndex);
            TileInfo& tileInfo = m_tiles.add(tileIndex, TileInfo()).iterator->value;

            coverageRect.unite(tileRect);

            bool shouldChangeTileLayerFrame = false;

            if (!tileInfo.layer) {
                tileInfo.layer = m_controller.createTileLayer(tileRect, *this);
                ASSERT(!m_tileRepaintCounts.contains(tileInfo.layer.get()));
            } else {
                // We already have a layer for this tile. Ensure that its size is correct.
                FloatSize tileLayerSize(tileInfo.layer->bounds().size());
                shouldChangeTileLayerFrame = tileLayerSize != FloatSize(tileRect.size());

                if (shouldChangeTileLayerFrame) {
                    tileInfo.layer->setBounds(FloatRect(FloatPoint(), tileRect.size()));
                    tileInfo.layer->setPosition(tileRect.location());
                    tileInfo.layer->setNeedsDisplay();
                }
            }

            if (newTileType == CoverageType::SecondaryTiles && !tileRect.intersects(m_primaryTileCoverageRect)) {
                tileInfo.cohort = currCohort;
                ++tilesInCohort;
            }

            if (!tileInfo.layer->superlayer())
                m_containerLayer.get().appendSublayer(*tileInfo.layer);
        }
    }

    if (tilesInCohort)
        startedNewCohort(currCohort);

    LOG_WITH_STREAM(Tiling, stream << "TileGrid " << this << " (bounds " << m_controller.bounds() << ") ensureTilesForRect: " << rect << " covered " << coverageRect);

    return coverageRect;
}

IntRect TileGrid::extent() const
{
    TileIndex topLeft;
    TileIndex bottomRight;
    if (getTileIndexRangeForRect(m_primaryTileCoverageRect, topLeft, bottomRight)) {
        // Return index of top, left tile and the number of tiles across and down.
        return IntRect(topLeft.x(), topLeft.y(), bottomRight.x() - topLeft.x() + 1, bottomRight.y() - topLeft.y() + 1);
    }

    return IntRect();
}

double TileGrid::retainedTileBackingStoreMemory() const
{
    double totalBytes = 0;
    for (auto& tileInfo : m_tiles.values()) {
        if (tileInfo.layer->superlayer()) {
            FloatRect bounds = tileInfo.layer->bounds();
            double contentsScale = tileInfo.layer->contentsScale();
            totalBytes += 4 * bounds.width() * contentsScale * bounds.height() * contentsScale;
        }
    }
    return totalBytes;
}

// Return the rect in layer coords, not tile coords.
IntRect TileGrid::tileCoverageRect() const
{
    IntRect coverageRectInLayerCoords(m_primaryTileCoverageRect);
    coverageRectInLayerCoords.scale(1 / m_scale);
    return coverageRectInLayerCoords;
}

void TileGrid::drawTileMapContents(CGContextRef context, CGRect layerBounds) const
{
    CGContextSetRGBFillColor(context, 0.3, 0.3, 0.3, 1);
    CGContextFillRect(context, layerBounds);

    CGFloat scaleFactor = layerBounds.size.width / m_controller.bounds().width();

    CGFloat contextScale = scaleFactor / m_scale;
    CGContextScaleCTM(context, contextScale, contextScale);
    
    for (auto& tileInfo : m_tiles.values()) {
        PlatformCALayer* tileLayer = tileInfo.layer.get();

        CGFloat red = 1;
        CGFloat green = 1;
        CGFloat blue = 1;
        CGFloat alpha = 1;
        if (tileInfo.hasStaleContent) {
            red = 0.25;
            green = 0.125;
            blue = 0;
        } else if (m_controller.shouldAggressivelyRetainTiles() && tileInfo.cohort != visibleTileCohort) {
            red = 0.8;
            green = 0.8;
            blue = 0.8;
        }

        TileCohort newestCohort = newestTileCohort();
        TileCohort oldestCohort = oldestTileCohort();

        if (!m_controller.shouldAggressivelyRetainTiles() && tileInfo.cohort != visibleTileCohort && newestCohort > oldestCohort)
            alpha = 1 - (static_cast<float>((newestCohort - tileInfo.cohort)) / (newestCohort - oldestCohort));

        CGContextSetRGBFillColor(context, red, green, blue, alpha);

        if (tileLayer->superlayer()) {
            CGContextSetLineWidth(context, 0.5 / contextScale);
            CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
        } else {
            CGContextSetLineWidth(context, 1 / contextScale);
            CGContextSetRGBStrokeColor(context, 0.2, 0.1, 0.9, 1);
        }

        CGRect frame = CGRectMake(tileLayer->position().x(), tileLayer->position().y(), tileLayer->bounds().size().width(), tileLayer->bounds().size().height());
        CGContextFillRect(context, frame);
        CGContextStrokeRect(context, frame);

        CGContextSetRGBFillColor(context, 0, 0, 0, 0.5);

        CGContextSaveGState(context);

        auto repaintCount = m_tileRepaintCounts.count(tileLayer);
        char repaintCountCharacters[lengthOfIntegerAsString(std::numeric_limits<decltype(repaintCount)>::max())];
        writeIntegerToBuffer(repaintCount, repaintCountCharacters);
        tileLayer->drawTextAtPoint(context, frame.origin.x + 64, frame.origin.y + 192, CGSizeMake(3, -3), 58,
            repaintCountCharacters, lengthOfIntegerAsString(repaintCount));

        CGContextRestoreGState(context);
    }
}

void TileGrid::platformCALayerPaintContents(PlatformCALayer* platformCALayer, GraphicsContext& context, const FloatRect&, GraphicsLayerPaintBehavior layerPaintBehavior)
{
#if PLATFORM(IOS_FAMILY)
    if (pthread_main_np())
        WebThreadLock();
#endif

    if (!platformCALayerRepaintCount(platformCALayer))
        layerPaintBehavior |= GraphicsLayerPaintFirstTilePaint;

    {
        GraphicsContextStateSaver stateSaver(context);

        FloatPoint3D layerOrigin = platformCALayer->position();
        context.translate(-layerOrigin.x(), -layerOrigin.y());
        context.scale(m_scale);

        PlatformCALayer::RepaintRectList dirtyRects = PlatformCALayer::collectRectsToPaint(context, platformCALayer);
        PlatformCALayer::drawLayerContents(context, &m_controller.rootLayer(), dirtyRects, layerPaintBehavior);
    }

    int repaintCount = platformCALayerIncrementRepaintCount(platformCALayer);
    if (m_controller.rootLayer().owner()->platformCALayerShowRepaintCounter(0))
        PlatformCALayer::drawRepaintIndicator(context, platformCALayer, repaintCount, m_controller.tileDebugBorderColor());

    if (m_controller.scrollingPerformanceTestingEnabled()) {
        FloatRect visiblePart(platformCALayer->position().x(), platformCALayer->position().y(), platformCALayer->bounds().size().width(), platformCALayer->bounds().size().height());
        visiblePart.intersect(m_controller.visibleRect());

        if (repaintCount == 1 && !visiblePart.isEmpty())
            m_controller.logFilledVisibleFreshTile(blankPixelCount());
    }
}

float TileGrid::platformCALayerDeviceScaleFactor() const
{
    if (auto* layerOwner = m_controller.rootLayer().owner())
        return layerOwner->platformCALayerDeviceScaleFactor();
    return 1.0f;
}

bool TileGrid::platformCALayerShowDebugBorders() const
{
    if (auto* layerOwner = m_controller.rootLayer().owner())
        return layerOwner->platformCALayerShowDebugBorders();
    return false;
}

bool TileGrid::platformCALayerShowRepaintCounter(PlatformCALayer*) const
{
    if (auto* layerOwner = m_controller.rootLayer().owner())
        return layerOwner->platformCALayerShowRepaintCounter(nullptr);
    return false;
}

bool TileGrid::isUsingDisplayListDrawing(PlatformCALayer*) const
{
    if (auto* layerOwner = m_controller.rootLayer().owner())
        return layerOwner->isUsingDisplayListDrawing(nullptr);
    return false;
}

bool TileGrid::platformCALayerContentsOpaque() const
{
    return m_controller.tilesAreOpaque();
}

int TileGrid::platformCALayerRepaintCount(PlatformCALayer* platformCALayer) const
{
    return m_tileRepaintCounts.count(platformCALayer);
}

int TileGrid::platformCALayerIncrementRepaintCount(PlatformCALayer* platformCALayer)
{
    return m_tileRepaintCounts.add(platformCALayer).iterator->value;
}

#if PLATFORM(IOS_FAMILY)
void TileGrid::removeUnparentedTilesNow()
{
    while (!m_cohortList.isEmpty())
        removeTilesInCohort(m_cohortList.takeFirst().cohort);
}
#endif

} // namespace WebCore

#endif
