// Copyright 2011 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 "cc/layer_tree_host.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/string_number_conversions.h"
#include "cc/animation_registrar.h"
#include "cc/heads_up_display_layer.h"
#include "cc/heads_up_display_layer_impl.h"
#include "cc/layer.h"
#include "cc/layer_animation_controller.h"
#include "cc/layer_iterator.h"
#include "cc/layer_tree_host_client.h"
#include "cc/layer_tree_host_common.h"
#include "cc/layer_tree_host_impl.h"
#include "cc/layer_tree_impl.h"
#include "cc/math_util.h"
#include "cc/occlusion_tracker.h"
#include "cc/overdraw_metrics.h"
#include "cc/prioritized_resource_manager.h"
#include "cc/single_thread_proxy.h"
#include "cc/switches.h"
#include "cc/thread.h"
#include "cc/thread_proxy.h"
#include "cc/top_controls_manager.h"
#include "cc/tree_synchronizer.h"

namespace {
static int numLayerTreeInstances;
}

namespace cc {

RendererCapabilities::RendererCapabilities()
    : bestTextureFormat(0)
    , usingPartialSwap(false)
    , usingAcceleratedPainting(false)
    , usingSetVisibility(false)
    , usingSwapCompleteCallback(false)
    , usingGpuMemoryManager(false)
    , usingEglImage(false)
    , allowPartialTextureUpdates(false)
    , usingOffscreenContext3d(false)
    , maxTextureSize(0)
    , avoidPow2Textures(false)
{
}

RendererCapabilities::~RendererCapabilities()
{
}

bool LayerTreeHost::anyLayerTreeHostInstanceExists()
{
    return numLayerTreeInstances > 0;
}

scoped_ptr<LayerTreeHost> LayerTreeHost::create(LayerTreeHostClient* client, const LayerTreeSettings& settings, scoped_ptr<Thread> implThread)
{
    scoped_ptr<LayerTreeHost> layerTreeHost(new LayerTreeHost(client, settings));
    if (!layerTreeHost->initialize(implThread.Pass()))
        return scoped_ptr<LayerTreeHost>();
    return layerTreeHost.Pass();
}

LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client, const LayerTreeSettings& settings)
    : m_animating(false)
    , m_needsFullTreeSync(true)
    , m_needsFilterContext(false)
    , m_client(client)
    , m_commitNumber(0)
    , m_renderingStats()
    , m_rendererInitialized(false)
    , m_outputSurfaceLost(false)
    , m_numFailedRecreateAttempts(0)
    , m_settings(settings)
    , m_debugState(settings.initialDebugState)
    , m_deviceScaleFactor(1)
    , m_visible(true)
    , m_pageScaleFactor(1)
    , m_minPageScaleFactor(1)
    , m_maxPageScaleFactor(1)
    , m_triggerIdleUpdates(true)
    , m_backgroundColor(SK_ColorWHITE)
    , m_hasTransparentBackground(false)
    , m_partialTextureUpdateRequests(0)
    , m_animationRegistrar(AnimationRegistrar::create())
{
    numLayerTreeInstances++;
}

bool LayerTreeHost::initialize(scoped_ptr<Thread> implThread)
{
    if (implThread)
        return initializeProxy(ThreadProxy::create(this, implThread.Pass()));
    else
        return initializeProxy(SingleThreadProxy::create(this));
}

bool LayerTreeHost::initializeForTesting(scoped_ptr<Proxy> proxyForTesting)
{
    return initializeProxy(proxyForTesting.Pass());
}

bool LayerTreeHost::initializeProxy(scoped_ptr<Proxy> proxy)
{
    TRACE_EVENT0("cc", "LayerTreeHost::initializeForReal");

    m_proxy = proxy.Pass();
    m_proxy->start();
    return m_proxy->initializeOutputSurface();
}

