AVPlayerLayer isn't available on every system
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebPage / mac / PlatformCALayerRemoteCustom.mm
1 /*
2  * Copyright (C) 2013 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 #include "config.h"
27 #import "PlatformCALayerRemoteCustom.h"
28
29 #import "LayerHostingContext.h"
30 #import "RemoteLayerTreeContext.h"
31 #import "RemoteLayerTreePropertyApplier.h"
32 #import "WebProcess.h"
33 #import <AVFoundation/AVFoundation.h>
34 #import <WebCore/GraphicsLayerCA.h>
35 #import <WebCore/PlatformCALayerCocoa.h>
36 #import <WebCore/SoftLinking.h>
37 #import <WebCore/WebCoreCALayerExtras.h>
38 #import <wtf/RetainPtr.h>
39
40 SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
41 SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVPlayerLayer)
42
43 using namespace WebCore;
44
45 namespace WebKit {
46
47 static NSString * const platformCALayerPointer = @"WKPlatformCALayer";
48
49 PassRefPtr<PlatformCALayerRemote> PlatformCALayerRemoteCustom::create(PlatformLayer *platformLayer, PlatformCALayerClient* owner, RemoteLayerTreeContext& context)
50 {
51     auto layer = adoptRef(*new PlatformCALayerRemoteCustom(PlatformCALayerCocoa::layerTypeForPlatformLayer(platformLayer), platformLayer, owner, context));
52     context.layerWasCreated(layer.get(), layer->layerType());
53
54     return WTFMove(layer);
55 }
56
57 PlatformCALayerRemoteCustom::PlatformCALayerRemoteCustom(LayerType layerType, PlatformLayer * customLayer, PlatformCALayerClient* owner, RemoteLayerTreeContext& context)
58     : PlatformCALayerRemote(layerType, owner, context)
59 {
60     switch (context.layerHostingMode()) {
61     case LayerHostingMode::InProcess:
62         m_layerHostingContext = LayerHostingContext::createForPort(WebProcess::singleton().compositingRenderServerPort());
63         break;
64 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
65     case LayerHostingMode::OutOfProcess:
66         m_layerHostingContext = LayerHostingContext::createForExternalHostingProcess();
67 #if PLATFORM(IOS)
68         if (layerType == LayerTypeAVPlayerLayer) {
69             float scaleFactor = context.deviceScaleFactor();
70             // Set a scale factor here to make convertRect:toLayer:nil take scale factor into account. <rdar://problem/18316542>.
71             // This scale factor is inverted in the hosting process.
72             [customLayer setTransform:CATransform3DMakeScale(scaleFactor, scaleFactor, 1)];
73         }
74 #endif
75         break;
76 #endif
77     }
78
79     m_layerHostingContext->setRootLayer(customLayer);
80     [customLayer setValue:[NSValue valueWithPointer:this] forKey:platformCALayerPointer];
81
82     m_platformLayer = customLayer;
83     [customLayer web_disableAllActions];
84
85     m_providesContents = layerType == LayerTypeWebGLLayer;
86
87     properties().position = FloatPoint3D(customLayer.position.x, customLayer.position.y, customLayer.zPosition);
88     properties().anchorPoint = FloatPoint3D(customLayer.anchorPoint.x, customLayer.anchorPoint.y, customLayer.anchorPointZ);
89     properties().bounds = customLayer.bounds;
90     properties().contentsRect = customLayer.contentsRect;
91 }
92
93 PlatformCALayerRemoteCustom::~PlatformCALayerRemoteCustom()
94 {
95     [m_platformLayer setValue:nil forKey:platformCALayerPointer];
96 }
97
98 uint32_t PlatformCALayerRemoteCustom::hostingContextID()
99 {
100     return m_layerHostingContext->contextID();
101 }
102
103 PassRefPtr<WebCore::PlatformCALayer> PlatformCALayerRemoteCustom::clone(PlatformCALayerClient* owner) const
104 {
105     RetainPtr<CALayer *> clonedLayer;
106     bool copyContents = true;
107
108     if (layerType() == LayerTypeAVPlayerLayer) {
109         
110         if ([platformLayer() isKindOfClass:getAVPlayerLayerClass()]) {
111             clonedLayer = adoptNS([allocAVPlayerLayerInstance() init]);
112
113             AVPlayerLayer* destinationPlayerLayer = static_cast<AVPlayerLayer *>(clonedLayer.get());
114             AVPlayerLayer* sourcePlayerLayer = static_cast<AVPlayerLayer *>(platformLayer());
115             dispatch_async(dispatch_get_main_queue(), ^{
116                 [destinationPlayerLayer setPlayer:[sourcePlayerLayer player]];
117             });
118         } else {
119             // On iOS, the AVPlayerLayer is inside a WebVideoContainerLayer. This code needs to share logic with MediaPlayerPrivateAVFoundationObjC::createAVPlayerLayer().
120             clonedLayer = adoptNS([[CALayer alloc] init]);
121         }
122
123         copyContents = false;
124     } else if (layerType() == LayerTypeWebGLLayer) {
125         clonedLayer = adoptNS([[CALayer alloc] init]);
126         // FIXME: currently copying WebGL contents breaks the original layer.
127         copyContents = false;
128     }
129
130     auto clone = adoptRef(*new PlatformCALayerRemoteCustom(layerType(), clonedLayer.get(), owner, *context()));
131     context()->layerWasCreated(clone.get(), clone->layerType());
132
133     updateClonedLayerProperties(clone.get(), copyContents);
134
135     clone->setClonedLayer(this);
136     return WTFMove(clone);
137 }
138
139 CFTypeRef PlatformCALayerRemoteCustom::contents() const
140 {
141     return [m_platformLayer contents];
142 }
143
144 void PlatformCALayerRemoteCustom::setContents(CFTypeRef contents)
145 {
146     [m_platformLayer setContents:(id)contents];
147 }
148
149 void PlatformCALayerRemoteCustom::setNeedsDisplayInRect(const FloatRect& rect)
150 {
151     if (m_providesContents)
152         [m_platformLayer setNeedsDisplayInRect:rect];
153     else
154         PlatformCALayerRemote::setNeedsDisplayInRect(rect);
155 }
156
157 void PlatformCALayerRemoteCustom::setNeedsDisplay()
158 {
159     if (m_providesContents)
160         [m_platformLayer setNeedsDisplay];
161     else
162         PlatformCALayerRemote::setNeedsDisplay();
163 }
164
165 } // namespace WebKit