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