LayerTreeHost::~LayerTreeHost()
{
    if (m_rootLayer)
        m_rootLayer->setLayerTreeHost(0);
    DCHECK(m_proxy);
    DCHECK(m_proxy->isMainThread());
    TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost");
    m_proxy->stop();
    numLayerTreeInstances--;
    RateLimiterMap::iterator it = m_rateLimiters.begin();
    if (it != m_rateLimiters.end())
        it->second->stop();

    if (m_rootLayer) {
        // The layer tree must be destroyed before the layer tree host. We've
        // made a contract with our animation controllers that the registrar
        // will outlive them, and we must make good.
        m_rootLayer = NULL;
    }
}

void LayerTreeHost::setSurfaceReady()
{
    m_proxy->setSurfaceReady();
}

void LayerTreeHost::initializeRenderer()
{
    TRACE_EVENT0("cc", "LayerTreeHost::initializeRenderer");
    if (!m_proxy->initializeRenderer()) {
        // Uh oh, better tell the client that we can't do anything with this output surface.
        m_client->didRecreateOutputSurface(false);
        return;
    }

    // Update m_settings based on capabilities that we got back from the renderer.
    m_settings.acceleratePainting = m_proxy->rendererCapabilities().usingAcceleratedPainting;

    // Update m_settings based on partial update capability.
    size_t maxPartialTextureUpdates = 0;
    if (m_proxy->rendererCapabilities().allowPartialTextureUpdates && !m_settings.implSidePainting)
        maxPartialTextureUpdates = std::min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates());
    m_settings.maxPartialTextureUpdates = maxPartialTextureUpdates;

    m_contentsTextureManager = PrioritizedResourceManager::create(m_proxy.get());
    m_surfaceMemoryPlaceholder = m_contentsTextureManager->createTexture(gfx::Size(), GL_RGBA);

    m_rendererInitialized = true;

    m_settings.defaultTileSize = gfx::Size(std::min(m_settings.defaultTileSize.width(), m_proxy->rendererCapabilities().maxTextureSize),
                                           std::min(m_settings.defaultTileSize.height(), m_proxy->rendererCapabilities().maxTextureSize));
    m_settings.maxUntiledLayerSize = gfx::Size(std::min(m_settings.maxUntiledLayerSize.width(), m_proxy->rendererCapabilities().maxTextureSize),
                                               std::min(m_settings.maxUntiledLayerSize.height(), m_proxy->rendererCapabilities().maxTextureSize));
}

LayerTreeHost::RecreateResult LayerTreeHost::recreateOutputSurface()
{
    TRACE_EVENT0("cc", "LayerTreeHost::recreateOutputSurface");
    DCHECK(m_outputSurfaceLost);

    if (m_proxy->recreateOutputSurface()) {
        m_client->didRecreateOutputSurface(true);
        m_outputSurfaceLost = false;
        return RecreateSucceeded;
    }

    m_client->willRetryRecreateOutputSurface();

    // Tolerate a certain number of recreation failures to work around races
    // in the output-surface-lost machinery.
    m_numFailedRecreateAttempts++;
    if (m_numFailedRecreateAttempts < 5) {
        // FIXME: The single thread does not self-schedule output surface
        // recreation. So force another recreation attempt to happen by requesting
        // another commit.
        if (!m_proxy->hasImplThread())
            setNeedsCommit();
        return RecreateFailedButTryAgain;
    }

    // We have tried too many times to recreate the output surface. Tell the
    // host to fall back to software rendering.
    m_client->didRecreateOutputSurface(false);
    return RecreateFailedAndGaveUp;
}

void LayerTreeHost::deleteContentsTexturesOnImplThread(ResourceProvider* resourceProvider)
{
    DCHECK(m_proxy->isImplThread());
    if (m_rendererInitialized)
        m_contentsTextureManager->clearAllMemory(resourceProvider);
}

void LayerTreeHost::acquireLayerTextures()
{
    DCHECK(m_proxy->isMainThread());
    m_proxy->acquireLayerTextures();
}

void LayerTreeHost::didBeginFrame()
{
    m_client->didBeginFrame();
}

