Only include those parts of AVFoundation.framework which are strictly needed.
[WebKit-https.git] / Source / WebCore / platform / graphics / ca / cocoa / PlatformCALayerCocoa.mm
1 /*
2  * Copyright (C) 2010, 2015 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 "PlatformCALayerCocoa.h"
28
29 #import "AnimationUtilities.h"
30 #import "GraphicsContext.h"
31 #import "GraphicsLayerCA.h"
32 #import "LengthFunctions.h"
33 #import "PlatformCAAnimationCocoa.h"
34 #import "PlatformCAFilters.h"
35 #import "PlatformScreen.h"
36 #import "QuartzCoreSPI.h"
37 #import "ScrollbarThemeMac.h"
38 #import "SoftLinking.h"
39 #import "TileController.h"
40 #import "TiledBacking.h"
41 #import "WebActionDisablingCALayerDelegate.h"
42 #import "WebCoreCALayerExtras.h"
43 #import "WebGLLayer.h"
44 #import "WebLayer.h"
45 #import "WebSystemBackdropLayer.h"
46 #import "WebTiledBackingLayer.h"
47 #import <AVFoundation/AVPlayer.h>
48 #import <AVFoundation/AVPlayerLayer.h>
49 #import <QuartzCore/QuartzCore.h>
50 #import <objc/runtime.h>
51 #import <wtf/BlockObjCExceptions.h>
52 #import <wtf/CurrentTime.h>
53 #import <wtf/RetainPtr.h>
54
55 #if PLATFORM(IOS)
56 #import "FontAntialiasingStateSaver.h"
57 #import "WAKWindow.h"
58 #import "WKGraphics.h"
59 #import "WebCoreThread.h"
60 #else
61 #import "ThemeMac.h"
62 #endif
63
64 SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
65
66 SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVPlayerLayer)
67
68 using namespace WebCore;
69
70 PassRefPtr<PlatformCALayer> PlatformCALayerCocoa::create(LayerType layerType, PlatformCALayerClient* owner)
71 {
72     return adoptRef(new PlatformCALayerCocoa(layerType, owner));
73 }
74
75 PassRefPtr<PlatformCALayer> PlatformCALayerCocoa::create(void* platformLayer, PlatformCALayerClient* owner)
76 {
77     return adoptRef(new PlatformCALayerCocoa(static_cast<PlatformLayer*>(platformLayer), owner));
78 }
79
80 static NSString * const platformCALayerPointer = @"WKPlatformCALayer";
81 PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
82 {
83     if (!platformLayer)
84         return 0;
85
86     // Pointer to PlatformCALayer is kept in a key of the CALayer
87     PlatformCALayer* platformCALayer = nil;
88     BEGIN_BLOCK_OBJC_EXCEPTIONS
89     platformCALayer = static_cast<PlatformCALayer*>([[static_cast<CALayer*>(platformLayer) valueForKey:platformCALayerPointer] pointerValue]);
90     END_BLOCK_OBJC_EXCEPTIONS
91     return platformCALayer;
92 }
93
94 static double mediaTimeToCurrentTime(CFTimeInterval t)
95 {
96     return monotonicallyIncreasingTime() + t - CACurrentMediaTime();
97 }
98
99 // Delegate for animationDidStart callback
100 @interface WebAnimationDelegate : NSObject {
101     PlatformCALayer* m_owner;
102 }
103
104 - (void)animationDidStart:(CAAnimation *)anim;
105 - (void)setOwner:(PlatformCALayer*)owner;
106
107 @end
108
109 @implementation WebAnimationDelegate
110
111 - (void)animationDidStart:(CAAnimation *)animation
112 {
113 #if PLATFORM(IOS)
114     WebThreadLock();
115 #endif
116     if (!m_owner)
117         return;
118
119     CFTimeInterval startTime;
120     if (hasExplicitBeginTime(animation)) {
121         // We don't know what time CA used to commit the animation, so just use the current time
122         // (even though this will be slightly off).
123         startTime = mediaTimeToCurrentTime(CACurrentMediaTime());
124     } else
125         startTime = mediaTimeToCurrentTime([animation beginTime]);
126
127     CALayer *layer = m_owner->platformLayer();
128
129     String animationKey;
130     for (NSString *key in [layer animationKeys]) {
131         if ([layer animationForKey:key] == animation) {
132             animationKey = key;
133             break;
134         }
135     }
136
137     if (!animationKey.isEmpty())
138         m_owner->animationStarted(animationKey, startTime);
139 }
140
141 - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
142 {
143 #if PLATFORM(IOS)
144     WebThreadLock();
145 #endif
146     UNUSED_PARAM(finished);
147
148     if (!m_owner)
149         return;
150     
151     CALayer *layer = m_owner->platformLayer();
152
153     String animationKey;
154     for (NSString *key in [layer animationKeys]) {
155         if ([layer animationForKey:key] == animation) {
156             animationKey = key;
157             break;
158         }
159     }
160
161     if (!animationKey.isEmpty())
162         m_owner->animationEnded(animationKey);
163 }
164
165 - (void)setOwner:(PlatformCALayer*)owner
166 {
167     m_owner = owner;
168 }
169
170 @end
171
172 void PlatformCALayerCocoa::setOwner(PlatformCALayerClient* owner)
173 {
174     PlatformCALayer::setOwner(owner);
175     
176     // Change the delegate's owner if needed
177     if (m_delegate)
178         [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:this];        
179 }
180
181 static NSString *toCAFilterType(PlatformCALayer::FilterType type)
182 {
183     switch (type) {
184     case PlatformCALayer::Linear: return kCAFilterLinear;
185     case PlatformCALayer::Nearest: return kCAFilterNearest;
186     case PlatformCALayer::Trilinear: return kCAFilterTrilinear;
187     default: return 0;
188     }
189 }
190
191 PlatformCALayer::LayerType PlatformCALayerCocoa::layerTypeForPlatformLayer(PlatformLayer* layer)
192 {
193     if ([layer isKindOfClass:getAVPlayerLayerClass()] || [layer isKindOfClass:objc_getClass("WebVideoContainerLayer")])
194         return LayerTypeAVPlayerLayer;
195
196     if ([layer isKindOfClass:[WebGLLayer class]])
197         return LayerTypeWebGLLayer;
198
199     return LayerTypeCustom;
200 }
201
202 PlatformCALayerCocoa::PlatformCALayerCocoa(LayerType layerType, PlatformCALayerClient* owner)
203     : PlatformCALayer(layerType, owner)
204     , m_customAppearance(GraphicsLayer::NoCustomAppearance)
205 {
206     Class layerClass = Nil;
207     switch (layerType) {
208     case LayerTypeLayer:
209     case LayerTypeRootLayer:
210         layerClass = [CALayer class];
211         break;
212     case LayerTypeScrollingLayer:
213         // Scrolling layers only have special behavior with PlatformCALayerRemote.
214         // fallthrough
215     case LayerTypeWebLayer:
216         layerClass = [WebLayer class];
217         break;
218     case LayerTypeSimpleLayer:
219     case LayerTypeTiledBackingTileLayer:
220         layerClass = [WebSimpleLayer class];
221         break;
222     case LayerTypeTransformLayer:
223         layerClass = [CATransformLayer class];
224         break;
225 #if ENABLE(FILTERS_LEVEL_2)
226     case LayerTypeBackdropLayer:
227         layerClass = [CABackdropLayer class];
228         break;
229     case LayerTypeLightSystemBackdropLayer:
230         layerClass = [WebLightSystemBackdropLayer class];
231         break;
232     case LayerTypeDarkSystemBackdropLayer:
233         layerClass = [WebDarkSystemBackdropLayer class];
234         break;
235 #else
236     case LayerTypeBackdropLayer:
237     case LayerTypeLightSystemBackdropLayer:
238     case LayerTypeDarkSystemBackdropLayer:
239         ASSERT_NOT_REACHED();
240         layerClass = [CALayer class];
241         break;
242 #endif
243     case LayerTypeWebTiledLayer:
244         ASSERT_NOT_REACHED();
245         break;
246     case LayerTypeTiledBackingLayer:
247     case LayerTypePageTiledBackingLayer:
248         layerClass = [WebTiledBackingLayer class];
249         break;
250     case LayerTypeAVPlayerLayer:
251         layerClass = getAVPlayerLayerClass();
252         break;
253     case LayerTypeWebGLLayer:
254         // We don't create PlatformCALayerCocoas wrapped around WebGLLayers.
255         ASSERT_NOT_REACHED();
256         break;
257     case LayerTypeShapeLayer:
258         layerClass = [CAShapeLayer class];
259         // fillColor defaults to opaque black.
260         break;
261     case LayerTypeCustom:
262         break;
263     }
264
265     if (layerClass)
266         m_layer = adoptNS([(CALayer *)[layerClass alloc] init]);
267
268 #if ENABLE(FILTERS_LEVEL_2) && PLATFORM(MAC)
269     if (layerType == LayerTypeBackdropLayer)
270         [(CABackdropLayer*)m_layer.get() setWindowServerAware:NO];
271 #endif
272
273     commonInit();
274 }
275
276 PlatformCALayerCocoa::PlatformCALayerCocoa(PlatformLayer* layer, PlatformCALayerClient* owner)
277     : PlatformCALayer(layerTypeForPlatformLayer(layer), owner)
278     , m_customAppearance(GraphicsLayer::NoCustomAppearance)
279 {
280     m_layer = layer;
281     commonInit();
282 }
283
284 void PlatformCALayerCocoa::commonInit()
285 {
286     BEGIN_BLOCK_OBJC_EXCEPTIONS
287     // Save a pointer to 'this' in the CALayer
288     [m_layer setValue:[NSValue valueWithPointer:this] forKey:platformCALayerPointer];
289     
290     // Clear all the implicit animations on the CALayer
291     if (m_layerType == LayerTypeAVPlayerLayer || m_layerType == LayerTypeWebGLLayer || m_layerType == LayerTypeScrollingLayer || m_layerType == LayerTypeCustom)
292         [m_layer web_disableAllActions];
293     else
294         [m_layer setDelegate:[WebActionDisablingCALayerDelegate shared]];
295
296     if (m_layerType == LayerTypeWebLayer || m_layerType == LayerTypeTiledBackingTileLayer) {
297 #if PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90300
298         if (screenSupportsExtendedColor())
299             [m_layer setContentsFormat:kCAContentsFormatRGBA10XR];
300 #endif
301     }
302
303     // So that the scrolling thread's performance logging code can find all the tiles, mark this as being a tile.
304     if (m_layerType == LayerTypeTiledBackingTileLayer)
305         [m_layer setValue:@YES forKey:@"isTile"];
306
307     if (usesTiledBackingLayer()) {
308         WebTiledBackingLayer* tiledBackingLayer = static_cast<WebTiledBackingLayer*>(m_layer.get());
309         TileController* tileController = [tiledBackingLayer createTileController:this];
310
311         m_customSublayers = std::make_unique<PlatformCALayerList>(tileController->containerLayers());
312     }
313
314     END_BLOCK_OBJC_EXCEPTIONS
315 }
316
317 PassRefPtr<PlatformCALayer> PlatformCALayerCocoa::clone(PlatformCALayerClient* owner) const
318 {
319     LayerType type;
320     switch (layerType()) {
321     case LayerTypeTransformLayer:
322         type = LayerTypeTransformLayer;
323         break;
324     case LayerTypeAVPlayerLayer:
325         type = LayerTypeAVPlayerLayer;
326         break;
327     case LayerTypeShapeLayer:
328         type = LayerTypeShapeLayer;
329         break;
330     case LayerTypeBackdropLayer:
331         type = LayerTypeBackdropLayer;
332         break;
333     case LayerTypeLayer:
334     default:
335         type = LayerTypeLayer;
336         break;
337     };
338     RefPtr<PlatformCALayer> newLayer = PlatformCALayerCocoa::create(type, owner);
339     
340     newLayer->setPosition(position());
341     newLayer->setBounds(bounds());
342     newLayer->setAnchorPoint(anchorPoint());
343     newLayer->setTransform(transform());
344     newLayer->setSublayerTransform(sublayerTransform());
345     newLayer->setContents(contents());
346     newLayer->setMasksToBounds(masksToBounds());
347     newLayer->setDoubleSided(isDoubleSided());
348     newLayer->setOpaque(isOpaque());
349     newLayer->setBackgroundColor(backgroundColor());
350     newLayer->setContentsScale(contentsScale());
351     newLayer->setCornerRadius(cornerRadius());
352     newLayer->copyFiltersFrom(*this);
353     newLayer->updateCustomAppearance(customAppearance());
354
355     if (type == LayerTypeAVPlayerLayer) {
356         ASSERT([newLayer->platformLayer() isKindOfClass:getAVPlayerLayerClass()]);
357
358         AVPlayerLayer *destinationPlayerLayer = static_cast<PlatformCALayerCocoa *>(newLayer.get())->avPlayerLayer();
359         AVPlayerLayer *sourcePlayerLayer = avPlayerLayer();
360         ASSERT(sourcePlayerLayer);
361
362         dispatch_async(dispatch_get_main_queue(), ^{
363             [destinationPlayerLayer setPlayer:[sourcePlayerLayer player]];
364         });
365     }
366     
367     if (type == LayerTypeShapeLayer)
368         newLayer->setShapeRoundedRect(shapeRoundedRect());
369
370     return newLayer;
371 }
372
373 PlatformCALayerCocoa::~PlatformCALayerCocoa()
374 {
375     [m_layer setValue:nil forKey:platformCALayerPointer];
376     
377     // Remove the owner pointer from the delegate in case there is a pending animationStarted event.
378     [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil];
379
380     if (usesTiledBackingLayer())
381         [static_cast<WebTiledBackingLayer *>(m_layer.get()) invalidate];
382 }
383
384 void PlatformCALayerCocoa::animationStarted(const String& animationKey, CFTimeInterval beginTime)
385 {
386     if (m_owner)
387         m_owner->platformCALayerAnimationStarted(animationKey, beginTime);
388 }
389
390 void PlatformCALayerCocoa::animationEnded(const String& animationKey)
391 {
392     if (m_owner)
393         m_owner->platformCALayerAnimationEnded(animationKey);
394 }
395
396 void PlatformCALayerCocoa::setNeedsDisplay()
397 {
398     BEGIN_BLOCK_OBJC_EXCEPTIONS
399     [m_layer setNeedsDisplay];
400     END_BLOCK_OBJC_EXCEPTIONS
401 }
402
403 void PlatformCALayerCocoa::setNeedsDisplayInRect(const FloatRect& dirtyRect)
404 {
405     BEGIN_BLOCK_OBJC_EXCEPTIONS
406     [m_layer setNeedsDisplayInRect:dirtyRect];
407     END_BLOCK_OBJC_EXCEPTIONS
408 }
409
410 void PlatformCALayerCocoa::copyContentsFromLayer(PlatformCALayer* layer)
411 {
412     BEGIN_BLOCK_OBJC_EXCEPTIONS
413     CALayer* caLayer = layer->m_layer.get();
414     if ([m_layer contents] != [caLayer contents])
415         [m_layer setContents:[caLayer contents]];
416     else
417         [m_layer setContentsChanged];
418     END_BLOCK_OBJC_EXCEPTIONS
419 }
420
421 PlatformCALayer* PlatformCALayerCocoa::superlayer() const
422 {
423     return platformCALayer([m_layer superlayer]);
424 }
425
426 void PlatformCALayerCocoa::removeFromSuperlayer()
427 {
428     BEGIN_BLOCK_OBJC_EXCEPTIONS
429     [m_layer removeFromSuperlayer];
430     END_BLOCK_OBJC_EXCEPTIONS
431 }
432
433 void PlatformCALayerCocoa::setSublayers(const PlatformCALayerList& list)
434 {
435     // Short circuiting here avoids the allocation of the array below.
436     if (!list.size()) {
437         removeAllSublayers();
438         return;
439     }
440
441     BEGIN_BLOCK_OBJC_EXCEPTIONS
442     NSMutableArray* sublayers = [[NSMutableArray alloc] init];
443     for (size_t i = 0; i < list.size(); ++i)
444         [sublayers addObject:list[i]->m_layer.get()];
445
446     [m_layer setSublayers:sublayers];
447     [sublayers release];
448     END_BLOCK_OBJC_EXCEPTIONS
449 }
450
451 void PlatformCALayerCocoa::removeAllSublayers()
452 {
453     BEGIN_BLOCK_OBJC_EXCEPTIONS
454     [m_layer setSublayers:nil];
455     END_BLOCK_OBJC_EXCEPTIONS
456 }
457
458 void PlatformCALayerCocoa::appendSublayer(PlatformCALayer& layer)
459 {
460     BEGIN_BLOCK_OBJC_EXCEPTIONS
461     ASSERT(m_layer != layer.m_layer);
462     [m_layer addSublayer:layer.m_layer.get()];
463     END_BLOCK_OBJC_EXCEPTIONS
464 }
465
466 void PlatformCALayerCocoa::insertSublayer(PlatformCALayer& layer, size_t index)
467 {
468     BEGIN_BLOCK_OBJC_EXCEPTIONS
469     ASSERT(m_layer != layer.m_layer);
470     [m_layer insertSublayer:layer.m_layer.get() atIndex:index];
471     END_BLOCK_OBJC_EXCEPTIONS
472 }
473
474 void PlatformCALayerCocoa::replaceSublayer(PlatformCALayer& reference, PlatformCALayer& layer)
475 {
476     BEGIN_BLOCK_OBJC_EXCEPTIONS
477     ASSERT(m_layer != layer.m_layer);
478     [m_layer replaceSublayer:reference.m_layer.get() with:layer.m_layer.get()];
479     END_BLOCK_OBJC_EXCEPTIONS
480 }
481
482 void PlatformCALayerCocoa::adoptSublayers(PlatformCALayer& source)
483 {
484     BEGIN_BLOCK_OBJC_EXCEPTIONS
485     [m_layer setSublayers:[source.m_layer.get() sublayers]];
486     END_BLOCK_OBJC_EXCEPTIONS
487 }
488
489 void PlatformCALayerCocoa::addAnimationForKey(const String& key, PlatformCAAnimation& animation)
490 {
491     // Add the delegate
492     if (!m_delegate) {
493         WebAnimationDelegate* webAnimationDelegate = [[WebAnimationDelegate alloc] init];
494         m_delegate = adoptNS(webAnimationDelegate);
495         [webAnimationDelegate setOwner:this];
496     }
497     
498     CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>(downcast<PlatformCAAnimationCocoa>(animation).platformAnimation());
499     if (![propertyAnimation delegate])
500         [propertyAnimation setDelegate:static_cast<id>(m_delegate.get())];
501
502     BEGIN_BLOCK_OBJC_EXCEPTIONS
503     [m_layer addAnimation:propertyAnimation forKey:key];
504     END_BLOCK_OBJC_EXCEPTIONS
505 }
506
507 void PlatformCALayerCocoa::removeAnimationForKey(const String& key)
508 {
509     BEGIN_BLOCK_OBJC_EXCEPTIONS
510     [m_layer removeAnimationForKey:key];
511     END_BLOCK_OBJC_EXCEPTIONS
512 }
513
514 PassRefPtr<PlatformCAAnimation> PlatformCALayerCocoa::animationForKey(const String& key)
515 {
516     CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>([m_layer animationForKey:key]);
517     if (!propertyAnimation)
518         return 0;
519     return PlatformCAAnimationCocoa::create(propertyAnimation);
520 }
521
522 void PlatformCALayerCocoa::setMask(PlatformCALayer* layer)
523 {
524     BEGIN_BLOCK_OBJC_EXCEPTIONS
525     [m_layer setMask:layer ? layer->platformLayer() : nil];
526     END_BLOCK_OBJC_EXCEPTIONS
527 }
528
529 bool PlatformCALayerCocoa::isOpaque() const
530 {
531     return [m_layer isOpaque];
532 }
533
534 void PlatformCALayerCocoa::setOpaque(bool value)
535 {
536     BEGIN_BLOCK_OBJC_EXCEPTIONS
537     [m_layer setOpaque:value];
538     END_BLOCK_OBJC_EXCEPTIONS
539 }
540
541 FloatRect PlatformCALayerCocoa::bounds() const
542 {
543     return [m_layer bounds];
544 }
545
546 void PlatformCALayerCocoa::setBounds(const FloatRect& value)
547 {
548     BEGIN_BLOCK_OBJC_EXCEPTIONS
549     [m_layer setBounds:value];
550     
551     if (requiresCustomAppearanceUpdateOnBoundsChange())
552         updateCustomAppearance(m_customAppearance);
553
554     END_BLOCK_OBJC_EXCEPTIONS
555 }
556
557 FloatPoint3D PlatformCALayerCocoa::position() const
558 {
559     CGPoint point = [m_layer position];
560     return FloatPoint3D(point.x, point.y, [m_layer zPosition]);
561 }
562
563 void PlatformCALayerCocoa::setPosition(const FloatPoint3D& value)
564 {
565     BEGIN_BLOCK_OBJC_EXCEPTIONS
566     [m_layer setPosition:CGPointMake(value.x(), value.y())];
567     [m_layer setZPosition:value.z()];
568     END_BLOCK_OBJC_EXCEPTIONS
569 }
570
571 FloatPoint3D PlatformCALayerCocoa::anchorPoint() const
572 {
573     CGPoint point = [m_layer anchorPoint];
574     float z = 0;
575     z = [m_layer anchorPointZ];
576     return FloatPoint3D(point.x, point.y, z);
577 }
578
579 void PlatformCALayerCocoa::setAnchorPoint(const FloatPoint3D& value)
580 {
581     BEGIN_BLOCK_OBJC_EXCEPTIONS
582     [m_layer setAnchorPoint:CGPointMake(value.x(), value.y())];
583     [m_layer setAnchorPointZ:value.z()];
584     END_BLOCK_OBJC_EXCEPTIONS
585 }
586
587 TransformationMatrix PlatformCALayerCocoa::transform() const
588 {
589     return [m_layer transform];
590 }
591
592 void PlatformCALayerCocoa::setTransform(const TransformationMatrix& value)
593 {
594     BEGIN_BLOCK_OBJC_EXCEPTIONS
595     [m_layer setTransform:value];
596     END_BLOCK_OBJC_EXCEPTIONS
597 }
598
599 TransformationMatrix PlatformCALayerCocoa::sublayerTransform() const
600 {
601     return [m_layer sublayerTransform];
602 }
603
604 void PlatformCALayerCocoa::setSublayerTransform(const TransformationMatrix& value)
605 {
606     BEGIN_BLOCK_OBJC_EXCEPTIONS
607     [m_layer setSublayerTransform:value];
608     END_BLOCK_OBJC_EXCEPTIONS
609 }
610
611 bool PlatformCALayerCocoa::isHidden() const
612 {
613     return [m_layer isHidden];
614 }
615
616 void PlatformCALayerCocoa::setHidden(bool value)
617 {
618     BEGIN_BLOCK_OBJC_EXCEPTIONS
619     [m_layer setHidden:value];
620     END_BLOCK_OBJC_EXCEPTIONS
621 }
622
623 bool PlatformCALayerCocoa::contentsHidden() const
624 {
625     return false;
626 }
627
628 void PlatformCALayerCocoa::setContentsHidden(bool)
629 {
630 }
631
632 bool PlatformCALayerCocoa::userInteractionEnabled() const
633 {
634     return true;
635 }
636
637 void PlatformCALayerCocoa::setUserInteractionEnabled(bool)
638 {
639 }
640
641 void PlatformCALayerCocoa::setBackingStoreAttached(bool)
642 {
643     // We could throw away backing store here with setContents:nil.
644 }
645
646 bool PlatformCALayerCocoa::backingStoreAttached() const
647 {
648     return true;
649 }
650
651 bool PlatformCALayerCocoa::geometryFlipped() const
652 {
653     return [m_layer isGeometryFlipped];
654 }
655
656 void PlatformCALayerCocoa::setGeometryFlipped(bool value)
657 {
658     BEGIN_BLOCK_OBJC_EXCEPTIONS
659     [m_layer setGeometryFlipped:value];
660     END_BLOCK_OBJC_EXCEPTIONS
661 }
662
663 bool PlatformCALayerCocoa::isDoubleSided() const
664 {
665     return [m_layer isDoubleSided];
666 }
667
668 void PlatformCALayerCocoa::setDoubleSided(bool value)
669 {
670     BEGIN_BLOCK_OBJC_EXCEPTIONS
671     [m_layer setDoubleSided:value];
672     END_BLOCK_OBJC_EXCEPTIONS
673 }
674
675 bool PlatformCALayerCocoa::masksToBounds() const
676 {
677     return [m_layer masksToBounds];
678 }
679
680 void PlatformCALayerCocoa::setMasksToBounds(bool value)
681 {
682     BEGIN_BLOCK_OBJC_EXCEPTIONS
683     [m_layer setMasksToBounds:value];
684     END_BLOCK_OBJC_EXCEPTIONS
685 }
686
687 bool PlatformCALayerCocoa::acceleratesDrawing() const
688 {
689     return [m_layer acceleratesDrawing];
690 }
691
692 void PlatformCALayerCocoa::setAcceleratesDrawing(bool acceleratesDrawing)
693 {
694     BEGIN_BLOCK_OBJC_EXCEPTIONS
695     [m_layer setAcceleratesDrawing:acceleratesDrawing];
696     END_BLOCK_OBJC_EXCEPTIONS
697 }
698
699 CFTypeRef PlatformCALayerCocoa::contents() const
700 {
701     return [m_layer contents];
702 }
703
704 void PlatformCALayerCocoa::setContents(CFTypeRef value)
705 {
706     BEGIN_BLOCK_OBJC_EXCEPTIONS
707     [m_layer setContents:static_cast<id>(const_cast<void*>(value))];
708     END_BLOCK_OBJC_EXCEPTIONS
709 }
710
711 void PlatformCALayerCocoa::setContentsRect(const FloatRect& value)
712 {
713     BEGIN_BLOCK_OBJC_EXCEPTIONS
714     [m_layer setContentsRect:value];
715     END_BLOCK_OBJC_EXCEPTIONS
716 }
717
718 void PlatformCALayerCocoa::setMinificationFilter(FilterType value)
719 {
720     BEGIN_BLOCK_OBJC_EXCEPTIONS
721     [m_layer setMinificationFilter:toCAFilterType(value)];
722     END_BLOCK_OBJC_EXCEPTIONS
723 }
724
725 void PlatformCALayerCocoa::setMagnificationFilter(FilterType value)
726 {
727     BEGIN_BLOCK_OBJC_EXCEPTIONS
728     [m_layer setMagnificationFilter:toCAFilterType(value)];
729     END_BLOCK_OBJC_EXCEPTIONS
730 }
731
732 Color PlatformCALayerCocoa::backgroundColor() const
733 {
734     return [m_layer backgroundColor];
735 }
736
737 void PlatformCALayerCocoa::setBackgroundColor(const Color& value)
738 {
739     BEGIN_BLOCK_OBJC_EXCEPTIONS
740     [m_layer setBackgroundColor:cachedCGColor(value)];
741     END_BLOCK_OBJC_EXCEPTIONS
742 }
743
744 void PlatformCALayerCocoa::setBorderWidth(float value)
745 {
746     BEGIN_BLOCK_OBJC_EXCEPTIONS
747     [m_layer setBorderWidth:value];
748     END_BLOCK_OBJC_EXCEPTIONS
749 }
750
751 void PlatformCALayerCocoa::setBorderColor(const Color& value)
752 {
753     if (value.isValid()) {
754         BEGIN_BLOCK_OBJC_EXCEPTIONS
755         [m_layer setBorderColor:cachedCGColor(value)];
756         END_BLOCK_OBJC_EXCEPTIONS
757     } else {
758         BEGIN_BLOCK_OBJC_EXCEPTIONS
759         [m_layer setBorderColor:nil];
760         END_BLOCK_OBJC_EXCEPTIONS
761     }
762 }
763
764 float PlatformCALayerCocoa::opacity() const
765 {
766     return [m_layer opacity];
767 }
768
769 void PlatformCALayerCocoa::setOpacity(float value)
770 {
771     BEGIN_BLOCK_OBJC_EXCEPTIONS
772     [m_layer setOpacity:value];
773     END_BLOCK_OBJC_EXCEPTIONS
774 }
775
776 void PlatformCALayerCocoa::setFilters(const FilterOperations& filters)
777 {
778     PlatformCAFilters::setFiltersOnLayer(platformLayer(), filters);
779 }
780
781 void PlatformCALayerCocoa::copyFiltersFrom(const PlatformCALayer& sourceLayer)
782 {
783     BEGIN_BLOCK_OBJC_EXCEPTIONS
784     [m_layer setFilters:[sourceLayer.platformLayer() filters]];
785     END_BLOCK_OBJC_EXCEPTIONS
786 }
787
788 bool PlatformCALayerCocoa::filtersCanBeComposited(const FilterOperations& filters)
789 {
790     // Return false if there are no filters to avoid needless work
791     if (!filters.size())
792         return false;
793     
794     for (unsigned i = 0; i < filters.size(); ++i) {
795         const FilterOperation* filterOperation = filters.at(i);
796         switch (filterOperation->type()) {
797         case FilterOperation::REFERENCE:
798             return false;
799         case FilterOperation::DROP_SHADOW:
800             // FIXME: For now we can only handle drop-shadow is if it's last in the list
801             if (i < (filters.size() - 1))
802                 return false;
803             break;
804         default:
805             break;
806         }
807     }
808
809     return true;
810 }
811
812 #if ENABLE(CSS_COMPOSITING)
813 void PlatformCALayerCocoa::setBlendMode(BlendMode blendMode)
814 {
815     PlatformCAFilters::setBlendingFiltersOnLayer(platformLayer(), blendMode);
816 }
817 #endif
818
819 void PlatformCALayerCocoa::setName(const String& value)
820 {
821     BEGIN_BLOCK_OBJC_EXCEPTIONS
822     [m_layer setName:value];
823     END_BLOCK_OBJC_EXCEPTIONS
824 }
825
826 void PlatformCALayerCocoa::setSpeed(float value)
827 {
828     BEGIN_BLOCK_OBJC_EXCEPTIONS
829     [m_layer setSpeed:value];
830     END_BLOCK_OBJC_EXCEPTIONS
831 }
832
833 void PlatformCALayerCocoa::setTimeOffset(CFTimeInterval value)
834 {
835     BEGIN_BLOCK_OBJC_EXCEPTIONS
836     [m_layer setTimeOffset:value];
837     END_BLOCK_OBJC_EXCEPTIONS
838 }
839
840 float PlatformCALayerCocoa::contentsScale() const
841 {
842     return [m_layer contentsScale];
843 }
844
845 void PlatformCALayerCocoa::setContentsScale(float value)
846 {
847     BEGIN_BLOCK_OBJC_EXCEPTIONS
848     [m_layer setContentsScale:value];
849 #if PLATFORM(IOS)
850     [m_layer setRasterizationScale:value];
851 #endif
852     END_BLOCK_OBJC_EXCEPTIONS
853 }
854
855 float PlatformCALayerCocoa::cornerRadius() const
856 {
857     return [m_layer cornerRadius];
858 }
859
860 void PlatformCALayerCocoa::setCornerRadius(float value)
861 {
862     BEGIN_BLOCK_OBJC_EXCEPTIONS
863     [m_layer setCornerRadius:value];
864     END_BLOCK_OBJC_EXCEPTIONS
865 }
866
867 void PlatformCALayerCocoa::setEdgeAntialiasingMask(unsigned mask)
868 {
869     BEGIN_BLOCK_OBJC_EXCEPTIONS
870     [m_layer setEdgeAntialiasingMask:mask];
871     END_BLOCK_OBJC_EXCEPTIONS
872 }
873
874 FloatRoundedRect PlatformCALayerCocoa::shapeRoundedRect() const
875 {
876     ASSERT(m_layerType == LayerTypeShapeLayer);
877     if (m_shapeRoundedRect)
878         return *m_shapeRoundedRect;
879
880     return FloatRoundedRect();
881 }
882
883 void PlatformCALayerCocoa::setShapeRoundedRect(const FloatRoundedRect& roundedRect)
884 {
885     ASSERT(m_layerType == LayerTypeShapeLayer);
886     m_shapeRoundedRect = std::make_unique<FloatRoundedRect>(roundedRect);
887
888     BEGIN_BLOCK_OBJC_EXCEPTIONS
889     Path shapePath;
890     shapePath.addRoundedRect(roundedRect);
891     [(CAShapeLayer *)m_layer setPath:shapePath.platformPath()];
892     END_BLOCK_OBJC_EXCEPTIONS
893 }
894
895 WindRule PlatformCALayerCocoa::shapeWindRule() const
896 {
897     ASSERT(m_layerType == LayerTypeShapeLayer);
898
899     NSString *fillRule = [(CAShapeLayer *)m_layer fillRule];
900     if ([fillRule isEqualToString:@"even-odd"])
901         return RULE_EVENODD;
902
903     return RULE_NONZERO;
904 }
905
906 void PlatformCALayerCocoa::setShapeWindRule(WindRule windRule)
907 {
908     ASSERT(m_layerType == LayerTypeShapeLayer);
909
910     switch (windRule) {
911     case RULE_NONZERO:
912         [(CAShapeLayer *)m_layer setFillRule:@"non-zero"];
913         break;
914     case RULE_EVENODD:
915         [(CAShapeLayer *)m_layer setFillRule:@"even-odd"];
916         break;
917     }
918 }
919
920 Path PlatformCALayerCocoa::shapePath() const
921 {
922     ASSERT(m_layerType == LayerTypeShapeLayer);
923
924     BEGIN_BLOCK_OBJC_EXCEPTIONS
925     return Path(CGPathCreateMutableCopy([(CAShapeLayer *)m_layer path]));
926     END_BLOCK_OBJC_EXCEPTIONS
927 }
928
929 void PlatformCALayerCocoa::setShapePath(const Path& path)
930 {
931     ASSERT(m_layerType == LayerTypeShapeLayer);
932
933     BEGIN_BLOCK_OBJC_EXCEPTIONS
934     [(CAShapeLayer *)m_layer setPath:path.platformPath()];
935     END_BLOCK_OBJC_EXCEPTIONS
936 }
937
938 bool PlatformCALayerCocoa::requiresCustomAppearanceUpdateOnBoundsChange() const
939 {
940     return m_customAppearance == GraphicsLayer::ScrollingShadow;
941 }
942
943 void PlatformCALayerCocoa::updateCustomAppearance(GraphicsLayer::CustomAppearance appearance)
944 {
945     if (m_customAppearance == appearance)
946         return;
947
948     m_customAppearance = appearance;
949
950 #if ENABLE(RUBBER_BANDING)
951     switch (appearance) {
952     case GraphicsLayer::NoCustomAppearance:
953     case GraphicsLayer::LightBackdropAppearance:
954     case GraphicsLayer::DarkBackdropAppearance:
955         ScrollbarThemeMac::removeOverhangAreaBackground(platformLayer());
956         ScrollbarThemeMac::removeOverhangAreaShadow(platformLayer());
957         break;
958     case GraphicsLayer::ScrollingOverhang:
959         ScrollbarThemeMac::setUpOverhangAreaBackground(platformLayer());
960         break;
961     case GraphicsLayer::ScrollingShadow:
962         ScrollbarThemeMac::setUpOverhangAreaShadow(platformLayer());
963         break;
964     }
965 #endif
966 }
967
968 TiledBacking* PlatformCALayerCocoa::tiledBacking()
969 {
970     if (!usesTiledBackingLayer())
971         return nullptr;
972
973     WebTiledBackingLayer *tiledBackingLayer = static_cast<WebTiledBackingLayer *>(m_layer.get());
974     return [tiledBackingLayer tiledBacking];
975 }
976
977 #if PLATFORM(IOS)
978 bool PlatformCALayer::isWebLayer()
979 {
980     BOOL result = NO;
981     BEGIN_BLOCK_OBJC_EXCEPTIONS
982     result = [m_layer isKindOfClass:[WebLayer self]];
983     END_BLOCK_OBJC_EXCEPTIONS
984     return result;
985 }
986
987 void PlatformCALayer::setBoundsOnMainThread(CGRect bounds)
988 {
989     CALayer *layer = m_layer.get();
990     dispatch_async(dispatch_get_main_queue(), ^{
991         BEGIN_BLOCK_OBJC_EXCEPTIONS
992         [layer setBounds:bounds];
993         END_BLOCK_OBJC_EXCEPTIONS
994     });
995 }
996
997 void PlatformCALayer::setPositionOnMainThread(CGPoint position)
998 {
999     CALayer *layer = m_layer.get();
1000     dispatch_async(dispatch_get_main_queue(), ^{
1001         BEGIN_BLOCK_OBJC_EXCEPTIONS
1002         [layer setPosition:position];
1003         END_BLOCK_OBJC_EXCEPTIONS
1004     });
1005 }
1006
1007 void PlatformCALayer::setAnchorPointOnMainThread(FloatPoint3D value)
1008 {
1009     CALayer *layer = m_layer.get();
1010     dispatch_async(dispatch_get_main_queue(), ^{
1011         BEGIN_BLOCK_OBJC_EXCEPTIONS
1012         [layer setAnchorPoint:CGPointMake(value.x(), value.y())];
1013         [layer setAnchorPointZ:value.z()];
1014         END_BLOCK_OBJC_EXCEPTIONS
1015     });
1016 }
1017 #endif // PLATFORM(IOS)
1018
1019 PlatformCALayer::RepaintRectList PlatformCALayer::collectRectsToPaint(CGContextRef context, PlatformCALayer* platformCALayer)
1020 {
1021     __block double totalRectArea = 0;
1022     __block unsigned rectCount = 0;
1023     __block RepaintRectList dirtyRects;
1024     
1025     platformCALayer->enumerateRectsBeingDrawn(context, ^(CGRect rect) {
1026         if (++rectCount > webLayerMaxRectsToPaint)
1027             return;
1028         
1029         totalRectArea += rect.size.width * rect.size.height;
1030         dirtyRects.append(rect);
1031     });
1032     
1033     FloatRect clipBounds = CGContextGetClipBoundingBox(context);
1034     double clipArea = clipBounds.width() * clipBounds.height();
1035     
1036     if (rectCount >= webLayerMaxRectsToPaint || totalRectArea >= clipArea * webLayerWastedSpaceThreshold) {
1037         dirtyRects.clear();
1038         dirtyRects.append(clipBounds);
1039     }
1040     
1041     return dirtyRects;
1042 }
1043
1044 void PlatformCALayer::drawLayerContents(CGContextRef context, WebCore::PlatformCALayer* platformCALayer, RepaintRectList& dirtyRects)
1045 {
1046     WebCore::PlatformCALayerClient* layerContents = platformCALayer->owner();
1047     if (!layerContents)
1048         return;
1049     
1050 #if PLATFORM(IOS)
1051     WKSetCurrentGraphicsContext(context);
1052 #endif
1053     
1054     CGContextSaveGState(context);
1055     
1056     // We never use CompositingCoordinatesBottomUp on Mac.
1057     ASSERT(layerContents->platformCALayerContentsOrientation() == GraphicsLayer::CompositingCoordinatesTopDown);
1058     
1059 #if PLATFORM(IOS)
1060     FontAntialiasingStateSaver fontAntialiasingState(context, [platformCALayer->platformLayer() isOpaque]);
1061     fontAntialiasingState.setup([WAKWindow hasLandscapeOrientation]);
1062 #else
1063     [NSGraphicsContext saveGraphicsState];
1064     
1065     // Set up an NSGraphicsContext for the context, so that parts of AppKit that rely on
1066     // the current NSGraphicsContext (e.g. NSCell drawing) get the right one.
1067     NSGraphicsContext* layerContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:YES];
1068     [NSGraphicsContext setCurrentContext:layerContext];
1069 #endif
1070     
1071     {
1072         GraphicsContext graphicsContext(context);
1073         graphicsContext.setIsCALayerContext(true);
1074         graphicsContext.setIsAcceleratedContext(platformCALayer->acceleratesDrawing());
1075         
1076         if (!layerContents->platformCALayerContentsOpaque()) {
1077             // Turn off font smoothing to improve the appearance of text rendered onto a transparent background.
1078             graphicsContext.setShouldSmoothFonts(false);
1079         }
1080         
1081 #if PLATFORM(MAC)
1082         // It's important to get the clip from the context, because it may be significantly
1083         // smaller than the layer bounds (e.g. tiled layers)
1084         ThemeMac::setFocusRingClipRect(CGContextGetClipBoundingBox(context));
1085 #endif
1086         
1087         for (const auto& rect : dirtyRects) {
1088             GraphicsContextStateSaver stateSaver(graphicsContext);
1089             graphicsContext.clip(rect);
1090             
1091             layerContents->platformCALayerPaintContents(platformCALayer, graphicsContext, rect);
1092         }
1093         
1094 #if PLATFORM(IOS)
1095         fontAntialiasingState.restore();
1096 #else
1097         ThemeMac::setFocusRingClipRect(FloatRect());
1098         
1099         [NSGraphicsContext restoreGraphicsState];
1100 #endif
1101     }
1102
1103     CGContextRestoreGState(context);
1104
1105     // Re-fetch the layer owner, since <rdar://problem/9125151> indicates that it might have been destroyed during painting.
1106     layerContents = platformCALayer->owner();
1107     ASSERT(layerContents);
1108     
1109     // Always update the repaint count so that it's accurate even if the count itself is not shown. This will be useful
1110     // for the Web Inspector feeding this information through the LayerTreeAgent.
1111     int repaintCount = layerContents->platformCALayerIncrementRepaintCount(platformCALayer);
1112
1113     if (!platformCALayer->usesTiledBackingLayer() && layerContents && layerContents->platformCALayerShowRepaintCounter(platformCALayer))
1114         drawRepaintIndicator(context, platformCALayer, repaintCount, nullptr);
1115 }
1116
1117 CGRect PlatformCALayer::frameForLayer(const PlatformLayer* tileLayer)
1118 {
1119     return [tileLayer frame];
1120 }
1121
1122 PassRefPtr<PlatformCALayer> PlatformCALayerCocoa::createCompatibleLayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* client) const
1123 {
1124     return PlatformCALayerCocoa::create(layerType, client);
1125 }
1126
1127 void PlatformCALayerCocoa::enumerateRectsBeingDrawn(CGContextRef context, void (^block)(CGRect))
1128 {
1129     wkCALayerEnumerateRectsBeingDrawnWithBlock(m_layer.get(), context, block);
1130 }
1131
1132 AVPlayerLayer *PlatformCALayerCocoa::avPlayerLayer() const
1133 {
1134     if (layerType() != LayerTypeAVPlayerLayer)
1135         return nil;
1136
1137     if ([platformLayer() isKindOfClass:getAVPlayerLayerClass()])
1138         return static_cast<AVPlayerLayer *>(platformLayer());
1139
1140     if ([platformLayer() isKindOfClass:objc_getClass("WebVideoContainerLayer")]) {
1141         ASSERT([platformLayer() sublayers].count == 1);
1142         ASSERT([[platformLayer() sublayers][0] isKindOfClass:getAVPlayerLayerClass()]);
1143         return static_cast<AVPlayerLayer *>([platformLayer() sublayers][0]);
1144     }
1145
1146     ASSERT_NOT_REACHED();
1147     return nil;
1148 }