/*
 * 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)
#include "TileControllerMemoryHandlerIOS.h"
#endif

namespace WebCore {

#if !LOG_DISABLED
static String validationPolicyAsString(TileGrid::TileValidationPolicy validationPolicy)
{
    StringBuilder builder;
    builder.appendLiteral("[");
    if (validationPolicy & TileGrid::PruneSecondaryTiles)
        builder.appendLiteral("prune secondary");

    if (validationPolicy & TileGrid::UnparentAllTiles) {
        if (builder.isEmpty())
            builder.appendLiteral(", ");
        builder.appendLiteral("unparent all");
    }
    builder.appendLiteral("]");

    return builder.toString();
}
#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);
                    
                    TileMap::iterator it = m_tiles.find(tileIndex);
                    if (it != m_tiles.end())
                        setTileNeedsDisplayInRect(tileIndex, it->value, repaintRectInTileCoords, m_primaryTileCoverageRect);
                }
            }
        }
        return;
    }

    for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it)
        setTileNeedsDisplayInRect(it->key, it->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 (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
        const TileInfo& tileInfo = it->value;
        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 (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
        if (PlatformLayer *layer = it->value.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.remove(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(TileValidationPolicy 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.tileSize();
    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)
    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();

    LOG_WITH_STREAM(Tiling, stream << "TileGrid " << this << " ensureTilesForRect: " << rect);

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

    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 (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
        const TileInfo& tileInfo = it->value;
        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 (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
        const TileInfo& tileInfo = it->value;
        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);

        String repaintCount = String::number(m_tileRepaintCounts.get(tileLayer));

        CGContextSaveGState(context);

        tileLayer->drawTextAtPoint(context, frame.origin.x + 64, frame.origin.y + 192, CGSizeMake(3, -3), 58,
            repaintCount.ascii().data(), repaintCount.length());

        CGContextRestoreGState(context);
    }
}

void TileGrid::platformCALayerPaintContents(PlatformCALayer* platformCALayer, GraphicsContext& context, const FloatRect&, GraphicsLayerPaintBehavior layerPaintBehavior)
{
#if PLATFORM(IOS)
    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.platformContext(), platformCALayer);
        PlatformCALayer::drawLayerContents(context.platformContext(), &m_controller.rootLayer(), dirtyRects, layerPaintBehavior);
    }

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

    if (m_controller.scrollingPerformanceLoggingEnabled()) {
        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
{
    return m_controller.rootLayer().owner()->platformCALayerDeviceScaleFactor();
}

bool TileGrid::platformCALayerShowDebugBorders() const
{
    return m_controller.rootLayer().owner()->platformCALayerShowDebugBorders();
}

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

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

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

int TileGrid::platformCALayerRepaintCount(PlatformCALayer* platformCALayer) const
{
    const auto it = m_tileRepaintCounts.find(platformCALayer);
    return it != m_tileRepaintCounts.end() ? it->value : 0;
}

int TileGrid::platformCALayerIncrementRepaintCount(PlatformCALayer* platformCALayer)
{
    int repaintCount = 0;

    if (m_tileRepaintCounts.contains(platformCALayer))
        repaintCount = m_tileRepaintCounts.get(platformCALayer);

    m_tileRepaintCounts.set(platformCALayer, ++repaintCount);

    return repaintCount;
}

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

} // namespace WebCore

#endif