void LayerTreeHost::updateAnimations(base::TimeTicks frameBeginTime)
{
    m_animating = true;
    m_client->animate((frameBeginTime - base::TimeTicks()).InSecondsF());
    animateLayers(frameBeginTime);
    m_animating = false;

    m_renderingStats.numAnimationFrames++;
}

void LayerTreeHost::didStopFlinging()
{
  m_proxy->mainThreadHasStoppedFlinging();
}

void LayerTreeHost::layout()
{
    m_client->layout();
}

void LayerTreeHost::beginCommitOnImplThread(LayerTreeHostImpl* hostImpl)
{
    DCHECK(m_proxy->isImplThread());
    TRACE_EVENT0("cc", "LayerTreeHost::commitTo");
}

// This function commits the LayerTreeHost to an impl tree. When modifying
// this function, keep in mind that the function *runs* on the impl thread! Any
// code that is logically a main thread operation, e.g. deletion of a Layer,
// should be delayed until the LayerTreeHost::commitComplete, which will run
// after the commit, but on the main thread.
void LayerTreeHost::finishCommitOnImplThread(LayerTreeHostImpl* hostImpl)
{
    DCHECK(m_proxy->isImplThread());

    // If there are linked evicted backings, these backings' resources may be put into the
    // impl tree, so we can't draw yet. Determine this before clearing all evicted backings.
    bool newImplTreeHasNoEvictedResources = !m_contentsTextureManager->linkedEvictedBackingsExist();

    m_contentsTextureManager->updateBackingsInDrawingImplTree();

    // In impl-side painting, synchronize to the pending tree so that it has
    // time to raster before being displayed.  If no pending tree is needed,
    // synchronization can happen directly to the active tree and
    // unlinked contents resources can be reclaimed immediately.
    LayerTreeImpl* syncTree;
    if (m_settings.implSidePainting) {
        // Commits should not occur while there is already a pending tree.
        DCHECK(!hostImpl->pendingTree());
        hostImpl->createPendingTree();
        syncTree = hostImpl->pendingTree();
    } else {
        m_contentsTextureManager->reduceMemory(hostImpl->resourceProvider());
        syncTree = hostImpl->activeTree();
    }

    if (m_needsFullTreeSync)
        syncTree->SetRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), syncTree->DetachLayerTree(), syncTree));
    {
        TRACE_EVENT0("cc", "LayerTreeHost::pushProperties");
        TreeSynchronizer::pushProperties(rootLayer(), syncTree->RootLayer());
    }

    syncTree->set_needs_full_tree_sync(m_needsFullTreeSync);
    m_needsFullTreeSync = false;

    if (m_rootLayer && m_hudLayer)
        syncTree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(LayerTreeHostCommon::findLayerInSubtree(syncTree->RootLayer(), m_hudLayer->id())));
    else
        syncTree->set_hud_layer(0);

    syncTree->set_source_frame_number(commitNumber());
    syncTree->set_background_color(m_backgroundColor);
    syncTree->set_has_transparent_background(m_hasTransparentBackground);

    syncTree->FindRootScrollLayer();

    float page_scale_delta, sent_page_scale_delta;
    if (m_settings.implSidePainting) {
        // Update the delta from the active tree, which may have
        // adjusted its delta prior to the pending tree being created.
        // This code is equivalent to that in LayerTreeImpl::SetPageScaleDelta.
        DCHECK_EQ(1, syncTree->sent_page_scale_delta());
        page_scale_delta = hostImpl->activeTree()->page_scale_delta();
        sent_page_scale_delta = hostImpl->activeTree()->sent_page_scale_delta();
    } else {
        page_scale_delta = syncTree->page_scale_delta();
        sent_page_scale_delta = syncTree->sent_page_scale_delta();
        syncTree->set_sent_page_scale_delta(1);
    }

    syncTree->SetPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor);
    syncTree->SetPageScaleDelta(page_scale_delta / sent_page_scale_delta);

    hostImpl->setViewportSize(layoutViewportSize(), deviceViewportSize());
    hostImpl->setDeviceScaleFactor(deviceScaleFactor());
    hostImpl->setDebugState(m_debugState);

    DCHECK(!syncTree->ViewportSizeInvalid());

    if (newImplTreeHasNoEvictedResources) {
        if (syncTree->ContentsTexturesPurged())
            syncTree->ResetContentsTexturesPurged();
    }

    if (!m_settings.implSidePainting) {
        // If we're not in impl-side painting, the tree is immediately
        // considered active.
        syncTree->DidBecomeActive();
    }

    if (m_debugState.continuousPainting)
        hostImpl->savePaintTime(m_renderingStats.totalPaintTime, commitNumber());

    m_commitNumber++;
}

