/*
Copyright (C) 2012 Google 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"

#include "core/platform/graphics/Canvas2DLayerManager.h"

#include "public/platform/Platform.h"
#include "wtf/StdLibExtras.h"

using blink::WebThread;

namespace {
enum {
    DefaultMaxBytesAllocated = 64*1024*1024,
    DefaultTargetBytesAllocated = 16*1024*1024,
};
}

namespace WebCore {

Canvas2DLayerManager::Canvas2DLayerManager()
    : m_bytesAllocated(0)
    , m_maxBytesAllocated(DefaultMaxBytesAllocated)
    , m_targetBytesAllocated(DefaultTargetBytesAllocated)
    , m_taskObserverActive(false)
{
}

Canvas2DLayerManager::~Canvas2DLayerManager()
{
    ASSERT(!m_bytesAllocated);
    ASSERT(!m_layerList.head());
    ASSERT(!m_taskObserverActive);
}

void Canvas2DLayerManager::init(size_t maxBytesAllocated, size_t targetBytesAllocated)
{
    ASSERT(maxBytesAllocated >= targetBytesAllocated);
    m_maxBytesAllocated = maxBytesAllocated;
    m_targetBytesAllocated = targetBytesAllocated;
    if (m_taskObserverActive) {
        blink::Platform::current()->currentThread()->removeTaskObserver(this);
        m_taskObserverActive = false;
    }
}

Canvas2DLayerManager& Canvas2DLayerManager::get()
{
    DEFINE_STATIC_LOCAL(Canvas2DLayerManager, manager, ());
    return manager;
}

void Canvas2DLayerManager::willProcessTask()
{
}

void Canvas2DLayerManager::didProcessTask()
{
    // Called after the script action for the current frame has been processed.
    ASSERT(m_taskObserverActive);
    blink::Platform::current()->currentThread()->removeTaskObserver(this);
    m_taskObserverActive = false;
    for (Canvas2DLayerBridge* layer = m_layerList.head(); layer; layer = layer->next())
        layer->limitPendingFrames();
}

void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer)
{
    if (isInList(layer)) {
        if (layer != m_layerList.head()) {
            m_layerList.remove(layer);
            m_layerList.push(layer); // Set as MRU
        }
    } else
        addLayerToList(layer);

    if (!m_taskObserverActive) {
        m_taskObserverActive = true;
        // Schedule a call to didProcessTask() after completion of the current script task.
        blink::Platform::current()->currentThread()->addTaskObserver(this);
    }
}

void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer)
{
    ASSERT(!isInList(layer));
    m_bytesAllocated += layer->bytesAllocated();
    m_layerList.push(layer); // Set as MRU
}

void Canvas2DLayerManager::layerAllocatedStorageChanged(Canvas2DLayerBridge* layer, intptr_t deltaBytes)
{
    if (!isInList(layer))
        addLayerToList(layer);
    else {
        ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0);
        m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes;
    }
    if (deltaBytes > 0)
        freeMemoryIfNecessary();
}

void Canvas2DLayerManager::layerToBeDestroyed(Canvas2DLayerBridge* layer)
{
    if (isInList(layer))
        removeLayerFromList(layer);
}

void Canvas2DLayerManager::freeMemoryIfNecessary()
{
    if (m_bytesAllocated > m_maxBytesAllocated) {
        // Pass 1: Free memory from caches
        Canvas2DLayerBridge* layer = m_layerList.tail(); // LRU
        while (m_bytesAllocated > m_targetBytesAllocated && layer) {
            layer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated);
            layer = layer->prev();
        }

        // Pass 2: Flush canvases
        Canvas2DLayerBridge* leastRecentlyUsedLayer = m_layerList.tail();
        while (m_bytesAllocated > m_targetBytesAllocated && leastRecentlyUsedLayer) {
            leastRecentlyUsedLayer->flush();
            leastRecentlyUsedLayer->freeMemoryIfPossible(~0);
            removeLayerFromList(leastRecentlyUsedLayer);
            leastRecentlyUsedLayer = m_layerList.tail();
        }
    }
}

void Canvas2DLayerManager::removeLayerFromList(Canvas2DLayerBridge* layer)
{
    ASSERT(isInList(layer));
    m_bytesAllocated -= layer->bytesAllocated();
    m_layerList.remove(layer);
    layer->setNext(0);
    layer->setPrev(0);
}

bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer)
{
    return layer->prev() || m_layerList.head() == layer;
}

}

