RemoteLayerTreeNode construction cleanups
[WebKit-https.git] / Source / WebKit / UIProcess / RemoteLayerTree / RemoteLayerTreeHost.mm
1 /*
2  * Copyright (C) 2012-2017 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "RemoteLayerTreeHost.h"
28
29 #import "Logging.h"
30 #import "RemoteLayerTreeDrawingAreaProxy.h"
31 #import "RemoteLayerTreePropertyApplier.h"
32 #import "RemoteLayerTreeTransaction.h"
33 #import "ShareableBitmap.h"
34 #import "WKAnimationDelegate.h"
35 #import "WebPageProxy.h"
36 #import "WebProcessProxy.h"
37 #import <QuartzCore/QuartzCore.h>
38 #import <WebCore/GraphicsContextCG.h>
39 #import <WebCore/IOSurface.h>
40 #import <WebCore/PlatformLayer.h>
41 #import <WebCore/WebCoreCALayerExtras.h>
42 #import <pal/spi/cocoa/QuartzCoreSPI.h>
43
44 #if PLATFORM(IOS_FAMILY)
45 #import <UIKit/UIView.h>
46 #endif
47
48 namespace WebKit {
49 using namespace WebCore;
50
51 #define RELEASE_LOG_IF_ALLOWED(...) RELEASE_LOG_IF(m_drawingArea && m_drawingArea->isAlwaysOnLoggingAllowed(), ViewState, __VA_ARGS__)
52
53 RemoteLayerTreeHost::RemoteLayerTreeHost(RemoteLayerTreeDrawingAreaProxy& drawingArea)
54     : m_drawingArea(&drawingArea)
55 {
56 }
57
58 RemoteLayerTreeHost::~RemoteLayerTreeHost()
59 {
60     for (auto& delegate : m_animationDelegates.values())
61         [delegate.get() invalidate];
62
63     clearLayers();
64 }
65
66 bool RemoteLayerTreeHost::updateLayerTree(const RemoteLayerTreeTransaction& transaction, float indicatorScaleFactor)
67 {
68     if (!m_drawingArea)
69         return false;
70
71     for (const auto& createdLayer : transaction.createdLayers())
72         createLayer(createdLayer);
73
74     bool rootLayerChanged = false;
75     auto* rootNode = nodeForID(transaction.rootLayerID());
76     
77     if (!rootNode)
78         RELEASE_LOG_IF_ALLOWED("%p RemoteLayerTreeHost::updateLayerTree - failed to find root layer with ID %llu", this, transaction.rootLayerID());
79
80     if (m_rootNode != rootNode) {
81         m_rootNode = rootNode;
82         rootLayerChanged = true;
83     }
84
85     typedef std::pair<GraphicsLayer::PlatformLayerID, GraphicsLayer::PlatformLayerID> LayerIDPair;
86     Vector<LayerIDPair> clonesToUpdate;
87
88 #if PLATFORM(MAC) || PLATFORM(IOSMAC)
89     // Can't use the iOS code on macOS yet: rdar://problem/31247730
90     auto layerContentsType = RemoteLayerBackingStore::LayerContentsType::IOSurface;
91 #else
92     auto layerContentsType = m_drawingArea->hasDebugIndicator() ? RemoteLayerBackingStore::LayerContentsType::IOSurface : RemoteLayerBackingStore::LayerContentsType::CAMachPort;
93 #endif
94     
95     for (auto& changedLayer : transaction.changedLayerProperties()) {
96         auto layerID = changedLayer.key;
97         const RemoteLayerTreeTransaction::LayerProperties& properties = *changedLayer.value;
98
99         auto* node = nodeForID(layerID);
100         ASSERT(node);
101
102         RemoteLayerTreePropertyApplier::RelatedLayerMap relatedLayers;
103         if (properties.changedProperties & RemoteLayerTreeTransaction::ChildrenChanged) {
104             for (auto& child : properties.children)
105                 relatedLayers.set(child, nodeForID(child));
106         }
107
108         if (properties.changedProperties & RemoteLayerTreeTransaction::MaskLayerChanged && properties.maskLayerID)
109             relatedLayers.set(properties.maskLayerID, nodeForID(properties.maskLayerID));
110
111         if (properties.changedProperties & RemoteLayerTreeTransaction::ClonedContentsChanged && properties.clonedLayerID)
112             clonesToUpdate.append(LayerIDPair(layerID, properties.clonedLayerID));
113
114         if (m_isDebugLayerTreeHost) {
115             RemoteLayerTreePropertyApplier::applyProperties(*node, this, properties, relatedLayers, layerContentsType);
116
117             if (properties.changedProperties & RemoteLayerTreeTransaction::BorderWidthChanged)
118                 node->layer().borderWidth = properties.borderWidth / indicatorScaleFactor;
119             node->layer().masksToBounds = false;
120         } else
121             RemoteLayerTreePropertyApplier::applyProperties(*node, this, properties, relatedLayers, layerContentsType);
122     }
123     
124     for (const auto& layerPair : clonesToUpdate) {
125         auto* layer = layerForID(layerPair.first);
126         auto* clonedLayer = layerForID(layerPair.second);
127         layer.contents = clonedLayer.contents;
128     }
129
130     for (auto& destroyedLayer : transaction.destroyedLayers())
131         layerWillBeRemoved(destroyedLayer);
132
133     // Drop the contents of any layers which were unparented; the Web process will re-send
134     // the backing store in the commit that reparents them.
135     for (auto& newlyUnreachableLayerID : transaction.layerIDsWithNewlyUnreachableBackingStore())
136         layerForID(newlyUnreachableLayerID).contents = nullptr;
137
138     return rootLayerChanged;
139 }
140
141 RemoteLayerTreeNode* RemoteLayerTreeHost::nodeForID(GraphicsLayer::PlatformLayerID layerID) const
142 {
143     if (!layerID)
144         return nullptr;
145
146     return m_nodes.get(layerID);
147 }
148
149 void RemoteLayerTreeHost::layerWillBeRemoved(WebCore::GraphicsLayer::PlatformLayerID layerID)
150 {
151     auto animationDelegateIter = m_animationDelegates.find(layerID);
152     if (animationDelegateIter != m_animationDelegates.end()) {
153         [animationDelegateIter->value invalidate];
154         m_animationDelegates.remove(animationDelegateIter);
155     }
156
157     auto embeddedViewIter = m_layerToEmbeddedViewMap.find(layerID);
158     if (embeddedViewIter != m_layerToEmbeddedViewMap.end()) {
159         m_embeddedViews.remove(embeddedViewIter->value);
160         m_layerToEmbeddedViewMap.remove(embeddedViewIter);
161     }
162
163     m_nodes.remove(layerID);
164 }
165
166 void RemoteLayerTreeHost::animationDidStart(WebCore::GraphicsLayer::PlatformLayerID layerID, CAAnimation *animation, MonotonicTime startTime)
167 {
168     if (!m_drawingArea)
169         return;
170
171     CALayer *layer = layerForID(layerID);
172     if (!layer)
173         return;
174
175     String animationKey;
176     for (NSString *key in [layer animationKeys]) {
177         if ([layer animationForKey:key] == animation) {
178             animationKey = key;
179             break;
180         }
181     }
182
183     if (!animationKey.isEmpty())
184         m_drawingArea->acceleratedAnimationDidStart(layerID, animationKey, startTime);
185 }
186
187 void RemoteLayerTreeHost::animationDidEnd(WebCore::GraphicsLayer::PlatformLayerID layerID, CAAnimation *animation)
188 {
189     if (!m_drawingArea)
190         return;
191
192     CALayer *layer = layerForID(layerID);
193     if (!layer)
194         return;
195
196     String animationKey;
197     for (NSString *key in [layer animationKeys]) {
198         if ([layer animationForKey:key] == animation) {
199             animationKey = key;
200             break;
201         }
202     }
203
204     if (!animationKey.isEmpty())
205         m_drawingArea->acceleratedAnimationDidEnd(layerID, animationKey);
206 }
207
208 void RemoteLayerTreeHost::detachFromDrawingArea()
209 {
210     m_drawingArea = nullptr;
211 }
212
213 void RemoteLayerTreeHost::clearLayers()
214 {
215     for (auto& keyAndNode : m_nodes) {
216         m_animationDelegates.remove(keyAndNode.key);
217         keyAndNode.value->detachFromParent();
218     }
219
220     m_nodes.clear();
221     m_embeddedViews.clear();
222     m_layerToEmbeddedViewMap.clear();
223     m_rootNode = nullptr;
224 }
225
226 CALayer *RemoteLayerTreeHost::layerWithIDForTesting(uint64_t layerID) const
227 {
228     return layerForID(layerID);
229 }
230
231 CALayer *RemoteLayerTreeHost::layerForID(WebCore::GraphicsLayer::PlatformLayerID layerID) const
232 {
233     auto* node = nodeForID(layerID);
234     if (!node)
235         return nil;
236     return node->layer();
237 }
238
239 CALayer *RemoteLayerTreeHost::rootLayer() const
240 {
241     if (!m_rootNode)
242         return nil;
243     return m_rootNode->layer();
244 }
245
246 void RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::LayerCreationProperties& properties)
247 {
248     ASSERT(!m_nodes.contains(properties.layerID));
249
250     auto node = makeNode(properties);
251
252     m_nodes.add(properties.layerID, WTFMove(node));
253 }
254
255 #if !PLATFORM(IOS_FAMILY)
256 std::unique_ptr<RemoteLayerTreeNode> RemoteLayerTreeHost::makeNode(const RemoteLayerTreeTransaction::LayerCreationProperties& properties)
257 {
258     auto makeWithLayer = [&] (RetainPtr<CALayer> layer) {
259         return std::make_unique<RemoteLayerTreeNode>(properties.layerID, WTFMove(layer));
260     };
261     auto makeAdoptingLayer = [&] (CALayer* layer) {
262         return makeWithLayer(adoptNS(layer));
263     };
264
265     switch (properties.type) {
266     case PlatformCALayer::LayerTypeLayer:
267     case PlatformCALayer::LayerTypeWebLayer:
268     case PlatformCALayer::LayerTypeRootLayer:
269     case PlatformCALayer::LayerTypeSimpleLayer:
270     case PlatformCALayer::LayerTypeTiledBackingLayer:
271     case PlatformCALayer::LayerTypePageTiledBackingLayer:
272     case PlatformCALayer::LayerTypeTiledBackingTileLayer:
273     case PlatformCALayer::LayerTypeScrollingLayer:
274     case PlatformCALayer::LayerTypeEditableImageLayer:
275         return makeAdoptingLayer([[CALayer alloc] init]);
276
277     case PlatformCALayer::LayerTypeTransformLayer:
278         return makeAdoptingLayer([[CATransformLayer alloc] init]);
279
280     case PlatformCALayer::LayerTypeBackdropLayer:
281     case PlatformCALayer::LayerTypeLightSystemBackdropLayer:
282     case PlatformCALayer::LayerTypeDarkSystemBackdropLayer:
283 #if ENABLE(FILTERS_LEVEL_2)
284         return makeAdoptingLayer([[CABackdropLayer alloc] init]);
285 #else
286         ASSERT_NOT_REACHED();
287         return makeAdoptingLayer([[CALayer alloc] init]);
288 #endif
289     case PlatformCALayer::LayerTypeCustom:
290     case PlatformCALayer::LayerTypeAVPlayerLayer:
291     case PlatformCALayer::LayerTypeContentsProvidedLayer:
292         if (m_isDebugLayerTreeHost)
293             return makeAdoptingLayer([[CALayer alloc] init]);
294         return makeWithLayer([CALayer _web_renderLayerWithContextID:properties.hostingContextID]);
295
296     case PlatformCALayer::LayerTypeShapeLayer:
297         return makeAdoptingLayer([[CAShapeLayer alloc] init]);
298             
299     default:
300         ASSERT_NOT_REACHED();
301         return nullptr;
302     }
303 }
304 #endif
305
306 void RemoteLayerTreeHost::detachRootLayer()
307 {
308     if (!m_rootNode)
309         return;
310     m_rootNode->detachFromParent();
311     m_rootNode = nullptr;
312 }
313
314 #if HAVE(IOSURFACE)
315 static void recursivelyMapIOSurfaceBackingStore(CALayer *layer)
316 {
317     if (layer.contents && CFGetTypeID((__bridge CFTypeRef)layer.contents) == CAMachPortGetTypeID()) {
318         MachSendRight port = MachSendRight::create(CAMachPortGetPort((__bridge CAMachPortRef)layer.contents));
319         auto surface = WebCore::IOSurface::createFromSendRight(WTFMove(port), sRGBColorSpaceRef());
320         layer.contents = surface ? surface->asLayerContents() : nil;
321     }
322
323     for (CALayer *sublayer in layer.sublayers)
324         recursivelyMapIOSurfaceBackingStore(sublayer);
325 }
326 #endif
327
328 void RemoteLayerTreeHost::mapAllIOSurfaceBackingStore()
329 {
330 #if HAVE(IOSURFACE)
331     recursivelyMapIOSurfaceBackingStore(rootLayer());
332 #endif
333 }
334
335 } // namespace WebKit
336
337 #undef RELEASE_LOG_IF_ALLOWED