void LayerTreeHost::willCommit()
{
    m_client->willCommit();
}

void LayerTreeHost::updateHudLayer()
{
    if (m_debugState.showHudInfo()) {
        if (!m_hudLayer)
            m_hudLayer = HeadsUpDisplayLayer::create();

        if (m_rootLayer && !m_hudLayer->parent())
            m_rootLayer->addChild(m_hudLayer);
    } else if (m_hudLayer) {
        m_hudLayer->removeFromParent();
        m_hudLayer = 0;
    }
}

void LayerTreeHost::commitComplete()
{
    m_client->didCommit();
}

scoped_ptr<OutputSurface> LayerTreeHost::createOutputSurface()
{
    return m_client->createOutputSurface();
}

scoped_ptr<InputHandler> LayerTreeHost::createInputHandler()
{
    return m_client->createInputHandler();
}

scoped_ptr<LayerTreeHostImpl> LayerTreeHost::createLayerTreeHostImpl(LayerTreeHostImplClient* client)
{
    DCHECK(m_proxy->isImplThread());
    scoped_ptr<LayerTreeHostImpl> hostImpl(LayerTreeHostImpl::create(m_settings, client, m_proxy.get()));
    if (m_settings.calculateTopControlsPosition && hostImpl->topControlsManager())
        m_topControlsManagerWeakPtr = hostImpl->topControlsManager()->AsWeakPtr();
    return hostImpl.Pass();
}

void LayerTreeHost::didLoseOutputSurface()
{
    TRACE_EVENT0("cc", "LayerTreeHost::didLoseOutputSurface");
    DCHECK(m_proxy->isMainThread());
    m_outputSurfaceLost = true;
    m_numFailedRecreateAttempts = 0;
    setNeedsCommit();
}

bool LayerTreeHost::compositeAndReadback(void *pixels, const gfx::Rect& rect)
{
    m_triggerIdleUpdates = false;
    bool ret = m_proxy->compositeAndReadback(pixels, rect);
    m_triggerIdleUpdates = true;
    return ret;
}

void LayerTreeHost::finishAllRendering()
{
    if (!m_rendererInitialized)
        return;
    m_proxy->finishAllRendering();
}

void LayerTreeHost::setDeferCommits(bool deferCommits)
{
    m_proxy->setDeferCommits(deferCommits);
}

void LayerTreeHost::didDeferCommit()
{
}

void LayerTreeHost::renderingStats(RenderingStats* stats) const
{
    CHECK(m_debugState.recordRenderingStats());
    *stats = m_renderingStats;
    m_proxy->renderingStats(stats);
}

const RendererCapabilities& LayerTreeHost::rendererCapabilities() const
{
    return m_proxy->rendererCapabilities();
}

void LayerTreeHost::setNeedsAnimate()
{
    DCHECK(m_proxy->hasImplThread());
    m_proxy->setNeedsAnimate();
}

void LayerTreeHost::setNeedsCommit()
{
    if (!m_prepaintCallback.IsCancelled()) {
        TRACE_EVENT_INSTANT0("cc", "LayerTreeHost::setNeedsCommit::cancel prepaint");
        m_prepaintCallback.Cancel();
    }
    m_proxy->setNeedsCommit();
}

void LayerTreeHost::setNeedsFullTreeSync()
{
    m_needsFullTreeSync = true;
    setNeedsCommit();
}

