654816f4b084309e9245b46bc5f4eef6b9e24e7c
[WebKit.git] / Source / WebKit / Shared / RemoteLayerTree / RemoteLayerBackingStoreCollection.mm
1  /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "RemoteLayerBackingStoreCollection.h"
28
29 #import "PlatformCALayerRemote.h"
30 #import "RemoteLayerBackingStore.h"
31 #import "RemoteLayerTreeContext.h"
32
33 using namespace std::literals::chrono_literals;
34
35 const std::chrono::seconds volatileBackingStoreAgeThreshold = 1s;
36 const std::chrono::milliseconds volatileSecondaryBackingStoreAgeThreshold = 200ms;
37 const Seconds volatilityTimerInterval = 200_ms;
38
39 namespace WebKit {
40
41 RemoteLayerBackingStoreCollection::RemoteLayerBackingStoreCollection()
42     : m_volatilityTimer(*this, &RemoteLayerBackingStoreCollection::volatilityTimerFired)
43 {
44 }
45
46 void RemoteLayerBackingStoreCollection::willFlushLayers()
47 {
48     m_inLayerFlush = true;
49     m_reachableBackingStoreInLatestFlush.clear();
50 }
51
52 void RemoteLayerBackingStoreCollection::willCommitLayerTree(RemoteLayerTreeTransaction& transaction)
53 {
54     ASSERT(m_inLayerFlush);
55     Vector<WebCore::GraphicsLayer::PlatformLayerID> newlyUnreachableLayerIDs;
56     for (auto& backingStore : m_liveBackingStore) {
57         if (!m_reachableBackingStoreInLatestFlush.contains(backingStore))
58             newlyUnreachableLayerIDs.append(backingStore->layer()->layerID());
59     }
60
61     transaction.setLayerIDsWithNewlyUnreachableBackingStore(newlyUnreachableLayerIDs);
62 }
63
64 void RemoteLayerBackingStoreCollection::didFlushLayers()
65 {
66     m_inLayerFlush = false;
67
68     Vector<RemoteLayerBackingStore*> newlyUnreachableBackingStore;
69     for (auto& backingStore : m_liveBackingStore) {
70         if (!m_reachableBackingStoreInLatestFlush.contains(backingStore))
71             newlyUnreachableBackingStore.append(backingStore);
72     }
73
74     for (auto& backingStore : newlyUnreachableBackingStore)
75         backingStoreBecameUnreachable(*backingStore);
76
77     if (!newlyUnreachableBackingStore.isEmpty())
78         scheduleVolatilityTimer();
79 }
80
81 void RemoteLayerBackingStoreCollection::backingStoreWasCreated(RemoteLayerBackingStore& backingStore)
82 {
83     m_liveBackingStore.add(&backingStore);
84 }
85
86 void RemoteLayerBackingStoreCollection::backingStoreWillBeDestroyed(RemoteLayerBackingStore& backingStore)
87 {
88     m_liveBackingStore.remove(&backingStore);
89     m_unparentedBackingStore.remove(&backingStore);
90 }
91
92 bool RemoteLayerBackingStoreCollection::backingStoreWillBeDisplayed(RemoteLayerBackingStore& backingStore)
93 {
94     ASSERT(m_inLayerFlush);
95     m_reachableBackingStoreInLatestFlush.add(&backingStore);
96
97     auto backingStoreIter = m_unparentedBackingStore.find(&backingStore);
98     if (backingStoreIter == m_unparentedBackingStore.end())
99         return false;
100
101     m_liveBackingStore.add(&backingStore);
102     m_unparentedBackingStore.remove(backingStoreIter);
103     return true;
104 }
105
106 bool RemoteLayerBackingStoreCollection::markBackingStoreVolatileImmediately(RemoteLayerBackingStore& backingStore, VolatilityMarkingFlags volatilityMarkingFlags)
107 {
108     ASSERT(!m_inLayerFlush);
109     bool successfullyMadeBackingStoreVolatile = true;
110
111     if (!backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::SecondaryBack, true))
112         successfullyMadeBackingStoreVolatile = false;
113
114     if (!backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::Back, true))
115         successfullyMadeBackingStoreVolatile = false;
116
117     if (!m_reachableBackingStoreInLatestFlush.contains(&backingStore) || (volatilityMarkingFlags & MarkBuffersIgnoringReachability)) {
118         if (!backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::Front, true))
119             successfullyMadeBackingStoreVolatile = false;
120     }
121
122     return successfullyMadeBackingStoreVolatile;
123 }
124
125 bool RemoteLayerBackingStoreCollection::markBackingStoreVolatile(RemoteLayerBackingStore& backingStore, std::chrono::steady_clock::time_point now)
126 {
127     if (now - backingStore.lastDisplayTime() < volatileBackingStoreAgeThreshold) {
128         if (now - backingStore.lastDisplayTime() >= volatileSecondaryBackingStoreAgeThreshold)
129             backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::SecondaryBack, true);
130
131         return false;
132     }
133     
134     return markBackingStoreVolatileImmediately(backingStore);
135 }
136
137 void RemoteLayerBackingStoreCollection::backingStoreBecameUnreachable(RemoteLayerBackingStore& backingStore)
138 {
139     ASSERT(backingStore.layer());
140
141     auto backingStoreIter = m_liveBackingStore.find(&backingStore);
142     if (backingStoreIter == m_liveBackingStore.end())
143         return;
144     m_unparentedBackingStore.add(&backingStore);
145     m_liveBackingStore.remove(backingStoreIter);
146
147     // This will not succeed in marking all buffers as volatile, because the commit unparenting the layer hasn't
148     // made it to the UI process yet. The volatility timer will finish marking the remaining buffers later.
149     markBackingStoreVolatileImmediately(backingStore);
150 }
151
152 bool RemoteLayerBackingStoreCollection::markAllBackingStoreVolatileImmediatelyIfPossible()
153 {
154     bool successfullyMadeBackingStoreVolatile = true;
155
156     for (const auto& backingStore : m_liveBackingStore)
157         successfullyMadeBackingStoreVolatile &= markBackingStoreVolatileImmediately(*backingStore, MarkBuffersIgnoringReachability);
158
159     for (const auto& backingStore : m_unparentedBackingStore)
160         successfullyMadeBackingStoreVolatile &= markBackingStoreVolatileImmediately(*backingStore, MarkBuffersIgnoringReachability);
161
162     return successfullyMadeBackingStoreVolatile;
163 }
164
165 void RemoteLayerBackingStoreCollection::volatilityTimerFired()
166 {
167     bool successfullyMadeBackingStoreVolatile = true;
168
169     auto now = std::chrono::steady_clock::now();
170     for (const auto& backingStore : m_liveBackingStore)
171         successfullyMadeBackingStoreVolatile &= markBackingStoreVolatile(*backingStore, now);
172
173     for (const auto& backingStore : m_unparentedBackingStore)
174         successfullyMadeBackingStoreVolatile &= markBackingStoreVolatileImmediately(*backingStore);
175
176     if (successfullyMadeBackingStoreVolatile)
177         m_volatilityTimer.stop();
178 }
179
180 void RemoteLayerBackingStoreCollection::scheduleVolatilityTimer()
181 {
182     if (m_volatilityTimer.isActive())
183         return;
184
185     m_volatilityTimer.startRepeating(volatilityTimerInterval);
186 }
187
188 } // namespace WebKit