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 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#import "PlatformCALayerMac.h" 29 30#import "AnimationUtilities.h" 31#import "BlockExceptions.h" 32#import "GraphicsContext.h" 33#import "GraphicsLayerCA.h" 34#import "LengthFunctions.h" 35#import "PlatformCAAnimationMac.h" 36#import "PlatformCAFilters.h" 37#import "PlatformCAFiltersMac.h" 38#import "ScrollbarThemeMac.h" 39#import "SoftLinking.h" 40#import "TiledBacking.h" 41#import "TileController.h" 42#import "WebActionDisablingCALayerDelegate.h" 43#import "WebCoreCALayerExtras.h" 44#import "WebLayer.h" 45#import "WebGLLayer.h" 46#import "WebTiledBackingLayer.h" 47#import <objc/objc-auto.h> 48#import <objc/runtime.h> 49#import <AVFoundation/AVFoundation.h> 50#import <QuartzCore/QuartzCore.h> 51#import <wtf/CurrentTime.h> 52#import <wtf/RetainPtr.h> 53 54#if PLATFORM(IOS) 55#import "WAKWindow.h" 56#import "WKGraphics.h" 57#import "WebCoreThread.h" 58#import "WebTiledLayer.h" 59#import <Foundation/NSGeometry.h> 60#import <QuartzCore/CATiledLayerPrivate.h> 61#else 62#import "ThemeMac.h" 63#endif 64 65 66SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation) 67SOFT_LINK_CLASS(AVFoundation, AVPlayerLayer) 68 69using namespace WebCore; 70 71PassRefPtr<PlatformCALayer> PlatformCALayerMac::create(LayerType layerType, PlatformCALayerClient* owner) 72{ 73 return adoptRef(new PlatformCALayerMac(layerType, owner)); 74} 75 76PassRefPtr<PlatformCALayer> PlatformCALayerMac::create(void* platformLayer, PlatformCALayerClient* owner) 77{ 78 return adoptRef(new PlatformCALayerMac(static_cast<PlatformLayer*>(platformLayer), owner)); 79} 80 81static NSString * const platformCALayerPointer = @"WKPlatformCALayer"; 82PlatformCALayer* 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 95static double mediaTimeToCurrentTime(CFTimeInterval t) 96{ 97 return monotonicallyIncreasingTime() + 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 CFTimeInterval startTime; 118 if (hasExplicitBeginTime(animation)) { 119 // We don't know what time CA used to commit the animation, so just use the current time 120 // (even though this will be slightly off). 121 startTime = mediaTimeToCurrentTime(CACurrentMediaTime()); 122 } else 123 startTime = mediaTimeToCurrentTime([animation beginTime]); 124 125 if (m_owner) { 126 CALayer *layer = m_owner->platformLayer(); 127 128 String animationKey; 129 for (NSString *key in [layer animationKeys]) { 130 if ([layer animationForKey:key] == animation) { 131 animationKey = key; 132 break; 133 } 134 } 135 136 if (!animationKey.isEmpty()) 137 m_owner->animationStarted(animationKey, startTime); 138 } 139} 140 141- (void)setOwner:(PlatformCALayer*)owner 142{ 143 m_owner = owner; 144} 145 146@end 147 148@interface CATiledLayer(GraphicsLayerCAPrivate) 149- (void)displayInRect:(CGRect)r levelOfDetail:(int)lod options:(NSDictionary *)dict; 150- (BOOL)canDrawConcurrently; 151- (void)setCanDrawConcurrently:(BOOL)flag; 152@end 153 154@interface CALayer(Private) 155- (void)setContentsChanged; 156- (void)setAcceleratesDrawing:(BOOL)flag; 157- (BOOL)acceleratesDrawing; 158@end 159 160void PlatformCALayerMac::setOwner(PlatformCALayerClient* owner) 161{ 162 PlatformCALayer::setOwner(owner); 163 164 // Change the delegate's owner if needed 165 if (m_delegate) 166 [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:this]; 167} 168 169static NSString *toCAFilterType(PlatformCALayer::FilterType type) 170{ 171 switch (type) { 172 case PlatformCALayer::Linear: return kCAFilterLinear; 173 case PlatformCALayer::Nearest: return kCAFilterNearest; 174 case PlatformCALayer::Trilinear: return kCAFilterTrilinear; 175 default: return 0; 176 } 177} 178 179PlatformCALayer::LayerType PlatformCALayerMac::layerTypeForPlatformLayer(PlatformLayer* layer) 180{ 181 if ([layer isKindOfClass:getAVPlayerLayerClass()] || [layer isKindOfClass:objc_getClass("WebVideoContainerLayer")]) 182 return LayerTypeAVPlayerLayer; 183 184 if ([layer isKindOfClass:[WebGLLayer class]]) 185 return LayerTypeWebGLLayer; 186 187 return LayerTypeCustom; 188} 189 190PlatformCALayerMac::PlatformCALayerMac(LayerType layerType, PlatformCALayerClient* owner) 191 : PlatformCALayer(layerType, owner) 192 , m_customAppearance(GraphicsLayer::NoCustomAppearance) 193 , m_customBehavior(GraphicsLayer::NoCustomBehavior) 194{ 195 Class layerClass = Nil; 196 switch (layerType) { 197 case LayerTypeLayer: 198 case LayerTypeRootLayer: 199 layerClass = [CALayer class]; 200 break; 201 case LayerTypeWebLayer: 202 layerClass = [WebLayer class]; 203 break; 204 case LayerTypeSimpleLayer: 205 case LayerTypeTiledBackingTileLayer: 206 layerClass = [WebSimpleLayer class]; 207 break; 208 case LayerTypeTransformLayer: 209 layerClass = [CATransformLayer class]; 210 break; 211 case LayerTypeWebTiledLayer: 212 ASSERT_NOT_REACHED(); 213 break; 214 case LayerTypeTiledBackingLayer: 215 case LayerTypePageTiledBackingLayer: 216 layerClass = [WebTiledBackingLayer class]; 217 break; 218 case LayerTypeAVPlayerLayer: 219 layerClass = getAVPlayerLayerClass(); 220 break; 221 case LayerTypeWebGLLayer: 222 // We don't create PlatformCALayerMacs wrapped around WebGLLayers. 223 ASSERT_NOT_REACHED(); 224 break; 225 case LayerTypeCustom: 226 break; 227 } 228 229 if (layerClass) 230 m_layer = adoptNS([[layerClass alloc] init]); 231 232 commonInit(); 233} 234 235PlatformCALayerMac::PlatformCALayerMac(PlatformLayer* layer, PlatformCALayerClient* owner) 236 : PlatformCALayer(layerTypeForPlatformLayer(layer), owner) 237 , m_customAppearance(GraphicsLayer::NoCustomAppearance) 238 , m_customBehavior(GraphicsLayer::NoCustomBehavior) 239{ 240 m_layer = layer; 241 commonInit(); 242} 243 244void PlatformCALayerMac::commonInit() 245{ 246 BEGIN_BLOCK_OBJC_EXCEPTIONS 247 // Save a pointer to 'this' in the CALayer 248 [m_layer setValue:[NSValue valueWithPointer:this] forKey:platformCALayerPointer]; 249 250 // Clear all the implicit animations on the CALayer 251 if (m_layerType == LayerTypeAVPlayerLayer || m_layerType == LayerTypeWebGLLayer || m_layerType == LayerTypeCustom) 252 [m_layer web_disableAllActions]; 253 else 254 [m_layer setDelegate:[WebActionDisablingCALayerDelegate shared]]; 255 256 // So that the scrolling thread's performance logging code can find all the tiles, mark this as being a tile. 257 if (m_layerType == LayerTypeTiledBackingTileLayer) 258 [m_layer setValue:@YES forKey:@"isTile"]; 259 260 if (usesTiledBackingLayer()) { 261 WebTiledBackingLayer* tiledBackingLayer = static_cast<WebTiledBackingLayer*>(m_layer.get()); 262 TileController* tileController = [tiledBackingLayer createTileController:this]; 263 264 m_customSublayers = std::make_unique<PlatformCALayerList>(tileController->containerLayers()); 265 } 266 267 END_BLOCK_OBJC_EXCEPTIONS 268} 269 270PassRefPtr<PlatformCALayer> PlatformCALayerMac::clone(PlatformCALayerClient* owner) const 271{ 272 LayerType type; 273 switch (layerType()) { 274 case LayerTypeTransformLayer: 275 type = LayerTypeTransformLayer; 276 break; 277 case LayerTypeAVPlayerLayer: 278 type = LayerTypeAVPlayerLayer; 279 break; 280 case LayerTypeLayer: 281 default: 282 type = LayerTypeLayer; 283 break; 284 }; 285 RefPtr<PlatformCALayer> newLayer = PlatformCALayerMac::create(type, owner); 286 287 newLayer->setPosition(position()); 288 newLayer->setBounds(bounds()); 289 newLayer->setAnchorPoint(anchorPoint()); 290 newLayer->setTransform(transform()); 291 newLayer->setSublayerTransform(sublayerTransform()); 292 newLayer->setContents(contents()); 293 newLayer->setMasksToBounds(masksToBounds()); 294 newLayer->setDoubleSided(isDoubleSided()); 295 newLayer->setOpaque(isOpaque()); 296 newLayer->setBackgroundColor(backgroundColor()); 297 newLayer->setContentsScale(contentsScale()); 298#if ENABLE(CSS_FILTERS) 299 newLayer->copyFiltersFrom(this); 300#endif 301 newLayer->updateCustomAppearance(customAppearance()); 302 303 if (type == LayerTypeAVPlayerLayer) { 304 ASSERT([newLayer->platformLayer() isKindOfClass:getAVPlayerLayerClass()]); 305 ASSERT([platformLayer() isKindOfClass:getAVPlayerLayerClass()]); 306 307 AVPlayerLayer* destinationPlayerLayer = static_cast<AVPlayerLayer *>(newLayer->platformLayer()); 308 AVPlayerLayer* sourcePlayerLayer = static_cast<AVPlayerLayer *>(platformLayer()); 309 dispatch_async(dispatch_get_main_queue(), ^{ 310 [destinationPlayerLayer setPlayer:[sourcePlayerLayer player]]; 311 }); 312 } 313 314 return newLayer; 315} 316 317PlatformCALayerMac::~PlatformCALayerMac() 318{ 319 [m_layer.get() setValue:nil forKey:platformCALayerPointer]; 320 321 // Remove the owner pointer from the delegate in case there is a pending animationStarted event. 322 [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil]; 323 324 if (usesTiledBackingLayer()) 325 [static_cast<WebTiledBackingLayer *>(m_layer.get()) invalidate]; 326} 327 328void PlatformCALayerMac::animationStarted(const String&, CFTimeInterval beginTime) 329{ 330 if (m_owner) 331 m_owner->platformCALayerAnimationStarted(beginTime); 332} 333 334void PlatformCALayerMac::setNeedsDisplay(const FloatRect* dirtyRect) 335{ 336 BEGIN_BLOCK_OBJC_EXCEPTIONS 337 if (dirtyRect) 338 [m_layer.get() setNeedsDisplayInRect:*dirtyRect]; 339 else 340 [m_layer.get() setNeedsDisplay]; 341 END_BLOCK_OBJC_EXCEPTIONS 342} 343 344void PlatformCALayerMac::copyContentsFromLayer(PlatformCALayer* layer) 345{ 346 BEGIN_BLOCK_OBJC_EXCEPTIONS 347 CALayer* caLayer = layer->m_layer.get(); 348 if ([m_layer contents] != [caLayer contents]) 349 [m_layer setContents:[caLayer contents]]; 350 else 351 [m_layer setContentsChanged]; 352 END_BLOCK_OBJC_EXCEPTIONS 353} 354 355PlatformCALayer* PlatformCALayerMac::superlayer() const 356{ 357 return platformCALayer([m_layer superlayer]); 358} 359 360void PlatformCALayerMac::removeFromSuperlayer() 361{ 362 BEGIN_BLOCK_OBJC_EXCEPTIONS 363 [m_layer.get() removeFromSuperlayer]; 364 END_BLOCK_OBJC_EXCEPTIONS 365} 366 367void PlatformCALayerMac::setSublayers(const PlatformCALayerList& list) 368{ 369 // Short circuiting here avoids the allocation of the array below. 370 if (list.size() == 0) { 371 removeAllSublayers(); 372 return; 373 } 374 375 BEGIN_BLOCK_OBJC_EXCEPTIONS 376 NSMutableArray* sublayers = [[NSMutableArray alloc] init]; 377 for (size_t i = 0; i < list.size(); ++i) 378 [sublayers addObject:list[i]->m_layer.get()]; 379 380 [m_layer.get() setSublayers:sublayers]; 381 [sublayers release]; 382 END_BLOCK_OBJC_EXCEPTIONS 383} 384 385void PlatformCALayerMac::removeAllSublayers() 386{ 387 BEGIN_BLOCK_OBJC_EXCEPTIONS 388 [m_layer.get() setSublayers:nil]; 389 END_BLOCK_OBJC_EXCEPTIONS 390} 391 392void PlatformCALayerMac::appendSublayer(PlatformCALayer* layer) 393{ 394 BEGIN_BLOCK_OBJC_EXCEPTIONS 395 ASSERT(m_layer != layer->m_layer); 396 [m_layer.get() addSublayer:layer->m_layer.get()]; 397 END_BLOCK_OBJC_EXCEPTIONS 398} 399 400void PlatformCALayerMac::insertSublayer(PlatformCALayer* layer, size_t index) 401{ 402 BEGIN_BLOCK_OBJC_EXCEPTIONS 403 ASSERT(m_layer != layer->m_layer); 404 [m_layer.get() insertSublayer:layer->m_layer.get() atIndex:index]; 405 END_BLOCK_OBJC_EXCEPTIONS 406} 407 408void PlatformCALayerMac::replaceSublayer(PlatformCALayer* reference, PlatformCALayer* layer) 409{ 410 BEGIN_BLOCK_OBJC_EXCEPTIONS 411 ASSERT(m_layer != layer->m_layer); 412 [m_layer.get() replaceSublayer:reference->m_layer.get() with:layer->m_layer.get()]; 413 END_BLOCK_OBJC_EXCEPTIONS 414} 415 416void PlatformCALayerMac::adoptSublayers(PlatformCALayer* source) 417{ 418 BEGIN_BLOCK_OBJC_EXCEPTIONS 419 [m_layer.get() setSublayers:[source->m_layer.get() sublayers]]; 420 END_BLOCK_OBJC_EXCEPTIONS 421} 422 423void PlatformCALayerMac::addAnimationForKey(const String& key, PlatformCAAnimation* animation) 424{ 425 // Add the delegate 426 if (!m_delegate) { 427 WebAnimationDelegate* webAnimationDelegate = [[WebAnimationDelegate alloc] init]; 428 m_delegate = adoptNS(webAnimationDelegate); 429 [webAnimationDelegate setOwner:this]; 430 } 431 432 CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>(toPlatformCAAnimationMac(animation)->platformAnimation()); 433 if (![propertyAnimation delegate]) 434 [propertyAnimation setDelegate:static_cast<id>(m_delegate.get())]; 435 436 BEGIN_BLOCK_OBJC_EXCEPTIONS 437 [m_layer.get() addAnimation:propertyAnimation forKey:key]; 438 END_BLOCK_OBJC_EXCEPTIONS 439} 440 441void PlatformCALayerMac::removeAnimationForKey(const String& key) 442{ 443 BEGIN_BLOCK_OBJC_EXCEPTIONS 444 [m_layer.get() removeAnimationForKey:key]; 445 END_BLOCK_OBJC_EXCEPTIONS 446} 447 448PassRefPtr<PlatformCAAnimation> PlatformCALayerMac::animationForKey(const String& key) 449{ 450 CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>([m_layer.get() animationForKey:key]); 451 if (!propertyAnimation) 452 return 0; 453 return PlatformCAAnimationMac::create(propertyAnimation); 454} 455 456void PlatformCALayerMac::setMask(PlatformCALayer* layer) 457{ 458 BEGIN_BLOCK_OBJC_EXCEPTIONS 459 [m_layer.get() setMask:layer ? layer->platformLayer() : 0]; 460 END_BLOCK_OBJC_EXCEPTIONS 461} 462 463bool PlatformCALayerMac::isOpaque() const 464{ 465 return [m_layer.get() isOpaque]; 466} 467 468void PlatformCALayerMac::setOpaque(bool value) 469{ 470 BEGIN_BLOCK_OBJC_EXCEPTIONS 471 [m_layer.get() setOpaque:value]; 472 END_BLOCK_OBJC_EXCEPTIONS 473} 474 475FloatRect PlatformCALayerMac::bounds() const 476{ 477 return [m_layer.get() bounds]; 478} 479 480void PlatformCALayerMac::setBounds(const FloatRect& value) 481{ 482 BEGIN_BLOCK_OBJC_EXCEPTIONS 483 [m_layer.get() setBounds:value]; 484 485 if (requiresCustomAppearanceUpdateOnBoundsChange()) 486 updateCustomAppearance(m_customAppearance); 487 488 END_BLOCK_OBJC_EXCEPTIONS 489} 490 491FloatPoint3D PlatformCALayerMac::position() const 492{ 493 CGPoint point = [m_layer.get() position]; 494 return FloatPoint3D(point.x, point.y, [m_layer.get() zPosition]); 495} 496 497void PlatformCALayerMac::setPosition(const FloatPoint3D& value) 498{ 499 BEGIN_BLOCK_OBJC_EXCEPTIONS 500 [m_layer.get() setPosition:CGPointMake(value.x(), value.y())]; 501 [m_layer.get() setZPosition:value.z()]; 502 END_BLOCK_OBJC_EXCEPTIONS 503} 504 505FloatPoint3D PlatformCALayerMac::anchorPoint() const 506{ 507 CGPoint point = [m_layer.get() anchorPoint]; 508 float z = 0; 509 z = [m_layer.get() anchorPointZ]; 510 return FloatPoint3D(point.x, point.y, z); 511} 512 513void PlatformCALayerMac::setAnchorPoint(const FloatPoint3D& value) 514{ 515 BEGIN_BLOCK_OBJC_EXCEPTIONS 516 [m_layer.get() setAnchorPoint:CGPointMake(value.x(), value.y())]; 517 [m_layer.get() setAnchorPointZ:value.z()]; 518 END_BLOCK_OBJC_EXCEPTIONS 519} 520 521TransformationMatrix PlatformCALayerMac::transform() const 522{ 523 return [m_layer.get() transform]; 524} 525 526void PlatformCALayerMac::setTransform(const TransformationMatrix& value) 527{ 528 BEGIN_BLOCK_OBJC_EXCEPTIONS 529 [m_layer.get() setTransform:value]; 530 END_BLOCK_OBJC_EXCEPTIONS 531} 532 533TransformationMatrix PlatformCALayerMac::sublayerTransform() const 534{ 535 return [m_layer.get() sublayerTransform]; 536} 537 538void PlatformCALayerMac::setSublayerTransform(const TransformationMatrix& value) 539{ 540 BEGIN_BLOCK_OBJC_EXCEPTIONS 541 [m_layer.get() setSublayerTransform:value]; 542 END_BLOCK_OBJC_EXCEPTIONS 543} 544 545void PlatformCALayerMac::setHidden(bool value) 546{ 547 BEGIN_BLOCK_OBJC_EXCEPTIONS 548 [m_layer.get() setHidden:value]; 549 END_BLOCK_OBJC_EXCEPTIONS 550} 551 552void PlatformCALayerMac::setGeometryFlipped(bool value) 553{ 554 BEGIN_BLOCK_OBJC_EXCEPTIONS 555 [m_layer.get() setGeometryFlipped:value]; 556 END_BLOCK_OBJC_EXCEPTIONS 557} 558 559bool PlatformCALayerMac::isDoubleSided() const 560{ 561 return [m_layer.get() isDoubleSided]; 562} 563 564void PlatformCALayerMac::setDoubleSided(bool value) 565{ 566 BEGIN_BLOCK_OBJC_EXCEPTIONS 567 [m_layer.get() setDoubleSided:value]; 568 END_BLOCK_OBJC_EXCEPTIONS 569} 570 571bool PlatformCALayerMac::masksToBounds() const 572{ 573 return [m_layer.get() masksToBounds]; 574} 575 576void PlatformCALayerMac::setMasksToBounds(bool value) 577{ 578 BEGIN_BLOCK_OBJC_EXCEPTIONS 579 [m_layer.get() setMasksToBounds:value]; 580 END_BLOCK_OBJC_EXCEPTIONS 581} 582 583bool PlatformCALayerMac::acceleratesDrawing() const 584{ 585 return [m_layer.get() acceleratesDrawing]; 586} 587 588void PlatformCALayerMac::setAcceleratesDrawing(bool acceleratesDrawing) 589{ 590 BEGIN_BLOCK_OBJC_EXCEPTIONS 591 [m_layer.get() setAcceleratesDrawing:acceleratesDrawing]; 592 END_BLOCK_OBJC_EXCEPTIONS 593} 594 595CFTypeRef PlatformCALayerMac::contents() const 596{ 597 return [m_layer.get() contents]; 598} 599 600void PlatformCALayerMac::setContents(CFTypeRef value) 601{ 602 BEGIN_BLOCK_OBJC_EXCEPTIONS 603 [m_layer.get() setContents:static_cast<id>(const_cast<void*>(value))]; 604 END_BLOCK_OBJC_EXCEPTIONS 605} 606 607void PlatformCALayerMac::setContentsRect(const FloatRect& value) 608{ 609 BEGIN_BLOCK_OBJC_EXCEPTIONS 610 [m_layer.get() setContentsRect:value]; 611 END_BLOCK_OBJC_EXCEPTIONS 612} 613 614void PlatformCALayerMac::setMinificationFilter(FilterType value) 615{ 616 BEGIN_BLOCK_OBJC_EXCEPTIONS 617 [m_layer.get() setMinificationFilter:toCAFilterType(value)]; 618 END_BLOCK_OBJC_EXCEPTIONS 619} 620 621void PlatformCALayerMac::setMagnificationFilter(FilterType value) 622{ 623 BEGIN_BLOCK_OBJC_EXCEPTIONS 624 [m_layer.get() setMagnificationFilter:toCAFilterType(value)]; 625 END_BLOCK_OBJC_EXCEPTIONS 626} 627 628Color PlatformCALayerMac::backgroundColor() const 629{ 630 return [m_layer.get() backgroundColor]; 631} 632 633void PlatformCALayerMac::setBackgroundColor(const Color& value) 634{ 635 CGFloat components[4]; 636 value.getRGBA(components[0], components[1], components[2], components[3]); 637 638 RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB()); 639 RetainPtr<CGColorRef> color = adoptCF(CGColorCreate(colorSpace.get(), components)); 640 641 BEGIN_BLOCK_OBJC_EXCEPTIONS 642 [m_layer.get() setBackgroundColor:color.get()]; 643 END_BLOCK_OBJC_EXCEPTIONS 644} 645 646void PlatformCALayerMac::setBorderWidth(float value) 647{ 648 BEGIN_BLOCK_OBJC_EXCEPTIONS 649 [m_layer.get() setBorderWidth:value]; 650 END_BLOCK_OBJC_EXCEPTIONS 651} 652 653void PlatformCALayerMac::setBorderColor(const Color& value) 654{ 655 CGFloat components[4]; 656 value.getRGBA(components[0], components[1], components[2], components[3]); 657 658 RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB()); 659 RetainPtr<CGColorRef> color = adoptCF(CGColorCreate(colorSpace.get(), components)); 660 661 BEGIN_BLOCK_OBJC_EXCEPTIONS 662 [m_layer.get() setBorderColor:color.get()]; 663 END_BLOCK_OBJC_EXCEPTIONS 664} 665 666float PlatformCALayerMac::opacity() const 667{ 668 return [m_layer.get() opacity]; 669} 670 671void PlatformCALayerMac::setOpacity(float value) 672{ 673 BEGIN_BLOCK_OBJC_EXCEPTIONS 674 [m_layer.get() setOpacity:value]; 675 END_BLOCK_OBJC_EXCEPTIONS 676} 677 678#if ENABLE(CSS_FILTERS) 679void PlatformCALayerMac::setFilters(const FilterOperations& filters) 680{ 681 PlatformCAFilters::setFiltersOnLayer(platformLayer(), filters); 682} 683 684void PlatformCALayerMac::copyFiltersFrom(const PlatformCALayer* sourceLayer) 685{ 686 BEGIN_BLOCK_OBJC_EXCEPTIONS 687 [m_layer.get() setFilters:[sourceLayer->platformLayer() filters]]; 688 END_BLOCK_OBJC_EXCEPTIONS 689} 690 691bool PlatformCALayerMac::filtersCanBeComposited(const FilterOperations& filters) 692{ 693 // Return false if there are no filters to avoid needless work 694 if (!filters.size()) 695 return false; 696 697 for (unsigned i = 0; i < filters.size(); ++i) { 698 const FilterOperation* filterOperation = filters.at(i); 699 switch (filterOperation->type()) { 700 case FilterOperation::REFERENCE: 701 return false; 702 case FilterOperation::DROP_SHADOW: 703 // FIXME: For now we can only handle drop-shadow is if it's last in the list 704 if (i < (filters.size() - 1)) 705 return false; 706 break; 707 default: 708 break; 709 } 710 } 711 712 return true; 713} 714#endif 715 716#if ENABLE(CSS_COMPOSITING) 717void PlatformCALayerMac::setBlendMode(BlendMode blendMode) 718{ 719 PlatformCAFilters::setBlendingFiltersOnLayer(platformLayer(), blendMode); 720} 721#endif 722 723void PlatformCALayerMac::setName(const String& value) 724{ 725 BEGIN_BLOCK_OBJC_EXCEPTIONS 726 [m_layer.get() setName:value]; 727 END_BLOCK_OBJC_EXCEPTIONS 728} 729 730void PlatformCALayerMac::setSpeed(float value) 731{ 732 BEGIN_BLOCK_OBJC_EXCEPTIONS 733 [m_layer.get() setSpeed:value]; 734 END_BLOCK_OBJC_EXCEPTIONS 735} 736 737void PlatformCALayerMac::setTimeOffset(CFTimeInterval value) 738{ 739 BEGIN_BLOCK_OBJC_EXCEPTIONS 740 [m_layer.get() setTimeOffset:value]; 741 END_BLOCK_OBJC_EXCEPTIONS 742} 743 744float PlatformCALayerMac::contentsScale() const 745{ 746 return [m_layer.get() contentsScale]; 747} 748 749void PlatformCALayerMac::setContentsScale(float value) 750{ 751 BEGIN_BLOCK_OBJC_EXCEPTIONS 752 [m_layer.get() setContentsScale:value]; 753#if PLATFORM(IOS) 754 [m_layer.get() setRasterizationScale:value]; 755 756 if (m_layerType == LayerTypeWebTiledLayer) { 757 // This will invalidate all the tiles so we won't end up with stale tiles with the wrong scale in the wrong place, 758 // see <rdar://problem/9434765> for more information. 759 static NSDictionary *optionsDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], kCATiledLayerRemoveImmediately, nil]; 760 [(CATiledLayer *)m_layer.get() setNeedsDisplayInRect:[m_layer.get() bounds] levelOfDetail:0 options:optionsDictionary]; 761 } 762#endif 763 END_BLOCK_OBJC_EXCEPTIONS 764} 765 766void PlatformCALayerMac::setEdgeAntialiasingMask(unsigned mask) 767{ 768 BEGIN_BLOCK_OBJC_EXCEPTIONS 769 [m_layer.get() setEdgeAntialiasingMask:mask]; 770 END_BLOCK_OBJC_EXCEPTIONS 771} 772 773bool PlatformCALayerMac::requiresCustomAppearanceUpdateOnBoundsChange() const 774{ 775 return m_customAppearance == GraphicsLayer::ScrollingShadow; 776} 777 778void PlatformCALayerMac::updateCustomAppearance(GraphicsLayer::CustomAppearance appearance) 779{ 780 m_customAppearance = appearance; 781 782#if ENABLE(RUBBER_BANDING) 783 switch (appearance) { 784 case GraphicsLayer::NoCustomAppearance: 785 ScrollbarThemeMac::removeOverhangAreaBackground(platformLayer()); 786 ScrollbarThemeMac::removeOverhangAreaShadow(platformLayer()); 787 break; 788 case GraphicsLayer::ScrollingOverhang: 789 ScrollbarThemeMac::setUpOverhangAreaBackground(platformLayer()); 790 break; 791 case GraphicsLayer::ScrollingShadow: 792 ScrollbarThemeMac::setUpOverhangAreaShadow(platformLayer()); 793 break; 794 } 795#endif 796} 797 798void PlatformCALayerMac::updateCustomBehavior(GraphicsLayer::CustomBehavior customBehavior) 799{ 800 m_customBehavior = customBehavior; 801 802 // Custom layers can get wrapped in UIViews (which clobbers the layer delegate), 803 // so fall back to the slower way of disabling implicit animations. 804 if (m_customBehavior != GraphicsLayer::NoCustomBehavior) { 805 if ([[m_layer delegate] isKindOfClass:[WebActionDisablingCALayerDelegate class]]) 806 [m_layer setDelegate:nil]; 807 [m_layer web_disableAllActions]; 808 } 809} 810 811TiledBacking* PlatformCALayerMac::tiledBacking() 812{ 813 if (!usesTiledBackingLayer()) 814 return 0; 815 816 WebTiledBackingLayer *tiledBackingLayer = static_cast<WebTiledBackingLayer *>(m_layer.get()); 817 return [tiledBackingLayer tiledBacking]; 818} 819 820#if PLATFORM(IOS) 821bool PlatformCALayer::isWebLayer() 822{ 823 BOOL result = NO; 824 BEGIN_BLOCK_OBJC_EXCEPTIONS 825 result = [m_layer.get() isKindOfClass:[WebLayer self]]; 826 END_BLOCK_OBJC_EXCEPTIONS 827 return result; 828} 829 830void PlatformCALayer::setBoundsOnMainThread(CGRect bounds) 831{ 832 CALayer *layer = m_layer.get(); 833 dispatch_async(dispatch_get_main_queue(), ^{ 834 BEGIN_BLOCK_OBJC_EXCEPTIONS 835 [layer setBounds:bounds]; 836 END_BLOCK_OBJC_EXCEPTIONS 837 }); 838} 839 840void PlatformCALayer::setPositionOnMainThread(CGPoint position) 841{ 842 CALayer *layer = m_layer.get(); 843 dispatch_async(dispatch_get_main_queue(), ^{ 844 BEGIN_BLOCK_OBJC_EXCEPTIONS 845 [layer setPosition:position]; 846 END_BLOCK_OBJC_EXCEPTIONS 847 }); 848} 849 850void PlatformCALayer::setAnchorPointOnMainThread(FloatPoint3D value) 851{ 852 CALayer *layer = m_layer.get(); 853 dispatch_async(dispatch_get_main_queue(), ^{ 854 BEGIN_BLOCK_OBJC_EXCEPTIONS 855 [layer setAnchorPoint:CGPointMake(value.x(), value.y())]; 856 [layer setAnchorPointZ:value.z()]; 857 END_BLOCK_OBJC_EXCEPTIONS 858 }); 859} 860 861void PlatformCALayer::setTileSize(const IntSize& tileSize) 862{ 863 if (m_layerType != LayerTypeWebTiledLayer) 864 return; 865 866 BEGIN_BLOCK_OBJC_EXCEPTIONS 867 [static_cast<WebTiledLayer*>(m_layer.get()) setTileSize:tileSize]; 868 END_BLOCK_OBJC_EXCEPTIONS 869} 870#endif // PLATFORM(IOS) 871 872PlatformCALayer::RepaintRectList PlatformCALayer::collectRectsToPaint(CGContextRef context, PlatformCALayer* platformCALayer) 873{ 874 __block double totalRectArea = 0; 875 __block unsigned rectCount = 0; 876 __block RepaintRectList dirtyRects; 877 878 platformCALayer->enumerateRectsBeingDrawn(context, ^(CGRect rect) { 879 if (++rectCount > webLayerMaxRectsToPaint) 880 return; 881 882 totalRectArea += rect.size.width * rect.size.height; 883 dirtyRects.append(rect); 884 }); 885 886 FloatRect clipBounds = CGContextGetClipBoundingBox(context); 887 double clipArea = clipBounds.width() * clipBounds.height(); 888 889 if (rectCount >= webLayerMaxRectsToPaint || totalRectArea >= clipArea * webLayerWastedSpaceThreshold) { 890 dirtyRects.clear(); 891 dirtyRects.append(clipBounds); 892 } 893 894 return dirtyRects; 895} 896 897void PlatformCALayer::drawLayerContents(CGContextRef context, WebCore::PlatformCALayer* platformCALayer, RepaintRectList& dirtyRects) 898{ 899 WebCore::PlatformCALayerClient* layerContents = platformCALayer->owner(); 900 if (!layerContents) 901 return; 902 903#if PLATFORM(IOS) 904 WKSetCurrentGraphicsContext(context); 905#endif 906 907 CGContextSaveGState(context); 908 909 // We never use CompositingCoordinatesBottomUp on Mac. 910 ASSERT(layerContents->platformCALayerContentsOrientation() == GraphicsLayer::CompositingCoordinatesTopDown); 911 912#if PLATFORM(IOS) 913 WKFontAntialiasingStateSaver fontAntialiasingState(context, [platformCALayer->platformLayer() isOpaque]); 914 fontAntialiasingState.setup([WAKWindow hasLandscapeOrientation]); 915#else 916 [NSGraphicsContext saveGraphicsState]; 917 918 // Set up an NSGraphicsContext for the context, so that parts of AppKit that rely on 919 // the current NSGraphicsContext (e.g. NSCell drawing) get the right one. 920 NSGraphicsContext* layerContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:YES]; 921 [NSGraphicsContext setCurrentContext:layerContext]; 922#endif 923 924 GraphicsContext graphicsContext(context); 925 graphicsContext.setIsCALayerContext(true); 926 graphicsContext.setIsAcceleratedContext(platformCALayer->acceleratesDrawing()); 927 928 if (!layerContents->platformCALayerContentsOpaque()) { 929 // Turn off font smoothing to improve the appearance of text rendered onto a transparent background. 930 graphicsContext.setShouldSmoothFonts(false); 931 } 932 933#if !PLATFORM(IOS) 934 // It's important to get the clip from the context, because it may be significantly 935 // smaller than the layer bounds (e.g. tiled layers) 936 FloatRect clipBounds = CGContextGetClipBoundingBox(context); 937 938 FloatRect focusRingClipRect = clipBounds; 939#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1090 940 // Set the focus ring clip rect which needs to be in base coordinates. 941 AffineTransform transform = CGContextGetCTM(context); 942 focusRingClipRect = transform.mapRect(clipBounds); 943#endif 944 ThemeMac::setFocusRingClipRect(focusRingClipRect); 945#endif // !PLATFORM(IOS) 946 947 for (const auto& rect : dirtyRects) { 948 GraphicsContextStateSaver stateSaver(graphicsContext); 949 graphicsContext.clip(rect); 950 951 layerContents->platformCALayerPaintContents(platformCALayer, graphicsContext, rect); 952 } 953 954#if PLATFORM(IOS) 955 fontAntialiasingState.restore(); 956#else 957 ThemeMac::setFocusRingClipRect(FloatRect()); 958 959 [NSGraphicsContext restoreGraphicsState]; 960#endif 961 962 // Re-fetch the layer owner, since <rdar://problem/9125151> indicates that it might have been destroyed during painting. 963 layerContents = platformCALayer->owner(); 964 ASSERT(layerContents); 965 966 CGContextRestoreGState(context); 967 968 // Always update the repaint count so that it's accurate even if the count itself is not shown. This will be useful 969 // for the Web Inspector feeding this information through the LayerTreeAgent. 970 int repaintCount = layerContents->platformCALayerIncrementRepaintCount(platformCALayer); 971 972 if (!platformCALayer->usesTiledBackingLayer() && layerContents && layerContents->platformCALayerShowRepaintCounter(platformCALayer)) 973 drawRepaintIndicator(context, platformCALayer, repaintCount, nullptr); 974} 975 976CGRect PlatformCALayer::frameForLayer(const PlatformLayer* tileLayer) 977{ 978 return [tileLayer frame]; 979} 980 981PassRefPtr<PlatformCALayer> PlatformCALayerMac::createCompatibleLayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* client) const 982{ 983 return PlatformCALayerMac::create(layerType, client); 984} 985 986void PlatformCALayerMac::enumerateRectsBeingDrawn(CGContextRef context, void (^block)(CGRect)) 987{ 988 wkCALayerEnumerateRectsBeingDrawnWithBlock(m_layer.get(), context, block); 989} 990