void LayerTreeHost::setNeedsRedraw()
{
    m_proxy->setNeedsRedraw();
    if (!m_proxy->implThread())
        m_client->scheduleComposite();
}

bool LayerTreeHost::commitRequested() const
{
    return m_proxy->commitRequested();
}

void LayerTreeHost::setAnimationEvents(scoped_ptr<AnimationEventsVector> events, base::Time wallClockTime)
{
    DCHECK(m_proxy->isMainThread());
    setAnimationEventsRecursive(*events.get(), m_rootLayer.get(), wallClockTime);
}

void LayerTreeHost::setRootLayer(scoped_refptr<Layer> rootLayer)
{
    if (m_rootLayer == rootLayer)
        return;

    if (m_rootLayer)
        m_rootLayer->setLayerTreeHost(0);
    m_rootLayer = rootLayer;
    if (m_rootLayer)
        m_rootLayer->setLayerTreeHost(this);

    if (m_hudLayer)
        m_hudLayer->removeFromParent();

    setNeedsFullTreeSync();
}

void LayerTreeHost::setDebugState(const LayerTreeDebugState& debugState)
{
    LayerTreeDebugState newDebugState = LayerTreeDebugState::unite(m_settings.initialDebugState, debugState);

    if (LayerTreeDebugState::equal(m_debugState, newDebugState))
        return;

    m_debugState = newDebugState;
    setNeedsCommit();
}

void LayerTreeHost::setViewportSize(const gfx::Size& layoutViewportSize, const gfx::Size& deviceViewportSize)
{
    if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
        return;

    m_layoutViewportSize = layoutViewportSize;
    m_deviceViewportSize = deviceViewportSize;

    setNeedsCommit();
}

void LayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
{
    if (pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
        return;

    m_pageScaleFactor = pageScaleFactor;
    m_minPageScaleFactor = minPageScaleFactor;
    m_maxPageScaleFactor = maxPageScaleFactor;
    setNeedsCommit();
}

void LayerTreeHost::setVisible(bool visible)
{
    if (m_visible == visible)
        return;
    m_visible = visible;
    m_proxy->setVisible(visible);
}

void LayerTreeHost::startPageScaleAnimation(gfx::Vector2d targetOffset, bool useAnchor, float scale, base::TimeDelta duration)
{
    m_proxy->startPageScaleAnimation(targetOffset, useAnchor, scale, duration);
}

PrioritizedResourceManager* LayerTreeHost::contentsTextureManager() const
{
    return m_contentsTextureManager.get();
}

void LayerTreeHost::composite()
{
    if (!m_proxy->hasImplThread())
        static_cast<SingleThreadProxy*>(m_proxy.get())->compositeImmediately();
    else
        setNeedsCommit();
}

void LayerTreeHost::scheduleComposite()
{
    m_client->scheduleComposite();
}

bool LayerTreeHost::initializeRendererIfNeeded()
{
    if (!m_rendererInitialized) {
        initializeRenderer();
        // If we couldn't initialize, then bail since we're returning to software mode.
        if (!m_rendererInitialized)
            return false;
    }
    if (m_outputSurfaceLost) {
        if (recreateOutputSurface() != RecreateSucceeded)
            return false;
    }
    return true;
}

void LayerTreeHost::updateLayers(ResourceUpdateQueue& queue, size_t memoryAllocationLimitBytes)
{
    DCHECK(m_rendererInitialized);

    if (!rootLayer())
        return;

    if (layoutViewportSize().IsEmpty())
        return;

    if (memoryAllocationLimitBytes)
        m_contentsTextureManager->setMaxMemoryLimitBytes(memoryAllocationLimitBytes);

    updateLayers(rootLayer(), queue);
}

static Layer* findFirstScrollableLayer(Layer* layer)
{
    if (!layer)
        return 0;

    if (layer->scrollable())
        return layer;

    for (size_t i = 0; i < layer->children().size(); ++i) {
        Layer* found = findFirstScrollableLayer(layer->children()[i].get());
        if (found)
            return found;
    }

    return 0;
}

void LayerTreeHost::updateLayers(Layer* rootLayer, ResourceUpdateQueue& queue)
{
    TRACE_EVENT0("cc", "LayerTreeHost::updateLayers");

    LayerList updateList;

    {
        Layer* rootScroll = findFirstScrollableLayer(rootLayer);
        if (rootScroll)
            rootScroll->setImplTransform(m_implTransform);

        updateHudLayer();

        TRACE_EVENT0("cc", "LayerTreeHost::updateLayers::calcDrawEtc");
        LayerTreeHostCommon::calculateDrawProperties(rootLayer, deviceViewportSize(), m_deviceScaleFactor, m_pageScaleFactor, rendererCapabilities().maxTextureSize, m_settings.canUseLCDText, updateList);
    }

    // Reset partial texture update requests.
    m_partialTextureUpdateRequests = 0;

    bool needMoreUpdates = paintLayerContents(updateList, queue);
    if (m_triggerIdleUpdates && needMoreUpdates) {
        TRACE_EVENT0("cc", "LayerTreeHost::updateLayers::posting prepaint task");
        m_prepaintCallback.Reset(base::Bind(&LayerTreeHost::triggerPrepaint, base::Unretained(this)));
        static base::TimeDelta prepaintDelay = base::TimeDelta::FromMilliseconds(100);
        MessageLoop::current()->PostDelayedTask(FROM_HERE, m_prepaintCallback.callback(), prepaintDelay);
    }

    for (size_t i = 0; i < updateList.size(); ++i)
        updateList[i]->clearRenderSurface();
}

void LayerTreeHost::triggerPrepaint()
{
    m_prepaintCallback.Cancel();
    TRACE_EVENT0("cc", "LayerTreeHost::triggerPrepaint");
    setNeedsCommit();
}

void LayerTreeHost::setPrioritiesForSurfaces(size_t surfaceMemoryBytes)
{
    // Surfaces have a place holder for their memory since they are managed
    // independantly but should still be tracked and reduce other memory usage.
    m_surfaceMemoryPlaceholder->setTextureManager(m_contentsTextureManager.get());
    m_surfaceMemoryPlaceholder->setRequestPriority(PriorityCalculator::renderSurfacePriority());
    m_surfaceMemoryPlaceholder->setToSelfManagedMemoryPlaceholder(surfaceMemoryBytes);
}

void LayerTreeHost::setPrioritiesForLayers(const LayerList& updateList)
{
    // Use BackToFront since it's cheap and this isn't order-dependent.
    typedef LayerIterator<Layer, LayerList, RenderSurface, LayerIteratorActions::BackToFront> LayerIteratorType;

    PriorityCalculator calculator;
    LayerIteratorType end = LayerIteratorType::end(&updateList);
    for (LayerIteratorType it = LayerIteratorType::begin(&updateList); it != end; ++it) {
        if (it.representsItself())
            it->setTexturePriorities(calculator);
        else if (it.representsTargetRenderSurface()) {
            if (it->maskLayer())
                it->maskLayer()->setTexturePriorities(calculator);
            if (it->replicaLayer() && it->replicaLayer()->maskLayer())
                it->replicaLayer()->maskLayer()->setTexturePriorities(calculator);
        }
    }
}

void LayerTreeHost::prioritizeTextures(const LayerList& renderSurfaceLayerList, OverdrawMetrics& metrics)
{
    m_contentsTextureManager->clearPriorities();

    size_t memoryForRenderSurfacesMetric = calculateMemoryForRenderSurfaces(renderSurfaceLayerList);

    setPrioritiesForLayers(renderSurfaceLayerList);
    setPrioritiesForSurfaces(memoryForRenderSurfacesMetric);

    metrics.didUseContentsTextureMemoryBytes(m_contentsTextureManager->memoryAboveCutoffBytes());
    metrics.didUseRenderSurfaceTextureMemoryBytes(memoryForRenderSurfacesMetric);

    m_contentsTextureManager->prioritizeTextures();
}

size_t LayerTreeHost::calculateMemoryForRenderSurfaces(const LayerList& updateList)
{
    size_t readbackBytes = 0;
    size_t maxBackgroundTextureBytes = 0;
    size_t contentsTextureBytes = 0;

    // Start iteration at 1 to skip the root surface as it does not have a texture cost.
    for (size_t i = 1; i < updateList.size(); ++i) {
        Layer* renderSurfaceLayer = updateList[i].get();
        RenderSurface* renderSurface = renderSurfaceLayer->renderSurface();

        size_t bytes = Resource::MemorySizeBytes(renderSurface->contentRect().size(), GL_RGBA);
        contentsTextureBytes += bytes;

        if (renderSurfaceLayer->backgroundFilters().isEmpty())
            continue;

        if (bytes > maxBackgroundTextureBytes)
            maxBackgroundTextureBytes = bytes;
        if (!readbackBytes)
            readbackBytes = Resource::MemorySizeBytes(m_deviceViewportSize, GL_RGBA);
    }
    return readbackBytes + maxBackgroundTextureBytes + contentsTextureBytes;
}

bool LayerTreeHost::paintMasksForRenderSurface(Layer* renderSurfaceLayer, ResourceUpdateQueue& queue)
{
    // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
    // in code, we already know that at least something will be drawn into this render surface, so the
    // mask and replica should be painted.

    RenderingStats* stats = m_debugState.recordRenderingStats() ? &m_renderingStats : NULL;

    bool needMoreUpdates = false;
    Layer* maskLayer = renderSurfaceLayer->maskLayer();
    if (maskLayer) {
        maskLayer->update(queue, 0, stats);
        needMoreUpdates |= maskLayer->needMoreUpdates();
    }

    Layer* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? renderSurfaceLayer->replicaLayer()->maskLayer() : 0;
    if (replicaMaskLayer) {
        replicaMaskLayer->update(queue, 0, stats);
        needMoreUpdates |= replicaMaskLayer->needMoreUpdates();
    }
    return needMoreUpdates;
}

bool LayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, ResourceUpdateQueue& queue)
{
    // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
    typedef LayerIterator<Layer, LayerList, RenderSurface, LayerIteratorActions::FrontToBack> LayerIteratorType;

    bool needMoreUpdates = false;
    bool recordMetricsForFrame = m_settings.showOverdrawInTracing && base::debug::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled();
    OcclusionTracker occlusionTracker(m_rootLayer->renderSurface()->contentRect(), recordMetricsForFrame);
    occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);

    prioritizeTextures(renderSurfaceLayerList, occlusionTracker.overdrawMetrics());

    RenderingStats* stats = m_debugState.recordRenderingStats() ? &m_renderingStats : NULL;

    LayerIteratorType end = LayerIteratorType::end(&renderSurfaceLayerList);
    for (LayerIteratorType it = LayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
        occlusionTracker.enterLayer(it);

        if (it.representsTargetRenderSurface()) {
            DCHECK(it->renderSurface()->drawOpacity() || it->renderSurface()->drawOpacityIsAnimating());
            needMoreUpdates |= paintMasksForRenderSurface(*it, queue);
        } else if (it.representsItself()) {
            DCHECK(!it->bounds().IsEmpty());
            it->update(queue, &occlusionTracker, stats);
            needMoreUpdates |= it->needMoreUpdates();
        }

        occlusionTracker.leaveLayer(it);
    }

    occlusionTracker.overdrawMetrics().recordMetrics(this);

    return needMoreUpdates;
}

