 /*
 * Copyright (C) 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. ``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
 * 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.
 */

#import "config.h"
#import "RemoteLayerBackingStoreCollection.h"

#import "PlatformCALayerRemote.h"
#import "RemoteLayerBackingStore.h"
#import "RemoteLayerTreeContext.h"

const Seconds volatileBackingStoreAgeThreshold = 1_s;
const Seconds volatileSecondaryBackingStoreAgeThreshold = 200_ms;
const Seconds volatilityTimerInterval = 200_ms;

namespace WebKit {

RemoteLayerBackingStoreCollection::RemoteLayerBackingStoreCollection()
    : m_volatilityTimer(*this, &RemoteLayerBackingStoreCollection::volatilityTimerFired)
{
}

void RemoteLayerBackingStoreCollection::willFlushLayers()
{
    m_inLayerFlush = true;
    m_reachableBackingStoreInLatestFlush.clear();
}

void RemoteLayerBackingStoreCollection::willCommitLayerTree(RemoteLayerTreeTransaction& transaction)
{
    ASSERT(m_inLayerFlush);
    Vector<WebCore::GraphicsLayer::PlatformLayerID> newlyUnreachableLayerIDs;
    for (auto& backingStore : m_liveBackingStore) {
        if (!m_reachableBackingStoreInLatestFlush.contains(backingStore))
            newlyUnreachableLayerIDs.append(backingStore->layer()->layerID());
    }

    transaction.setLayerIDsWithNewlyUnreachableBackingStore(newlyUnreachableLayerIDs);
}

void RemoteLayerBackingStoreCollection::didFlushLayers()
{
    m_inLayerFlush = false;

    Vector<RemoteLayerBackingStore*> newlyUnreachableBackingStore;
    for (auto& backingStore : m_liveBackingStore) {
        if (!m_reachableBackingStoreInLatestFlush.contains(backingStore))
            newlyUnreachableBackingStore.append(backingStore);
    }

    for (auto& backingStore : newlyUnreachableBackingStore)
        backingStoreBecameUnreachable(*backingStore);

    if (!newlyUnreachableBackingStore.isEmpty())
        scheduleVolatilityTimer();
}

void RemoteLayerBackingStoreCollection::backingStoreWasCreated(RemoteLayerBackingStore& backingStore)
{
    m_liveBackingStore.add(&backingStore);
}

void RemoteLayerBackingStoreCollection::backingStoreWillBeDestroyed(RemoteLayerBackingStore& backingStore)
{
    m_liveBackingStore.remove(&backingStore);
    m_unparentedBackingStore.remove(&backingStore);
}

bool RemoteLayerBackingStoreCollection::backingStoreWillBeDisplayed(RemoteLayerBackingStore& backingStore)
{
    ASSERT(m_inLayerFlush);
    m_reachableBackingStoreInLatestFlush.add(&backingStore);

    auto backingStoreIter = m_unparentedBackingStore.find(&backingStore);
    if (backingStoreIter == m_unparentedBackingStore.end())
        return false;

    m_liveBackingStore.add(&backingStore);
    m_unparentedBackingStore.remove(backingStoreIter);
    return true;
}

bool RemoteLayerBackingStoreCollection::markBackingStoreVolatileImmediately(RemoteLayerBackingStore& backingStore, VolatilityMarkingFlags volatilityMarkingFlags)
{
    ASSERT(!m_inLayerFlush);
    bool successfullyMadeBackingStoreVolatile = true;

    if (!backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::SecondaryBack, true))
        successfullyMadeBackingStoreVolatile = false;

    if (!backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::Back, true))
        successfullyMadeBackingStoreVolatile = false;

    if (!m_reachableBackingStoreInLatestFlush.contains(&backingStore) || (volatilityMarkingFlags & MarkBuffersIgnoringReachability)) {
        if (!backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::Front, true))
            successfullyMadeBackingStoreVolatile = false;
    }

    return successfullyMadeBackingStoreVolatile;
}

bool RemoteLayerBackingStoreCollection::markBackingStoreVolatile(RemoteLayerBackingStore& backingStore, MonotonicTime now)
{
    if (now - backingStore.lastDisplayTime() < volatileBackingStoreAgeThreshold) {
        if (now - backingStore.lastDisplayTime() >= volatileSecondaryBackingStoreAgeThreshold)
            backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::SecondaryBack, true);

        return false;
    }
    
    return markBackingStoreVolatileImmediately(backingStore);
}

void RemoteLayerBackingStoreCollection::backingStoreBecameUnreachable(RemoteLayerBackingStore& backingStore)
{
    ASSERT(backingStore.layer());

    auto backingStoreIter = m_liveBackingStore.find(&backingStore);
    if (backingStoreIter == m_liveBackingStore.end())
        return;
    m_unparentedBackingStore.add(&backingStore);
    m_liveBackingStore.remove(backingStoreIter);

    // This will not succeed in marking all buffers as volatile, because the commit unparenting the layer hasn't
    // made it to the UI process yet. The volatility timer will finish marking the remaining buffers later.
    markBackingStoreVolatileImmediately(backingStore);
}

bool RemoteLayerBackingStoreCollection::markAllBackingStoreVolatileImmediatelyIfPossible()
{
    bool successfullyMadeBackingStoreVolatile = true;

    for (const auto& backingStore : m_liveBackingStore)
        successfullyMadeBackingStoreVolatile &= markBackingStoreVolatileImmediately(*backingStore, MarkBuffersIgnoringReachability);

    for (const auto& backingStore : m_unparentedBackingStore)
        successfullyMadeBackingStoreVolatile &= markBackingStoreVolatileImmediately(*backingStore, MarkBuffersIgnoringReachability);

    return successfullyMadeBackingStoreVolatile;
}

void RemoteLayerBackingStoreCollection::volatilityTimerFired()
{
    bool successfullyMadeBackingStoreVolatile = true;

    auto now = MonotonicTime::now();
    for (const auto& backingStore : m_liveBackingStore)
        successfullyMadeBackingStoreVolatile &= markBackingStoreVolatile(*backingStore, now);

    for (const auto& backingStore : m_unparentedBackingStore)
        successfullyMadeBackingStoreVolatile &= markBackingStoreVolatileImmediately(*backingStore);

    if (successfullyMadeBackingStoreVolatile)
        m_volatilityTimer.stop();
}

void RemoteLayerBackingStoreCollection::scheduleVolatilityTimer()
{
    if (m_volatilityTimer.isActive())
        return;

    m_volatilityTimer.startRepeating(volatilityTimerInterval);
}

} // namespace WebKit
