blob: 3b039276a87531786d6d57e284c9f627bf294ea3 [file] [log] [blame]
/*
* 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