void LayerTreeHost::applyScrollAndScale(const ScrollAndScaleSet& info)
{
    if (!m_rootLayer)
        return;

    Layer* rootScrollLayer = findFirstScrollableLayer(m_rootLayer.get());
    gfx::Vector2d rootScrollDelta;

    for (size_t i = 0; i < info.scrolls.size(); ++i) {
        Layer* layer = LayerTreeHostCommon::findLayerInSubtree(m_rootLayer.get(), info.scrolls[i].layerId);
        if (!layer)
            continue;
        if (layer == rootScrollLayer)
            rootScrollDelta += info.scrolls[i].scrollDelta;
        else
            layer->setScrollOffset(layer->scrollOffset() + info.scrolls[i].scrollDelta);
    }
    if (!rootScrollDelta.IsZero() || info.pageScaleDelta != 1)
        m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta);
}

void LayerTreeHost::setImplTransform(const gfx::Transform& transform)
{
    m_implTransform = transform;
}

void LayerTreeHost::startRateLimiter(WebKit::WebGraphicsContext3D* context)
{
    if (m_animating)
        return;

    DCHECK(context);
    RateLimiterMap::iterator it = m_rateLimiters.find(context);
    if (it != m_rateLimiters.end())
        it->second->start();
    else {
        scoped_refptr<RateLimiter> rateLimiter = RateLimiter::create(context, this, m_proxy->mainThread());
        m_rateLimiters[context] = rateLimiter;
        rateLimiter->start();
    }
}

