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