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 "GraphicsLayerFactory.h" 36#include "PlatformCAFilters.h" 37#include "PlatformCALayer.h" 38#include "RotateTransformOperation.h" 39#include "ScaleTransformOperation.h" 40#include "TextStream.h" 41#include "TiledBacking.h" 42#include "TransformState.h" 43#include "TranslateTransformOperation.h" 44#include <QuartzCore/CATransform3D.h> 45#include <limits.h> 46#include <wtf/CurrentTime.h> 47#include <wtf/text/WTFString.h> 48 49#if PLATFORM(MAC) 50#include "WebCoreSystemInterface.h" 51#endif 52 53using namespace std; 54 55namespace WebCore { 56 57// The threshold width or height above which a tiled layer will be used. This should be 58// large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL 59// texture size limit on all supported hardware. 60static const int cMaxPixelDimension = 2000; 61 62// Derived empirically: <rdar://problem/13401861> 63static const int cMaxLayerTreeDepth = 250; 64 65// If we send a duration of 0 to CA, then it will use the default duration 66// of 250ms. So send a very small value instead. 67static const float cAnimationAlmostZeroDuration = 1e-3f; 68 69static inline bool isIntegral(float value) 70{ 71 return static_cast<int>(value) == value; 72} 73 74static float clampedContentsScaleForScale(float scale) 75{ 76 // Define some limits as a sanity check for the incoming scale value 77 // those too small to see. 78 const float maxScale = 10.0f; 79 const float minScale = 0.01f; 80 return std::max(minScale, std::min(scale, maxScale)); 81} 82 83static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType) 84{ 85 switch (transformType) { 86 case TransformOperation::SKEW_X: 87 case TransformOperation::SKEW_Y: 88 case TransformOperation::SKEW: 89 case TransformOperation::MATRIX: 90 case TransformOperation::ROTATE_3D: 91 case TransformOperation::MATRIX_3D: 92 case TransformOperation::PERSPECTIVE: 93 case TransformOperation::IDENTITY: 94 case TransformOperation::NONE: 95 return true; 96 default: 97 return false; 98 } 99} 100 101static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType) 102{ 103 switch (transformType) { 104 case TransformOperation::SCALE: 105 case TransformOperation::SCALE_3D: 106 case TransformOperation::TRANSLATE: 107 case TransformOperation::TRANSLATE_3D: 108 return true; 109 default: 110 return false; 111 } 112} 113 114static bool isTransformTypeNumber(TransformOperation::OperationType transformType) 115{ 116 return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType); 117} 118 119static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, float& value) 120{ 121 switch (transformType) { 122 case TransformOperation::ROTATE: 123 case TransformOperation::ROTATE_X: 124 case TransformOperation::ROTATE_Y: 125 value = transformOp ? narrowPrecisionToFloat(deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle())) : 0; 126 break; 127 case TransformOperation::SCALE_X: 128 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1; 129 break; 130 case TransformOperation::SCALE_Y: 131 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1; 132 break; 133 case TransformOperation::SCALE_Z: 134 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1; 135 break; 136 case TransformOperation::TRANSLATE_X: 137 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0; 138 break; 139 case TransformOperation::TRANSLATE_Y: 140 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0; 141 break; 142 case TransformOperation::TRANSLATE_Z: 143 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0; 144 break; 145 default: 146 break; 147 } 148} 149 150static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, FloatPoint3D& value) 151{ 152 switch (transformType) { 153 case TransformOperation::SCALE: 154 case TransformOperation::SCALE_3D: 155 value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1); 156 value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1); 157 value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1); 158 break; 159 case TransformOperation::TRANSLATE: 160 case TransformOperation::TRANSLATE_3D: 161 value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0); 162 value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0); 163 value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0); 164 break; 165 default: 166 break; 167 } 168} 169 170static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, TransformationMatrix& value) 171{ 172 switch (transformType) { 173 case TransformOperation::SKEW_X: 174 case TransformOperation::SKEW_Y: 175 case TransformOperation::SKEW: 176 case TransformOperation::MATRIX: 177 case TransformOperation::ROTATE_3D: 178 case TransformOperation::MATRIX_3D: 179 case TransformOperation::PERSPECTIVE: 180 case TransformOperation::IDENTITY: 181 case TransformOperation::NONE: 182 if (transformOp) 183 transformOp->apply(value, size); 184 else 185 value.makeIdentity(); 186 break; 187 default: 188 break; 189 } 190} 191 192static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType) 193{ 194 // Use literal strings to avoid link-time dependency on those symbols. 195 switch (transformType) { 196 case TransformOperation::ROTATE_X: 197 return PlatformCAAnimation::RotateX; 198 case TransformOperation::ROTATE_Y: 199 return PlatformCAAnimation::RotateY; 200 case TransformOperation::ROTATE: 201 return PlatformCAAnimation::RotateZ; 202 case TransformOperation::SCALE_X: 203 return PlatformCAAnimation::ScaleX; 204 case TransformOperation::SCALE_Y: 205 return PlatformCAAnimation::ScaleY; 206 case TransformOperation::SCALE_Z: 207 return PlatformCAAnimation::ScaleZ; 208 case TransformOperation::TRANSLATE_X: 209 return PlatformCAAnimation::TranslateX; 210 case TransformOperation::TRANSLATE_Y: 211 return PlatformCAAnimation::TranslateY; 212 case TransformOperation::TRANSLATE_Z: 213 return PlatformCAAnimation::TranslateZ; 214 case TransformOperation::SCALE: 215 case TransformOperation::SCALE_3D: 216 return PlatformCAAnimation::Scale; 217 case TransformOperation::TRANSLATE: 218 case TransformOperation::TRANSLATE_3D: 219 return PlatformCAAnimation::Translate; 220 default: 221 return PlatformCAAnimation::NoValueFunction; 222 } 223} 224 225static String propertyIdToString(AnimatedPropertyID property) 226{ 227 switch (property) { 228 case AnimatedPropertyWebkitTransform: 229 return "transform"; 230 case AnimatedPropertyOpacity: 231 return "opacity"; 232 case AnimatedPropertyBackgroundColor: 233 return "backgroundColor"; 234 case AnimatedPropertyWebkitFilter: 235#if ENABLE(CSS_FILTERS) 236 return "filters"; 237#else 238 ASSERT_NOT_REACHED(); 239#endif 240 case AnimatedPropertyInvalid: 241 ASSERT_NOT_REACHED(); 242 } 243 ASSERT_NOT_REACHED(); 244 return ""; 245} 246 247static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index, int subIndex) 248{ 249 return animationName + '_' + String::number(property) + '_' + String::number(index) + '_' + String::number(subIndex); 250} 251 252static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim) 253{ 254 if (anim->timingFunction()->isStepsTimingFunction()) 255 return true; 256 257 for (unsigned i = 0; i < valueList.size(); ++i) { 258 if (const TimingFunction* timingFunction = valueList.at(i).timingFunction()) { 259 if (timingFunction->isStepsTimingFunction()) 260 return true; 261 } 262 } 263 264 return false; 265} 266 267#if ENABLE(CSS_FILTERS) || !ASSERT_DISABLED 268static inline bool supportsAcceleratedFilterAnimations() 269{ 270// <rdar://problem/10907251> - WebKit2 doesn't support CA animations of CI filters on Lion and below 271#if PLATFORM(MAC) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) 272 return true; 273#else 274 return false; 275#endif 276} 277#endif 278 279PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) 280{ 281 if (!factory) 282 return adoptPtr(new GraphicsLayerCA(client)); 283 284 return factory->createGraphicsLayer(client); 285} 286 287PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 288{ 289 return adoptPtr(new GraphicsLayerCA(client)); 290} 291 292GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) 293 : GraphicsLayer(client) 294 , m_contentsLayerPurpose(NoContentsLayer) 295 , m_allowTiledLayer(true) 296 , m_isPageTiledBackingLayer(false) 297 , m_uncommittedChanges(0) 298{ 299 PlatformCALayer::LayerType layerType = PlatformCALayer::LayerTypeWebLayer; 300 if (client && client->shouldUseTiledBacking(this)) { 301 layerType = PlatformCALayer::LayerTypePageTiledBackingLayer; 302 m_isPageTiledBackingLayer = true; 303 } 304 305 m_layer = PlatformCALayer::create(layerType, this); 306 noteLayerPropertyChanged(ContentsScaleChanged); 307} 308 309GraphicsLayerCA::~GraphicsLayerCA() 310{ 311 // Do cleanup while we can still safely call methods on the derived class. 312 willBeDestroyed(); 313} 314 315void GraphicsLayerCA::willBeDestroyed() 316{ 317 // We release our references to the PlatformCALayers here, but do not actively unparent them, 318 // since that will cause a commit and break our batched commit model. The layers will 319 // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers. 320 321 // Clean up the layer. 322 if (m_layer) 323 m_layer->setOwner(0); 324 325 if (m_contentsLayer) 326 m_contentsLayer->setOwner(0); 327 328 if (m_structuralLayer) 329 m_structuralLayer->setOwner(0); 330 331 removeCloneLayers(); 332 333 GraphicsLayer::willBeDestroyed(); 334} 335 336void GraphicsLayerCA::setName(const String& name) 337{ 338 String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer->platformLayer(), this) + name; 339 GraphicsLayer::setName(longName); 340 noteLayerPropertyChanged(NameChanged); 341} 342 343PlatformLayer* GraphicsLayerCA::platformLayer() const 344{ 345 return primaryLayer()->platformLayer(); 346} 347 348bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children) 349{ 350 bool childrenChanged = GraphicsLayer::setChildren(children); 351 if (childrenChanged) 352 noteSublayersChanged(); 353 354 return childrenChanged; 355} 356 357void GraphicsLayerCA::addChild(GraphicsLayer* childLayer) 358{ 359 GraphicsLayer::addChild(childLayer); 360 noteSublayersChanged(); 361} 362 363void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index) 364{ 365 GraphicsLayer::addChildAtIndex(childLayer, index); 366 noteSublayersChanged(); 367} 368 369void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) 370{ 371 GraphicsLayer::addChildBelow(childLayer, sibling); 372 noteSublayersChanged(); 373} 374 375void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) 376{ 377 GraphicsLayer::addChildAbove(childLayer, sibling); 378 noteSublayersChanged(); 379} 380 381bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 382{ 383 if (GraphicsLayer::replaceChild(oldChild, newChild)) { 384 noteSublayersChanged(); 385 return true; 386 } 387 return false; 388} 389 390void GraphicsLayerCA::removeFromParent() 391{ 392 if (m_parent) 393 static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged(); 394 GraphicsLayer::removeFromParent(); 395} 396 397void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer) 398{ 399 if (layer == m_maskLayer) 400 return; 401 402 GraphicsLayer::setMaskLayer(layer); 403 noteLayerPropertyChanged(MaskLayerChanged); 404 405 propagateLayerChangeToReplicas(); 406 407 if (m_replicatedLayer) 408 static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas(); 409} 410 411void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer) 412{ 413 if (layer == m_replicatedLayer) 414 return; 415 416 GraphicsLayer::setReplicatedLayer(layer); 417 noteLayerPropertyChanged(ReplicatedLayerChanged); 418} 419 420void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer) 421{ 422 if (layer == m_replicaLayer) 423 return; 424 425 GraphicsLayer::setReplicatedByLayer(layer); 426 noteSublayersChanged(); 427 noteLayerPropertyChanged(ReplicatedLayerChanged); 428} 429 430void GraphicsLayerCA::setPosition(const FloatPoint& point) 431{ 432 if (point == m_position) 433 return; 434 435 GraphicsLayer::setPosition(point); 436 noteLayerPropertyChanged(GeometryChanged); 437} 438 439void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point) 440{ 441 if (point == m_anchorPoint) 442 return; 443 444 GraphicsLayer::setAnchorPoint(point); 445 noteLayerPropertyChanged(GeometryChanged); 446} 447 448void GraphicsLayerCA::setSize(const FloatSize& size) 449{ 450 if (size == m_size) 451 return; 452 453 GraphicsLayer::setSize(size); 454 noteLayerPropertyChanged(GeometryChanged); 455} 456 457void GraphicsLayerCA::setBoundsOrigin(const FloatPoint& origin) 458{ 459 if (origin == m_boundsOrigin) 460 return; 461 462 GraphicsLayer::setBoundsOrigin(origin); 463 noteLayerPropertyChanged(GeometryChanged); 464} 465 466void GraphicsLayerCA::setTransform(const TransformationMatrix& t) 467{ 468 if (t == m_transform) 469 return; 470 471 GraphicsLayer::setTransform(t); 472 noteLayerPropertyChanged(TransformChanged); 473} 474 475void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t) 476{ 477 if (t == m_childrenTransform) 478 return; 479 480 GraphicsLayer::setChildrenTransform(t); 481 noteLayerPropertyChanged(ChildrenTransformChanged); 482} 483 484void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer) 485{ 486 RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier); 487 if (!anim) 488 return; 489 490 switch (operation) { 491 case Move: 492 fromLayer->removeAnimationForKey(animationIdentifier); 493 toLayer->addAnimationForKey(animationIdentifier, anim.get()); 494 break; 495 496 case Copy: 497 toLayer->addAnimationForKey(animationIdentifier, anim.get()); 498 break; 499 } 500} 501 502void GraphicsLayerCA::moveOrCopyAnimations(MoveOrCopy operation, PlatformCALayer *fromLayer, PlatformCALayer *toLayer) 503{ 504 // Look for running animations affecting this property. 505 AnimationsMap::const_iterator end = m_runningAnimations.end(); 506 for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) { 507 const Vector<LayerPropertyAnimation>& propertyAnimations = it->value; 508 size_t numAnimations = propertyAnimations.size(); 509 for (size_t i = 0; i < numAnimations; ++i) { 510 const LayerPropertyAnimation& currAnimation = propertyAnimations[i]; 511 512 if (currAnimation.m_property == AnimatedPropertyWebkitTransform || currAnimation.m_property == AnimatedPropertyOpacity 513 || currAnimation.m_property == AnimatedPropertyBackgroundColor 514#if ENABLE(CSS_FILTERS) 515 || currAnimation.m_property == AnimatedPropertyWebkitFilter 516#endif 517 ) 518 moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index, currAnimation.m_subIndex), fromLayer, toLayer); 519 } 520 } 521} 522 523void GraphicsLayerCA::setPreserves3D(bool preserves3D) 524{ 525 if (preserves3D == m_preserves3D) 526 return; 527 528 GraphicsLayer::setPreserves3D(preserves3D); 529 noteLayerPropertyChanged(Preserves3DChanged); 530} 531 532void GraphicsLayerCA::setMasksToBounds(bool masksToBounds) 533{ 534 if (masksToBounds == m_masksToBounds) 535 return; 536 537 GraphicsLayer::setMasksToBounds(masksToBounds); 538 noteLayerPropertyChanged(MasksToBoundsChanged | DebugIndicatorsChanged); 539} 540 541void GraphicsLayerCA::setDrawsContent(bool drawsContent) 542{ 543 if (drawsContent == m_drawsContent) 544 return; 545 546 GraphicsLayer::setDrawsContent(drawsContent); 547 noteLayerPropertyChanged(DrawsContentChanged | DebugIndicatorsChanged); 548} 549 550void GraphicsLayerCA::setContentsVisible(bool contentsVisible) 551{ 552 if (contentsVisible == m_contentsVisible) 553 return; 554 555 GraphicsLayer::setContentsVisible(contentsVisible); 556 noteLayerPropertyChanged(ContentsVisibilityChanged); 557 // Visibility affects whether the contentsLayer is parented. 558 if (m_contentsLayer) 559 noteSublayersChanged(); 560} 561 562void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing) 563{ 564 if (acceleratesDrawing == m_acceleratesDrawing) 565 return; 566 567 GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing); 568 noteLayerPropertyChanged(AcceleratesDrawingChanged); 569} 570 571void GraphicsLayerCA::setAllowTiledLayer(bool allowTiledLayer) 572{ 573 if (allowTiledLayer == m_allowTiledLayer) 574 return; 575 576 m_allowTiledLayer = allowTiledLayer; 577 578 // Handling this as a BoundsChanged will cause use to switch in or out of tiled layer as needed 579 noteLayerPropertyChanged(GeometryChanged); 580} 581 582void GraphicsLayerCA::setBackgroundColor(const Color& color) 583{ 584 if (m_backgroundColor == color) 585 return; 586 587 GraphicsLayer::setBackgroundColor(color); 588 noteLayerPropertyChanged(BackgroundColorChanged); 589} 590 591void GraphicsLayerCA::setContentsOpaque(bool opaque) 592{ 593 if (m_contentsOpaque == opaque) 594 return; 595 596 GraphicsLayer::setContentsOpaque(opaque); 597 noteLayerPropertyChanged(ContentsOpaqueChanged); 598} 599 600void GraphicsLayerCA::setBackfaceVisibility(bool visible) 601{ 602 if (m_backfaceVisibility == visible) 603 return; 604 605 GraphicsLayer::setBackfaceVisibility(visible); 606 noteLayerPropertyChanged(BackfaceVisibilityChanged); 607} 608 609void GraphicsLayerCA::setOpacity(float opacity) 610{ 611 float clampedOpacity = max(0.0f, min(opacity, 1.0f)); 612 613 if (clampedOpacity == m_opacity) 614 return; 615 616 GraphicsLayer::setOpacity(clampedOpacity); 617 noteLayerPropertyChanged(OpacityChanged); 618} 619 620#if ENABLE(CSS_FILTERS) 621bool GraphicsLayerCA::setFilters(const FilterOperations& filterOperations) 622{ 623 bool canCompositeFilters = PlatformCALayer::filtersCanBeComposited(filterOperations); 624 625 if (m_filters == filterOperations) 626 return canCompositeFilters; 627 628 // Filters cause flattening, so we should never have filters on a layer with preserves3D(). 629 ASSERT(!filterOperations.size() || !preserves3D()); 630 631 if (canCompositeFilters) { 632 GraphicsLayer::setFilters(filterOperations); 633 noteLayerPropertyChanged(FiltersChanged); 634 } else if (filters().size()) { 635 // In this case filters are rendered in software, so we need to remove any 636 // previously attached hardware filters. 637 clearFilters(); 638 noteLayerPropertyChanged(FiltersChanged); 639 } 640 return canCompositeFilters; 641} 642#endif 643 644void GraphicsLayerCA::setNeedsDisplay() 645{ 646 FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2, 647 numeric_limits<float>::max(), numeric_limits<float>::max()); 648 649 setNeedsDisplayInRect(hugeRect); 650} 651 652void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r) 653{ 654 if (!drawsContent()) 655 return; 656 657 FloatRect rect(r); 658 FloatRect layerBounds(FloatPoint(), m_size); 659 rect.intersect(layerBounds); 660 if (rect.isEmpty()) 661 return; 662 663 const size_t maxDirtyRects = 32; 664 665 for (size_t i = 0; i < m_dirtyRects.size(); ++i) { 666 if (m_dirtyRects[i].contains(rect)) 667 return; 668 } 669 670 if (m_dirtyRects.size() < maxDirtyRects) 671 m_dirtyRects.append(rect); 672 else 673 m_dirtyRects[0].unite(rect); 674 675 noteLayerPropertyChanged(DirtyRectsChanged); 676 677 addRepaintRect(rect); 678} 679 680void GraphicsLayerCA::setContentsNeedsDisplay() 681{ 682 noteLayerPropertyChanged(ContentsNeedsDisplay); 683} 684 685void GraphicsLayerCA::setContentsRect(const IntRect& rect) 686{ 687 if (rect == m_contentsRect) 688 return; 689 690 GraphicsLayer::setContentsRect(rect); 691 noteLayerPropertyChanged(ContentsRectChanged); 692} 693 694bool GraphicsLayerCA::shouldRepaintOnSizeChange() const 695{ 696 return drawsContent() && !tiledBacking(); 697} 698 699bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset) 700{ 701 ASSERT(!animationName.isEmpty()); 702 703 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) 704 return false; 705 706 // CoreAnimation does not handle the steps() timing function. Fall back 707 // to software animation in that case. 708 if (animationHasStepsTimingFunction(valueList, anim)) 709 return false; 710 711 bool createdAnimations = false; 712 if (valueList.property() == AnimatedPropertyWebkitTransform) 713 createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize); 714#if ENABLE(CSS_FILTERS) 715 else if (valueList.property() == AnimatedPropertyWebkitFilter) { 716 if (supportsAcceleratedFilterAnimations()) 717 createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, timeOffset); 718 } 719#endif 720 else 721 createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset); 722 723 if (createdAnimations) 724 noteLayerPropertyChanged(AnimationChanged); 725 726 return createdAnimations; 727} 728 729void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset) 730{ 731 if (!animationIsRunning(animationName)) 732 return; 733 734 AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName); 735 if (it != m_animationsToProcess.end()) { 736 AnimationProcessingAction& processingInfo = it->value; 737 // If an animation is scheduled to be removed, don't change the remove to a pause. 738 if (processingInfo.action != Remove) 739 processingInfo.action = Pause; 740 } else 741 m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset)); 742 743 noteLayerPropertyChanged(AnimationChanged); 744} 745 746void GraphicsLayerCA::removeAnimation(const String& animationName) 747{ 748 if (!animationIsRunning(animationName)) 749 return; 750 751 m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove)); 752 noteLayerPropertyChanged(AnimationChanged); 753} 754 755void GraphicsLayerCA::platformCALayerAnimationStarted(CFTimeInterval startTime) 756{ 757 if (m_client) 758 m_client->notifyAnimationStarted(this, startTime); 759} 760 761void GraphicsLayerCA::setContentsToSolidColor(const Color& color) 762{ 763 if (color == m_contentsSolidColor) 764 return; 765 766 m_contentsSolidColor = color; 767 768 if (m_contentsSolidColor.isValid()) { 769 m_contentsLayerPurpose = ContentsLayerForBackgroundColor; 770 m_contentsLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); 771#ifndef NDEBUG 772 m_contentsLayer->setName("Background Color Layer"); 773#endif 774 } else { 775 m_contentsLayerPurpose = NoContentsLayer; 776 m_contentsLayer = 0; 777 } 778 779 noteSublayersChanged(); 780 noteLayerPropertyChanged(ContentsColorLayerChanged); 781} 782 783void GraphicsLayerCA::setContentsToImage(Image* image) 784{ 785 if (image) { 786 CGImageRef newImage = image->nativeImageForCurrentFrame(); 787 if (!newImage) 788 return; 789 790 // Check to see if the image changed; we have to do this because the call to 791 // CGImageCreateCopyWithColorSpace() below can create a new image every time. 792 if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage) 793 return; 794 795 m_uncorrectedContentsImage = newImage; 796 m_pendingContentsImage = newImage; 797 798#if !PLATFORM(WIN) 799 CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get()); 800 801 static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); 802 if (colorSpace && CFEqual(colorSpace, deviceRGB)) { 803 // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such 804 // images to CA we need to tag them similarly so CA rendering matches CG rendering. 805 static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay); 806 m_pendingContentsImage = adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB)); 807 } 808#endif 809 m_contentsLayerPurpose = ContentsLayerForImage; 810 if (!m_contentsLayer) 811 noteSublayersChanged(); 812 } else { 813 m_uncorrectedContentsImage = 0; 814 m_pendingContentsImage = 0; 815 m_contentsLayerPurpose = NoContentsLayer; 816 if (m_contentsLayer) 817 noteSublayersChanged(); 818 } 819 820 noteLayerPropertyChanged(ContentsImageChanged); 821} 822 823void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer) 824{ 825 if (m_contentsLayer && mediaLayer == m_contentsLayer->platformLayer()) 826 return; 827 828 // FIXME: The passed in layer might be a raw layer or an externally created 829 // PlatformCALayer. To determine this we attempt to get the 830 // PlatformCALayer pointer. If this returns a null pointer we assume it's 831 // raw. This test might be invalid if the raw layer is, for instance, the 832 // PlatformCALayer is using a user data pointer in the raw layer, and 833 // the creator of the raw layer is using it for some other purpose. 834 // For now we don't support such a case. 835 PlatformCALayer* platformCALayer = PlatformCALayer::platformCALayer(mediaLayer); 836 m_contentsLayer = mediaLayer ? (platformCALayer ? platformCALayer : PlatformCALayer::create(mediaLayer, this)) : 0; 837 m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer; 838 839 noteSublayersChanged(); 840 noteLayerPropertyChanged(ContentsMediaLayerChanged); 841} 842 843void GraphicsLayerCA::setContentsToCanvas(PlatformLayer* canvasLayer) 844{ 845 if (m_contentsLayer && canvasLayer == m_contentsLayer->platformLayer()) 846 return; 847 848 // Create the PlatformCALayer to wrap the incoming layer 849 m_contentsLayer = canvasLayer ? PlatformCALayer::create(canvasLayer, this) : 0; 850 851 m_contentsLayerPurpose = canvasLayer ? ContentsLayerForCanvas : NoContentsLayer; 852 853 noteSublayersChanged(); 854 noteLayerPropertyChanged(ContentsCanvasLayerChanged); 855} 856 857void GraphicsLayerCA::layerDidDisplay(PlatformLayer* layer) 858{ 859 PlatformCALayer* currentLayer = PlatformCALayer::platformCALayer(layer); 860 PlatformCALayer* sourceLayer; 861 LayerMap* layerCloneMap; 862 863 if (currentLayer == m_layer) { 864 sourceLayer = m_layer.get(); 865 layerCloneMap = m_layerClones.get(); 866 } else if (currentLayer == m_contentsLayer) { 867 sourceLayer = m_contentsLayer.get(); 868 layerCloneMap = m_contentsLayerClones.get(); 869 } else 870 return; 871 872 if (layerCloneMap) { 873 LayerMap::const_iterator end = layerCloneMap->end(); 874 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 875 PlatformCALayer* currClone = it->value.get(); 876 if (!currClone) 877 continue; 878 879 if (currClone->contents() != sourceLayer->contents()) 880 currClone->setContents(sourceLayer->contents()); 881 else 882 currClone->setContentsChanged(); 883 } 884 } 885} 886 887FloatPoint GraphicsLayerCA::computePositionRelativeToBase(float& pageScale) const 888{ 889 pageScale = 1; 890 891 FloatPoint offset; 892 for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) { 893 if (currLayer->appliesPageScale()) { 894 if (currLayer->client()) 895 pageScale = currLayer->pageScaleFactor(); 896 return offset; 897 } 898 899 offset += currLayer->position(); 900 } 901 902 return FloatPoint(); 903} 904 905void GraphicsLayerCA::flushCompositingState(const FloatRect& clipRect) 906{ 907 TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect)); 908 recursiveCommitChanges(CommitState(), state); 909} 910 911void GraphicsLayerCA::flushCompositingStateForThisLayerOnly() 912{ 913 float pageScaleFactor; 914 bool hadChanges = m_uncommittedChanges; 915 916 CommitState commitState; 917 918 FloatPoint offset = computePositionRelativeToBase(pageScaleFactor); 919 commitLayerChangesBeforeSublayers(commitState, pageScaleFactor, offset, m_visibleRect); 920 commitLayerChangesAfterSublayers(commitState); 921 922 if (hadChanges && client()) 923 client()->didCommitChangesForLayer(this); 924} 925 926bool GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush(const TransformState& state) const 927{ 928 TransformState localState = state; 929 930 // This may be called at times when layout has not been updated, so we want to avoid calling out to the client 931 // for animating transforms. 932 FloatRect newVisibleRect = computeVisibleRect(localState, 0); 933 if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer) 934 newVisibleRect = adjustTiledLayerVisibleRect(tiledBacking(), m_visibleRect, newVisibleRect, m_sizeAtLastVisibleRectUpdate, m_size); 935 936 if (newVisibleRect != m_visibleRect) { 937 if (TiledBacking* tiledBacking = this->tiledBacking()) { 938 if (tiledBacking->tilesWouldChangeForVisibleRect(newVisibleRect)) 939 return true; 940 } 941 } 942 943 if (m_maskLayer) { 944 GraphicsLayerCA* maskLayerCA = static_cast<GraphicsLayerCA*>(m_maskLayer); 945 if (maskLayerCA->recursiveVisibleRectChangeRequiresFlush(localState)) 946 return true; 947 } 948 949 const Vector<GraphicsLayer*>& childLayers = children(); 950 size_t numChildren = childLayers.size(); 951 952 for (size_t i = 0; i < numChildren; ++i) { 953 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 954 if (curChild->recursiveVisibleRectChangeRequiresFlush(localState)) 955 return true; 956 } 957 958 if (m_replicaLayer) 959 if (static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveVisibleRectChangeRequiresFlush(localState)) 960 return true; 961 962 return false; 963} 964 965bool GraphicsLayerCA::visibleRectChangeRequiresFlush(const FloatRect& clipRect) const 966{ 967 TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect)); 968 return recursiveVisibleRectChangeRequiresFlush(state); 969} 970 971TiledBacking* GraphicsLayerCA::tiledBacking() const 972{ 973 return m_layer->tiledBacking(); 974} 975 976FloatRect GraphicsLayerCA::computeVisibleRect(TransformState& state, ComputeVisibleRectFlags flags) const 977{ 978 bool preserve3D = preserves3D() || (parent() ? parent()->preserves3D() : false); 979 TransformState::TransformAccumulation accumulation = preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform; 980 981 TransformationMatrix layerTransform; 982 FloatPoint position = m_position; 983 if (client()) 984 client()->customPositionForVisibleRectComputation(this, position); 985 986 layerTransform.translate(position.x(), position.y()); 987 988 TransformationMatrix currentTransform; 989 if (!(flags & RespectAnimatingTransforms) || !client() || !client()->getCurrentTransform(this, currentTransform)) 990 currentTransform = m_transform; 991 992 if (!currentTransform.isIdentity()) { 993 FloatPoint3D absoluteAnchorPoint(anchorPoint()); 994 absoluteAnchorPoint.scale(size().width(), size().height(), 1); 995 layerTransform.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z()); 996 layerTransform.multiply(currentTransform); 997 layerTransform.translate3d(-absoluteAnchorPoint.x(), -absoluteAnchorPoint.y(), -absoluteAnchorPoint.z()); 998 } 999 1000 if (GraphicsLayer* parentLayer = parent()) { 1001 if (!parentLayer->childrenTransform().isIdentity()) { 1002 FloatPoint3D parentAnchorPoint(parentLayer->anchorPoint()); 1003 parentAnchorPoint.scale(parentLayer->size().width(), parentLayer->size().height(), 1); 1004 1005 layerTransform.translateRight3d(-parentAnchorPoint.x(), -parentAnchorPoint.y(), -parentAnchorPoint.z()); 1006 layerTransform = parentLayer->childrenTransform() * layerTransform; 1007 layerTransform.translateRight3d(parentAnchorPoint.x(), parentAnchorPoint.y(), parentAnchorPoint.z()); 1008 } 1009 } 1010 1011 bool applyWasClamped; 1012 state.applyTransform(layerTransform, accumulation, &applyWasClamped); 1013 1014 bool mapWasClamped; 1015 FloatRect clipRectForChildren = state.mappedQuad(&mapWasClamped).boundingBox(); 1016 FloatPoint boundsOrigin = m_boundsOrigin; 1017 clipRectForChildren.move(boundsOrigin.x(), boundsOrigin.y()); 1018 1019 FloatRect clipRectForSelf(boundsOrigin, m_size); 1020 if (!applyWasClamped && !mapWasClamped) 1021 clipRectForSelf.intersect(clipRectForChildren); 1022 1023 if (masksToBounds()) { 1024 ASSERT(accumulation == TransformState::FlattenTransform); 1025 // Replace the quad in the TransformState with one that is clipped to this layer's bounds 1026 state.setQuad(clipRectForSelf); 1027 } 1028 1029 return clipRectForSelf; 1030} 1031 1032void GraphicsLayerCA::recursiveCommitChanges(const CommitState& commitState, const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale) 1033{ 1034 TransformState localState = state; 1035 CommitState childCommitState = commitState; 1036 bool affectedByTransformAnimation = commitState.ancestorHasTransformAnimation; 1037 1038 FloatRect visibleRect = computeVisibleRect(localState); 1039 FloatRect oldVisibleRect = m_visibleRect; 1040 if (visibleRect != m_visibleRect) { 1041 m_uncommittedChanges |= VisibleRectChanged; 1042 m_visibleRect = visibleRect; 1043 } 1044 1045#ifdef VISIBLE_TILE_WASH 1046 // Use having a transform as a key to making the tile wash layer. If every layer gets a wash, 1047 // they start to obscure useful information. 1048 if ((!m_transform.isIdentity() || m_usingTiledBacking) && !m_visibleTileWashLayer) { 1049 static Color washFillColor(255, 0, 0, 50); 1050 static Color washBorderColor(255, 0, 0, 100); 1051 1052 m_visibleTileWashLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); 1053 String name = String::format("Visible Tile Wash Layer %p", m_visibleTileWashLayer->platformLayer()); 1054 m_visibleTileWashLayer->setName(name); 1055 m_visibleTileWashLayer->setAnchorPoint(FloatPoint3D(0, 0, 0)); 1056 m_visibleTileWashLayer->setBorderColor(washBorderColor); 1057 m_visibleTileWashLayer->setBorderWidth(8); 1058 m_visibleTileWashLayer->setBackgroundColor(washFillColor); 1059 noteSublayersChanged(); 1060 } 1061 1062 if (m_visibleTileWashLayer) 1063 m_visibleTileWashLayer->setFrame(m_visibleRect); 1064#endif 1065 1066 bool hadChanges = m_uncommittedChanges; 1067 1068 if (appliesPageScale()) { 1069 pageScaleFactor = this->pageScaleFactor(); 1070 affectedByPageScale = true; 1071 } 1072 1073 // Accumulate an offset from the ancestral pixel-aligned layer. 1074 FloatPoint baseRelativePosition = positionRelativeToBase; 1075 if (affectedByPageScale) 1076 baseRelativePosition += m_position; 1077 1078 commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect); 1079 1080 if (isRunningTransformAnimation()) { 1081 childCommitState.ancestorHasTransformAnimation = true; 1082 affectedByTransformAnimation = true; 1083 } 1084 1085 if (m_maskLayer) { 1086 GraphicsLayerCA* maskLayerCA = static_cast<GraphicsLayerCA*>(m_maskLayer); 1087 maskLayerCA->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, maskLayerCA->visibleRect()); 1088 } 1089 1090 const Vector<GraphicsLayer*>& childLayers = children(); 1091 size_t numChildren = childLayers.size(); 1092 1093 for (size_t i = 0; i < numChildren; ++i) { 1094 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 1095 curChild->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale); 1096 } 1097 1098 if (m_replicaLayer) 1099 static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale); 1100 1101 if (m_maskLayer) 1102 static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers(childCommitState); 1103 1104 commitLayerChangesAfterSublayers(childCommitState); 1105 1106 if (affectedByTransformAnimation && client() && m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer) 1107 client()->notifyFlushBeforeDisplayRefresh(this); 1108 1109 if (hadChanges && client()) 1110 client()->didCommitChangesForLayer(this); 1111} 1112 1113bool GraphicsLayerCA::platformCALayerShowRepaintCounter(PlatformCALayer* platformLayer) const 1114{ 1115 // The repaint counters are painted into the TileController tiles (which have no corresponding platform layer), 1116 // so we don't want to overpaint the repaint counter when called with the TileController's own layer. 1117 if (m_isPageTiledBackingLayer && platformLayer) 1118 return false; 1119 1120 return isShowingRepaintCounter(); 1121} 1122 1123void GraphicsLayerCA::platformCALayerPaintContents(GraphicsContext& context, const IntRect& clip) 1124{ 1125 paintGraphicsLayerContents(context, clip); 1126} 1127 1128void GraphicsLayerCA::platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) 1129{ 1130 ASSERT(m_layer->usesTiledBackingLayer()); 1131 1132 for (size_t i = 0; i < dirtyRects.size(); ++i) 1133 setNeedsDisplayInRect(dirtyRects[i]); 1134 1135 noteLayerPropertyChanged(TilesAdded); 1136} 1137 1138float GraphicsLayerCA::platformCALayerDeviceScaleFactor() 1139{ 1140 return deviceScaleFactor(); 1141} 1142 1143void GraphicsLayerCA::commitLayerChangesBeforeSublayers(CommitState& commitState, float pageScaleFactor, const FloatPoint& positionRelativeToBase, const FloatRect& oldVisibleRect) 1144{ 1145 ++commitState.treeDepth; 1146 if (m_structuralLayer) 1147 ++commitState.treeDepth; 1148 1149 if (!m_uncommittedChanges) { 1150 // Ensure that we cap layer depth in commitLayerChangesAfterSublayers(). 1151 if (commitState.treeDepth > cMaxLayerTreeDepth) 1152 m_uncommittedChanges |= ChildrenChanged; 1153 return; 1154 } 1155 1156 bool needTiledLayer = requiresTiledLayer(pageScaleFactor); 1157 if (needTiledLayer != m_usingTiledBacking) 1158 swapFromOrToTiledLayer(needTiledLayer); 1159 1160 // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to 1161 if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged)) 1162 updateStructuralLayer(); 1163 1164 if (m_uncommittedChanges & GeometryChanged) 1165 updateGeometry(pageScaleFactor, positionRelativeToBase); 1166 1167 if (m_uncommittedChanges & DrawsContentChanged) 1168 updateLayerDrawsContent(); 1169 1170 if (m_uncommittedChanges & NameChanged) 1171 updateLayerNames(); 1172 1173 if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged 1174 updateContentsImage(); 1175 1176 if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged 1177 updateContentsMediaLayer(); 1178 1179 if (m_uncommittedChanges & ContentsCanvasLayerChanged) // Needs to happen before ChildrenChanged 1180 updateContentsCanvasLayer(); 1181 1182 if (m_uncommittedChanges & ContentsColorLayerChanged) // Needs to happen before ChildrenChanged 1183 updateContentsColorLayer(); 1184 1185 if (m_uncommittedChanges & BackgroundColorChanged) 1186 updateBackgroundColor(); 1187 1188 if (m_uncommittedChanges & TransformChanged) 1189 updateTransform(); 1190 1191 if (m_uncommittedChanges & ChildrenTransformChanged) 1192 updateChildrenTransform(); 1193 1194 if (m_uncommittedChanges & MasksToBoundsChanged) 1195 updateMasksToBounds(); 1196 1197 if (m_uncommittedChanges & ContentsVisibilityChanged) 1198 updateContentsVisibility(); 1199 1200 // Note that contentsScale can affect whether the layer can be opaque. 1201 if (m_uncommittedChanges & ContentsOpaqueChanged) 1202 updateContentsOpaque(pageScaleFactor); 1203 1204 if (m_uncommittedChanges & BackfaceVisibilityChanged) 1205 updateBackfaceVisibility(); 1206 1207 if (m_uncommittedChanges & OpacityChanged) 1208 updateOpacityOnLayer(); 1209 1210#if ENABLE(CSS_FILTERS) 1211 if (m_uncommittedChanges & FiltersChanged) 1212 updateFilters(); 1213#endif 1214 1215 if (m_uncommittedChanges & AnimationChanged) 1216 updateAnimations(); 1217 1218 // Updating the contents scale can cause parts of the layer to be invalidated, 1219 // so make sure to update the contents scale before updating the dirty rects. 1220 if (m_uncommittedChanges & ContentsScaleChanged) 1221 updateContentsScale(pageScaleFactor); 1222 1223 if (m_uncommittedChanges & VisibleRectChanged) 1224 updateVisibleRect(oldVisibleRect); 1225 1226 if (m_uncommittedChanges & DirtyRectsChanged) 1227 repaintLayerDirtyRects(); 1228 1229 if (m_uncommittedChanges & ContentsRectChanged) 1230 updateContentsRect(); 1231 1232 if (m_uncommittedChanges & MaskLayerChanged) 1233 updateMaskLayer(); 1234 1235 if (m_uncommittedChanges & ContentsNeedsDisplay) 1236 updateContentsNeedsDisplay(); 1237 1238 if (m_uncommittedChanges & AcceleratesDrawingChanged) 1239 updateAcceleratesDrawing(); 1240 1241 if (m_uncommittedChanges & DebugIndicatorsChanged) 1242 updateDebugBorder(); 1243 1244 if (m_uncommittedChanges & ChildrenChanged) { 1245 updateSublayerList(); 1246 // Sublayers may set this flag again, so clear it to avoid always updating sublayers in commitLayerChangesAfterSublayers(). 1247 m_uncommittedChanges &= ~ChildrenChanged; 1248 } 1249 1250 // Ensure that we cap layer depth in commitLayerChangesAfterSublayers(). 1251 if (commitState.treeDepth > cMaxLayerTreeDepth) 1252 m_uncommittedChanges |= ChildrenChanged; 1253} 1254 1255void GraphicsLayerCA::commitLayerChangesAfterSublayers(CommitState& commitState) 1256{ 1257 if (!m_uncommittedChanges) 1258 return; 1259 1260 if (m_uncommittedChanges & ChildrenChanged) 1261 updateSublayerList(commitState.treeDepth > cMaxLayerTreeDepth); 1262 1263 if (m_uncommittedChanges & ReplicatedLayerChanged) 1264 updateReplicatedLayers(); 1265 1266 m_uncommittedChanges = NoChange; 1267} 1268 1269void GraphicsLayerCA::updateLayerNames() 1270{ 1271 switch (structuralLayerPurpose()) { 1272 case StructuralLayerForPreserves3D: 1273 m_structuralLayer->setName("Transform layer " + name()); 1274 break; 1275 case StructuralLayerForReplicaFlattening: 1276 m_structuralLayer->setName("Replica flattening layer " + name()); 1277 break; 1278 case NoStructuralLayer: 1279 break; 1280 } 1281 m_layer->setName(name()); 1282} 1283 1284void GraphicsLayerCA::updateSublayerList(bool maxLayerDepthReached) 1285{ 1286 if (maxLayerDepthReached) { 1287 m_layer->setSublayers(PlatformCALayerList()); 1288 return; 1289 } 1290 1291 const PlatformCALayerList* customSublayers = m_layer->customSublayers(); 1292 1293 PlatformCALayerList structuralLayerChildren; 1294 PlatformCALayerList primaryLayerChildren; 1295 1296 PlatformCALayerList& childListForSublayers = m_structuralLayer ? structuralLayerChildren : primaryLayerChildren; 1297 1298 if (customSublayers) 1299 primaryLayerChildren.appendVector(*customSublayers); 1300 1301 if (m_structuralLayer) { 1302 if (m_replicaLayer) 1303 structuralLayerChildren.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer()); 1304 1305 structuralLayerChildren.append(m_layer); 1306 } 1307 1308 if (m_contentsLayer && m_contentsVisible) { 1309 // FIXME: add the contents layer in the correct order with negative z-order children. 1310 // This does not cause visible rendering issues because currently contents layers are only used 1311 // for replaced elements that don't have children. 1312 primaryLayerChildren.append(m_contentsLayer); 1313 } 1314 1315 const Vector<GraphicsLayer*>& childLayers = children(); 1316 size_t numChildren = childLayers.size(); 1317 for (size_t i = 0; i < numChildren; ++i) { 1318 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 1319 PlatformCALayer* childLayer = curChild->layerForSuperlayer(); 1320 childListForSublayers.append(childLayer); 1321 } 1322 1323#ifdef VISIBLE_TILE_WASH 1324 if (m_visibleTileWashLayer) 1325 childListForSublayers.append(m_visibleTileWashLayer); 1326#endif 1327 1328 if (m_structuralLayer) 1329 m_structuralLayer->setSublayers(structuralLayerChildren); 1330 1331 m_layer->setSublayers(primaryLayerChildren); 1332} 1333 1334void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& positionRelativeToBase) 1335{ 1336 FloatPoint scaledPosition; 1337 FloatPoint3D scaledAnchorPoint; 1338 FloatSize scaledSize; 1339 FloatSize pixelAlignmentOffset; 1340 computePixelAlignment(pageScaleFactor, positionRelativeToBase, scaledPosition, scaledSize, scaledAnchorPoint, pixelAlignmentOffset); 1341 1342 FloatRect adjustedBounds(m_boundsOrigin - pixelAlignmentOffset, scaledSize); 1343 1344 // Update position. 1345 // Position is offset on the layer by the layer anchor point. 1346 FloatPoint adjustedPosition(scaledPosition.x() + scaledAnchorPoint.x() * scaledSize.width(), scaledPosition.y() + scaledAnchorPoint.y() * scaledSize.height()); 1347 1348 if (m_structuralLayer) { 1349 FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(), m_position.y() + m_anchorPoint.y() * m_size.height()); 1350 FloatRect layerBounds(m_boundsOrigin, m_size); 1351 1352 m_structuralLayer->setPosition(layerPosition); 1353 m_structuralLayer->setBounds(layerBounds); 1354 m_structuralLayer->setAnchorPoint(m_anchorPoint); 1355 1356 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { 1357 LayerMap::const_iterator end = layerCloneMap->end(); 1358 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1359 PlatformCALayer* clone = it->value.get(); 1360 FloatPoint clonePosition = layerPosition; 1361 1362 if (m_replicaLayer && isReplicatedRootClone(it->key)) { 1363 // Maintain the special-case position for the root of a clone subtree, 1364 // which we set up in replicatedLayerRoot(). 1365 clonePosition = positionForCloneRootLayer(); 1366 } 1367 1368 clone->setPosition(clonePosition); 1369 clone->setBounds(layerBounds); 1370 clone->setAnchorPoint(m_anchorPoint); 1371 } 1372 } 1373 1374 // If we have a structural layer, we just use 0.5, 0.5 for the anchor point of the main layer. 1375 scaledAnchorPoint = FloatPoint(0.5f, 0.5f); 1376 adjustedPosition = FloatPoint(scaledAnchorPoint.x() * scaledSize.width() - pixelAlignmentOffset.width(), scaledAnchorPoint.y() * scaledSize.height() - pixelAlignmentOffset.height()); 1377 } 1378 1379 m_layer->setPosition(adjustedPosition); 1380 m_layer->setBounds(adjustedBounds); 1381 m_layer->setAnchorPoint(scaledAnchorPoint); 1382 1383 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1384 LayerMap::const_iterator end = layerCloneMap->end(); 1385 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1386 PlatformCALayer* clone = it->value.get(); 1387 FloatPoint clonePosition = adjustedPosition; 1388 1389 if (!m_structuralLayer && m_replicaLayer && isReplicatedRootClone(it->key)) { 1390 // Maintain the special-case position for the root of a clone subtree, 1391 // which we set up in replicatedLayerRoot(). 1392 clonePosition = positionForCloneRootLayer(); 1393 } 1394 1395 clone->setPosition(clonePosition); 1396 clone->setBounds(adjustedBounds); 1397 clone->setAnchorPoint(scaledAnchorPoint); 1398 } 1399 } 1400} 1401 1402void GraphicsLayerCA::updateTransform() 1403{ 1404 primaryLayer()->setTransform(m_transform); 1405 1406 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1407 LayerMap::const_iterator end = layerCloneMap->end(); 1408 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1409 PlatformCALayer* currLayer = it->value.get(); 1410 if (m_replicaLayer && isReplicatedRootClone(it->key)) { 1411 // Maintain the special-case transform for the root of a clone subtree, 1412 // which we set up in replicatedLayerRoot(). 1413 currLayer->setTransform(TransformationMatrix()); 1414 } else 1415 currLayer->setTransform(m_transform); 1416 } 1417 } 1418} 1419 1420void GraphicsLayerCA::updateChildrenTransform() 1421{ 1422 primaryLayer()->setSublayerTransform(m_childrenTransform); 1423 1424 if (LayerMap* layerCloneMap = primaryLayerClones()) { 1425 LayerMap::const_iterator end = layerCloneMap->end(); 1426 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1427 it->value->setSublayerTransform(m_childrenTransform); 1428 } 1429} 1430 1431void GraphicsLayerCA::updateMasksToBounds() 1432{ 1433 m_layer->setMasksToBounds(m_masksToBounds); 1434 1435 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1436 LayerMap::const_iterator end = layerCloneMap->end(); 1437 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1438 it->value->setMasksToBounds(m_masksToBounds); 1439 } 1440} 1441 1442void GraphicsLayerCA::updateContentsVisibility() 1443{ 1444 // Note that m_contentsVisible also affects whether m_contentsLayer is parented. 1445 if (m_contentsVisible) { 1446 if (m_drawsContent) 1447 m_layer->setNeedsDisplay(); 1448 } else { 1449 m_layer->setContents(0); 1450 1451 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1452 LayerMap::const_iterator end = layerCloneMap->end(); 1453 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1454 it->value->setContents(0); 1455 } 1456 } 1457} 1458 1459void GraphicsLayerCA::updateContentsOpaque(float pageScaleFactor) 1460{ 1461 bool contentsOpaque = m_contentsOpaque; 1462 if (contentsOpaque) { 1463 float contentsScale = clampedContentsScaleForScale(pageScaleFactor * deviceScaleFactor()); 1464 if (!isIntegral(contentsScale)) 1465 contentsOpaque = false; 1466 } 1467 1468 m_layer->setOpaque(contentsOpaque); 1469 1470 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1471 LayerMap::const_iterator end = layerCloneMap->end(); 1472 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1473 it->value->setOpaque(contentsOpaque); 1474 } 1475} 1476 1477void GraphicsLayerCA::updateBackfaceVisibility() 1478{ 1479 if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) { 1480 m_structuralLayer->setDoubleSided(m_backfaceVisibility); 1481 1482 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { 1483 LayerMap::const_iterator end = layerCloneMap->end(); 1484 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1485 it->value->setDoubleSided(m_backfaceVisibility); 1486 } 1487 } 1488 1489 m_layer->setDoubleSided(m_backfaceVisibility); 1490 1491 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1492 LayerMap::const_iterator end = layerCloneMap->end(); 1493 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) 1494 it->value->setDoubleSided(m_backfaceVisibility); 1495 } 1496} 1497 1498#if ENABLE(CSS_FILTERS) 1499void GraphicsLayerCA::updateFilters() 1500{ 1501 m_layer->setFilters(m_filters); 1502 1503 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1504 LayerMap::const_iterator end = layerCloneMap->end(); 1505 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1506 if (m_replicaLayer && isReplicatedRootClone(it->key)) 1507 continue; 1508 1509 it->value->setFilters(m_filters); 1510 } 1511 } 1512} 1513#endif 1514 1515void GraphicsLayerCA::updateStructuralLayer() 1516{ 1517 ensureStructuralLayer(structuralLayerPurpose()); 1518} 1519 1520void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose) 1521{ 1522 const LayerChangeFlags structuralLayerChangeFlags = NameChanged 1523 | GeometryChanged 1524 | TransformChanged 1525 | ChildrenTransformChanged 1526 | ChildrenChanged 1527 | BackfaceVisibilityChanged 1528#if ENABLE(CSS_FILTERS) 1529 | FiltersChanged 1530#endif 1531 | OpacityChanged; 1532 1533 if (purpose == NoStructuralLayer) { 1534 if (m_structuralLayer) { 1535 // Replace the transformLayer in the parent with this layer. 1536 m_layer->removeFromSuperlayer(); 1537 1538 // If m_layer doesn't have a parent, it means it's the root layer and 1539 // is likely hosted by something that is not expecting to be changed 1540 ASSERT(m_structuralLayer->superlayer()); 1541 m_structuralLayer->superlayer()->replaceSublayer(m_structuralLayer.get(), m_layer.get()); 1542 1543 moveOrCopyAnimations(Move, m_structuralLayer.get(), m_layer.get()); 1544 1545 // Release the structural layer. 1546 m_structuralLayer = 0; 1547 1548 m_uncommittedChanges |= structuralLayerChangeFlags; 1549 } 1550 return; 1551 } 1552 1553 bool structuralLayerChanged = false; 1554 1555 if (purpose == StructuralLayerForPreserves3D) { 1556 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer) 1557 m_structuralLayer = 0; 1558 1559 if (!m_structuralLayer) { 1560 m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeTransformLayer, this); 1561 structuralLayerChanged = true; 1562 } 1563 } else { 1564 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer) 1565 m_structuralLayer = 0; 1566 1567 if (!m_structuralLayer) { 1568 m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); 1569 structuralLayerChanged = true; 1570 } 1571 } 1572 1573 if (!structuralLayerChanged) 1574 return; 1575 1576 m_uncommittedChanges |= structuralLayerChangeFlags; 1577 1578 // We've changed the layer that our parent added to its sublayer list, so tell it to update 1579 // sublayers again in its commitLayerChangesAfterSublayers(). 1580 static_cast<GraphicsLayerCA*>(parent())->noteSublayersChanged(); 1581 1582 // Set properties of m_layer to their default values, since these are expressed on on the structural layer. 1583 FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f); 1584 FloatPoint3D anchorPoint(0.5f, 0.5f, 0); 1585 m_layer->setPosition(point); 1586 m_layer->setAnchorPoint(anchorPoint); 1587 m_layer->setTransform(TransformationMatrix()); 1588 m_layer->setOpacity(1); 1589 if (m_layerClones) { 1590 LayerMap::const_iterator end = m_layerClones->end(); 1591 for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) { 1592 PlatformCALayer* currLayer = it->value.get(); 1593 currLayer->setPosition(point); 1594 currLayer->setAnchorPoint(anchorPoint); 1595 currLayer->setTransform(TransformationMatrix()); 1596 currLayer->setOpacity(1); 1597 } 1598 } 1599 1600 moveOrCopyAnimations(Move, m_layer.get(), m_structuralLayer.get()); 1601} 1602 1603GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const 1604{ 1605 if (preserves3D()) 1606 return StructuralLayerForPreserves3D; 1607 1608 if (isReplicated()) 1609 return StructuralLayerForReplicaFlattening; 1610 1611 return NoStructuralLayer; 1612} 1613 1614void GraphicsLayerCA::updateLayerDrawsContent() 1615{ 1616 if (m_drawsContent) 1617 m_layer->setNeedsDisplay(); 1618 else { 1619 m_layer->setContents(0); 1620 if (m_layerClones) { 1621 LayerMap::const_iterator end = m_layerClones->end(); 1622 for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) 1623 it->value->setContents(0); 1624 } 1625 } 1626} 1627 1628void GraphicsLayerCA::updateAcceleratesDrawing() 1629{ 1630 m_layer->setAcceleratesDrawing(m_acceleratesDrawing); 1631} 1632 1633void GraphicsLayerCA::updateDebugBorder() 1634{ 1635 if (isShowingDebugBorder()) 1636 updateDebugIndicators(); 1637 else 1638 m_layer->setBorderWidth(0); 1639} 1640 1641FloatRect GraphicsLayerCA::adjustTiledLayerVisibleRect(TiledBacking* tiledBacking, const FloatRect& oldVisibleRect, const FloatRect& newVisibleRect, const FloatSize& oldSize, const FloatSize& newSize) 1642{ 1643 // If the old visible rect is empty, we have no information about how the visible area is changing 1644 // (maybe the layer was just created), so don't attempt to expand. Also don't attempt to expand 1645 // if the size changed. 1646 if (oldVisibleRect.isEmpty() || newSize != oldSize) 1647 return newVisibleRect; 1648 1649 const float paddingMultiplier = 2; 1650 1651 float leftEdgeDelta = paddingMultiplier * (newVisibleRect.x() - oldVisibleRect.x()); 1652 float rightEdgeDelta = paddingMultiplier * (newVisibleRect.maxX() - oldVisibleRect.maxX()); 1653 1654 float topEdgeDelta = paddingMultiplier * (newVisibleRect.y() - oldVisibleRect.y()); 1655 float bottomEdgeDelta = paddingMultiplier * (newVisibleRect.maxY() - oldVisibleRect.maxY()); 1656 1657 FloatRect existingTileBackingRect = tiledBacking->visibleRect(); 1658 FloatRect expandedRect = newVisibleRect; 1659 1660 // More exposed on left side. 1661 if (leftEdgeDelta < 0) { 1662 float newLeft = expandedRect.x() + leftEdgeDelta; 1663 // Pad to the left, but don't reduce padding that's already in the backing store (since we're still exposing to the left). 1664 if (newLeft < existingTileBackingRect.x()) 1665 expandedRect.shiftXEdgeTo(newLeft); 1666 else 1667 expandedRect.shiftXEdgeTo(existingTileBackingRect.x()); 1668 } 1669 1670 // More exposed on right. 1671 if (rightEdgeDelta > 0) { 1672 float newRight = expandedRect.maxX() + rightEdgeDelta; 1673 // Pad to the right, but don't reduce padding that's already in the backing store (since we're still exposing to the right). 1674 if (newRight > existingTileBackingRect.maxX()) 1675 expandedRect.setWidth(newRight - expandedRect.x()); 1676 else 1677 expandedRect.setWidth(existingTileBackingRect.maxX() - expandedRect.x()); 1678 } 1679 1680 // More exposed at top. 1681 if (topEdgeDelta < 0) { 1682 float newTop = expandedRect.y() + topEdgeDelta; 1683 if (newTop < existingTileBackingRect.y()) 1684 expandedRect.shiftYEdgeTo(newTop); 1685 else 1686 expandedRect.shiftYEdgeTo(existingTileBackingRect.y()); 1687 } 1688 1689 // More exposed on bottom. 1690 if (bottomEdgeDelta > 0) { 1691 float newBottom = expandedRect.maxY() + bottomEdgeDelta; 1692 if (newBottom > existingTileBackingRect.maxY()) 1693 expandedRect.setHeight(newBottom - expandedRect.y()); 1694 else 1695 expandedRect.setHeight(existingTileBackingRect.maxY() - expandedRect.y()); 1696 } 1697 1698 return expandedRect; 1699} 1700 1701void GraphicsLayerCA::updateVisibleRect(const FloatRect& oldVisibleRect) 1702{ 1703 if (!m_layer->usesTiledBackingLayer()) 1704 return; 1705 1706 FloatRect tileArea = m_visibleRect; 1707 if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer) 1708 tileArea = adjustTiledLayerVisibleRect(tiledBacking(), oldVisibleRect, tileArea, m_sizeAtLastVisibleRectUpdate, m_size); 1709 1710 tiledBacking()->setVisibleRect(tileArea); 1711 1712 m_sizeAtLastVisibleRectUpdate = m_size; 1713} 1714 1715void GraphicsLayerCA::updateBackgroundColor() 1716{ 1717 m_layer->setBackgroundColor(m_backgroundColor); 1718} 1719 1720void GraphicsLayerCA::updateContentsImage() 1721{ 1722 if (m_pendingContentsImage) { 1723 if (!m_contentsLayer.get()) { 1724 m_contentsLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); 1725#ifndef NDEBUG 1726 m_contentsLayer->setName("Image Layer"); 1727#endif 1728 setupContentsLayer(m_contentsLayer.get()); 1729 // m_contentsLayer will be parented by updateSublayerList 1730 } 1731 1732 // FIXME: maybe only do trilinear if the image is being scaled down, 1733 // but then what if the layer size changes? 1734 m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear); 1735 m_contentsLayer->setContents(m_pendingContentsImage.get()); 1736 m_pendingContentsImage = 0; 1737 1738 if (m_contentsLayerClones) { 1739 LayerMap::const_iterator end = m_contentsLayerClones->end(); 1740 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) 1741 it->value->setContents(m_contentsLayer->contents()); 1742 } 1743 1744 updateContentsRect(); 1745 } else { 1746 // No image. 1747 // m_contentsLayer will be removed via updateSublayerList. 1748 m_contentsLayer = 0; 1749 } 1750} 1751 1752void GraphicsLayerCA::updateContentsMediaLayer() 1753{ 1754 // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList(). 1755 if (m_contentsLayer) { 1756 setupContentsLayer(m_contentsLayer.get()); 1757 updateContentsRect(); 1758 } 1759} 1760 1761void GraphicsLayerCA::updateContentsCanvasLayer() 1762{ 1763 // CanvasLayer was set as m_contentsLayer, and will get parented in updateSublayerList(). 1764 if (m_contentsLayer) { 1765 setupContentsLayer(m_contentsLayer.get()); 1766 m_contentsLayer->setNeedsDisplay(); 1767 updateContentsRect(); 1768 } 1769} 1770 1771void GraphicsLayerCA::updateContentsColorLayer() 1772{ 1773 // Color layer was set as m_contentsLayer, and will get parented in updateSublayerList(). 1774 if (m_contentsLayer) { 1775 setupContentsLayer(m_contentsLayer.get()); 1776 updateContentsRect(); 1777 ASSERT(m_contentsSolidColor.isValid()); // An invalid color should have removed the contents layer. 1778 m_contentsLayer->setBackgroundColor(m_contentsSolidColor); 1779 1780 if (m_contentsLayerClones) { 1781 LayerMap::const_iterator end = m_contentsLayerClones->end(); 1782 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) 1783 it->value->setBackgroundColor(m_contentsSolidColor); 1784 } 1785 } 1786} 1787 1788void GraphicsLayerCA::updateContentsRect() 1789{ 1790 if (!m_contentsLayer) 1791 return; 1792 1793 FloatPoint point(m_contentsRect.x(), m_contentsRect.y()); 1794 FloatRect rect(0, 0, m_contentsRect.width(), m_contentsRect.height()); 1795 1796 m_contentsLayer->setPosition(point); 1797 m_contentsLayer->setBounds(rect); 1798 1799 if (m_contentsLayerClones) { 1800 LayerMap::const_iterator end = m_contentsLayerClones->end(); 1801 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) { 1802 it->value->setPosition(point); 1803 it->value->setBounds(rect); 1804 } 1805 } 1806} 1807 1808void GraphicsLayerCA::updateMaskLayer() 1809{ 1810 PlatformCALayer* maskCALayer = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayer() : 0; 1811 m_layer->setMask(maskCALayer); 1812 1813 LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0; 1814 1815 if (LayerMap* layerCloneMap = m_layerClones.get()) { 1816 LayerMap::const_iterator end = layerCloneMap->end(); 1817 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1818 PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->key) : 0; 1819 it->value->setMask(maskClone); 1820 } 1821 } 1822} 1823 1824void GraphicsLayerCA::updateReplicatedLayers() 1825{ 1826 // Clone the descendants of the replicated layer, and parent under us. 1827 ReplicaState replicaState(ReplicaState::ReplicaBranch); 1828 1829 RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState); 1830 if (!replicaRoot) 1831 return; 1832 1833 if (m_structuralLayer) 1834 m_structuralLayer->insertSublayer(replicaRoot.get(), 0); 1835 else 1836 m_layer->insertSublayer(replicaRoot.get(), 0); 1837} 1838 1839// For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1. 1840GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const 1841{ 1842 size_t depth = m_replicaBranches.size(); 1843 1844 const size_t bitsPerUChar = sizeof(UChar) * 8; 1845 size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar; 1846 1847 Vector<UChar> result(vectorSize); 1848 result.fill(0); 1849 1850 // Create a string from the bit sequence which we can use to identify the clone. 1851 // Note that the string may contain embedded nulls, but that's OK. 1852 for (size_t i = 0; i < depth; ++i) { 1853 UChar& currChar = result[i / bitsPerUChar]; 1854 currChar = (currChar << 1) | m_replicaBranches[i]; 1855 } 1856 1857 return String::adopt(result); 1858} 1859 1860PassRefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState) 1861{ 1862 // Limit replica nesting, to avoid 2^N explosion of replica layers. 1863 if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth) 1864 return 0; 1865 1866 GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer); 1867 1868 RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel); 1869 FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer(); 1870 1871 // Replica root has no offset or transform 1872 clonedLayerRoot->setPosition(cloneRootPosition); 1873 clonedLayerRoot->setTransform(TransformationMatrix()); 1874 1875 return clonedLayerRoot; 1876} 1877 1878void GraphicsLayerCA::updateAnimations() 1879{ 1880 if (m_animationsToProcess.size()) { 1881 AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end(); 1882 for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) { 1883 const String& currAnimationName = it->key; 1884 AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName); 1885 if (animationIt == m_runningAnimations.end()) 1886 continue; 1887 1888 const AnimationProcessingAction& processingInfo = it->value; 1889 const Vector<LayerPropertyAnimation>& animations = animationIt->value; 1890 for (size_t i = 0; i < animations.size(); ++i) { 1891 const LayerPropertyAnimation& currAnimation = animations[i]; 1892 switch (processingInfo.action) { 1893 case Remove: 1894 removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, currAnimation.m_subIndex); 1895 break; 1896 case Pause: 1897 pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, currAnimation.m_subIndex, processingInfo.timeOffset); 1898 break; 1899 } 1900 } 1901 1902 if (processingInfo.action == Remove) 1903 m_runningAnimations.remove(currAnimationName); 1904 } 1905 1906 m_animationsToProcess.clear(); 1907 } 1908 1909 size_t numAnimations; 1910 if ((numAnimations = m_uncomittedAnimations.size())) { 1911 for (size_t i = 0; i < numAnimations; ++i) { 1912 const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i]; 1913 setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_subIndex, pendingAnimation.m_timeOffset); 1914 1915 AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name); 1916 if (it == m_runningAnimations.end()) { 1917 Vector<LayerPropertyAnimation> animations; 1918 animations.append(pendingAnimation); 1919 m_runningAnimations.add(pendingAnimation.m_name, animations); 1920 } else { 1921 Vector<LayerPropertyAnimation>& animations = it->value; 1922 animations.append(pendingAnimation); 1923 } 1924 } 1925 1926 m_uncomittedAnimations.clear(); 1927 } 1928} 1929 1930bool GraphicsLayerCA::isRunningTransformAnimation() const 1931{ 1932 AnimationsMap::const_iterator end = m_runningAnimations.end(); 1933 for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) { 1934 const Vector<LayerPropertyAnimation>& propertyAnimations = it->value; 1935 size_t numAnimations = propertyAnimations.size(); 1936 for (size_t i = 0; i < numAnimations; ++i) { 1937 const LayerPropertyAnimation& currAnimation = propertyAnimations[i]; 1938 if (currAnimation.m_property == AnimatedPropertyWebkitTransform) 1939 return true; 1940 } 1941 } 1942 return false; 1943} 1944 1945void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, int subIndex, double timeOffset) 1946{ 1947 PlatformCALayer* layer = animatedLayer(property); 1948 1949 if (timeOffset) 1950 caAnim->setBeginTime(CACurrentMediaTime() - timeOffset); 1951 1952 String animationID = animationIdentifier(animationName, property, index, subIndex); 1953 1954 layer->removeAnimationForKey(animationID); 1955 layer->addAnimationForKey(animationID, caAnim); 1956 1957 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 1958 LayerMap::const_iterator end = layerCloneMap->end(); 1959 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1960 // Skip immediate replicas, since they move with the original. 1961 if (m_replicaLayer && isReplicatedRootClone(it->key)) 1962 continue; 1963 1964 it->value->removeAnimationForKey(animationID); 1965 it->value->addAnimationForKey(animationID, caAnim); 1966 } 1967 } 1968} 1969 1970// Workaround for <rdar://problem/7311367> 1971static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform) 1972{ 1973 if (!transformLayer) 1974 return; 1975 1976 TransformationMatrix caTransform = transform; 1977 caTransform.setM41(caTransform.m41() + 1); 1978 transformLayer->setTransform(caTransform); 1979 1980 caTransform.setM41(caTransform.m41() - 1); 1981 transformLayer->setTransform(caTransform); 1982} 1983 1984bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex) 1985{ 1986 PlatformCALayer* layer = animatedLayer(property); 1987 1988 String animationID = animationIdentifier(animationName, property, index, subIndex); 1989 1990 if (!layer->animationForKey(animationID)) 1991 return false; 1992 1993 layer->removeAnimationForKey(animationID); 1994 bug7311367Workaround(m_structuralLayer.get(), m_transform); 1995 1996 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 1997 LayerMap::const_iterator end = layerCloneMap->end(); 1998 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 1999 // Skip immediate replicas, since they move with the original. 2000 if (m_replicaLayer && isReplicatedRootClone(it->key)) 2001 continue; 2002 2003 it->value->removeAnimationForKey(animationID); 2004 } 2005 } 2006 return true; 2007} 2008 2009void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex, double timeOffset) 2010{ 2011 PlatformCALayer* layer = animatedLayer(property); 2012 2013 String animationID = animationIdentifier(animationName, property, index, subIndex); 2014 2015 RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID); 2016 if (!curAnim) 2017 return; 2018 2019 // Animations on the layer are immutable, so we have to clone and modify. 2020 RefPtr<PlatformCAAnimation> newAnim = curAnim->copy(); 2021 2022 newAnim->setSpeed(0); 2023 newAnim->setTimeOffset(timeOffset); 2024 2025 layer->addAnimationForKey(animationID, newAnim.get()); // This will replace the running animation. 2026 2027 // Pause the animations on the clones too. 2028 if (LayerMap* layerCloneMap = animatedLayerClones(property)) { 2029 LayerMap::const_iterator end = layerCloneMap->end(); 2030 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2031 // Skip immediate replicas, since they move with the original. 2032 if (m_replicaLayer && isReplicatedRootClone(it->key)) 2033 continue; 2034 it->value->addAnimationForKey(animationID, newAnim.get()); 2035 } 2036 } 2037} 2038 2039void GraphicsLayerCA::repaintLayerDirtyRects() 2040{ 2041 if (!m_dirtyRects.size()) 2042 return; 2043 2044 for (size_t i = 0; i < m_dirtyRects.size(); ++i) 2045 m_layer->setNeedsDisplay(&(m_dirtyRects[i])); 2046 2047 m_dirtyRects.clear(); 2048} 2049 2050void GraphicsLayerCA::updateContentsNeedsDisplay() 2051{ 2052 if (m_contentsLayer) 2053 m_contentsLayer->setNeedsDisplay(); 2054} 2055 2056bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset) 2057{ 2058 ASSERT(valueList.property() != AnimatedPropertyWebkitTransform && (!supportsAcceleratedFilterAnimations() || valueList.property() != AnimatedPropertyWebkitFilter)); 2059 2060 bool isKeyframe = valueList.size() > 2; 2061 bool valuesOK; 2062 2063 bool additive = false; 2064 int animationIndex = 0; 2065 2066 RefPtr<PlatformCAAnimation> caAnimation; 2067 2068 if (isKeyframe) { 2069 caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive); 2070 valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get()); 2071 } else { 2072 caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive); 2073 valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get()); 2074 } 2075 2076 if (!valuesOK) 2077 return false; 2078 2079 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, 0, timeOffset)); 2080 2081 return true; 2082} 2083 2084bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperations* operations, const Animation* animation, const String& animationName, const IntSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation) 2085{ 2086 TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : operations->operations().at(animationIndex)->getOperationType(); 2087 bool additive = animationIndex > 0; 2088 bool isKeyframe = valueList.size() > 2; 2089 2090 RefPtr<PlatformCAAnimation> caAnimation; 2091 bool validMatrices = true; 2092 if (isKeyframe) { 2093 caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive); 2094 validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize); 2095 } else { 2096 caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive); 2097 validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize); 2098 } 2099 2100 if (!validMatrices) 2101 return false; 2102 2103 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, 0, timeOffset)); 2104 return true; 2105} 2106 2107bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize) 2108{ 2109 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); 2110 2111 bool hasBigRotation; 2112 int listIndex = validateTransformOperations(valueList, hasBigRotation); 2113 const TransformOperations* operations = (listIndex >= 0) ? &static_cast<const TransformAnimationValue&>(valueList.at(listIndex)).value() : 0; 2114 2115 // We need to fall back to software animation if we don't have setValueFunction:, and 2116 // we would need to animate each incoming transform function separately. This is the 2117 // case if we have a rotation >= 180 or we have more than one transform function. 2118 if ((hasBigRotation || (operations && operations->size() > 1)) && !PlatformCAAnimation::supportsValueFunction()) 2119 return false; 2120 2121 bool validMatrices = true; 2122 2123 // If function lists don't match we do a matrix animation, otherwise we do a component hardware animation. 2124 // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation 2125 // if that's not true as well. 2126 bool isMatrixAnimation = listIndex < 0 || !PlatformCAAnimation::supportsValueFunction(); 2127 int numAnimations = isMatrixAnimation ? 1 : operations->size(); 2128 2129 bool reverseAnimationList = true; 2130#if !PLATFORM(IOS) && !PLATFORM(WIN) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 2131 // Old versions of Core Animation apply animations in reverse order (<rdar://problem/7095638>) so we need to flip the list. 2132 // to be non-additive. For binary compatibility, the current version of Core Animation preserves this behavior for applications linked 2133 // on or before Snow Leopard. 2134 // FIXME: This fix has not been added to QuartzCore on Windows yet (<rdar://problem/9112233>) so we expect the 2135 // reversed animation behavior 2136 static bool executableWasLinkedOnOrBeforeSnowLeopard = wkExecutableWasLinkedOnOrBeforeSnowLeopard(); 2137 if (!executableWasLinkedOnOrBeforeSnowLeopard) 2138 reverseAnimationList = false; 2139#endif 2140 if (reverseAnimationList) { 2141 for (int animationIndex = numAnimations - 1; animationIndex >= 0; --animationIndex) { 2142 if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) { 2143 validMatrices = false; 2144 break; 2145 } 2146 } 2147 } else { 2148 for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) { 2149 if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) { 2150 validMatrices = false; 2151 break; 2152 } 2153 } 2154 } 2155 2156 return validMatrices; 2157} 2158 2159#if ENABLE(CSS_FILTERS) 2160bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const FilterOperation* operation, const Animation* animation, const String& animationName, int animationIndex, double timeOffset) 2161{ 2162 bool isKeyframe = valueList.size() > 2; 2163 2164 FilterOperation::OperationType filterOp = operation->getOperationType(); 2165 int numAnimatedProperties = PlatformCAFilters::numAnimatedFilterProperties(filterOp); 2166 2167 // Each filter might need to animate multiple properties, each with their own keyPath. The keyPath is always of the form: 2168 // 2169 // filter.filter_<animationIndex>.<filterPropertyName> 2170 // 2171 // PlatformCAAnimation tells us how many properties each filter has and we iterate that many times and create an animation 2172 // for each. This internalFilterPropertyIndex gets passed to PlatformCAAnimation so it can properly create the property animation 2173 // values. 2174 for (int internalFilterPropertyIndex = 0; internalFilterPropertyIndex < numAnimatedProperties; ++internalFilterPropertyIndex) { 2175 bool valuesOK; 2176 RefPtr<PlatformCAAnimation> caAnimation; 2177 String keyPath = String::format("filters.filter_%d.%s", animationIndex, PlatformCAFilters::animatedFilterPropertyName(filterOp, internalFilterPropertyIndex)); 2178 2179 if (isKeyframe) { 2180 caAnimation = createKeyframeAnimation(animation, keyPath, false); 2181 valuesOK = setFilterAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex, filterOp); 2182 } else { 2183 caAnimation = createBasicAnimation(animation, keyPath, false); 2184 valuesOK = setFilterAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex); 2185 } 2186 2187 ASSERT(valuesOK); 2188 2189 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, internalFilterPropertyIndex, timeOffset)); 2190 } 2191 2192 return true; 2193} 2194 2195bool GraphicsLayerCA::createFilterAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset) 2196{ 2197 ASSERT(valueList.property() == AnimatedPropertyWebkitFilter); 2198 2199 int listIndex = validateFilterOperations(valueList); 2200 if (listIndex < 0) 2201 return false; 2202 2203 const FilterOperations& operations = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value(); 2204 // Make sure the platform layer didn't fallback to using software filter compositing instead. 2205 if (!PlatformCALayer::filtersCanBeComposited(operations)) 2206 return false; 2207 2208 int numAnimations = operations.size(); 2209 2210 // FIXME: We can't currently hardware animate shadows. 2211 for (int i = 0; i < numAnimations; ++i) { 2212 if (operations.at(i)->getOperationType() == FilterOperation::DROP_SHADOW) 2213 return false; 2214 } 2215 2216 for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) { 2217 if (!appendToUncommittedAnimations(valueList, operations.operations().at(animationIndex).get(), animation, animationName, animationIndex, timeOffset)) 2218 return false; 2219 } 2220 2221 return true; 2222} 2223#endif 2224 2225PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, const String& keyPath, bool additive) 2226{ 2227 RefPtr<PlatformCAAnimation> basicAnim = PlatformCAAnimation::create(PlatformCAAnimation::Basic, keyPath); 2228 setupAnimation(basicAnim.get(), anim, additive); 2229 return basicAnim; 2230} 2231 2232PassRefPtr<PlatformCAAnimation>GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, const String& keyPath, bool additive) 2233{ 2234 RefPtr<PlatformCAAnimation> keyframeAnim = PlatformCAAnimation::create(PlatformCAAnimation::Keyframe, keyPath); 2235 setupAnimation(keyframeAnim.get(), anim, additive); 2236 return keyframeAnim; 2237} 2238 2239void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive) 2240{ 2241 double duration = anim->duration(); 2242 if (duration <= 0) 2243 duration = cAnimationAlmostZeroDuration; 2244 2245 float repeatCount = anim->iterationCount(); 2246 if (repeatCount == Animation::IterationCountInfinite) 2247 repeatCount = numeric_limits<float>::max(); 2248 else if (anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse) 2249 repeatCount /= 2; 2250 2251 PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode; 2252 switch (anim->fillMode()) { 2253 case AnimationFillModeNone: 2254 fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash. 2255 break; 2256 case AnimationFillModeBackwards: 2257 fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash. 2258 break; 2259 case AnimationFillModeForwards: 2260 fillMode = PlatformCAAnimation::Forwards; 2261 break; 2262 case AnimationFillModeBoth: 2263 fillMode = PlatformCAAnimation::Both; 2264 break; 2265 } 2266 2267 propertyAnim->setDuration(duration); 2268 propertyAnim->setRepeatCount(repeatCount); 2269 propertyAnim->setAutoreverses(anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse); 2270 propertyAnim->setRemovedOnCompletion(false); 2271 propertyAnim->setAdditive(additive); 2272 propertyAnim->setFillMode(fillMode); 2273} 2274 2275const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue& animValue, const Animation& anim) 2276{ 2277 if (animValue.timingFunction()) 2278 return animValue.timingFunction(); 2279 if (anim.isTimingFunctionSet()) 2280 return anim.timingFunction().get(); 2281 2282 return CubicBezierTimingFunction::defaultTimingFunction(); 2283} 2284 2285bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim) 2286{ 2287 bool forwards = animation->directionIsForwards(); 2288 2289 unsigned fromIndex = !forwards; 2290 unsigned toIndex = forwards; 2291 2292 switch (valueList.property()) { 2293 case AnimatedPropertyOpacity: { 2294 basicAnim->setFromValue(static_cast<const FloatAnimationValue&>(valueList.at(fromIndex)).value()); 2295 basicAnim->setToValue(static_cast<const FloatAnimationValue&>(valueList.at(toIndex)).value()); 2296 break; 2297 } 2298 default: 2299 ASSERT_NOT_REACHED(); // we don't animate color yet 2300 break; 2301 } 2302 2303 // This codepath is used for 2-keyframe animations, so we still need to look in the start 2304 // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function. 2305 const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), *animation); 2306 if (timingFunction) 2307 basicAnim->setTimingFunction(timingFunction, !forwards); 2308 2309 return true; 2310} 2311 2312bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim) 2313{ 2314 Vector<float> keyTimes; 2315 Vector<float> values; 2316 Vector<const TimingFunction*> timingFunctions; 2317 2318 bool forwards = animation->directionIsForwards(); 2319 2320 for (unsigned i = 0; i < valueList.size(); ++i) { 2321 unsigned index = forwards ? i : (valueList.size() - i - 1); 2322 const AnimationValue& curValue = valueList.at(index); 2323 keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime())); 2324 2325 switch (valueList.property()) { 2326 case AnimatedPropertyOpacity: { 2327 const FloatAnimationValue& floatValue = static_cast<const FloatAnimationValue&>(curValue); 2328 values.append(floatValue.value()); 2329 break; 2330 } 2331 default: 2332 ASSERT_NOT_REACHED(); // we don't animate color yet 2333 break; 2334 } 2335 2336 if (i < (valueList.size() - 1)) 2337 timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation)); 2338 } 2339 2340 keyframeAnim->setKeyTimes(keyTimes); 2341 keyframeAnim->setValues(values); 2342 keyframeAnim->setTimingFunctions(timingFunctions, !forwards); 2343 2344 return true; 2345} 2346 2347bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) 2348{ 2349 ASSERT(valueList.size() == 2); 2350 2351 bool forwards = animation->directionIsForwards(); 2352 2353 unsigned fromIndex = !forwards; 2354 unsigned toIndex = forwards; 2355 2356 const TransformAnimationValue& startValue = static_cast<const TransformAnimationValue&>(valueList.at(fromIndex)); 2357 const TransformAnimationValue& endValue = static_cast<const TransformAnimationValue&>(valueList.at(toIndex)); 2358 2359 if (isMatrixAnimation) { 2360 TransformationMatrix fromTransform, toTransform; 2361 startValue.value().apply(boxSize, fromTransform); 2362 endValue.value().apply(boxSize, toTransform); 2363 2364 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation 2365 if (!fromTransform.isInvertible() || !toTransform.isInvertible()) 2366 return false; 2367 2368 basicAnim->setFromValue(fromTransform); 2369 basicAnim->setToValue(toTransform); 2370 } else { 2371 if (isTransformTypeNumber(transformOpType)) { 2372 float fromValue; 2373 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue); 2374 basicAnim->setFromValue(fromValue); 2375 2376 float toValue; 2377 getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue); 2378 basicAnim->setToValue(toValue); 2379 } else if (isTransformTypeFloatPoint3D(transformOpType)) { 2380 FloatPoint3D fromValue; 2381 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue); 2382 basicAnim->setFromValue(fromValue); 2383 2384 FloatPoint3D toValue; 2385 getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue); 2386 basicAnim->setToValue(toValue); 2387 } else { 2388 TransformationMatrix fromValue; 2389 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue); 2390 basicAnim->setFromValue(fromValue); 2391 2392 TransformationMatrix toValue; 2393 getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue); 2394 basicAnim->setToValue(toValue); 2395 } 2396 } 2397 2398 // This codepath is used for 2-keyframe animations, so we still need to look in the start 2399 // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function. 2400 const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), *animation); 2401 basicAnim->setTimingFunction(timingFunction, !forwards); 2402 2403 PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType); 2404 if (valueFunction != PlatformCAAnimation::NoValueFunction) 2405 basicAnim->setValueFunction(valueFunction); 2406 2407 return true; 2408} 2409 2410bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) 2411{ 2412 Vector<float> keyTimes; 2413 Vector<float> floatValues; 2414 Vector<FloatPoint3D> floatPoint3DValues; 2415 Vector<TransformationMatrix> transformationMatrixValues; 2416 Vector<const TimingFunction*> timingFunctions; 2417 2418 bool forwards = animation->directionIsForwards(); 2419 2420 for (unsigned i = 0; i < valueList.size(); ++i) { 2421 unsigned index = forwards ? i : (valueList.size() - i - 1); 2422 const TransformAnimationValue& curValue = static_cast<const TransformAnimationValue&>(valueList.at(index)); 2423 keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime())); 2424 2425 if (isMatrixAnimation) { 2426 TransformationMatrix transform; 2427 curValue.value().apply(boxSize, transform); 2428 2429 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation 2430 if (!transform.isInvertible()) 2431 return false; 2432 2433 transformationMatrixValues.append(transform); 2434 } else { 2435 const TransformOperation* transformOp = curValue.value().at(functionIndex); 2436 if (isTransformTypeNumber(transformOpType)) { 2437 float value; 2438 getTransformFunctionValue(transformOp, transformOpType, boxSize, value); 2439 floatValues.append(value); 2440 } else if (isTransformTypeFloatPoint3D(transformOpType)) { 2441 FloatPoint3D value; 2442 getTransformFunctionValue(transformOp, transformOpType, boxSize, value); 2443 floatPoint3DValues.append(value); 2444 } else { 2445 TransformationMatrix value; 2446 getTransformFunctionValue(transformOp, transformOpType, boxSize, value); 2447 transformationMatrixValues.append(value); 2448 } 2449 } 2450 2451 if (i < (valueList.size() - 1)) 2452 timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation)); 2453 } 2454 2455 keyframeAnim->setKeyTimes(keyTimes); 2456 2457 if (isTransformTypeNumber(transformOpType)) 2458 keyframeAnim->setValues(floatValues); 2459 else if (isTransformTypeFloatPoint3D(transformOpType)) 2460 keyframeAnim->setValues(floatPoint3DValues); 2461 else 2462 keyframeAnim->setValues(transformationMatrixValues); 2463 2464 keyframeAnim->setTimingFunctions(timingFunctions, !forwards); 2465 2466 PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType); 2467 if (valueFunction != PlatformCAAnimation::NoValueFunction) 2468 keyframeAnim->setValueFunction(valueFunction); 2469 2470 return true; 2471} 2472 2473#if ENABLE(CSS_FILTERS) 2474bool GraphicsLayerCA::setFilterAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, int internalFilterPropertyIndex) 2475{ 2476 ASSERT(valueList.size() == 2); 2477 2478 bool forwards = animation->directionIsForwards(); 2479 2480 unsigned fromIndex = !forwards; 2481 unsigned toIndex = forwards; 2482 2483 const FilterAnimationValue& fromValue = static_cast<const FilterAnimationValue&>(valueList.at(fromIndex)); 2484 const FilterAnimationValue& toValue = static_cast<const FilterAnimationValue&>(valueList.at(toIndex)); 2485 2486 const FilterOperation* fromOperation = fromValue.value().at(functionIndex); 2487 const FilterOperation* toOperation = toValue.value().at(functionIndex); 2488 2489 RefPtr<DefaultFilterOperation> defaultFromOperation; 2490 RefPtr<DefaultFilterOperation> defaultToOperation; 2491 2492 ASSERT(fromOperation || toOperation); 2493 2494 if (!fromOperation) { 2495 defaultFromOperation = DefaultFilterOperation::create(toOperation->getOperationType()); 2496 fromOperation = defaultFromOperation.get(); 2497 } 2498 2499 if (!toOperation) { 2500 defaultToOperation = DefaultFilterOperation::create(fromOperation->getOperationType()); 2501 toOperation = defaultToOperation.get(); 2502 } 2503 2504 basicAnim->setFromValue(fromOperation, internalFilterPropertyIndex); 2505 basicAnim->setToValue(toOperation, internalFilterPropertyIndex); 2506 2507 // This codepath is used for 2-keyframe animations, so we still need to look in the start 2508 // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function. 2509 basicAnim->setTimingFunction(timingFunctionForAnimationValue(valueList.at(0), *animation), !forwards); 2510 2511 return true; 2512} 2513 2514bool GraphicsLayerCA::setFilterAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, int internalFilterPropertyIndex, FilterOperation::OperationType filterOp) 2515{ 2516 Vector<float> keyTimes; 2517 Vector<RefPtr<FilterOperation> > values; 2518 Vector<const TimingFunction*> timingFunctions; 2519 RefPtr<DefaultFilterOperation> defaultOperation; 2520 2521 bool forwards = animation->directionIsForwards(); 2522 2523 for (unsigned i = 0; i < valueList.size(); ++i) { 2524 unsigned index = forwards ? i : (valueList.size() - i - 1); 2525 const FilterAnimationValue& curValue = static_cast<const FilterAnimationValue&>(valueList.at(index)); 2526 keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime())); 2527 2528 if (curValue.value().operations().size() > static_cast<size_t>(functionIndex)) 2529 values.append(curValue.value().operations()[functionIndex]); 2530 else { 2531 if (!defaultOperation) 2532 defaultOperation = DefaultFilterOperation::create(filterOp); 2533 values.append(defaultOperation); 2534 } 2535 2536 if (i < (valueList.size() - 1)) 2537 timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation)); 2538 } 2539 2540 keyframeAnim->setKeyTimes(keyTimes); 2541 keyframeAnim->setValues(values, internalFilterPropertyIndex); 2542 keyframeAnim->setTimingFunctions(timingFunctions, !forwards); 2543 2544 return true; 2545} 2546#endif 2547 2548void GraphicsLayerCA::suspendAnimations(double time) 2549{ 2550 double t = PlatformCALayer::currentTimeToMediaTime(time ? time : currentTime()); 2551 primaryLayer()->setSpeed(0); 2552 primaryLayer()->setTimeOffset(t); 2553 2554 // Suspend the animations on the clones too. 2555 if (LayerMap* layerCloneMap = primaryLayerClones()) { 2556 LayerMap::const_iterator end = layerCloneMap->end(); 2557 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2558 it->value->setSpeed(0); 2559 it->value->setTimeOffset(t); 2560 } 2561 } 2562} 2563 2564void GraphicsLayerCA::resumeAnimations() 2565{ 2566 primaryLayer()->setSpeed(1); 2567 primaryLayer()->setTimeOffset(0); 2568 2569 // Resume the animations on the clones too. 2570 if (LayerMap* layerCloneMap = primaryLayerClones()) { 2571 LayerMap::const_iterator end = layerCloneMap->end(); 2572 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2573 it->value->setSpeed(1); 2574 it->value->setTimeOffset(0); 2575 } 2576 } 2577} 2578 2579PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const 2580{ 2581 return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); 2582} 2583 2584PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const 2585{ 2586 return m_structuralLayer ? m_structuralLayer.get() : m_layer.get(); 2587} 2588 2589PlatformCALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const 2590{ 2591 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer(); 2592} 2593 2594GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const 2595{ 2596 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones(); 2597} 2598 2599void GraphicsLayerCA::updateContentsScale(float pageScaleFactor) 2600{ 2601 float contentsScale = clampedContentsScaleForScale(pageScaleFactor * deviceScaleFactor()); 2602 2603 m_layer->setContentsScale(contentsScale); 2604 if (drawsContent()) 2605 m_layer->setNeedsDisplay(); 2606} 2607 2608void GraphicsLayerCA::setShowDebugBorder(bool showBorder) 2609{ 2610 if (showBorder == m_showDebugBorder) 2611 return; 2612 2613 GraphicsLayer::setShowDebugBorder(showBorder); 2614 noteLayerPropertyChanged(DebugIndicatorsChanged); 2615} 2616 2617void GraphicsLayerCA::setShowRepaintCounter(bool showCounter) 2618{ 2619 if (showCounter == m_showRepaintCounter) 2620 return; 2621 2622 GraphicsLayer::setShowRepaintCounter(showCounter); 2623 noteLayerPropertyChanged(DebugIndicatorsChanged); 2624} 2625 2626void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) 2627{ 2628 if (color.isValid()) 2629 m_layer->setBackgroundColor(color); 2630 else 2631 m_layer->setBackgroundColor(Color::transparent); 2632} 2633 2634void GraphicsLayerCA::getDebugBorderInfo(Color& color, float& width) const 2635{ 2636 if (m_isPageTiledBackingLayer) { 2637 color = Color(0, 0, 128, 128); // tile cache layer: dark blue 2638 width = 0.5; 2639 return; 2640 } 2641 2642 GraphicsLayer::getDebugBorderInfo(color, width); 2643} 2644 2645void GraphicsLayerCA::dumpAdditionalProperties(TextStream& textStream, int indent, LayerTreeAsTextBehavior behavior) const 2646{ 2647 if (behavior & LayerTreeAsTextIncludeVisibleRects) { 2648 writeIndent(textStream, indent + 1); 2649 textStream << "(visible rect " << m_visibleRect.x() << ", " << m_visibleRect.y() << " " << m_visibleRect.width() << " x " << m_visibleRect.height() << ")\n"; 2650 } 2651 2652 if (tiledBacking() && (behavior & LayerTreeAsTextIncludeTileCaches)) { 2653 if (behavior & LayerTreeAsTextDebug) { 2654 writeIndent(textStream, indent + 1); 2655 textStream << "(tiled backing " << tiledBacking() << ")\n"; 2656 } 2657 2658 IntRect tileCoverageRect = tiledBacking()->tileCoverageRect(); 2659 writeIndent(textStream, indent + 1); 2660 textStream << "(tile cache coverage " << tileCoverageRect.x() << ", " << tileCoverageRect.y() << " " << tileCoverageRect.width() << " x " << tileCoverageRect.height() << ")\n"; 2661 2662 IntSize tileSize = tiledBacking()->tileSize(); 2663 writeIndent(textStream, indent + 1); 2664 textStream << "(tile size " << tileSize.width() << " x " << tileSize.height() << ")\n"; 2665 2666 IntRect gridExtent = tiledBacking()->tileGridExtent(); 2667 writeIndent(textStream, indent + 1); 2668 textStream << "(top left tile " << gridExtent.x() << ", " << gridExtent.y() << " tiles grid " << gridExtent.width() << " x " << gridExtent.height() << ")\n"; 2669 } 2670} 2671 2672void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) 2673{ 2674 if (color.isValid()) { 2675 m_layer->setBorderColor(color); 2676 m_layer->setBorderWidth(borderWidth); 2677 } else { 2678 m_layer->setBorderColor(Color::transparent); 2679 m_layer->setBorderWidth(0); 2680 } 2681} 2682 2683bool GraphicsLayerCA::requiresTiledLayer(float pageScaleFactor) const 2684{ 2685 if (!m_drawsContent || !m_allowTiledLayer || m_isPageTiledBackingLayer) 2686 return false; 2687 2688 // FIXME: catch zero-size height or width here (or earlier)? 2689 return m_size.width() * pageScaleFactor > cMaxPixelDimension || m_size.height() * pageScaleFactor > cMaxPixelDimension; 2690} 2691 2692void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) 2693{ 2694 ASSERT(m_layer->layerType() != PlatformCALayer::LayerTypePageTiledBackingLayer); 2695 ASSERT(useTiledLayer != m_usingTiledBacking); 2696 RefPtr<PlatformCALayer> oldLayer = m_layer; 2697 2698#if PLATFORM(WIN) 2699 PlatformCALayer::LayerType layerType = useTiledLayer ? PlatformCALayer::LayerTypeWebTiledLayer : PlatformCALayer::LayerTypeWebLayer; 2700#else 2701 PlatformCALayer::LayerType layerType = useTiledLayer ? PlatformCALayer::LayerTypeTiledBackingLayer : PlatformCALayer::LayerTypeWebLayer; 2702#endif 2703 2704 m_layer = PlatformCALayer::create(layerType, this); 2705 2706 m_usingTiledBacking = useTiledLayer; 2707 2708 m_layer->adoptSublayers(oldLayer.get()); 2709 2710#ifdef VISIBLE_TILE_WASH 2711 if (m_visibleTileWashLayer) 2712 m_layer->appendSublayer(m_visibleTileWashLayer.get()); 2713#endif 2714 2715 // Skip this step if we don't have a superlayer. This is probably a benign 2716 // case that happens while restructuring the layer tree, and also occurs with 2717 // WebKit2 page overlays, which can become tiled but are out-of-tree. 2718 if (oldLayer->superlayer()) 2719 oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get()); 2720 2721 m_uncommittedChanges |= ChildrenChanged 2722 | GeometryChanged 2723 | TransformChanged 2724 | ChildrenTransformChanged 2725 | MasksToBoundsChanged 2726 | ContentsOpaqueChanged 2727 | BackfaceVisibilityChanged 2728 | BackgroundColorChanged 2729 | ContentsScaleChanged 2730 | AcceleratesDrawingChanged 2731 | FiltersChanged 2732 | OpacityChanged 2733 | DebugIndicatorsChanged; 2734 2735 if (m_usingTiledBacking) 2736 m_uncommittedChanges |= VisibleRectChanged; 2737 2738#ifndef NDEBUG 2739 String name = String::format("%sCALayer(%p) GraphicsLayer(%p) ", (m_layer->layerType() == PlatformCALayer::LayerTypeWebTiledLayer) ? "Tiled " : "", m_layer->platformLayer(), this) + m_name; 2740 m_layer->setName(name); 2741#endif 2742 2743 // move over animations 2744 moveOrCopyAnimations(Move, oldLayer.get(), m_layer.get()); 2745 2746 // need to tell new layer to draw itself 2747 setNeedsDisplay(); 2748 2749 if (client()) 2750 client()->tiledBackingUsageChanged(this, m_usingTiledBacking); 2751} 2752 2753GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const 2754{ 2755 return CompositingCoordinatesTopDown; 2756} 2757 2758void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer) 2759{ 2760 // Turn off implicit animations on the inner layer. 2761 contentsLayer->setMasksToBounds(true); 2762 2763 if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) { 2764 TransformationMatrix flipper( 2765 1.0f, 0.0f, 0.0f, 0.0f, 2766 0.0f, -1.0f, 0.0f, 0.0f, 2767 0.0f, 0.0f, 1.0f, 0.0f, 2768 0.0f, 0.0f, 0.0f, 1.0f); 2769 contentsLayer->setTransform(flipper); 2770 contentsLayer->setAnchorPoint(FloatPoint3D(0, 1, 0)); 2771 } else 2772 contentsLayer->setAnchorPoint(FloatPoint3D()); 2773 2774 if (isShowingDebugBorder()) { 2775 contentsLayer->setBorderColor(Color(0, 0, 128, 180)); 2776 contentsLayer->setBorderWidth(1.0f); 2777 } 2778} 2779 2780PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, PlatformCALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel) 2781{ 2782 if (!sourceLayer) 2783 return 0; 2784 2785 RefPtr<PlatformCALayer> resultLayer; 2786 2787 // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells 2788 // us whether there's an item there. This technique avoids two hash lookups. 2789 RefPtr<PlatformCALayer> dummy; 2790 LayerMap::AddResult addResult = clones->add(cloneID, dummy); 2791 if (!addResult.isNewEntry) { 2792 // Value was not added, so it exists already. 2793 resultLayer = addResult.iterator->value.get(); 2794 } else { 2795 resultLayer = cloneLayer(sourceLayer, cloneLevel); 2796#ifndef NDEBUG 2797 resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer->platformLayer())); 2798#endif 2799 addResult.iterator->value = resultLayer; 2800 } 2801 2802 return resultLayer; 2803} 2804 2805void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer, RefPtr<PlatformCALayer>& contentsLayer, CloneLevel cloneLevel) 2806{ 2807 structuralLayer = 0; 2808 contentsLayer = 0; 2809 2810 if (!m_layerClones) 2811 m_layerClones = adoptPtr(new LayerMap); 2812 2813 if (!m_structuralLayerClones && m_structuralLayer) 2814 m_structuralLayerClones = adoptPtr(new LayerMap); 2815 2816 if (!m_contentsLayerClones && m_contentsLayer) 2817 m_contentsLayerClones = adoptPtr(new LayerMap); 2818 2819 primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel); 2820 structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel); 2821 contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel); 2822} 2823 2824void GraphicsLayerCA::removeCloneLayers() 2825{ 2826 m_layerClones = nullptr; 2827 m_structuralLayerClones = nullptr; 2828 m_contentsLayerClones = nullptr; 2829} 2830 2831FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const 2832{ 2833 // This can get called during a flush when we've just removed the m_replicaLayer. 2834 if (!m_replicaLayer) 2835 return FloatPoint(); 2836 2837 FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition(); 2838 return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(), 2839 replicaPosition.y() + m_anchorPoint.y() * m_size.height()); 2840} 2841 2842void GraphicsLayerCA::propagateLayerChangeToReplicas() 2843{ 2844 for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) { 2845 GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer); 2846 if (!currLayerCA->hasCloneLayers()) 2847 break; 2848 2849 if (currLayerCA->replicaLayer()) 2850 static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged); 2851 } 2852} 2853 2854PassRefPtr<PlatformCALayer> GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel) 2855{ 2856 RefPtr<PlatformCALayer> primaryLayer; 2857 RefPtr<PlatformCALayer> structuralLayer; 2858 RefPtr<PlatformCALayer> contentsLayer; 2859 ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel); 2860 2861 if (m_maskLayer) { 2862 RefPtr<PlatformCALayer> maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); 2863 primaryLayer->setMask(maskClone.get()); 2864 } 2865 2866 if (m_replicatedLayer) { 2867 // We are a replica being asked for clones of our layers. 2868 RefPtr<PlatformCALayer> replicaRoot = replicatedLayerRoot(replicaState); 2869 if (!replicaRoot) 2870 return 0; 2871 2872 if (structuralLayer) { 2873 structuralLayer->insertSublayer(replicaRoot.get(), 0); 2874 return structuralLayer; 2875 } 2876 2877 primaryLayer->insertSublayer(replicaRoot.get(), 0); 2878 return primaryLayer; 2879 } 2880 2881 const Vector<GraphicsLayer*>& childLayers = children(); 2882 Vector<RefPtr<PlatformCALayer> > clonalSublayers; 2883 2884 RefPtr<PlatformCALayer> replicaLayer; 2885 2886 if (m_replicaLayer && m_replicaLayer != replicaRoot) { 2887 // We have nested replicas. Ask the replica layer for a clone of its contents. 2888 replicaState.setBranchType(ReplicaState::ReplicaBranch); 2889 replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel); 2890 replicaState.setBranchType(ReplicaState::ChildBranch); 2891 } 2892 2893 if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) { 2894 if (structuralLayer) { 2895 // Replicas render behind the actual layer content. 2896 if (replicaLayer) 2897 clonalSublayers.append(replicaLayer); 2898 2899 // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind. 2900 clonalSublayers.append(primaryLayer); 2901 } else if (contentsLayer) { 2902 // FIXME: add the contents layer in the correct order with negative z-order children. 2903 // This does not cause visible rendering issues because currently contents layers are only used 2904 // for replaced elements that don't have children. 2905 clonalSublayers.append(contentsLayer); 2906 } 2907 2908 replicaState.push(ReplicaState::ChildBranch); 2909 2910 size_t numChildren = childLayers.size(); 2911 for (size_t i = 0; i < numChildren; ++i) { 2912 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); 2913 2914 RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); 2915 if (childLayer) 2916 clonalSublayers.append(childLayer); 2917 } 2918 2919 replicaState.pop(); 2920 2921 for (size_t i = 0; i < clonalSublayers.size(); ++i) 2922 clonalSublayers[i]->removeFromSuperlayer(); 2923 } 2924 2925 RefPtr<PlatformCALayer> result; 2926 if (structuralLayer) { 2927 structuralLayer->setSublayers(clonalSublayers); 2928 2929 if (contentsLayer) { 2930 // If we have a transform layer, then the contents layer is parented in the 2931 // primary layer (which is itself a child of the transform layer). 2932 primaryLayer->removeAllSublayers(); 2933 primaryLayer->appendSublayer(contentsLayer.get()); 2934 } 2935 2936 result = structuralLayer; 2937 } else { 2938 primaryLayer->setSublayers(clonalSublayers); 2939 result = primaryLayer; 2940 } 2941 2942 return result; 2943} 2944 2945PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, CloneLevel cloneLevel) 2946{ 2947 RefPtr<PlatformCALayer> newLayer = layer->clone(this); 2948 2949 if (cloneLevel == IntermediateCloneLevel) { 2950 newLayer->setOpacity(layer->opacity()); 2951 moveOrCopyAnimations(Copy, layer, newLayer.get()); 2952 } 2953 2954 if (isShowingDebugBorder()) { 2955 newLayer->setBorderColor(Color(255, 122, 251)); 2956 newLayer->setBorderWidth(2); 2957 } 2958 2959 return newLayer; 2960} 2961 2962void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) 2963{ 2964 LayerMap* layerCloneMap = 0; 2965 2966 if (preserves3D()) { 2967 m_layer->setOpacity(accumulatedOpacity); 2968 layerCloneMap = m_layerClones.get(); 2969 } else { 2970 primaryLayer()->setOpacity(accumulatedOpacity); 2971 layerCloneMap = primaryLayerClones(); 2972 } 2973 2974 if (layerCloneMap) { 2975 LayerMap::const_iterator end = layerCloneMap->end(); 2976 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2977 if (m_replicaLayer && isReplicatedRootClone(it->key)) 2978 continue; 2979 it->value->setOpacity(m_opacity); 2980 } 2981 } 2982} 2983 2984void GraphicsLayerCA::updateOpacityOnLayer() 2985{ 2986 primaryLayer()->setOpacity(m_opacity); 2987 2988 if (LayerMap* layerCloneMap = primaryLayerClones()) { 2989 LayerMap::const_iterator end = layerCloneMap->end(); 2990 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { 2991 if (m_replicaLayer && isReplicatedRootClone(it->key)) 2992 continue; 2993 2994 it->value->setOpacity(m_opacity); 2995 } 2996 2997 } 2998} 2999 3000void GraphicsLayerCA::setMaintainsPixelAlignment(bool maintainsAlignment) 3001{ 3002 if (maintainsAlignment == m_maintainsPixelAlignment) 3003 return; 3004 3005 GraphicsLayer::setMaintainsPixelAlignment(maintainsAlignment); 3006 noteChangesForScaleSensitiveProperties(); 3007} 3008 3009void GraphicsLayerCA::deviceOrPageScaleFactorChanged() 3010{ 3011 noteChangesForScaleSensitiveProperties(); 3012} 3013 3014void GraphicsLayerCA::noteChangesForScaleSensitiveProperties() 3015{ 3016 noteLayerPropertyChanged(GeometryChanged | ContentsScaleChanged | ContentsOpaqueChanged); 3017} 3018 3019void GraphicsLayerCA::computePixelAlignment(float pageScaleFactor, const FloatPoint& positionRelativeToBase, 3020 FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset) const 3021{ 3022 if (!m_maintainsPixelAlignment || isIntegral(pageScaleFactor) || !m_drawsContent || m_masksToBounds) { 3023 position = m_position; 3024 size = m_size; 3025 anchorPoint = m_anchorPoint; 3026 alignmentOffset = FloatSize(); 3027 return; 3028 } 3029 3030 FloatRect baseRelativeBounds(positionRelativeToBase, m_size); 3031 FloatRect scaledBounds = baseRelativeBounds; 3032 // Scale by the page scale factor to compute the screen-relative bounds. 3033 scaledBounds.scale(pageScaleFactor); 3034 // Round to integer boundaries. 3035 FloatRect alignedBounds = enclosingIntRect(scaledBounds); 3036 3037 // Convert back to layer coordinates. 3038 alignedBounds.scale(1 / pageScaleFactor); 3039 3040 // Epsilon is necessary to ensure that backing store size computation in CA, which involves integer truncation, 3041 // will match our aligned bounds. 3042 const float epsilon = 1e-5f; 3043 alignedBounds.expand(epsilon, epsilon); 3044 3045 alignmentOffset = baseRelativeBounds.location() - alignedBounds.location(); 3046 position = m_position - alignmentOffset; 3047 size = alignedBounds.size(); 3048 3049 // Now we have to compute a new anchor point which compensates for rounding. 3050 float anchorPointX = m_anchorPoint.x(); 3051 float anchorPointY = m_anchorPoint.y(); 3052 3053 if (alignedBounds.width()) 3054 anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width(); 3055 3056 if (alignedBounds.height()) 3057 anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height(); 3058 3059 anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * pageScaleFactor); 3060} 3061 3062void GraphicsLayerCA::noteSublayersChanged() 3063{ 3064 noteLayerPropertyChanged(ChildrenChanged); 3065 propagateLayerChangeToReplicas(); 3066} 3067 3068bool GraphicsLayerCA::canThrottleLayerFlush() const 3069{ 3070 // Tile layers are currently plain CA layers, attached directly by TileController. They require immediate flush as they may contain garbage. 3071 return !(m_uncommittedChanges & TilesAdded); 3072} 3073 3074void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) 3075{ 3076 bool hadUncommittedChanges = !!m_uncommittedChanges; 3077 bool oldCanThrottleLayerFlush = canThrottleLayerFlush(); 3078 3079 m_uncommittedChanges |= flags; 3080 3081 bool needsFlush = !hadUncommittedChanges || oldCanThrottleLayerFlush != canThrottleLayerFlush(); 3082 if (needsFlush && m_client) 3083 m_client->notifyFlushRequired(this); 3084} 3085 3086double GraphicsLayerCA::backingStoreMemoryEstimate() const 3087{ 3088 if (!drawsContent()) 3089 return 0; 3090 3091 // contentsLayer is given to us, so we don't really know anything about its contents. 3092 // FIXME: ignores layer clones. 3093 3094 if (TiledBacking* tiledBacking = this->tiledBacking()) 3095 return tiledBacking->retainedTileBackingStoreMemory(); 3096 3097 return 4.0 * size().width() * m_layer->contentsScale() * size().height() * m_layer->contentsScale(); 3098} 3099 3100} // namespace WebCore 3101 3102#endif // USE(ACCELERATED_COMPOSITING) 3103