void LayerTreeHost::stopRateLimiter(WebKit::WebGraphicsContext3D* context)
{
    RateLimiterMap::iterator it = m_rateLimiters.find(context);
    if (it != m_rateLimiters.end()) {
        it->second->stop();
        m_rateLimiters.erase(it);
    }
}

void LayerTreeHost::rateLimit()
{
    // Force a no-op command on the compositor context, so that any ratelimiting commands will wait for the compositing
    // context, and therefore for the SwapBuffers.
    m_proxy->forceSerializeOnSwapBuffers();
}

bool LayerTreeHost::bufferedUpdates()
{
    return m_settings.maxPartialTextureUpdates != std::numeric_limits<size_t>::max();
}

bool LayerTreeHost::requestPartialTextureUpdate()
{
    if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates)
        return false;

    m_partialTextureUpdateRequests++;
    return true;
}

void LayerTreeHost::setDeviceScaleFactor(float deviceScaleFactor)
{
    if (deviceScaleFactor ==  m_deviceScaleFactor)
        return;
    m_deviceScaleFactor = deviceScaleFactor;

    setNeedsCommit();
}

void LayerTreeHost::enableHidingTopControls(bool enable)
{
    if (!m_settings.calculateTopControlsPosition)
        return;

    m_proxy->implThread()->postTask(
        base::Bind(&TopControlsManager::enable_hiding_top_controls,
                   m_topControlsManagerWeakPtr, enable));
}

bool LayerTreeHost::blocksPendingCommit() const
{
    if (!m_rootLayer)
        return false;
    return m_rootLayer->blocksPendingCommitRecursive();
}

scoped_ptr<base::Value> LayerTreeHost::asValue() const
{
    scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
    state->Set("proxy", m_proxy->asValue().release());
    return state.PassAs<base::Value>();
}

void LayerTreeHost::animateLayers(base::TimeTicks time)
{
    if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_animation_controllers().empty())
        return;

    TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");

    double monotonicTime = (time - base::TimeTicks()).InSecondsF();

    AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->active_animation_controllers();
    for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); iter != copy.end(); ++iter) {
        (*iter).second->animate(monotonicTime);
        (*iter).second->updateState(0);
    }
}

void LayerTreeHost::setAnimationEventsRecursive(const AnimationEventsVector& events, Layer* layer, base::Time wallClockTime)
{
    if (!layer)
        return;

    for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
        if (layer->id() == events[eventIndex].layerId) {
            if (events[eventIndex].type == AnimationEvent::Started)
                layer->notifyAnimationStarted(events[eventIndex], wallClockTime.ToDoubleT());
            else
                layer->notifyAnimationFinished(wallClockTime.ToDoubleT());
        }
    }

    for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex)
        setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime);
}

skia::RefPtr<SkPicture> LayerTreeHost::capturePicture()
{
    return m_proxy->capturePicture();
}

}  // namespace cc
