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 #include "GraphicsLayerCA.h" 31 32 #include "Animation.h" 33 #include "FloatConversion.h" 34 #include "FloatRect.h" 35 #include "PlatformCALayer.h" 36 #include "PlatformString.h" 37 #include "RotateTransformOperation.h" 38 #include "ScaleTransformOperation.h" 39 #include "SystemTime.h" 40 #include "TranslateTransformOperation.h" 41 #include <QuartzCore/CATransform3D.h> 42 #include <limits.h> 43 #include <wtf/CurrentTime.h> 44 #include <wtf/text/StringConcatenate.h> 45 46 using namespace std; 47 48 #define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)) 49 50 namespace WebCore { 51 52 // The threshold width or height above which a tiled layer will be used. This should be 53 // large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL 54 // texture size limit on all supported hardware. 55 static const int cMaxPixelDimension = 2000; 56 57 // If we send a duration of 0 to CA, then it will use the default duration 58 // of 250ms. So send a very small value instead. 59 static const float cAnimationAlmostZeroDuration = 1e-3f; 60 61 // CACurrentMediaTime() is a time since boot. These methods convert between that and 62 // WebCore time, which is system time (UTC). 63 static CFTimeInterval currentTimeToMediaTime(double t) 64 { 65 return CACurrentMediaTime() + t - WTF::currentTime(); 66 } 67 68 static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType) 69 { 70 switch (transformType) { 71 case TransformOperation::SKEW_X: 72 case TransformOperation::SKEW_Y: 73 case TransformOperation::SKEW: 74 case TransformOperation::MATRIX: 75 case TransformOperation::ROTATE_3D: 76 case TransformOperation::MATRIX_3D: 77 case TransformOperation::PERSPECTIVE: 78 case TransformOperation::IDENTITY: 79 case TransformOperation::NONE: 80 return true; 81 default: 82 return false; 83 } 84 } 85 86 static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType) 87 { 88 switch (transformType) { 89 case TransformOperation::SCALE: 90 case TransformOperation::SCALE_3D: 91 case TransformOperation::TRANSLATE: 92 case TransformOperation::TRANSLATE_3D: 93 return true; 94 default: 95 return false; 96 } 97 } 98 99 static bool isTransformTypeNumber(TransformOperation::OperationType transformType) 100 { 101 return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType); 102 } 103 104 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, float& value) 105 { 106 switch (transformType) { 107 case TransformOperation::ROTATE: 108 case TransformOperation::ROTATE_X: 109 case TransformOperation::ROTATE_Y: 110 value = transformOp ? narrowPrecisionToFloat(deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle())) : 0; 111 break; 112 case TransformOperation::SCALE_X: 113 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1; 114 break; 115 case TransformOperation::SCALE_Y: 116 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1; 117 break; 118 case TransformOperation::SCALE_Z: 119 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1; 120 break; 121 case TransformOperation::TRANSLATE_X: 122 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0; 123 break; 124 case TransformOperation::TRANSLATE_Y: 125 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0; 126 break; 127 case TransformOperation::TRANSLATE_Z: 128 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0; 129 break; 130 default: 131 break; 132 } 133 } 134 135 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, FloatPoint3D& value) 136 { 137 switch (transformType) { 138 case TransformOperation::SCALE: 139 case TransformOperation::SCALE_3D: 140 value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1); 141 value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1); 142 value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1); 143 break; 144 case TransformOperation::TRANSLATE: 145 case TransformOperation::TRANSLATE_3D: 146 value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0); 147 value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0); 148 value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0); 149 break; 150 default: 151 break; 152 } 153 } 154 155 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, TransformationMatrix& value) 156 { 157 switch (transformType) { 158 case TransformOperation::SKEW_X: 159 case TransformOperation::SKEW_Y: 160 case TransformOperation::SKEW: 161 case TransformOperation::MATRIX: 162 case TransformOperation::ROTATE_3D: 163 case TransformOperation::MATRIX_3D: 164 case TransformOperation::PERSPECTIVE: 165 case TransformOperation::IDENTITY: 166 case TransformOperation::NONE: 167 if (transformOp) 168 transformOp->apply(value, size); 169 else 170 value.makeIdentity(); 171 break; 172 default: 173 break; 174 } 175 } 176 177 #if HAVE_MODERN_QUARTZCORE 178 static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType) 179 { 180 // Use literal strings to avoid link-time dependency on those symbols. 181 switch (transformType) { 182 case TransformOperation::ROTATE_X: 183 return PlatformCAAnimation::RotateX; 184 case TransformOperation::ROTATE_Y: 185 return PlatformCAAnimation::RotateY; 186 case TransformOperation::ROTATE: 187 return PlatformCAAnimation::RotateZ; 188 case TransformOperation::SCALE_X: 189 return PlatformCAAnimation::ScaleX; 190 case TransformOperation::SCALE_Y: 191 return PlatformCAAnimation::ScaleY; 192 case TransformOperation::SCALE_Z: 193 return PlatformCAAnimation::ScaleZ; 194 case TransformOperation::TRANSLATE_X: 195 return PlatformCAAnimation::TranslateX; 196 case TransformOperation::TRANSLATE_Y: 197 return PlatformCAAnimation::TranslateY; 198 case TransformOperation::TRANSLATE_Z: 199 return PlatformCAAnimation::TranslateZ; 200 case TransformOperation::SCALE: 201 case TransformOperation::SCALE_3D: 202 return PlatformCAAnimation::Scale; 203 case TransformOperation::TRANSLATE: 204 case TransformOperation::TRANSLATE_3D: 205 return PlatformCAAnimation::Translate; 206 default: 207 return PlatformCAAnimation::NoValueFunction; 208 } 209 } 210 #endif 211 212 static String propertyIdToString(AnimatedPropertyID property) 213 { 214 switch (property) { 215 case AnimatedPropertyWebkitTransform: 216 return "transform"; 217 case AnimatedPropertyOpacity: 218 return "opacity"; 219 case AnimatedPropertyBackgroundColor: 220 return "backgroundColor"; 221 case AnimatedPropertyInvalid: 222 ASSERT_NOT_REACHED(); 223 } 224 ASSERT_NOT_REACHED(); 225 return ""; 226 } 227 228 static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index) 229 { 230 return makeString(animationName, '_', String::number(property), '_', String::number(index)); 231 } 232 233 static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim) 234 { 235 if (anim->timingFunction()->isStepsTimingFunction()) 236 return true; 237 238 for (unsigned i = 0; i < valueList.size(); ++i) { 239 const TimingFunction* timingFunction = valueList.at(i)->timingFunction(); 240 if (timingFunction && timingFunction->isStepsTimingFunction()) 241 return true; 242 } 243 244 return false; 245 } 246 247 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 248 { 249 return new GraphicsLayerCA(client); 250 } 251 252 GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) 253 : GraphicsLayer(client) 254 , m_contentsLayerPurpose(NoContentsLayer) 255 , m_contentsLayerHasBackgroundColor(false) 256 , m_uncommittedChanges(NoChange) 257 , m_contentsScale(1) 258 , m_allowTiledLayer(true) 259 { 260 m_layer = PlatformCALayer::create(PlatformCALayer::LayerTypeWebLayer, this); 261 262 #if !HAVE_MODERN_QUARTZCORE 263 setContentsOrientation(defaultContentsOrientation()); 264 #endif 265 266 updateDebugIndicators(); 267 } 268 269 GraphicsLayerCA::~GraphicsLayerCA() 270 { 271 // We release our references to the PlatformCALayers here, but do not actively unparent them, 272 // since that will cause a commit and break our batched commit model. The layers will 273 // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers. 274 275 // Clean up the layer. 276 if (m_layer) 277 m_layer->setOwner(0); 278 279 if (m_contentsLayer) 280 m_contentsLayer->setOwner(0); 281 282 if (m_structuralLayer) 283 m_structuralLayer->setOwner(0); 284 285 removeCloneLayers(); 286 } 287 288 void GraphicsLayerCA::setName(const String& name) 289 { 290 String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name; 291 GraphicsLayer::setName(longName); 292 noteLayerPropertyChanged(NameChanged); 293 } 294 295 PlatformLayer* GraphicsLayerCA::platformLayer() const 296 { 297 return primaryLayer()->platformLayer(); 298 } 299 300 bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children) 301 { 302 bool childrenChanged = GraphicsLayer::setChildren(children); 303 if (childrenChanged) 304 noteSublayersChanged(); 305 306 return childrenChanged; 307 } 308 309 void GraphicsLayerCA::addChild(GraphicsLayer* childLayer) 310 { 311 GraphicsLayer::addChild(childLayer); 312 noteSublayersChanged(); 313 } 314 315 void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index) 316 { 317 GraphicsLayer::addChildAtIndex(childLayer, index); 318 noteSublayersChanged(); 319 } 320 321 void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) 322 { 323 GraphicsLayer::addChildBelow(childLayer, sibling); 324 noteSublayersChanged(); 325 } 326 327 void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) 328 { 329 GraphicsLayer::addChildAbove(childLayer, sibling); 330 noteSublayersChanged(); 331 } 332 333 bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 334 { 335 if (GraphicsLayer::replaceChild(oldChild, newChild)) { 336 noteSublayersChanged(); 337 return true; 338 } 339 return false; 340 } 341 342 void GraphicsLayerCA::removeFromParent() 343 { 344 if (m_parent) 345 static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged(); 346 GraphicsLayer::removeFromParent(); 347 } 348 349 void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer) 350 { 351 if (layer == m_maskLayer) 352 return; 353 354 GraphicsLayer::setMaskLayer(layer); 355 noteLayerPropertyChanged(MaskLayerChanged); 356 357 propagateLayerChangeToReplicas(); 358 359 if (m_replicatedLayer) 360 static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas(); 361 } 362 363 void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer) 364 { 365 if (layer == m_replicatedLayer) 366 return; 367 368 GraphicsLayer::setReplicatedLayer(layer); 369 noteLayerPropertyChanged(ReplicatedLayerChanged); 370 } 371 372 void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer) 373 { 374 if (layer == m_replicaLayer) 375 return; 376 377 GraphicsLayer::setReplicatedByLayer(layer); 378 noteSublayersChanged(); 379 noteLayerPropertyChanged(ReplicatedLayerChanged); 380 } 381 382 void GraphicsLayerCA::setPosition(const FloatPoint& point) 383 { 384 if (point == m_position) 385 return; 386 387 GraphicsLayer::setPosition(point); 388 noteLayerPropertyChanged(PositionChanged); 389 } 390 391 void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point) 392 { 393 if (point == m_anchorPoint) 394 return; 395 396 GraphicsLayer::setAnchorPoint(point); 397 noteLayerPropertyChanged(AnchorPointChanged); 398 } 399 400 void GraphicsLayerCA::setSize(const FloatSize& size) 401 { 402 if (size == m_size) 403 return; 404 405 GraphicsLayer::setSize(size); 406 noteLayerPropertyChanged(SizeChanged); 407 } 408 409 void GraphicsLayerCA::setTransform(const TransformationMatrix& t) 410 { 411 if (t == m_transform) 412 return; 413 414 GraphicsLayer::setTransform(t); 415 noteLayerPropertyChanged(TransformChanged); 416 } 417 418 void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t) 419 { 420 if (t == m_childrenTransform) 421 return; 422 423 GraphicsLayer::setChildrenTransform(t); 424 noteLayerPropertyChanged(ChildrenTransformChanged); 425 } 426 427 void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer) 428 { 429 RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier); 430 if (!anim) 431 return; 432 433 switch (operation) { 434 case Move: 435 fromLayer->removeAnimationForKey(animationIdentifier); 436 toLayer->addAnimationForKey(animationIdentifier, anim.get()); 437 break; 438 439 case Copy: 440 toLayer->addAnimationForKey(animationIdentifier, anim.get()); 441 break; 442 } 443 } 444 445 void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, PlatformCALayer *fromLayer, PlatformCALayer *toLayer) 446 { 447 // Look for running animations affecting this property. 448 AnimationsMap::const_iterator end = m_runningAnimations.end(); 449 for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) { 450 const Vector<LayerPropertyAnimation>& propertyAnimations = it->second; 451 size_t numAnimations = propertyAnimations.size(); 452 for (size_t i = 0; i < numAnimations; ++i) { 453 const LayerPropertyAnimation& currAnimation = propertyAnimations[i]; 454 if (currAnimation.m_property == property) 455 moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index), fromLayer, toLayer); 456 } 457 } 458 } 459 460 void GraphicsLayerCA::setPreserves3D(bool preserves3D) 461 { 462 if (preserves3D == m_preserves3D) 463 return; 464 465 GraphicsLayer::setPreserves3D(preserves3D); 466 noteLayerPropertyChanged(Preserves3DChanged); 467 } 468 469 void GraphicsLayerCA::setMasksToBounds(bool masksToBounds) 470 { 471 if (masksToBounds == m_masksToBounds) 472 return; 473 474 GraphicsLayer::setMasksToBounds(masksToBounds); 475 noteLayerPropertyChanged(MasksToBoundsChanged); 476 } 477 478 void GraphicsLayerCA::setDrawsContent(bool drawsContent) 479 { 480 if (drawsContent == m_drawsContent) 481 return; 482 483 GraphicsLayer::setDrawsContent(drawsContent); 484 noteLayerPropertyChanged(DrawsContentChanged); 485 } 486 487 void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing) 488 { 489 if (acceleratesDrawing == m_acceleratesDrawing) 490 return; 491 492 GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing); 493 noteLayerPropertyChanged(AcceleratesDrawingChanged); 494 } 495 496 void GraphicsLayerCA::setAllowTiledLayer(bool allowTiledLayer) 497 { 498 if (allowTiledLayer == m_allowTiledLayer) 499 return; 500 501 m_allowTiledLayer = allowTiledLayer; 502 503 // Handling this as a SizeChanged will cause use to switch in or out of tiled layer as needed 504 noteLayerPropertyChanged(SizeChanged); 505 } 506 507 void GraphicsLayerCA::setBackgroundColor(const Color& color) 508 { 509 if (m_backgroundColorSet && m_backgroundColor == color) 510 return; 511 512 GraphicsLayer::setBackgroundColor(color); 513 514 m_contentsLayerHasBackgroundColor = true; 515 noteLayerPropertyChanged(BackgroundColorChanged); 516 } 517 518 void GraphicsLayerCA::clearBackgroundColor() 519 { 520 if (!m_backgroundColorSet) 521 return; 522 523 GraphicsLayer::clearBackgroundColor(); 524 m_contentsLayerHasBackgroundColor = false; 525 noteLayerPropertyChanged(BackgroundColorChanged); 526 } 527 528 void GraphicsLayerCA::setContentsOpaque(bool opaque) 529 { 530 if (m_contentsOpaque == opaque) 531 return; 532 533 GraphicsLayer::setContentsOpaque(opaque); 534 noteLayerPropertyChanged(ContentsOpaqueChanged); 535 } 536 537 void GraphicsLayerCA::setBackfaceVisibility(bool visible) 538 { 539 if (m_backfaceVisibility == visible) 540 return; 541 542 GraphicsLayer::setBackfaceVisibility(visible); 543 noteLayerPropertyChanged(BackfaceVisibilityChanged); 544 } 545 546 void GraphicsLayerCA::setOpacity(float opacity) 547 { 548 float clampedOpacity = max(0.0f, min(opacity, 1.0f)); 549 550 if (clampedOpacity == m_opacity) 551 return; 552 553 GraphicsLayer::setOpacity(clampedOpacity); 554 noteLayerPropertyChanged(OpacityChanged); 555 } 556 557 void GraphicsLayerCA::setNeedsDisplay() 558 { 559 FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2, 560 numeric_limits<float>::max(), numeric_limits<float>::max()); 561 562 setNeedsDisplayInRect(hugeRect); 563 } 564 565 void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r) 566 { 567 if (!drawsContent()) 568 return; 569 570 FloatRect rect(r); 571 FloatRect layerBounds(FloatPoint(), m_size); 572 rect.intersect(layerBounds); 573 if (rect.isEmpty()) 574 return; 575 576 const size_t maxDirtyRects = 32; 577 578 for (size_t i = 0; i < m_dirtyRects.size(); ++i) { 579 if (m_dirtyRects[i].contains(rect)) 580 return; 581 } 582 583 if (m_dirtyRects.size() < maxDirtyRects) 584 m_dirtyRects.append(rect); 585 else 586 m_dirtyRects[0].unite(rect); 587 588 noteLayerPropertyChanged(DirtyRectsChanged); 589 } 590 591 void GraphicsLayerCA::setContentsNeedsDisplay() 592 { 593 noteLayerPropertyChanged(ContentsNeedsDisplay); 594 } 595 596 void GraphicsLayerCA::setContentsRect(const IntRect& rect) 597 { 598 if (rect == m_contentsRect) 599 return; 600 601 GraphicsLayer::setContentsRect(rect); 602 noteLayerPropertyChanged(ContentsRectChanged); 603 } 604 605 bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset) 606 { 607 ASSERT(!animationName.isEmpty()); 608 609 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) 610 return false; 611 612 #if !HAVE_MODERN_QUARTZCORE 613 // Older versions of QuartzCore do not handle opacity in transform layers properly, so we will 614 // always do software animation in that case. 615 if (valueList.property() == AnimatedPropertyOpacity) 616 return false; 617 #endif 618 619 // CoreAnimation does not handle the steps() timing function. Fall back 620 // to software animation in that case. 621 if (animationHasStepsTimingFunction(valueList, anim)) 622 return false; 623 624 bool createdAnimations = false; 625 if (valueList.property() == AnimatedPropertyWebkitTransform) 626 createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize); 627 else 628 createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset); 629 630 if (createdAnimations) 631 noteLayerPropertyChanged(AnimationChanged); 632 633 return createdAnimations; 634 } 635 636 void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset) 637 { 638 if (!animationIsRunning(animationName)) 639 return; 640 641 AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName); 642 if (it != m_animationsToProcess.end()) { 643 AnimationProcessingAction& processingInfo = it->second; 644 // If an animation is scheduled to be removed, don't change the remove to a pause. 645 if (processingInfo.action != Remove) 646 processingInfo.action = Pause; 647 } else 648 m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset)); 649 650 noteLayerPropertyChanged(AnimationChanged); 651 } 652 653 void GraphicsLayerCA::removeAnimation(const String& animationName) 654 { 655 if (!animationIsRunning(animationName)) 656 return; 657 658 m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove)); 659 noteLayerPropertyChanged(AnimationChanged); 660 } 661 662 void GraphicsLayerCA::platformCALayerAnimationStarted(CFTimeInterval startTime) 663 { 664 if (m_client) 665 m_client->notifyAnimationStarted(this, startTime); 666 } 667 668 void GraphicsLayerCA::setContentsToImage(Image* image) 669 { 670 if (image) { 671 CGImageRef newImage = image->nativeImageForCurrentFrame(); 672 if (!newImage) 673 return; 674 675 // Check to see if the image changed; we have to do this because the call to 676 // CGImageCreateCopyWithColorSpace() below can create a new image every time. 677 if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage) 678 return; 679 680 m_uncorrectedContentsImage = newImage; 681 m_pendingContentsImage = newImage; 682 683 #if !PLATFORM(WIN) 684 CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get()); 685 686 static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); 687 if (colorSpace && CFEqual(colorSpace, deviceRGB)) { 688 // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such 689 // images to CA we need to tag them similarly so CA rendering matches CG rendering. 690 static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay); 691 m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB)); 692 } 693 #endif 694 m_contentsLayerPurpose = ContentsLayerForImage; 695 if (!m_contentsLayer) 696 noteSublayersChanged(); 697 } else { 698 m_uncorrectedContentsImage = 0; 699 m_pendingContentsImage = 0; 700 m_contentsLayerPurpose = NoContentsLayer; 701 if (m_contentsLayer) 702 noteSublayersChanged(); 703 } 704 705 noteLayerPropertyChanged(ContentsImageChanged); 706 } 707 708 void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer) 709 { 710 if (m_contentsLayer && mediaLayer == m_contentsLayer->platformLayer()) 711 return; 712 713 // FIXME: The passed in layer might be a raw layer or an externally created 714 // PlatformCALayer. To determine this we attempt to get the 715 // PlatformCALayer pointer. If this returns a null pointer we assume it's 716 // raw. This test might be invalid if the raw layer is, for instance, the 717 // PlatformCALayer is using a user data pointer in the raw layer, and 718 // the creator of the raw layer is using it for some other purpose. 719 // For now we don't support such a case. 720 PlatformCALayer* platformCALayer = PlatformCALayer::platformCALayer(mediaLayer); 721 m_contentsLayer = mediaLayer ? (platformCALayer ? platformCALayer : PlatformCALayer::create(mediaLayer, this)) : 0; 722 m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer; 723 724 noteSublayersChanged(); 725 noteLayerPropertyChanged(ContentsMediaLayerChanged); 726 } 727 728 void GraphicsLayerCA::setContentsToCanvas(PlatformLayer* canvasLayer) 729 { 730 if (m_contentsLayer && canvasLayer == m_contentsLayer->platformLayer()) 731 return; 732 733 // Create the PlatformCALayer to wrap the incoming layer 734 m_contentsLayer = canvasLayer ? PlatformCALayer::create(canvasLayer, this) : 0; 735 736 m_contentsLayerPurpose = canvasLayer ? ContentsLayerForCanvas : NoContentsLayer; 737 738 noteSublayersChanged(); 739 noteLayerPropertyChanged(ContentsCanvasLayerChanged); 740 } 741 742 void GraphicsLayerCA::layerDidDisplay(PlatformLayer* layer) 743 { 744 PlatformCALayer* currentLayer = PlatformCALayer::platformCALayer(layer); 745 PlatformCALayer* sourceLayer; 746 LayerMap* layerCloneMap; 747 748 if (currentLayer == m_layer) { 749 sourceLayer = m_layer.get(); 750 layerCloneMap = m_layerClones.get(); 751 } else if (currentLayer == m_contentsLayer) { 752 sourceLayer = m_contentsLayer.get(); 753 layerCloneMap = m_contentsLayerClones.get(); 754 } else 755 return; 756 757 if (layerCloneMap) { 758 LayerMap::const_iterator end = layerCloneMap->end(); 759 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 760 PlatformCALayer* currClone = it->second.get(); 761 if (!currClone) 762 continue; 763 764 if (currClone->contents() != sourceLayer->contents()) 765 currClone->setContents(sourceLayer->contents()); 766 else 767 currClone->setContentsChanged(); 768 } 769 } 770 } 771 772 void GraphicsLayerCA::syncCompositingState() 773 { 774 recursiveCommitChanges(); 775 } 776 777 void GraphicsLayerCA::syncCompositingStateForThisLayerOnly() 778 { 779 commitLayerChangesBeforeSublayers(); 780 commitLayerChangesAfterSublayers(); 781 } 782 783 void GraphicsLayerCA::recursiveCommitChanges() 784 { 785 commitLayerChangesBeforeSublayers(); 786 787 if (m_maskLayer) 788 static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesBeforeSublayers(); 789 790 const Vector<GraphicsLayer*>& childLayers = children(); 791 size_t numChildren = childLayers.size(); 792 for (size_t i = 0; i < numChildren; ++i) { 793 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 794 curChild->recursiveCommitChanges(); 795 } 796 797 if (m_replicaLayer) 798 static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges(); 799 800 if (m_maskLayer) 801 static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers(); 802 803 commitLayerChangesAfterSublayers(); 804 } 805 806 void GraphicsLayerCA::commitLayerChangesBeforeSublayers() 807 { 808 if (!m_uncommittedChanges) 809 return; 810 811 // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to 812 if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged)) 813 updateStructuralLayer(); 814 815 if (m_uncommittedChanges & NameChanged) 816 updateLayerNames(); 817 818 if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged 819 updateContentsImage(); 820 821 if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged 822 updateContentsMediaLayer(); 823 824 if (m_uncommittedChanges & ContentsCanvasLayerChanged) // Needs to happen before ChildrenChanged 825 updateContentsCanvasLayer(); 826 827 if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video 828 updateLayerBackgroundColor(); 829 830 if (m_uncommittedChanges & ChildrenChanged) 831 updateSublayerList(); 832 833 if (m_uncommittedChanges & PositionChanged) 834 updateLayerPosition(); 835 836 if (m_uncommittedChanges & AnchorPointChanged) 837 updateAnchorPoint(); 838 839 if (m_uncommittedChanges & SizeChanged) 840 updateLayerSize(); 841 842 if (m_uncommittedChanges & TransformChanged) 843 updateTransform(); 844 845 if (m_uncommittedChanges & ChildrenTransformChanged) 846 updateChildrenTransform(); 847 848 if (m_uncommittedChanges & MasksToBoundsChanged) 849 updateMasksToBounds(); 850 851 if (m_uncommittedChanges & DrawsContentChanged) 852 updateLayerDrawsContent(); 853 854 if (m_uncommittedChanges & ContentsOpaqueChanged) 855 updateContentsOpaque(); 856 857 if (m_uncommittedChanges & BackfaceVisibilityChanged) 858 updateBackfaceVisibility(); 859 860 if (m_uncommittedChanges & OpacityChanged) 861 updateOpacityOnLayer(); 862 863 if (m_uncommittedChanges & AnimationChanged) 864 updateLayerAnimations(); 865 866 if (m_uncommittedChanges & DirtyRectsChanged) 867 repaintLayerDirtyRects(); 868 869 if (m_uncommittedChanges & ContentsRectChanged) 870 updateContentsRect(); 871 872 if (m_uncommittedChanges & MaskLayerChanged) 873 updateMaskLayer(); 874 875 if (m_uncommittedChanges & ContentsNeedsDisplay) 876 updateContentsNeedsDisplay(); 877 878 if (m_uncommittedChanges & AcceleratesDrawingChanged) 879 updateAcceleratesDrawing(); 880 881 if (m_uncommittedChanges & ContentsScaleChanged) 882 updateContentsScale(); 883 } 884 885 void GraphicsLayerCA::commitLayerChangesAfterSublayers() 886 { 887 if (!m_uncommittedChanges) 888 return; 889 890 if (m_uncommittedChanges & ReplicatedLayerChanged) 891 updateReplicatedLayers(); 892 893 m_uncommittedChanges = NoChange; 894 } 895 896 void GraphicsLayerCA::updateLayerNames() 897 { 898 switch (structuralLayerPurpose()) { 899 case StructuralLayerForPreserves3D: 900 m_structuralLayer->setName("Transform layer " + name()); 901 break; 902 case StructuralLayerForReplicaFlattening: 903 m_structuralLayer->setName("Replica flattening layer " + name()); 904 break; 905 case NoStructuralLayer: 906 break; 907 } 908 m_layer->setName(name()); 909 } 910 911 void GraphicsLayerCA::updateSublayerList() 912 { 913 PlatformCALayerList newSublayers; 914 const Vector<GraphicsLayer*>& childLayers = children(); 915 916 if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) { 917 if (m_structuralLayer) { 918 // Add the replica layer first. 919 if (m_replicaLayer) 920 newSublayers.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer()); 921 // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind. 922 newSublayers.append(m_layer); 923 } else if (m_contentsLayer) { 924 // FIXME: add the contents layer in the correct order with negative z-order children. 925 // This does not cause visible rendering issues because currently contents layers are only used 926 // for replaced elements that don't have children. 927 newSublayers.append(m_contentsLayer); 928 } 929 930 size_t numChildren = childLayers.size(); 931 for (size_t i = 0; i < numChildren; ++i) { 932 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 933 PlatformCALayer* childLayer = curChild->layerForSuperlayer(); 934 newSublayers.append(childLayer); 935 } 936 937 for (size_t i = 0; i < newSublayers.size(); --i) 938 newSublayers[i]->removeFromSuperlayer(); 939 } 940 941 if (m_structuralLayer) { 942 m_structuralLayer->setSublayers(newSublayers); 943 944 if (m_contentsLayer) { 945 // If we have a transform layer, then the contents layer is parented in the 946 // primary layer (which is itself a child of the transform layer). 947 m_layer->removeAllSublayers(); 948 m_layer->appendSublayer(m_contentsLayer.get()); 949 } 950 } else 951 m_layer->setSublayers(newSublayers); 952 } 953 954 void GraphicsLayerCA::updateLayerPosition() 955 { 956 FloatSize usedSize = m_usingTiledLayer ? constrainedSize() : m_size; 957 958 // Position is offset on the layer by the layer anchor point. 959 FloatPoint posPoint(m_position.x() + m_anchorPoint.x() * usedSize.width(), 960 m_position.y() + m_anchorPoint.y() * usedSize.height()); 961 962 primaryLayer()->setPosition(posPoint); 963 964 if (LayerMap* layerCloneMap = primaryLayerClones()) { 965 LayerMap::const_iterator end = layerCloneMap->end(); 966 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 967 FloatPoint clonePosition = posPoint; 968 if (m_replicaLayer && isReplicatedRootClone(it->first)) { 969 // Maintain the special-case position for the root of a clone subtree, 970 // which we set up in replicatedLayerRoot(). 971 clonePosition = positionForCloneRootLayer(); 972 } 973 it->second->setPosition(clonePosition); 974 } 975 } 976 } 977 978 void GraphicsLayerCA::updateLayerSize() 979 { 980 FloatRect rect(0, 0, m_size.width(), m_size.height()); 981 if (m_structuralLayer) { 982 m_structuralLayer->setBounds(rect); 983 984 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { 985 LayerMap::const_iterator end = layerCloneMap->end(); 986 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 987 it->second->setBounds(rect); 988 } 989 990 // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative. 991 CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f); 992 m_layer->setPosition(centerPoint); 993 994 if (LayerMap* layerCloneMap = m_layerClones.get()) { 995 LayerMap::const_iterator end = layerCloneMap->end(); 996 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 997 it->second->setPosition(centerPoint); 998 } 999 } 1000 1001 bool needTiledLayer = requiresTiledLayer(m_size); 1002 if (needTiledLayer != m_usingTiledLayer) 1003 swapFromOrToTiledLayer(needTiledLayer); 1004 1005 if (m_usingTiledLayer) { 1006 FloatSize sizeToUse = constrainedSize(); 1007 rect = CGRectMake(0, 0, sizeToUse.width(), sizeToUse.height()); 1008 } 1009 1010 m_layer->setBounds(rect); 1011 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1012 LayerMap::const_iterator end = layerCloneMap->end(); 1013 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1014 it->second->setBounds(rect); 1015 } 1016 1017 // Contents transform may depend on height. 1018 updateContentsTransform(); 1019 1020 // Note that we don't resize m_contentsLayer. It's up the caller to do that. 1021 1022 // if we've changed the bounds, we need to recalculate the position 1023 // of the layer, taking anchor point into account. 1024 updateLayerPosition(); 1025 } 1026 1027 void GraphicsLayerCA::updateAnchorPoint() 1028 { 1029 primaryLayer()->setAnchorPoint(m_anchorPoint); 1030 1031 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1032 LayerMap::const_iterator end = layerCloneMap->end(); 1033 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1034 PlatformCALayer* currLayer = it->second.get(); 1035 currLayer->setAnchorPoint(m_anchorPoint); 1036 } 1037 } 1038 1039 updateLayerPosition(); 1040 } 1041 1042 void GraphicsLayerCA::updateTransform() 1043 { 1044 primaryLayer()->setTransform(m_transform); 1045 1046 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1047 LayerMap::const_iterator end = layerCloneMap->end(); 1048 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1049 PlatformCALayer* currLayer = it->second.get(); 1050 if (m_replicaLayer && isReplicatedRootClone(it->first)) { 1051 // Maintain the special-case transform for the root of a clone subtree, 1052 // which we set up in replicatedLayerRoot(). 1053 currLayer->setTransform(TransformationMatrix()); 1054 } else 1055 currLayer->setTransform(m_transform); 1056 } 1057 } 1058 } 1059 1060 void GraphicsLayerCA::updateChildrenTransform() 1061 { 1062 primaryLayer()->setSublayerTransform(m_childrenTransform); 1063 1064 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1065 LayerMap::const_iterator end = layerCloneMap->end(); 1066 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1067 it->second->setSublayerTransform(m_childrenTransform); 1068 } 1069 } 1070 1071 void GraphicsLayerCA::updateMasksToBounds() 1072 { 1073 m_layer->setMasksToBounds(m_masksToBounds); 1074 1075 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1076 LayerMap::const_iterator end = layerCloneMap->end(); 1077 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1078 it->second->setMasksToBounds(m_masksToBounds); 1079 } 1080 1081 updateDebugIndicators(); 1082 } 1083 1084 void GraphicsLayerCA::updateContentsOpaque() 1085 { 1086 m_layer.get()->setOpaque(m_contentsOpaque); 1087 1088 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1089 LayerMap::const_iterator end = layerCloneMap->end(); 1090 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1091 it->second->setOpaque(m_contentsOpaque); 1092 } 1093 } 1094 1095 void GraphicsLayerCA::updateBackfaceVisibility() 1096 { 1097 if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) { 1098 m_structuralLayer->setDoubleSided(m_backfaceVisibility); 1099 1100 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { 1101 LayerMap::const_iterator end = layerCloneMap->end(); 1102 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1103 it->second->setDoubleSided(m_backfaceVisibility); 1104 } 1105 } 1106 1107 m_layer->setDoubleSided(m_backfaceVisibility); 1108 1109 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1110 LayerMap::const_iterator end = layerCloneMap->end(); 1111 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1112 it->second->setDoubleSided(m_backfaceVisibility); 1113 } 1114 } 1115 1116 void GraphicsLayerCA::updateStructuralLayer() 1117 { 1118 ensureStructuralLayer(structuralLayerPurpose()); 1119 } 1120 1121 void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose) 1122 { 1123 if (purpose == NoStructuralLayer) { 1124 if (m_structuralLayer) { 1125 // Replace the transformLayer in the parent with this layer. 1126 m_layer->removeFromSuperlayer(); 1127 1128 // If m_layer doesn't have a parent, it means it's the root layer and 1129 // is likely hosted by something that is not expecting to be changed 1130 ASSERT(m_structuralLayer->superlayer()); 1131 m_structuralLayer->superlayer()->replaceSublayer(m_structuralLayer.get(), m_layer.get()); 1132 1133 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_structuralLayer.get(), m_layer.get()); 1134 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_structuralLayer.get(), m_layer.get()); 1135 1136 // Release the structural layer. 1137 m_structuralLayer = 0; 1138 1139 // Update the properties of m_layer now that we no longer have a structural layer. 1140 updateLayerPosition(); 1141 updateLayerSize(); 1142 updateAnchorPoint(); 1143 updateTransform(); 1144 updateChildrenTransform(); 1145 1146 updateSublayerList(); 1147 updateOpacityOnLayer(); 1148 } 1149 return; 1150 } 1151 1152 bool structuralLayerChanged = false; 1153 1154 if (purpose == StructuralLayerForPreserves3D) { 1155 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer) 1156 m_structuralLayer = 0; 1157 1158 if (!m_structuralLayer) { 1159 m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeTransformLayer, this); 1160 structuralLayerChanged = true; 1161 } 1162 } else { 1163 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer) 1164 m_structuralLayer = 0; 1165 1166 if (!m_structuralLayer) { 1167 m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); 1168 structuralLayerChanged = true; 1169 } 1170 } 1171 1172 if (!structuralLayerChanged) 1173 return; 1174 1175 updateLayerNames(); 1176 1177 // Update the properties of the structural layer. 1178 updateLayerPosition(); 1179 updateLayerSize(); 1180 updateAnchorPoint(); 1181 updateTransform(); 1182 updateChildrenTransform(); 1183 updateBackfaceVisibility(); 1184 1185 // Set properties of m_layer to their default values, since these are expressed on on the structural layer. 1186 FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f); 1187 FloatPoint3D anchorPoint(0.5f, 0.5f, 0); 1188 m_layer->setPosition(point); 1189 m_layer->setAnchorPoint(anchorPoint); 1190 m_layer->setTransform(TransformationMatrix()); 1191 m_layer->setOpacity(1); 1192 if (m_layerClones) { 1193 LayerMap::const_iterator end = m_layerClones->end(); 1194 for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) { 1195 PlatformCALayer* currLayer = it->second.get(); 1196 currLayer->setPosition(point); 1197 currLayer->setAnchorPoint(anchorPoint); 1198 currLayer->setTransform(TransformationMatrix()); 1199 currLayer->setOpacity(1); 1200 } 1201 } 1202 1203 // Move this layer to be a child of the transform layer. 1204 // If m_layer doesn't have a parent, it means it's the root layer and 1205 // is likely hosted by something that is not expecting to be changed 1206 ASSERT(m_layer->superlayer()); 1207 m_layer->superlayer()->replaceSublayer(m_layer.get(), m_structuralLayer.get()); 1208 m_structuralLayer->appendSublayer(m_layer.get()); 1209 1210 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_layer.get(), m_structuralLayer.get()); 1211 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_layer.get(), m_structuralLayer.get()); 1212 1213 updateSublayerList(); 1214 updateOpacityOnLayer(); 1215 } 1216 1217 GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const 1218 { 1219 if (preserves3D()) 1220 return StructuralLayerForPreserves3D; 1221 1222 if (isReplicated()) 1223 return StructuralLayerForReplicaFlattening; 1224 1225 return NoStructuralLayer; 1226 } 1227 1228 void GraphicsLayerCA::updateLayerDrawsContent() 1229 { 1230 bool needTiledLayer = requiresTiledLayer(m_size); 1231 if (needTiledLayer != m_usingTiledLayer) 1232 swapFromOrToTiledLayer(needTiledLayer); 1233 1234 if (m_drawsContent) 1235 m_layer->setNeedsDisplay(); 1236 else 1237 m_layer->setContents(0); 1238 1239 updateDebugIndicators(); 1240 } 1241 1242 void GraphicsLayerCA::updateAcceleratesDrawing() 1243 { 1244 m_layer->setAcceleratesDrawing(m_acceleratesDrawing); 1245 } 1246 1247 void GraphicsLayerCA::updateLayerBackgroundColor() 1248 { 1249 if (!m_contentsLayer) 1250 return; 1251 1252 // We never create the contents layer just for background color yet. 1253 if (m_backgroundColorSet) 1254 m_contentsLayer->setBackgroundColor(m_backgroundColor); 1255 else 1256 m_contentsLayer->setBackgroundColor(Color::transparent); 1257 } 1258 1259 void GraphicsLayerCA::updateContentsImage() 1260 { 1261 if (m_pendingContentsImage) { 1262 if (!m_contentsLayer.get()) { 1263 m_contentsLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); 1264 #ifndef NDEBUG 1265 m_contentsLayer->setName("Image Layer"); 1266 #endif 1267 setupContentsLayer(m_contentsLayer.get()); 1268 // m_contentsLayer will be parented by updateSublayerList 1269 } 1270 1271 // FIXME: maybe only do trilinear if the image is being scaled down, 1272 // but then what if the layer size changes? 1273 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 1274 m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear); 1275 #endif 1276 m_contentsLayer->setContents(m_pendingContentsImage.get()); 1277 m_pendingContentsImage = 0; 1278 1279 if (m_contentsLayerClones) { 1280 LayerMap::const_iterator end = m_contentsLayerClones->end(); 1281 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) 1282 it->second->setContents(m_contentsLayer->contents()); 1283 } 1284 1285 updateContentsRect(); 1286 } else { 1287 // No image. 1288 // m_contentsLayer will be removed via updateSublayerList. 1289 m_contentsLayer = 0; 1290 } 1291 } 1292 1293 void GraphicsLayerCA::updateContentsMediaLayer() 1294 { 1295 // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList(). 1296 if (m_contentsLayer) { 1297 setupContentsLayer(m_contentsLayer.get()); 1298 updateContentsRect(); 1299 } 1300 } 1301 1302 void GraphicsLayerCA::updateContentsCanvasLayer() 1303 { 1304 // CanvasLayer was set as m_contentsLayer, and will get parented in updateSublayerList(). 1305 if (m_contentsLayer) { 1306 setupContentsLayer(m_contentsLayer.get()); 1307 m_contentsLayer->setNeedsDisplay(); 1308 updateContentsRect(); 1309 } 1310 } 1311 1312 void GraphicsLayerCA::updateContentsRect() 1313 { 1314 if (!m_contentsLayer) 1315 return; 1316 1317 FloatPoint point(m_contentsRect.x(), m_contentsRect.y()); 1318 FloatRect rect(0, 0, m_contentsRect.width(), m_contentsRect.height()); 1319 1320 m_contentsLayer->setPosition(point); 1321 m_contentsLayer->setBounds(rect); 1322 1323 if (m_contentsLayerClones) { 1324 LayerMap::const_iterator end = m_contentsLayerClones->end(); 1325 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) { 1326 it->second->setPosition(point); 1327 it->second->setBounds(rect); 1328 } 1329 } 1330 } 1331 1332 void GraphicsLayerCA::updateMaskLayer() 1333 { 1334 PlatformCALayer* maskCALayer = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayer() : 0; 1335 m_layer->setMask(maskCALayer); 1336 1337 LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0; 1338 1339 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1340 LayerMap::const_iterator end = layerCloneMap->end(); 1341 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1342 PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0; 1343 it->second->setMask(maskClone); 1344 } 1345 } 1346 } 1347 1348 void GraphicsLayerCA::updateReplicatedLayers() 1349 { 1350 // Clone the descendants of the replicated layer, and parent under us. 1351 ReplicaState replicaState(ReplicaState::ReplicaBranch); 1352 1353 RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState); 1354 if (!replicaRoot) 1355 return; 1356 1357 if (m_structuralLayer) 1358 m_structuralLayer->insertSublayer(replicaRoot.get(), 0); 1359 else 1360 m_layer->insertSublayer(replicaRoot.get(), 0); 1361 } 1362 1363 // For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1. 1364 GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const 1365 { 1366 size_t depth = m_replicaBranches.size(); 1367 1368 const size_t bitsPerUChar = sizeof(UChar) * 8; 1369 size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar; 1370 1371 Vector<UChar> result(vectorSize); 1372 result.fill(0); 1373 1374 // Create a string from the bit sequence which we can use to identify the clone. 1375 // Note that the string may contain embedded nulls, but that's OK. 1376 for (size_t i = 0; i < depth; ++i) { 1377 UChar& currChar = result[i / bitsPerUChar]; 1378 currChar = (currChar << 1) | m_replicaBranches[i]; 1379 } 1380 1381 return String::adopt(result); 1382 } 1383 1384 PassRefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState) 1385 { 1386 // Limit replica nesting, to avoid 2^N explosion of replica layers. 1387 if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth) 1388 return 0; 1389 1390 GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer); 1391 1392 RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel); 1393 FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer(); 1394 1395 // Replica root has no offset or transform 1396 clonedLayerRoot->setPosition(cloneRootPosition); 1397 clonedLayerRoot->setTransform(TransformationMatrix()); 1398 1399 return clonedLayerRoot; 1400 } 1401 1402 void GraphicsLayerCA::updateLayerAnimations() 1403 { 1404 if (m_animationsToProcess.size()) { 1405 AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end(); 1406 for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) { 1407 const String& currAnimationName = it->first; 1408 AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName); 1409 if (animationIt == m_runningAnimations.end()) 1410 continue; 1411 1412 const AnimationProcessingAction& processingInfo = it->second; 1413 const Vector<LayerPropertyAnimation>& animations = animationIt->second; 1414 for (size_t i = 0; i < animations.size(); ++i) { 1415 const LayerPropertyAnimation& currAnimation = animations[i]; 1416 switch (processingInfo.action) { 1417 case Remove: 1418 removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index); 1419 break; 1420 case Pause: 1421 pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, processingInfo.timeOffset); 1422 break; 1423 } 1424 } 1425 1426 if (processingInfo.action == Remove) 1427 m_runningAnimations.remove(currAnimationName); 1428 } 1429 1430 m_animationsToProcess.clear(); 1431 } 1432 1433 size_t numAnimations; 1434 if ((numAnimations = m_uncomittedAnimations.size())) { 1435 for (size_t i = 0; i < numAnimations; ++i) { 1436 const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i]; 1437 setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_timeOffset); 1438 1439 AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name); 1440 if (it == m_runningAnimations.end()) { 1441 Vector<LayerPropertyAnimation> animations; 1442 animations.append(pendingAnimation); 1443 m_runningAnimations.add(pendingAnimation.m_name, animations); 1444 } else { 1445 Vector<LayerPropertyAnimation>& animations = it->second; 1446 animations.append(pendingAnimation); 1447 } 1448 } 1449 1450 m_uncomittedAnimations.clear(); 1451 } 1452 } 1453 1454 void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset) 1455 { 1456 PlatformCALayer* layer = animatedLayer(property); 1457 1458 if (timeOffset) 1459 caAnim->setBeginTime(CACurrentMediaTime() - timeOffset); 1460 1461 String animationID = animationIdentifier(animationName, property, index); 1462 1463 layer->removeAnimationForKey(animationID); 1464 layer->addAnimationForKey(animationID, caAnim); 1465 1466 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 1467 LayerMap::const_iterator end = layerCloneMap->end(); 1468 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1469 // Skip immediate replicas, since they move with the original. 1470 if (m_replicaLayer && isReplicatedRootClone(it->first)) 1471 continue; 1472 1473 it->second->removeAnimationForKey(animationID); 1474 it->second->addAnimationForKey(animationID, caAnim); 1475 } 1476 } 1477 } 1478 1479 // Workaround for <rdar://problem/7311367> 1480 static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform) 1481 { 1482 if (!transformLayer) 1483 return; 1484 1485 TransformationMatrix caTransform = transform; 1486 caTransform.setM41(caTransform.m41() + 1); 1487 transformLayer->setTransform(caTransform); 1488 1489 caTransform.setM41(caTransform.m41() - 1); 1490 transformLayer->setTransform(caTransform); 1491 } 1492 1493 bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index) 1494 { 1495 PlatformCALayer* layer = animatedLayer(property); 1496 1497 String animationID = animationIdentifier(animationName, property, index); 1498 1499 if (!layer->animationForKey(animationID)) 1500 return false; 1501 1502 layer->removeAnimationForKey(animationID); 1503 bug7311367Workaround(m_structuralLayer.get(), m_transform); 1504 1505 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 1506 LayerMap::const_iterator end = layerCloneMap->end(); 1507 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1508 // Skip immediate replicas, since they move with the original. 1509 if (m_replicaLayer && isReplicatedRootClone(it->first)) 1510 continue; 1511 1512 it->second ->removeAnimationForKey(animationID); 1513 } 1514 } 1515 return true; 1516 } 1517 1518 void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset) 1519 { 1520 PlatformCALayer* layer = animatedLayer(property); 1521 1522 String animationID = animationIdentifier(animationName, property, index); 1523 1524 RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID); 1525 if (!curAnim) 1526 return; 1527 1528 // Animations on the layer are immutable, so we have to clone and modify. 1529 RefPtr<PlatformCAAnimation> newAnim = curAnim->copy(); 1530 1531 newAnim->setSpeed(0); 1532 newAnim->setTimeOffset(timeOffset); 1533 1534 layer->addAnimationForKey(animationID, newAnim.get()); // This will replace the running animation. 1535 1536 // Pause the animations on the clones too. 1537 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 1538 LayerMap::const_iterator end = layerCloneMap->end(); 1539 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1540 // Skip immediate replicas, since they move with the original. 1541 if (m_replicaLayer && isReplicatedRootClone(it->first)) 1542 continue; 1543 it->second->addAnimationForKey(animationID, newAnim.get()); 1544 } 1545 } 1546 } 1547 1548 void GraphicsLayerCA::repaintLayerDirtyRects() 1549 { 1550 if (!m_dirtyRects.size()) 1551 return; 1552 1553 for (size_t i = 0; i < m_dirtyRects.size(); ++i) 1554 m_layer->setNeedsDisplay(&(m_dirtyRects[i])); 1555 1556 m_dirtyRects.clear(); 1557 } 1558 1559 void GraphicsLayerCA::updateContentsNeedsDisplay() 1560 { 1561 if (m_contentsLayer) 1562 m_contentsLayer->setNeedsDisplay(); 1563 } 1564 1565 bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset) 1566 { 1567 ASSERT(valueList.property() != AnimatedPropertyWebkitTransform); 1568 1569 bool isKeyframe = valueList.size() > 2; 1570 bool valuesOK; 1571 1572 bool additive = false; 1573 int animationIndex = 0; 1574 1575 RefPtr<PlatformCAAnimation> caAnimation; 1576 1577 if (isKeyframe) { 1578 caAnimation = createKeyframeAnimation(animation, valueList.property(), additive); 1579 valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get()); 1580 } else { 1581 caAnimation = createBasicAnimation(animation, valueList.property(), additive); 1582 valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get()); 1583 } 1584 1585 if (!valuesOK) 1586 return false; 1587 1588 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset)); 1589 1590 return true; 1591 } 1592 1593 bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize) 1594 { 1595 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); 1596 1597 TransformOperationList functionList; 1598 bool listsMatch, hasBigRotation; 1599 fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation); 1600 1601 // We need to fall back to software animation if we don't have setValueFunction:, and 1602 // we would need to animate each incoming transform function separately. This is the 1603 // case if we have a rotation >= 180 or we have more than one transform function. 1604 if ((hasBigRotation || functionList.size() > 1) && !PlatformCAAnimation::supportsValueFunction()) 1605 return false; 1606 1607 bool validMatrices = true; 1608 1609 // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation. 1610 // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation 1611 // if that's not true as well. 1612 bool isMatrixAnimation = !listsMatch || !PlatformCAAnimation::supportsValueFunction(); 1613 1614 size_t numAnimations = isMatrixAnimation ? 1 : functionList.size(); 1615 bool isKeyframe = valueList.size() > 2; 1616 1617 // Iterate through the transform functions, sending an animation for each one. 1618 for (size_t animationIndex = 0; animationIndex < numAnimations; ++animationIndex) { 1619 TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex]; 1620 RefPtr<PlatformCAAnimation> caAnimation; 1621 1622 #if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) || PLATFORM(WIN) 1623 // CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property) 1624 // to be non-additive. 1625 // FIXME: This fix has not been added to QuartzCore on Windows yet (<rdar://problem/9112233>) so we expect the 1626 // reversed animation behavior 1627 bool additive = animationIndex < (numAnimations - 1); 1628 #else 1629 bool additive = animationIndex > 0; 1630 #endif 1631 if (isKeyframe) { 1632 caAnimation = createKeyframeAnimation(animation, valueList.property(), additive); 1633 validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize); 1634 } else { 1635 caAnimation = createBasicAnimation(animation, valueList.property(), additive); 1636 validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize); 1637 } 1638 1639 if (!validMatrices) 1640 break; 1641 1642 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset)); 1643 } 1644 1645 return validMatrices; 1646 } 1647 1648 PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) 1649 { 1650 RefPtr<PlatformCAAnimation> basicAnim = PlatformCAAnimation::create(PlatformCAAnimation::Basic, propertyIdToString(property)); 1651 setupAnimation(basicAnim.get(), anim, additive); 1652 return basicAnim; 1653 } 1654 1655 PassRefPtr<PlatformCAAnimation>GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) 1656 { 1657 RefPtr<PlatformCAAnimation> keyframeAnim = PlatformCAAnimation::create(PlatformCAAnimation::Keyframe, propertyIdToString(property)); 1658 setupAnimation(keyframeAnim.get(), anim, additive); 1659 return keyframeAnim; 1660 } 1661 1662 void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive) 1663 { 1664 double duration = anim->duration(); 1665 if (duration <= 0) 1666 duration = cAnimationAlmostZeroDuration; 1667 1668 float repeatCount = anim->iterationCount(); 1669 if (repeatCount == Animation::IterationCountInfinite) 1670 repeatCount = numeric_limits<float>::max(); 1671 else if (anim->direction() == Animation::AnimationDirectionAlternate) 1672 repeatCount /= 2; 1673 1674 PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode; 1675 switch (anim->fillMode()) { 1676 case AnimationFillModeNone: 1677 fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash. 1678 break; 1679 case AnimationFillModeBackwards: 1680 fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash. 1681 break; 1682 case AnimationFillModeForwards: 1683 fillMode = PlatformCAAnimation::Forwards; 1684 break; 1685 case AnimationFillModeBoth: 1686 fillMode = PlatformCAAnimation::Both; 1687 break; 1688 } 1689 1690 propertyAnim->setDuration(duration); 1691 propertyAnim->setRepeatCount(repeatCount); 1692 propertyAnim->setAutoreverses(anim->direction()); 1693 propertyAnim->setRemovedOnCompletion(false); 1694 propertyAnim->setAdditive(additive); 1695 propertyAnim->setFillMode(fillMode); 1696 } 1697 1698 const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim) 1699 { 1700 if (animValue->timingFunction()) 1701 return animValue->timingFunction(); 1702 if (anim->isTimingFunctionSet()) 1703 return anim->timingFunction().get(); 1704 1705 return CubicBezierTimingFunction::defaultTimingFunction(); 1706 } 1707 1708 bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim) 1709 { 1710 switch (valueList.property()) { 1711 case AnimatedPropertyOpacity: { 1712 basicAnim->setFromValue(static_cast<const FloatAnimationValue*>(valueList.at(0))->value()); 1713 basicAnim->setToValue(static_cast<const FloatAnimationValue*>(valueList.at(1))->value()); 1714 break; 1715 } 1716 default: 1717 ASSERT_NOT_REACHED(); // we don't animate color yet 1718 break; 1719 } 1720 1721 // This codepath is used for 2-keyframe animations, so we still need to look in the start 1722 // for a timing function. 1723 const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim); 1724 if (timingFunction) 1725 basicAnim->setTimingFunction(timingFunction); 1726 1727 return true; 1728 } 1729 1730 bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* keyframeAnim) 1731 { 1732 Vector<float> keyTimes; 1733 Vector<float> values; 1734 Vector<const TimingFunction*> timingFunctions; 1735 1736 for (unsigned i = 0; i < valueList.size(); ++i) { 1737 const AnimationValue* curValue = valueList.at(i); 1738 keyTimes.append(curValue->keyTime()); 1739 1740 switch (valueList.property()) { 1741 case AnimatedPropertyOpacity: { 1742 const FloatAnimationValue* floatValue = static_cast<const FloatAnimationValue*>(curValue); 1743 values.append(floatValue->value()); 1744 break; 1745 } 1746 default: 1747 ASSERT_NOT_REACHED(); // we don't animate color yet 1748 break; 1749 } 1750 1751 timingFunctions.append(timingFunctionForAnimationValue(curValue, anim)); 1752 } 1753 1754 // We toss the last tfArray value because it has to one shorter than the others. 1755 timingFunctions.removeLast(); 1756 1757 keyframeAnim->setKeyTimes(keyTimes); 1758 keyframeAnim->setValues(values); 1759 keyframeAnim->setTimingFunctions(timingFunctions); 1760 1761 return true; 1762 } 1763 1764 bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) 1765 { 1766 ASSERT(valueList.size() == 2); 1767 const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(0)); 1768 const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(1)); 1769 1770 if (isMatrixAnimation) { 1771 TransformationMatrix fromTransform, toTransform; 1772 startValue->value()->apply(boxSize, fromTransform); 1773 endValue->value()->apply(boxSize, toTransform); 1774 1775 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation 1776 if (!fromTransform.isInvertible() || !toTransform.isInvertible()) 1777 return false; 1778 1779 basicAnim->setFromValue(fromTransform); 1780 basicAnim->setToValue(toTransform); 1781 } else { 1782 if (isTransformTypeNumber(transformOpType)) { 1783 float fromValue; 1784 getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue); 1785 basicAnim->setFromValue(fromValue); 1786 1787 float toValue; 1788 getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue); 1789 basicAnim->setToValue(toValue); 1790 } else if (isTransformTypeFloatPoint3D(transformOpType)) { 1791 FloatPoint3D fromValue; 1792 getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue); 1793 basicAnim->setFromValue(fromValue); 1794 1795 FloatPoint3D toValue; 1796 getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue); 1797 basicAnim->setToValue(toValue); 1798 } else { 1799 TransformationMatrix fromValue; 1800 getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue); 1801 basicAnim->setFromValue(fromValue); 1802 1803 TransformationMatrix toValue; 1804 getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue); 1805 basicAnim->setToValue(toValue); 1806 } 1807 } 1808 1809 // This codepath is used for 2-keyframe animations, so we still need to look in the start 1810 // for a timing function. 1811 const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim); 1812 basicAnim->setTimingFunction(timingFunction); 1813 1814 #if HAVE_MODERN_QUARTZCORE 1815 PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType); 1816 if (valueFunction != PlatformCAAnimation::NoValueFunction) 1817 basicAnim->setValueFunction(valueFunction); 1818 #endif 1819 1820 return true; 1821 } 1822 1823 bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) 1824 { 1825 Vector<float> keyTimes; 1826 Vector<float> floatValues; 1827 Vector<FloatPoint3D> floatPoint3DValues; 1828 Vector<TransformationMatrix> transformationMatrixValues; 1829 Vector<const TimingFunction*> timingFunctions; 1830 1831 for (unsigned i = 0; i < valueList.size(); ++i) { 1832 const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(i)); 1833 keyTimes.append(curValue->keyTime()); 1834 1835 if (isMatrixAnimation) { 1836 TransformationMatrix transform; 1837 curValue->value()->apply(boxSize, transform); 1838 1839 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation 1840 if (!transform.isInvertible()) 1841 return false; 1842 1843 transformationMatrixValues.append(transform); 1844 } else { 1845 const TransformOperation* transformOp = curValue->value()->at(functionIndex); 1846 if (isTransformTypeNumber(transformOpType)) { 1847 float value; 1848 getTransformFunctionValue(transformOp, transformOpType, boxSize, value); 1849 floatValues.append(value); 1850 } else if (isTransformTypeFloatPoint3D(transformOpType)) { 1851 FloatPoint3D value; 1852 getTransformFunctionValue(transformOp, transformOpType, boxSize, value); 1853 floatPoint3DValues.append(value); 1854 } else { 1855 TransformationMatrix value; 1856 getTransformFunctionValue(transformOp, transformOpType, boxSize, value); 1857 transformationMatrixValues.append(value); 1858 } 1859 } 1860 1861 const TimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation); 1862 timingFunctions.append(timingFunction); 1863 } 1864 1865 // We toss the last tfArray value because it has to one shorter than the others. 1866 timingFunctions.removeLast(); 1867 1868 keyframeAnim->setKeyTimes(keyTimes); 1869 1870 if (isTransformTypeNumber(transformOpType)) 1871 keyframeAnim->setValues(floatValues); 1872 else if (isTransformTypeFloatPoint3D(transformOpType)) 1873 keyframeAnim->setValues(floatPoint3DValues); 1874 else 1875 keyframeAnim->setValues(transformationMatrixValues); 1876 1877 keyframeAnim->setTimingFunctions(timingFunctions); 1878 1879 #if HAVE_MODERN_QUARTZCORE 1880 PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType); 1881 if (valueFunction != PlatformCAAnimation::NoValueFunction) 1882 keyframeAnim->setValueFunction(valueFunction); 1883 #endif 1884 return true; 1885 } 1886 1887 void GraphicsLayerCA::suspendAnimations(double time) 1888 { 1889 double t = currentTimeToMediaTime(time ? time : currentTime()); 1890 primaryLayer()->setSpeed(0); 1891 primaryLayer()->setTimeOffset(t); 1892 1893 // Suspend the animations on the clones too. 1894 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1895 LayerMap::const_iterator end = layerCloneMap->end(); 1896 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1897 it->second->setSpeed(0); 1898 it->second->setTimeOffset(t); 1899 } 1900 } 1901 } 1902 1903 void GraphicsLayerCA::resumeAnimations() 1904 { 1905 primaryLayer()->setSpeed(1); 1906 primaryLayer()->setTimeOffset(0); 1907 1908 // Resume the animations on the clones too. 1909 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1910 LayerMap::const_iterator end = layerCloneMap->end(); 1911 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1912 it->second->setSpeed(1); 1913 it->second->setTimeOffset(0); 1914 } 1915 } 1916 } 1917 1918 PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const 1919 { 1920 return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); 1921 } 1922 1923 PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const 1924 { 1925 return m_structuralLayer ? m_structuralLayer.get() : m_layer.get(); 1926 } 1927 1928 PlatformCALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const 1929 { 1930 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer(); 1931 } 1932 1933 GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const 1934 { 1935 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones(); 1936 } 1937 1938 void GraphicsLayerCA::setContentsScale(float scale) 1939 { 1940 float newScale = clampedContentsScaleForScale(scale); 1941 if (newScale == m_contentsScale) 1942 return; 1943 1944 m_contentsScale = newScale; 1945 noteLayerPropertyChanged(ContentsScaleChanged); 1946 } 1947 1948 float GraphicsLayerCA::clampedContentsScaleForScale(float scale) const 1949 { 1950 // Define some limits as a sanity check for the incoming scale value 1951 // those too small to see. 1952 const float maxScale = 5.0f; 1953 const float minScale = 0.01f; 1954 1955 // Avoid very slight scale changes that would be doing extra work for no benefit 1956 const float maxAllowableDelta = 0.05f; 1957 1958 // Clamp 1959 float result = max(minScale, min(scale, maxScale)); 1960 1961 // If it hasn't changed much, don't do any work 1962 return ((fabs(result - m_contentsScale) / m_contentsScale) < maxAllowableDelta) ? m_contentsScale : result; 1963 } 1964 1965 void GraphicsLayerCA::updateContentsScale() 1966 { 1967 bool needTiledLayer = requiresTiledLayer(m_size); 1968 if (needTiledLayer != m_usingTiledLayer) 1969 swapFromOrToTiledLayer(needTiledLayer); 1970 1971 m_layer->setContentsScale(m_contentsScale); 1972 if (drawsContent()) 1973 m_layer->setNeedsDisplay(); 1974 } 1975 1976 void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) 1977 { 1978 if (color.isValid()) 1979 m_layer->setBackgroundColor(color); 1980 else 1981 m_layer->setBackgroundColor(Color::transparent); 1982 } 1983 1984 void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) 1985 { 1986 if (color.isValid()) { 1987 m_layer->setBorderColor(color); 1988 m_layer->setBorderWidth(borderWidth); 1989 } else { 1990 m_layer->setBorderColor(Color::transparent); 1991 m_layer->setBorderWidth(0); 1992 } 1993 } 1994 1995 FloatSize GraphicsLayerCA::constrainedSize() const 1996 { 1997 float tileColumns = ceilf(m_size.width() / kTiledLayerTileSize); 1998 float tileRows = ceilf(m_size.height() / kTiledLayerTileSize); 1999 double numTiles = tileColumns * tileRows; 2000 2001 FloatSize constrainedSize = m_size; 2002 const unsigned cMaxTileCount = 512; 2003 while (numTiles > cMaxTileCount) { 2004 // Constrain the wider dimension. 2005 if (constrainedSize.width() >= constrainedSize.height()) { 2006 tileColumns = max(floorf(cMaxTileCount / tileRows), 1.0f); 2007 constrainedSize.setWidth(tileColumns * kTiledLayerTileSize); 2008 } else { 2009 tileRows = max(floorf(cMaxTileCount / tileColumns), 1.0f); 2010 constrainedSize.setHeight(tileRows * kTiledLayerTileSize); 2011 } 2012 numTiles = tileColumns * tileRows; 2013 } 2014 2015 return constrainedSize; 2016 } 2017 2018 bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const 2019 { 2020 if (!m_drawsContent || !m_allowTiledLayer) 2021 return false; 2022 2023 // FIXME: catch zero-size height or width here (or earlier)? 2024 return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension; 2025 } 2026 2027 void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) 2028 { 2029 ASSERT(useTiledLayer != m_usingTiledLayer); 2030 RefPtr<PlatformCALayer> oldLayer = m_layer; 2031 2032 m_layer = PlatformCALayer::create(useTiledLayer ? PlatformCALayer::LayerTypeWebTiledLayer : PlatformCALayer::LayerTypeWebLayer, this); 2033 m_layer->setContentsScale(m_contentsScale); 2034 2035 m_usingTiledLayer = useTiledLayer; 2036 2037 if (useTiledLayer) { 2038 #if !HAVE_MODERN_QUARTZCORE 2039 // Tiled layer has issues with flipped coordinates. 2040 setContentsOrientation(CompositingCoordinatesTopDown); 2041 #endif 2042 } else { 2043 #if !HAVE_MODERN_QUARTZCORE 2044 setContentsOrientation(GraphicsLayerCA::defaultContentsOrientation()); 2045 #endif 2046 } 2047 2048 m_layer->adoptSublayers(oldLayer.get()); 2049 2050 // If m_layer doesn't have a parent, it means it's the root layer and 2051 // is likely hosted by something that is not expecting to be changed 2052 ASSERT(oldLayer->superlayer()); 2053 oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get()); 2054 2055 updateContentsTransform(); 2056 2057 updateLayerPosition(); 2058 updateLayerSize(); 2059 updateAnchorPoint(); 2060 updateTransform(); 2061 updateChildrenTransform(); 2062 updateMasksToBounds(); 2063 updateContentsOpaque(); 2064 updateBackfaceVisibility(); 2065 updateLayerBackgroundColor(); 2066 2067 updateOpacityOnLayer(); 2068 2069 #ifndef NDEBUG 2070 String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + m_name; 2071 m_layer->setName(name); 2072 #endif 2073 2074 // move over animations 2075 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get()); 2076 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, oldLayer.get(), m_layer.get()); 2077 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get()); 2078 2079 // need to tell new layer to draw itself 2080 setNeedsDisplay(); 2081 2082 updateDebugIndicators(); 2083 } 2084 2085 GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const 2086 { 2087 #if !HAVE_MODERN_QUARTZCORE 2088 // Older QuartzCore does not support -geometryFlipped, so we manually flip the root 2089 // layer geometry, and then flip the contents of each layer back so that the CTM for CG 2090 // is unflipped, allowing it to do the correct font auto-hinting. 2091 return CompositingCoordinatesBottomUp; 2092 #else 2093 return CompositingCoordinatesTopDown; 2094 #endif 2095 } 2096 2097 void GraphicsLayerCA::updateContentsTransform() 2098 { 2099 #if !HAVE_MODERN_QUARTZCORE 2100 if (contentsOrientation() == CompositingCoordinatesBottomUp) { 2101 CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1); 2102 contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -m_layer->bounds().size().height()); 2103 m_layer->setContentsTransform(TransformationMatrix(contentsTransform)); 2104 } 2105 #endif 2106 } 2107 2108 void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer) 2109 { 2110 // Turn off implicit animations on the inner layer. 2111 contentsLayer->setMasksToBounds(true); 2112 2113 if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) { 2114 TransformationMatrix flipper( 2115 1.0f, 0.0f, 0.0f, 0.0f, 2116 0.0f, -1.0f, 0.0f, 0.0f, 2117 0.0f, 0.0f, 1.0f, 0.0f, 2118 0.0f, 0.0f, 0.0f, 1.0f); 2119 contentsLayer->setTransform(flipper); 2120 contentsLayer->setAnchorPoint(FloatPoint3D(0, 1, 0)); 2121 } else 2122 contentsLayer->setAnchorPoint(FloatPoint3D()); 2123 2124 if (showDebugBorders()) { 2125 contentsLayer->setBorderColor(Color(0, 0, 128, 180)); 2126 contentsLayer->setBorderWidth(1.0f); 2127 } 2128 } 2129 2130 PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, PlatformCALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel) 2131 { 2132 if (!sourceLayer) 2133 return 0; 2134 2135 RefPtr<PlatformCALayer> resultLayer; 2136 2137 // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells 2138 // us whether there's an item there. This technique avoids two hash lookups. 2139 RefPtr<PlatformCALayer> dummy; 2140 pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy); 2141 if (!addResult.second) { 2142 // Value was not added, so it exists already. 2143 resultLayer = addResult.first->second.get(); 2144 } else { 2145 resultLayer = cloneLayer(sourceLayer, cloneLevel); 2146 #ifndef NDEBUG 2147 resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer)); 2148 #endif 2149 addResult.first->second = resultLayer; 2150 } 2151 2152 return resultLayer; 2153 } 2154 2155 void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer, RefPtr<PlatformCALayer>& contentsLayer, CloneLevel cloneLevel) 2156 { 2157 structuralLayer = 0; 2158 contentsLayer = 0; 2159 2160 if (!m_layerClones) 2161 m_layerClones = new LayerMap; 2162 2163 if (!m_structuralLayerClones && m_structuralLayer) 2164 m_structuralLayerClones = new LayerMap; 2165 2166 if (!m_contentsLayerClones && m_contentsLayer) 2167 m_contentsLayerClones = new LayerMap; 2168 2169 primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel); 2170 structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel); 2171 contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel); 2172 } 2173 2174 void GraphicsLayerCA::removeCloneLayers() 2175 { 2176 m_layerClones = 0; 2177 m_structuralLayerClones = 0; 2178 m_contentsLayerClones = 0; 2179 } 2180 2181 FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const 2182 { 2183 // This can get called during a sync when we've just removed the m_replicaLayer. 2184 if (!m_replicaLayer) 2185 return FloatPoint(); 2186 2187 FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition(); 2188 return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(), 2189 replicaPosition.y() + m_anchorPoint.y() * m_size.height()); 2190 } 2191 2192 void GraphicsLayerCA::propagateLayerChangeToReplicas() 2193 { 2194 for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) { 2195 GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer); 2196 if (!currLayerCA->hasCloneLayers()) 2197 break; 2198 2199 if (currLayerCA->replicaLayer()) 2200 static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged); 2201 } 2202 } 2203 2204 PassRefPtr<PlatformCALayer> GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel) 2205 { 2206 RefPtr<PlatformCALayer> primaryLayer; 2207 RefPtr<PlatformCALayer> structuralLayer; 2208 RefPtr<PlatformCALayer> contentsLayer; 2209 ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel); 2210 2211 if (m_maskLayer) { 2212 RefPtr<PlatformCALayer> maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); 2213 primaryLayer->setMask(maskClone.get()); 2214 } 2215 2216 if (m_replicatedLayer) { 2217 // We are a replica being asked for clones of our layers. 2218 RefPtr<PlatformCALayer> replicaRoot = replicatedLayerRoot(replicaState); 2219 if (!replicaRoot) 2220 return 0; 2221 2222 if (structuralLayer) { 2223 structuralLayer->insertSublayer(replicaRoot.get(), 0); 2224 return structuralLayer; 2225 } 2226 2227 primaryLayer->insertSublayer(replicaRoot.get(), 0); 2228 return primaryLayer; 2229 } 2230 2231 const Vector<GraphicsLayer*>& childLayers = children(); 2232 Vector<RefPtr<PlatformCALayer> > clonalSublayers; 2233 2234 RefPtr<PlatformCALayer> replicaLayer; 2235 2236 if (m_replicaLayer && m_replicaLayer != replicaRoot) { 2237 // We have nested replicas. Ask the replica layer for a clone of its contents. 2238 replicaState.setBranchType(ReplicaState::ReplicaBranch); 2239 replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel); 2240 replicaState.setBranchType(ReplicaState::ChildBranch); 2241 } 2242 2243 if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) { 2244 if (structuralLayer) { 2245 // Replicas render behind the actual layer content. 2246 if (replicaLayer) 2247 clonalSublayers.append(replicaLayer); 2248 2249 // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind. 2250 clonalSublayers.append(primaryLayer); 2251 } else if (contentsLayer) { 2252 // FIXME: add the contents layer in the correct order with negative z-order children. 2253 // This does not cause visible rendering issues because currently contents layers are only used 2254 // for replaced elements that don't have children. 2255 clonalSublayers.append(contentsLayer); 2256 } 2257 2258 replicaState.push(ReplicaState::ChildBranch); 2259 2260 size_t numChildren = childLayers.size(); 2261 for (size_t i = 0; i < numChildren; ++i) { 2262 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 2263 2264 RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); 2265 if (childLayer) 2266 clonalSublayers.append(childLayer); 2267 } 2268 2269 replicaState.pop(); 2270 2271 for (size_t i = 0; i < clonalSublayers.size(); ++i) 2272 clonalSublayers[i]->removeFromSuperlayer(); 2273 } 2274 2275 RefPtr<PlatformCALayer> result; 2276 if (structuralLayer) { 2277 structuralLayer->setSublayers(clonalSublayers); 2278 2279 if (contentsLayer) { 2280 // If we have a transform layer, then the contents layer is parented in the 2281 // primary layer (which is itself a child of the transform layer). 2282 primaryLayer->removeAllSublayers(); 2283 primaryLayer->appendSublayer(contentsLayer.get()); 2284 } 2285 2286 result = structuralLayer; 2287 } else { 2288 primaryLayer->setSublayers(clonalSublayers); 2289 result = primaryLayer; 2290 } 2291 2292 return result; 2293 } 2294 2295 PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, CloneLevel cloneLevel) 2296 { 2297 PlatformCALayer::LayerType layerType = (layer->layerType() == PlatformCALayer::LayerTypeTransformLayer) ? 2298 PlatformCALayer::LayerTypeTransformLayer : PlatformCALayer::LayerTypeLayer; 2299 RefPtr<PlatformCALayer> newLayer = PlatformCALayer::create(layerType, this); 2300 2301 newLayer->setPosition(layer->position()); 2302 newLayer->setBounds(layer->bounds()); 2303 newLayer->setAnchorPoint(layer->anchorPoint()); 2304 newLayer->setTransform(layer->transform()); 2305 newLayer->setSublayerTransform(layer->sublayerTransform()); 2306 newLayer->setContents(layer->contents()); 2307 newLayer->setMasksToBounds(layer->masksToBounds()); 2308 newLayer->setDoubleSided(layer->isDoubleSided()); 2309 newLayer->setOpaque(layer->isOpaque()); 2310 newLayer->setBackgroundColor(layer->backgroundColor()); 2311 newLayer->setContentsScale(layer->contentsScale()); 2312 2313 if (cloneLevel == IntermediateCloneLevel) { 2314 newLayer->setOpacity(layer->opacity()); 2315 moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyWebkitTransform, layer, newLayer.get()); 2316 moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyOpacity, layer, newLayer.get()); 2317 } 2318 2319 if (showDebugBorders()) { 2320 newLayer->setBorderColor(Color(255, 122, 251)); 2321 newLayer->setBorderWidth(2); 2322 } 2323 2324 return newLayer; 2325 } 2326 2327 void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) 2328 { 2329 LayerMap* layerCloneMap = 0; 2330 2331 if (preserves3D()) { 2332 m_layer->setOpacity(accumulatedOpacity); 2333 layerCloneMap = m_layerClones.get(); 2334 } else { 2335 primaryLayer()->setOpacity(accumulatedOpacity); 2336 layerCloneMap = primaryLayerClones(); 2337 } 2338 2339 if (layerCloneMap) { 2340 LayerMap::const_iterator end = layerCloneMap->end(); 2341 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2342 if (m_replicaLayer && isReplicatedRootClone(it->first)) 2343 continue; 2344 it->second->setOpacity(m_opacity); 2345 } 2346 } 2347 } 2348 2349 void GraphicsLayerCA::updateOpacityOnLayer() 2350 { 2351 #if !HAVE_MODERN_QUARTZCORE 2352 // Distribute opacity either to our own layer or to our children. We pass in the 2353 // contribution from our parent(s). 2354 distributeOpacity(parent() ? parent()->accumulatedOpacity() : 1); 2355 #else 2356 primaryLayer()->setOpacity(m_opacity); 2357 2358 if (LayerMap* layerCloneMap = primaryLayerClones()) { 2359 LayerMap::const_iterator end = layerCloneMap->end(); 2360 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2361 if (m_replicaLayer && isReplicatedRootClone(it->first)) 2362 continue; 2363 2364 it->second->setOpacity(m_opacity); 2365 } 2366 2367 } 2368 #endif 2369 } 2370 2371 void GraphicsLayerCA::noteSublayersChanged() 2372 { 2373 noteLayerPropertyChanged(ChildrenChanged); 2374 propagateLayerChangeToReplicas(); 2375 } 2376 2377 void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) 2378 { 2379 if (!m_uncommittedChanges && m_client) 2380 m_client->notifySyncRequired(this); 2381 2382 m_uncommittedChanges |= flags; 2383 } 2384 2385 } // namespace WebCore 2386 2387 #endif // USE(ACCELERATED_COMPOSITING) 2388