1/*
2 * Copyright (C) 2010 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 COMPUTER, 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
28#if USE(ACCELERATED_COMPOSITING)
29
30#import "PlatformCALayer.h"
31
32#import "AnimationUtilities.h"
33#import "BlockExceptions.h"
34#import "GraphicsContext.h"
35#import "GraphicsLayerCA.h"
36#import "LengthFunctions.h"
37#import "PlatformCAFilters.h"
38#import "SoftLinking.h"
39#import "TiledBacking.h"
40#import "WebLayer.h"
41#import "WebTiledLayer.h"
42#import "WebTiledBackingLayer.h"
43#import <objc/objc-auto.h>
44#import <objc/runtime.h>
45#import <AVFoundation/AVFoundation.h>
46#import <QuartzCore/QuartzCore.h>
47#import <wtf/CurrentTime.h>
48#import <wtf/MathExtras.h>
49#import <wtf/RetainPtr.h>
50
51SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
52SOFT_LINK_CLASS(AVFoundation, AVPlayerLayer)
53
54using std::min;
55using std::max;
56
57using namespace WebCore;
58
59// This value must be the same as in PlatformCAAnimationMac.mm
60static NSString * const WKNonZeroBeginTimeFlag = @"WKPlatformCAAnimationNonZeroBeginTimeFlag";
61
62static double mediaTimeToCurrentTime(CFTimeInterval t)
63{
64    return WTF::currentTime() + t - CACurrentMediaTime();
65}
66
67// Delegate for animationDidStart callback
68@interface WebAnimationDelegate : NSObject {
69    PlatformCALayer* m_owner;
70}
71
72- (void)animationDidStart:(CAAnimation *)anim;
73- (void)setOwner:(PlatformCALayer*)owner;
74
75@end
76
77@implementation WebAnimationDelegate
78
79- (void)animationDidStart:(CAAnimation *)animation
80{
81    // hasNonZeroBeginTime is stored in a key in the animation
82    bool hasNonZeroBeginTime = [[animation valueForKey:WKNonZeroBeginTimeFlag] boolValue];
83    CFTimeInterval startTime;
84
85    if (hasNonZeroBeginTime) {
86        // We don't know what time CA used to commit the animation, so just use the current time
87        // (even though this will be slightly off).
88        startTime = mediaTimeToCurrentTime(CACurrentMediaTime());
89    } else
90        startTime = mediaTimeToCurrentTime([animation beginTime]);
91
92    if (m_owner)
93        m_owner->animationStarted(startTime);
94}
95
96- (void)setOwner:(PlatformCALayer*)owner
97{
98    m_owner = owner;
99}
100
101@end
102
103#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
104@interface CATiledLayer(GraphicsLayerCAPrivate)
105- (void)displayInRect:(CGRect)r levelOfDetail:(int)lod options:(NSDictionary *)dict;
106- (BOOL)canDrawConcurrently;
107- (void)setCanDrawConcurrently:(BOOL)flag;
108@end
109#endif
110
111@interface CALayer(Private)
112- (void)setContentsChanged;
113#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
114- (void)setAcceleratesDrawing:(BOOL)flag;
115- (BOOL)acceleratesDrawing;
116#endif
117@end
118
119static NSString * const platformCALayerPointer = @"WKPlatformCALayer";
120
121bool PlatformCALayer::isValueFunctionSupported()
122{
123    static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
124    return sHaveValueFunction;
125}
126
127void PlatformCALayer::setOwner(PlatformCALayerClient* owner)
128{
129    m_owner = owner;
130
131    // Change the delegate's owner if needed
132    if (m_delegate)
133        [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:this];
134}
135
136static NSDictionary* nullActionsDictionary()
137{
138    NSNull* nullValue = [NSNull null];
139    NSDictionary* actions = [NSDictionary dictionaryWithObjectsAndKeys:
140                             nullValue, @"anchorPoint",
141                             nullValue, @"anchorPointZ",
142                             nullValue, @"bounds",
143                             nullValue, @"contents",
144                             nullValue, @"contentsRect",
145                             nullValue, @"opacity",
146                             nullValue, @"position",
147                             nullValue, @"shadowColor",
148                             nullValue, @"sublayerTransform",
149                             nullValue, @"sublayers",
150                             nullValue, @"transform",
151                             nullValue, @"zPosition",
152                             nil];
153    return actions;
154}
155
156static NSString* toCAFilterType(PlatformCALayer::FilterType type)
157{
158    switch (type) {
159    case PlatformCALayer::Linear: return kCAFilterLinear;
160    case PlatformCALayer::Nearest: return kCAFilterNearest;
161    case PlatformCALayer::Trilinear: return kCAFilterTrilinear;
162    default: return 0;
163    }
164}
165
166PassRefPtr<PlatformCALayer> PlatformCALayer::create(LayerType layerType, PlatformCALayerClient* owner)
167{
168    return adoptRef(new PlatformCALayer(layerType, 0, owner));
169}
170
171PassRefPtr<PlatformCALayer> PlatformCALayer::create(void* platformLayer, PlatformCALayerClient* owner)
172{
173    return adoptRef(new PlatformCALayer(LayerTypeCustom, static_cast<PlatformLayer*>(platformLayer), owner));
174}
175
176PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, PlatformCALayerClient* owner)
177    : m_owner(owner)
178{
179    BEGIN_BLOCK_OBJC_EXCEPTIONS
180    if (layer) {
181        if ([layer isKindOfClass:getAVPlayerLayerClass()])
182            m_layerType = LayerTypeAVPlayerLayer;
183        else
184            m_layerType = LayerTypeCustom;
185        m_layer = layer;
186    } else {
187        m_layerType = layerType;
188
189        Class layerClass = Nil;
190        switch (layerType) {
191            case LayerTypeLayer:
192            case LayerTypeRootLayer:
193                layerClass = [CALayer class];
194                break;
195            case LayerTypeWebLayer:
196                layerClass = [WebLayer class];
197                break;
198            case LayerTypeTransformLayer:
199                layerClass = [CATransformLayer class];
200                break;
201            case LayerTypeWebTiledLayer:
202                layerClass = [WebTiledLayer class];
203                break;
204            case LayerTypeTiledBackingLayer:
205            case LayerTypePageTiledBackingLayer:
206                layerClass = [WebTiledBackingLayer class];
207                break;
208            case LayerTypeAVPlayerLayer:
209                layerClass = getAVPlayerLayerClass();
210                break;
211            case LayerTypeCustom:
212                break;
213        }
214
215        if (layerClass)
216            m_layer = adoptNS([[layerClass alloc] init]);
217    }
218
219    // Save a pointer to 'this' in the CALayer
220    [m_layer.get() setValue:[NSValue valueWithPointer:this] forKey:platformCALayerPointer];
221
222    // Clear all the implicit animations on the CALayer
223    [m_layer.get() setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
224
225    // If this is a TiledLayer, set some initial values
226    if (m_layerType == LayerTypeWebTiledLayer) {
227        WebTiledLayer* tiledLayer = static_cast<WebTiledLayer*>(m_layer.get());
228        [tiledLayer setTileSize:CGSizeMake(GraphicsLayerCA::kTiledLayerTileSize, GraphicsLayerCA::kTiledLayerTileSize)];
229        [tiledLayer setLevelsOfDetail:1];
230        [tiledLayer setLevelsOfDetailBias:0];
231        [tiledLayer setContentsGravity:@"bottomLeft"];
232    }
233
234    if (usesTiledBackingLayer()) {
235        m_customSublayers = adoptPtr(new PlatformCALayerList(1));
236        CALayer* tileCacheTileContainerLayer = [static_cast<WebTiledBackingLayer *>(m_layer.get()) tileContainerLayer];
237        (*m_customSublayers)[0] = PlatformCALayer::create(tileCacheTileContainerLayer, 0);
238    }
239
240    END_BLOCK_OBJC_EXCEPTIONS
241}
242
243PassRefPtr<PlatformCALayer> PlatformCALayer::clone(PlatformCALayerClient* owner) const
244{
245    LayerType type;
246    switch (layerType()) {
247    case LayerTypeTransformLayer:
248        type = LayerTypeTransformLayer;
249        break;
250    case LayerTypeAVPlayerLayer:
251        type = LayerTypeAVPlayerLayer;
252        break;
253    case LayerTypeLayer:
254    default:
255        type = LayerTypeLayer;
256        break;
257    };
258    RefPtr<PlatformCALayer> newLayer = PlatformCALayer::create(type, owner);
259
260    newLayer->setPosition(position());
261    newLayer->setBounds(bounds());
262    newLayer->setAnchorPoint(anchorPoint());
263    newLayer->setTransform(transform());
264    newLayer->setSublayerTransform(sublayerTransform());
265    newLayer->setContents(contents());
266    newLayer->setMasksToBounds(masksToBounds());
267    newLayer->setDoubleSided(isDoubleSided());
268    newLayer->setOpaque(isOpaque());
269    newLayer->setBackgroundColor(backgroundColor());
270    newLayer->setContentsScale(contentsScale());
271#if ENABLE(CSS_FILTERS)
272    newLayer->copyFiltersFrom(this);
273#endif
274
275    if (type == LayerTypeAVPlayerLayer) {
276        AVPlayerLayer* destinationPlayerLayer = newLayer->playerLayer();
277        AVPlayerLayer* sourcePlayerLayer = playerLayer();
278        dispatch_async(dispatch_get_main_queue(), ^{
279            [destinationPlayerLayer setPlayer:[sourcePlayerLayer player]];
280        });
281    }
282
283    return newLayer;
284}
285
286PlatformCALayer::~PlatformCALayer()
287{
288    [m_layer.get() setValue:nil forKey:platformCALayerPointer];
289
290    // Clear the owner, which also clears it in the delegate to prevent attempts
291    // to use the GraphicsLayerCA after it has been destroyed.
292    setOwner(0);
293
294    // Remove the owner pointer from the delegate in case there is a pending animationStarted event.
295    [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil];
296
297    if (usesTiledBackingLayer())
298        [static_cast<WebTiledBackingLayer *>(m_layer.get()) invalidate];
299}
300
301PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
302{
303    if (!platformLayer)
304        return 0;
305
306    // Pointer to PlatformCALayer is kept in a key of the CALayer
307    PlatformCALayer* platformCALayer = nil;
308    BEGIN_BLOCK_OBJC_EXCEPTIONS
309    platformCALayer = static_cast<PlatformCALayer*>([[static_cast<CALayer*>(platformLayer) valueForKey:platformCALayerPointer] pointerValue]);
310    END_BLOCK_OBJC_EXCEPTIONS
311    return platformCALayer;
312}
313
314PlatformLayer* PlatformCALayer::platformLayer() const
315{
316    return m_layer.get();
317}
318
319void PlatformCALayer::animationStarted(CFTimeInterval beginTime)
320{
321    if (m_owner)
322        m_owner->platformCALayerAnimationStarted(beginTime);
323}
324
325void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect)
326{
327    BEGIN_BLOCK_OBJC_EXCEPTIONS
328    if (dirtyRect)
329        [m_layer.get() setNeedsDisplayInRect:*dirtyRect];
330    else
331        [m_layer.get() setNeedsDisplay];
332    END_BLOCK_OBJC_EXCEPTIONS
333}
334
335void PlatformCALayer::setContentsChanged()
336{
337    BEGIN_BLOCK_OBJC_EXCEPTIONS
338    [m_layer.get() setContentsChanged];
339    END_BLOCK_OBJC_EXCEPTIONS
340}
341
342PlatformCALayer* PlatformCALayer::superlayer() const
343{
344    return platformCALayer([m_layer.get() superlayer]);
345}
346
347void PlatformCALayer::removeFromSuperlayer()
348{
349    BEGIN_BLOCK_OBJC_EXCEPTIONS
350    [m_layer.get() removeFromSuperlayer];
351    END_BLOCK_OBJC_EXCEPTIONS
352}
353
354void PlatformCALayer::setSublayers(const PlatformCALayerList& list)
355{
356    // Short circuiting here not only avoids the allocation of sublayers, but avoids <rdar://problem/7390716> (see below)
357    if (list.size() == 0) {
358        removeAllSublayers();
359        return;
360    }
361
362    BEGIN_BLOCK_OBJC_EXCEPTIONS
363    NSMutableArray* sublayers = [[NSMutableArray alloc] init];
364    for (size_t i = 0; i < list.size(); ++i)
365        [sublayers addObject:list[i]->m_layer.get()];
366
367    [m_layer.get() setSublayers:sublayers];
368    [sublayers release];
369    END_BLOCK_OBJC_EXCEPTIONS
370}
371
372void PlatformCALayer::removeAllSublayers()
373{
374    // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
375    BEGIN_BLOCK_OBJC_EXCEPTIONS
376    if (objc_collectingEnabled())
377        while ([[m_layer.get() sublayers] count])
378            [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
379    else
380        [m_layer.get() setSublayers:nil];
381    END_BLOCK_OBJC_EXCEPTIONS
382}
383
384void PlatformCALayer::appendSublayer(PlatformCALayer* layer)
385{
386    BEGIN_BLOCK_OBJC_EXCEPTIONS
387    ASSERT(m_layer != layer->m_layer);
388    [m_layer.get() addSublayer:layer->m_layer.get()];
389    END_BLOCK_OBJC_EXCEPTIONS
390}
391
392void PlatformCALayer::insertSublayer(PlatformCALayer* layer, size_t index)
393{
394    BEGIN_BLOCK_OBJC_EXCEPTIONS
395    ASSERT(m_layer != layer->m_layer);
396    [m_layer.get() insertSublayer:layer->m_layer.get() atIndex:index];
397    END_BLOCK_OBJC_EXCEPTIONS
398}
399
400void PlatformCALayer::replaceSublayer(PlatformCALayer* reference, PlatformCALayer* layer)
401{
402    BEGIN_BLOCK_OBJC_EXCEPTIONS
403    ASSERT(m_layer != layer->m_layer);
404    [m_layer.get() replaceSublayer:reference->m_layer.get() with:layer->m_layer.get()];
405    END_BLOCK_OBJC_EXCEPTIONS
406}
407
408size_t PlatformCALayer::sublayerCount() const
409{
410    return [[m_layer.get() sublayers] count];
411}
412
413void PlatformCALayer::adoptSublayers(PlatformCALayer* source)
414{
415    // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
416    NSArray* sublayers = [source->m_layer.get() sublayers];
417
418    if (objc_collectingEnabled() && ![sublayers count]) {
419        BEGIN_BLOCK_OBJC_EXCEPTIONS
420        while ([[m_layer.get() sublayers] count])
421            [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
422        END_BLOCK_OBJC_EXCEPTIONS
423        return;
424    }
425
426    BEGIN_BLOCK_OBJC_EXCEPTIONS
427    [m_layer.get() setSublayers:sublayers];
428    END_BLOCK_OBJC_EXCEPTIONS
429}
430
431void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation* animation)
432{
433    // Add the delegate
434    if (!m_delegate) {
435        WebAnimationDelegate* webAnimationDelegate = [[WebAnimationDelegate alloc] init];
436        m_delegate = adoptNS(webAnimationDelegate);
437        [webAnimationDelegate setOwner:this];
438    }
439
440    CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>(animation->platformAnimation());
441    if (![propertyAnimation delegate])
442        [propertyAnimation setDelegate:static_cast<id>(m_delegate.get())];
443
444    BEGIN_BLOCK_OBJC_EXCEPTIONS
445    [m_layer.get() addAnimation:animation->m_animation.get() forKey:key];
446    END_BLOCK_OBJC_EXCEPTIONS
447}
448
449void PlatformCALayer::removeAnimationForKey(const String& key)
450{
451    BEGIN_BLOCK_OBJC_EXCEPTIONS
452    [m_layer.get() removeAnimationForKey:key];
453    END_BLOCK_OBJC_EXCEPTIONS
454}
455
456PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& key)
457{
458    CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>([m_layer.get() animationForKey:key]);
459    if (!propertyAnimation)
460        return 0;
461    return PlatformCAAnimation::create(propertyAnimation);
462}
463
464PlatformCALayer* PlatformCALayer::mask() const
465{
466    return platformCALayer([m_layer.get() mask]);
467}
468
469void PlatformCALayer::setMask(PlatformCALayer* layer)
470{
471    BEGIN_BLOCK_OBJC_EXCEPTIONS
472    [m_layer.get() setMask:layer ? layer->platformLayer() : 0];
473    END_BLOCK_OBJC_EXCEPTIONS
474}
475
476bool PlatformCALayer::isOpaque() const
477{
478    return [m_layer.get() isOpaque];
479}
480
481void PlatformCALayer::setOpaque(bool value)
482{
483    BEGIN_BLOCK_OBJC_EXCEPTIONS
484    [m_layer.get() setOpaque:value];
485    END_BLOCK_OBJC_EXCEPTIONS
486}
487
488FloatRect PlatformCALayer::bounds() const
489{
490    return [m_layer.get() bounds];
491}
492
493void PlatformCALayer::setBounds(const FloatRect& value)
494{
495    BEGIN_BLOCK_OBJC_EXCEPTIONS
496    [m_layer.get() setBounds:value];
497    END_BLOCK_OBJC_EXCEPTIONS
498}
499
500FloatPoint3D PlatformCALayer::position() const
501{
502    CGPoint point = [m_layer.get() position];
503    return FloatPoint3D(point.x, point.y, [m_layer.get() zPosition]);
504}
505
506void PlatformCALayer::setPosition(const FloatPoint3D& value)
507{
508    BEGIN_BLOCK_OBJC_EXCEPTIONS
509    [m_layer.get() setPosition:CGPointMake(value.x(), value.y())];
510    [m_layer.get() setZPosition:value.z()];
511    END_BLOCK_OBJC_EXCEPTIONS
512}
513
514FloatPoint3D PlatformCALayer::anchorPoint() const
515{
516    CGPoint point = [m_layer.get() anchorPoint];
517    float z = 0;
518    z = [m_layer.get() anchorPointZ];
519    return FloatPoint3D(point.x, point.y, z);
520}
521
522void PlatformCALayer::setAnchorPoint(const FloatPoint3D& value)
523{
524    BEGIN_BLOCK_OBJC_EXCEPTIONS
525    [m_layer.get() setAnchorPoint:CGPointMake(value.x(), value.y())];
526    [m_layer.get() setAnchorPointZ:value.z()];
527    END_BLOCK_OBJC_EXCEPTIONS
528}
529
530TransformationMatrix PlatformCALayer::transform() const
531{
532    return [m_layer.get() transform];
533}
534
535void PlatformCALayer::setTransform(const TransformationMatrix& value)
536{
537    BEGIN_BLOCK_OBJC_EXCEPTIONS
538    [m_layer.get() setTransform:value];
539    END_BLOCK_OBJC_EXCEPTIONS
540}
541
542TransformationMatrix PlatformCALayer::sublayerTransform() const
543{
544    return [m_layer.get() sublayerTransform];
545}
546
547void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value)
548{
549    BEGIN_BLOCK_OBJC_EXCEPTIONS
550    [m_layer.get() setSublayerTransform:value];
551    END_BLOCK_OBJC_EXCEPTIONS
552}
553
554TransformationMatrix PlatformCALayer::contentsTransform() const
555{
556    // FIXME: This function can be removed.
557    return TransformationMatrix();
558}
559
560void PlatformCALayer::setContentsTransform(const TransformationMatrix& value)
561{
562    // FIXME: This function can be removed.
563    UNUSED_PARAM(value);
564}
565
566bool PlatformCALayer::isHidden() const
567{
568    return [m_layer.get() isHidden];
569}
570
571void PlatformCALayer::setHidden(bool value)
572{
573    BEGIN_BLOCK_OBJC_EXCEPTIONS
574    [m_layer.get() setHidden:value];
575    END_BLOCK_OBJC_EXCEPTIONS
576}
577
578bool PlatformCALayer::isGeometryFlipped() const
579{
580    return [m_layer.get() isGeometryFlipped];
581}
582
583void PlatformCALayer::setGeometryFlipped(bool value)
584{
585    BEGIN_BLOCK_OBJC_EXCEPTIONS
586    [m_layer.get() setGeometryFlipped:value];
587    END_BLOCK_OBJC_EXCEPTIONS
588}
589
590bool PlatformCALayer::isDoubleSided() const
591{
592    return [m_layer.get() isDoubleSided];
593}
594
595void PlatformCALayer::setDoubleSided(bool value)
596{
597    BEGIN_BLOCK_OBJC_EXCEPTIONS
598    [m_layer.get() setDoubleSided:value];
599    END_BLOCK_OBJC_EXCEPTIONS
600}
601
602bool PlatformCALayer::masksToBounds() const
603{
604    return [m_layer.get() masksToBounds];
605}
606
607void PlatformCALayer::setMasksToBounds(bool value)
608{
609    BEGIN_BLOCK_OBJC_EXCEPTIONS
610    [m_layer.get() setMasksToBounds:value];
611    END_BLOCK_OBJC_EXCEPTIONS
612}
613
614bool PlatformCALayer::acceleratesDrawing() const
615{
616#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
617    return [m_layer.get() acceleratesDrawing];
618#else
619    return false;
620#endif
621}
622
623void PlatformCALayer::setAcceleratesDrawing(bool acceleratesDrawing)
624{
625#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
626    BEGIN_BLOCK_OBJC_EXCEPTIONS
627    [m_layer.get() setAcceleratesDrawing:acceleratesDrawing];
628    END_BLOCK_OBJC_EXCEPTIONS
629#else
630    UNUSED_PARAM(acceleratesDrawing);
631#endif
632}
633
634CFTypeRef PlatformCALayer::contents() const
635{
636    return [m_layer.get() contents];
637}
638
639void PlatformCALayer::setContents(CFTypeRef value)
640{
641    BEGIN_BLOCK_OBJC_EXCEPTIONS
642    [m_layer.get() setContents:static_cast<id>(const_cast<void*>(value))];
643    END_BLOCK_OBJC_EXCEPTIONS
644}
645
646FloatRect PlatformCALayer::contentsRect() const
647{
648    return [m_layer.get() contentsRect];
649}
650
651void PlatformCALayer::setContentsRect(const FloatRect& value)
652{
653    BEGIN_BLOCK_OBJC_EXCEPTIONS
654    [m_layer.get() setContentsRect:value];
655    END_BLOCK_OBJC_EXCEPTIONS
656}
657
658void PlatformCALayer::setMinificationFilter(FilterType value)
659{
660    BEGIN_BLOCK_OBJC_EXCEPTIONS
661    [m_layer.get() setMinificationFilter:toCAFilterType(value)];
662    END_BLOCK_OBJC_EXCEPTIONS
663}
664
665void PlatformCALayer::setMagnificationFilter(FilterType value)
666{
667    BEGIN_BLOCK_OBJC_EXCEPTIONS
668    [m_layer.get() setMagnificationFilter:toCAFilterType(value)];
669    END_BLOCK_OBJC_EXCEPTIONS
670}
671
672Color PlatformCALayer::backgroundColor() const
673{
674    return [m_layer.get() backgroundColor];
675}
676
677void PlatformCALayer::setBackgroundColor(const Color& value)
678{
679    CGFloat components[4];
680    value.getRGBA(components[0], components[1], components[2], components[3]);
681
682    RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
683    RetainPtr<CGColorRef> color = adoptCF(CGColorCreate(colorSpace.get(), components));
684
685    BEGIN_BLOCK_OBJC_EXCEPTIONS
686    [m_layer.get() setBackgroundColor:color.get()];
687    END_BLOCK_OBJC_EXCEPTIONS
688}
689
690float PlatformCALayer::borderWidth() const
691{
692    return [m_layer.get() borderWidth];
693}
694
695void PlatformCALayer::setBorderWidth(float value)
696{
697    BEGIN_BLOCK_OBJC_EXCEPTIONS
698    [m_layer.get() setBorderWidth:value];
699    END_BLOCK_OBJC_EXCEPTIONS
700}
701
702Color PlatformCALayer::borderColor() const
703{
704    return [m_layer.get() borderColor];
705}
706
707void PlatformCALayer::setBorderColor(const Color& value)
708{
709    CGFloat components[4];
710    value.getRGBA(components[0], components[1], components[2], components[3]);
711
712    RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
713    RetainPtr<CGColorRef> color = adoptCF(CGColorCreate(colorSpace.get(), components));
714
715    BEGIN_BLOCK_OBJC_EXCEPTIONS
716    [m_layer.get() setBorderColor:color.get()];
717    END_BLOCK_OBJC_EXCEPTIONS
718}
719
720float PlatformCALayer::opacity() const
721{
722    return [m_layer.get() opacity];
723}
724
725void PlatformCALayer::setOpacity(float value)
726{
727    BEGIN_BLOCK_OBJC_EXCEPTIONS
728    [m_layer.get() setOpacity:value];
729    END_BLOCK_OBJC_EXCEPTIONS
730}
731
732#if ENABLE(CSS_FILTERS)
733void PlatformCALayer::setFilters(const FilterOperations& filters)
734{
735    PlatformCAFilters::setFiltersOnLayer(this, filters);
736}
737
738void PlatformCALayer::copyFiltersFrom(const PlatformCALayer* sourceLayer)
739{
740    BEGIN_BLOCK_OBJC_EXCEPTIONS
741    [m_layer.get() setFilters:[sourceLayer->platformLayer() filters]];
742    END_BLOCK_OBJC_EXCEPTIONS
743}
744
745bool PlatformCALayer::filtersCanBeComposited(const FilterOperations& filters)
746{
747    // Return false if there are no filters to avoid needless work
748    if (!filters.size())
749        return false;
750
751    for (unsigned i = 0; i < filters.size(); ++i) {
752        const FilterOperation* filterOperation = filters.at(i);
753        switch (filterOperation->getOperationType()) {
754        case FilterOperation::REFERENCE:
755#if ENABLE(CSS_SHADERS)
756        case FilterOperation::CUSTOM:
757        case FilterOperation::VALIDATED_CUSTOM:
758#endif
759            return false;
760        case FilterOperation::DROP_SHADOW:
761            // FIXME: For now we can only handle drop-shadow is if it's last in the list
762            if (i < (filters.size() - 1))
763                return false;
764            break;
765        default:
766            break;
767        }
768    }
769
770    return true;
771}
772#endif
773
774String PlatformCALayer::name() const
775{
776    return [m_layer.get() name];
777}
778
779void PlatformCALayer::setName(const String& value)
780{
781    BEGIN_BLOCK_OBJC_EXCEPTIONS
782    [m_layer.get() setName:value];
783    END_BLOCK_OBJC_EXCEPTIONS
784}
785
786FloatRect PlatformCALayer::frame() const
787{
788    return [m_layer.get() frame];
789}
790
791void PlatformCALayer::setFrame(const FloatRect& value)
792{
793    BEGIN_BLOCK_OBJC_EXCEPTIONS
794    [m_layer.get() setFrame:value];
795    END_BLOCK_OBJC_EXCEPTIONS
796}
797
798float PlatformCALayer::speed() const
799{
800    return [m_layer.get() speed];
801}
802
803void PlatformCALayer::setSpeed(float value)
804{
805    BEGIN_BLOCK_OBJC_EXCEPTIONS
806    [m_layer.get() setSpeed:value];
807    END_BLOCK_OBJC_EXCEPTIONS
808}
809
810CFTimeInterval PlatformCALayer::timeOffset() const
811{
812    return [m_layer.get() timeOffset];
813}
814
815void PlatformCALayer::setTimeOffset(CFTimeInterval value)
816{
817    BEGIN_BLOCK_OBJC_EXCEPTIONS
818    [m_layer.get() setTimeOffset:value];
819    END_BLOCK_OBJC_EXCEPTIONS
820}
821
822float PlatformCALayer::contentsScale() const
823{
824#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
825    return [m_layer.get() contentsScale];
826#else
827    return 1;
828#endif
829}
830
831void PlatformCALayer::setContentsScale(float value)
832{
833#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
834    BEGIN_BLOCK_OBJC_EXCEPTIONS
835    [m_layer.get() setContentsScale:value];
836    END_BLOCK_OBJC_EXCEPTIONS
837#else
838    UNUSED_PARAM(value);
839#endif
840}
841
842TiledBacking* PlatformCALayer::tiledBacking()
843{
844    if (!usesTiledBackingLayer())
845        return 0;
846
847    WebTiledBackingLayer *tiledBackingLayer = static_cast<WebTiledBackingLayer *>(m_layer.get());
848    return [tiledBackingLayer tiledBacking];
849}
850
851#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
852void PlatformCALayer::synchronouslyDisplayTilesInRect(const FloatRect& rect)
853{
854    if (m_layerType != LayerTypeWebTiledLayer)
855        return;
856
857    WebTiledLayer *tiledLayer = static_cast<WebTiledLayer*>(m_layer.get());
858
859    BEGIN_BLOCK_OBJC_EXCEPTIONS
860    BOOL oldCanDrawConcurrently = [tiledLayer canDrawConcurrently];
861    [tiledLayer setCanDrawConcurrently:NO];
862    [tiledLayer displayInRect:rect levelOfDetail:0 options:nil];
863    [tiledLayer setCanDrawConcurrently:oldCanDrawConcurrently];
864    END_BLOCK_OBJC_EXCEPTIONS
865}
866#endif
867
868AVPlayerLayer* PlatformCALayer::playerLayer() const
869{
870    ASSERT([m_layer.get() isKindOfClass:getAVPlayerLayerClass()]);
871    return (AVPlayerLayer*)m_layer.get();
872}
873
874#endif // USE(ACCELERATED_COMPOSITING)
875