Changeset 181515 in webkit
- Timestamp:
- Mar 15, 2015, 4:07:37 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 20 added
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r181512 r181515 1 2015-03-15 Simon Fraser <simon.fraser@apple.com> 2 3 Reduce the side-effects of animations turning off overlap testing 4 https://bugs.webkit.org/show_bug.cgi?id=92791 5 6 Reviewed by Dean Jackson. 7 8 These test overlay an animated element with a grid of position: relative squares. 9 These reveal the overlap area by selectively getting composited. 10 11 * compositing/layer-creation/animation-overlap-with-children-expected.txt: 12 * compositing/layer-creation/mismatched-rotated-transform-animation-overlap-expected.txt: Added. 13 * compositing/layer-creation/mismatched-rotated-transform-animation-overlap.html: Added. 14 * compositing/layer-creation/mismatched-rotated-transform-transition-overlap-expected.txt: Added. 15 * compositing/layer-creation/mismatched-rotated-transform-transition-overlap.html: Added. 16 * compositing/layer-creation/mismatched-transform-transition-overlap-expected.txt: Added. 17 * compositing/layer-creation/mismatched-transform-transition-overlap.html: Added. 18 * compositing/layer-creation/multiple-keyframes-animation-overlap-expected.txt: Added. 19 * compositing/layer-creation/multiple-keyframes-animation-overlap.html: Added. 20 * compositing/layer-creation/scale-rotation-animation-overlap-expected.txt: Added. 21 * compositing/layer-creation/scale-rotation-animation-overlap.html: Added. 22 * compositing/layer-creation/scale-rotation-transition-overlap-expected.txt: Added. 23 * compositing/layer-creation/scale-rotation-transition-overlap.html: Added. 24 * compositing/layer-creation/translate-animation-overlap-expected.txt: Added. 25 * compositing/layer-creation/translate-animation-overlap.html: Added. 26 * compositing/layer-creation/translate-scale-animation-overlap-expected.txt: Added. 27 * compositing/layer-creation/translate-scale-animation-overlap.html: Added. 28 * compositing/layer-creation/translate-scale-transition-overlap-expected.txt: Added. 29 * compositing/layer-creation/translate-scale-transition-overlap.html: Added. 30 * compositing/layer-creation/translate-transition-overlap-expected.txt: Added. 31 * compositing/layer-creation/translate-transition-overlap.html: Added. 32 1 33 2015-03-15 Benjamin Poulain <bpoulain@apple.com> 2 34 -
trunk/LayoutTests/compositing/layer-creation/animation-overlap-with-children-expected.txt
r180441 r181515 8 8 (bounds 800.00 600.00) 9 9 (contentsOpaque 1) 10 (children 210 (children 1 11 11 (GraphicsLayer 12 12 (position 8.00 8.00) … … 27 27 ) 28 28 ) 29 (GraphicsLayer30 (position 18.00 230.00)31 (bounds 100.00 100.00)32 (contentsOpaque 1)33 (drawsContent 1)34 )35 29 ) 36 30 ) -
trunk/Source/WebCore/ChangeLog
r181514 r181515 1 2015-03-15 Simon Fraser <simon.fraser@apple.com> 2 3 Reduce the side-effects of animations turning off overlap testing 4 https://bugs.webkit.org/show_bug.cgi?id=92791 5 6 Reviewed by Dean Jackson. 7 8 When a layer is running a transition or animation of the transform property, 9 we would simply disable overlap testing for later layers, which had the side-effect 10 of promoting lots of unrelated elements into layers temporarily. 11 12 Fix by maintaining overlap, but computing an overlap extent that takes the animation 13 into account. 14 15 Rotations are currently treated as full rotations. If an extent for the overlap is 16 hard to compute (e.g. 3d transforms, or matrix animations with a rotation component), 17 then we fall back to the current behavior. 18 19 Tests: compositing/layer-creation/mismatched-rotated-transform-animation-overlap.html 20 compositing/layer-creation/mismatched-rotated-transform-transition-overlap.html 21 compositing/layer-creation/mismatched-transform-transition-overlap.html 22 compositing/layer-creation/multiple-keyframes-animation-overlap.html 23 compositing/layer-creation/scale-rotation-animation-overlap.html 24 compositing/layer-creation/scale-rotation-transition-overlap.html 25 compositing/layer-creation/translate-animation-overlap.html 26 compositing/layer-creation/translate-scale-animation-overlap.html 27 compositing/layer-creation/translate-scale-transition-overlap.html 28 compositing/layer-creation/translate-transition-overlap.html 29 30 * page/animation/AnimationBase.cpp: 31 (WebCore::containsRotation): 32 (WebCore::AnimationBase::computeTransformedExtentViaTransformList): When we have matched 33 transform lists, we can map a rectangle through the various operations. Transform-origin 34 is used to shift the origin of the box first, and then unshift after. If we encounter 35 a rotation, for now assume it's a full rotation (a future patch could tighten this up). 36 (WebCore::AnimationBase::computeTransformedExtentViaMatrix): If we're using matrix 37 interpolation, we have to decompose the matrix to see if there's any rotation component, 38 and, if there is, fall back to current behavior. 39 * page/animation/AnimationBase.h: 40 * page/animation/AnimationController.cpp: 41 (WebCore::AnimationControllerPrivate::computeExtentOfAnimation): 42 (WebCore::AnimationController::computeExtentOfAnimation): 43 * page/animation/AnimationController.h: 44 * page/animation/AnimationControllerPrivate.h: 45 * page/animation/CompositeAnimation.cpp: 46 (WebCore::CompositeAnimation::computeExtentOfTransformAnimation): Ask active keyframe 47 animations and transitions to compute the bounds extent. 48 * page/animation/CompositeAnimation.h: 49 * page/animation/ImplicitAnimation.cpp: 50 (WebCore::ImplicitAnimation::computeExtentOfTransformAnimation): Compute the extent 51 of the start and end transforms, and union them. 52 * page/animation/ImplicitAnimation.h: 53 * page/animation/KeyframeAnimation.cpp: 54 (WebCore::KeyframeAnimation::animate): 55 (WebCore::KeyframeAnimation::getAnimatedStyle): Some nullptr goodness. 56 (WebCore::KeyframeAnimation::computeExtentOfTransformAnimation): Compute an extent 57 for each keyframe, and take their union. 58 * page/animation/KeyframeAnimation.h: 59 * platform/graphics/GeometryUtilities.cpp: 60 (WebCore::euclidianDistance): Use Pythagoras to compute a distance. 61 (WebCore::boundsOfRotatingRect): Given a rect whose location is relative 62 to the rotation origin, compute a bounds for the rotated rect by computing 63 the furthest corner from the origin, and sweeping out a circle. 64 * platform/graphics/GeometryUtilities.h: 65 * platform/graphics/transforms/Matrix3DTransformOperation.h: 66 * platform/graphics/transforms/MatrixTransformOperation.h: 67 * platform/graphics/transforms/PerspectiveTransformOperation.h: 68 * platform/graphics/transforms/RotateTransformOperation.h: 69 * platform/graphics/transforms/ScaleTransformOperation.h: 70 * platform/graphics/transforms/SkewTransformOperation.h: 71 * platform/graphics/transforms/TransformOperation.h: 72 (WebCore::TransformOperation::isAffectedByTransformOrigin): 73 * platform/graphics/transforms/TransformOperations.cpp: 74 (WebCore::TransformOperations::affectedByTransformOrigin): Ask all the operations if 75 they are affected by transform-origin. 76 (WebCore::TransformOperations::blendByMatchingOperations): nullptr. 77 * platform/graphics/transforms/TransformOperations.h: 78 * rendering/RenderBox.cpp: 79 (WebCore::RenderBox::pushMappingToContainer): Comment fix. Only take transforms into account 80 if the geometry map says so (which is most of the time). 81 * rendering/RenderGeometryMap.cpp: 82 (WebCore::RenderGeometryMap::mapToContainer): RenderLayerCompositor is now using the 83 geometry map in a way that is incompatible with this assertion; it deliberately ignores 84 transforms sometimes, so we can't easily verify that the mapping matches mapping through 85 renderers. 86 (WebCore::RenderGeometryMap::pushMappingsToAncestor): Save and restore the UseTransforms 87 bit. 88 * rendering/RenderGeometryMap.h: 89 * rendering/RenderLayer.cpp: 90 (WebCore::RenderLayer::boundingBox): Whitespace. 91 (WebCore::RenderLayer::getOverlapBoundsIncludingChildrenAccountingForTransformAnimations): Helper 92 function to get the bounds of a layer, including descendants, when a transform animation is running. 93 * rendering/RenderLayer.h: 94 * rendering/RenderLayerCompositor.cpp: 95 (WebCore::RenderLayerCompositor::CompositingState::CompositingState): Add a ancestorHasTransformAnimation 96 flag to detect nested animated transforms. 97 (WebCore::RenderLayerCompositor::OverlapExtent::knownToBeHaveExtentUncertainty): This returns true when 98 the layer is animating transform, and the transition/animation is such that we can't easily compute the 99 bounds of the animation. 100 (WebCore::RenderLayerCompositor::computeExtent): const RenderLayer&. 101 Compute the animated bounds if there's a transform animation running. 102 (WebCore::RenderLayerCompositor::addToOverlapMap): const RenderLayer& 103 (WebCore::RenderLayerCompositor::addToOverlapMapRecursive): const RenderLayer& 104 (WebCore::RenderLayerCompositor::computeCompositingRequirements): 105 Delay the call to pushMappingsToAncestor() until knowing if there's a transform animation running, and 106 if there is, push the mapping while ignoring transforms (since the transform is implicitly taken into account 107 for overlap via the computed animated bounds). 108 If this layer is running a transform animation, set the childState.ancestorHasTransformAnimation flag so 109 that descendants will know (nested transform animations fall back to current behavior). 110 The if (.... && isRunningAcceleratedTransformAnimation()) is what previously caused us to turn off overlap 111 testing in the face of animations. That now only happens if we were unable to easily compute the animation bounds. 112 (WebCore::RenderLayerCompositor::isRunningTransformAnimation): This previously tested whether an accelerated animation 113 was running, but that's timing sensitive; AnimationController can start the transform animation, but it's not yet 114 considered accelerated until we get an async callback from GraphicsLayer, yet this code needed to know if the 115 animation was running. 116 Since transform animations are always accelerated, we can just test for a running transform animation. 117 (WebCore::RenderLayerCompositor::isRunningAcceleratedTransformAnimation): Deleted. 118 * rendering/RenderLayerCompositor.h: 119 * rendering/style/RenderStyle.cpp: 120 (WebCore::requireTransformOrigin): Some FIXME comments. 121 1 122 2015-03-15 Simon Fraser <simon.fraser@apple.com> 2 123 -
trunk/Source/WebCore/page/animation/AnimationBase.cpp
r174587 r181515 37 37 #include "EventNames.h" 38 38 #include "FloatConversion.h" 39 #include "GeometryUtilities.h" 39 40 #include "Logging.h" 40 41 #include "RenderBox.h" … … 698 699 } 699 700 701 static bool containsRotation(const Vector<RefPtr<TransformOperation>>& operations) 702 { 703 for (const auto& operation : operations) { 704 if (operation->type() == TransformOperation::ROTATE) 705 return true; 706 } 707 return false; 708 } 709 710 bool AnimationBase::computeTransformedExtentViaTransformList(const FloatRect& rendererBox, const RenderStyle& style, LayoutRect& bounds) const 711 { 712 FloatRect floatBounds = bounds; 713 FloatPoint transformOrigin; 714 715 bool applyTransformOrigin = containsRotation(style.transform().operations()) || style.transform().affectedByTransformOrigin(); 716 if (applyTransformOrigin) { 717 float offsetX = style.transformOriginX().isPercentNotCalculated() ? rendererBox.x() : 0; 718 float offsetY = style.transformOriginY().isPercentNotCalculated() ? rendererBox.y() : 0; 719 720 transformOrigin.setX(floatValueForLength(style.transformOriginX(), rendererBox.width()) + offsetX); 721 transformOrigin.setY(floatValueForLength(style.transformOriginY(), rendererBox.height()) + offsetY); 722 // Ignore transformOriginZ because we'll bail if we encounter any 3D transforms. 723 724 floatBounds.moveBy(-transformOrigin); 725 } 726 727 for (const auto& operation : style.transform().operations()) { 728 if (operation->type() == TransformOperation::ROTATE) { 729 // For now, just treat this as a full rotation. This could take angle into account to reduce inflation. 730 floatBounds = boundsOfRotatingRect(floatBounds); 731 } else { 732 TransformationMatrix transform; 733 operation->apply(transform, rendererBox.size()); 734 if (!transform.isAffine()) 735 return false; 736 737 if (operation->type() == TransformOperation::MATRIX || operation->type() == TransformOperation::MATRIX_3D) { 738 TransformationMatrix::Decomposed2Type toDecomp; 739 transform.decompose2(toDecomp); 740 // Any rotation prevents us from using a simple start/end rect union. 741 if (toDecomp.angle) 742 return false; 743 } 744 745 floatBounds = transform.mapRect(floatBounds); 746 } 747 } 748 749 if (applyTransformOrigin) 750 floatBounds.moveBy(transformOrigin); 751 752 bounds = LayoutRect(floatBounds); 753 return true; 754 } 755 756 bool AnimationBase::computeTransformedExtentViaMatrix(const FloatRect& rendererBox, const RenderStyle& style, LayoutRect& bounds) const 757 { 758 TransformationMatrix transform; 759 style.applyTransform(transform, rendererBox, RenderStyle::IncludeTransformOrigin); 760 if (!transform.isAffine()) 761 return false; 762 763 TransformationMatrix::Decomposed2Type fromDecomp; 764 transform.decompose2(fromDecomp); 765 // Any rotation prevents us from using a simple start/end rect union. 766 if (fromDecomp.angle) 767 return false; 768 769 bounds = LayoutRect(transform.mapRect(bounds)); 770 return true; 771 772 } 773 700 774 } // namespace WebCore -
trunk/Source/WebCore/page/animation/AnimationBase.h
r173268 r181515 40 40 namespace WebCore { 41 41 42 class AnimationController;43 42 class CompositeAnimation; 44 43 class Element; 44 class FloatRect; 45 class LayoutRect; 45 46 class RenderElement; 46 47 class RenderStyle; 47 48 class TimingFunction; 49 48 50 class AnimationBase : public RefCounted<AnimationBase> { 49 51 friend class CompositeAnimation; … … 137 139 virtual void getAnimatedStyle(RefPtr<RenderStyle>& /*animatedStyle*/) = 0; 138 140 141 virtual bool computeExtentOfTransformAnimation(LayoutRect&) const = 0; 142 139 143 virtual bool shouldFireEvents() const { return false; } 140 144 … … 237 241 double fractionalTime(double scale, double elapsedTime, double offset) const; 238 242 243 // These return true if we can easily compute a bounding box by applying the style's transform to the bounds rect. 244 bool computeTransformedExtentViaTransformList(const FloatRect& rendererBox, const RenderStyle&, LayoutRect& bounds) const; 245 bool computeTransformedExtentViaMatrix(const FloatRect& rendererBox, const RenderStyle&, LayoutRect& bounds) const; 246 239 247 AnimationState m_animationState; 240 248 -
trunk/Source/WebCore/page/animation/AnimationController.cpp
r177302 r181515 418 418 } 419 419 420 bool AnimationControllerPrivate::computeExtentOfAnimation(RenderElement& renderer, LayoutRect& bounds) const 421 { 422 ASSERT(renderer.isCSSAnimating()); 423 ASSERT(m_compositeAnimations.contains(&renderer)); 424 425 const CompositeAnimation& rendererAnimations = *m_compositeAnimations.get(&renderer); 426 if (!rendererAnimations.isAnimatingProperty(CSSPropertyWebkitTransform, false, AnimationBase::Running | AnimationBase::Paused)) 427 return true; 428 429 return rendererAnimations.computeExtentOfTransformAnimation(bounds); 430 } 431 420 432 unsigned AnimationControllerPrivate::numberOfActiveAnimations(Document* document) const 421 433 { … … 578 590 } 579 591 592 bool AnimationController::computeExtentOfAnimation(RenderElement& renderer, LayoutRect& bounds) const 593 { 594 if (!renderer.isCSSAnimating()) 595 return true; 596 597 return m_data->computeExtentOfAnimation(renderer, bounds); 598 } 599 580 600 void AnimationController::notifyAnimationStarted(RenderElement&, double startTime) 581 601 { -
trunk/Source/WebCore/page/animation/AnimationController.h
r177302 r181515 40 40 class Element; 41 41 class Frame; 42 class LayoutRect; 42 43 class RenderElement; 43 44 class RenderStyle; … … 51 52 Ref<RenderStyle> updateAnimations(RenderElement&, Ref<RenderStyle>&& newStyle); 52 53 PassRefPtr<RenderStyle> getAnimatedStyleForRenderer(RenderElement&); 54 55 // If possible, compute the visual extent of any transform animation on the given renderer 56 // using the given rect, returning the result in the rect. Return false if there is some 57 // transform animation but we were unable to cheaply compute its affect on the extent. 58 bool computeExtentOfAnimation(RenderElement&, LayoutRect&) const; 53 59 54 60 // This is called when an accelerated animation or transition has actually started to animate. -
trunk/Source/WebCore/page/animation/AnimationControllerPrivate.h
r177302 r181515 96 96 PassRefPtr<RenderStyle> getAnimatedStyleForRenderer(RenderElement&); 97 97 98 bool computeExtentOfAnimation(RenderElement&, LayoutRect&) const; 99 98 100 double beginAnimationUpdateTime(); 99 101 void setBeginAnimationUpdateTime(double t) { m_beginAnimationUpdateTime = t; } -
trunk/Source/WebCore/page/animation/CompositeAnimation.cpp
r177259 r181515 400 400 } 401 401 402 bool CompositeAnimation::computeExtentOfTransformAnimation(LayoutRect& bounds) const 403 { 404 // If more than one transition and animation affect transform, give up. 405 bool seenTransformAnimation = false; 406 407 for (auto& it : m_keyframeAnimations) { 408 if (KeyframeAnimation* anim = it.value.get()) { 409 if (!anim->hasAnimationForProperty(CSSPropertyWebkitTransform)) 410 continue; 411 412 if (seenTransformAnimation) 413 return false; 414 415 seenTransformAnimation = true; 416 417 if (!anim->computeExtentOfTransformAnimation(bounds)) 418 return false; 419 } 420 } 421 422 for (auto& it : m_transitions) { 423 if (ImplicitAnimation* anim = it.value.get()) { 424 if (anim->animatingProperty() != CSSPropertyWebkitTransform || !anim->hasStyle()) 425 continue; 426 427 if (seenTransformAnimation) 428 return false; 429 430 if (!anim->computeExtentOfTransformAnimation(bounds)) 431 return false; 432 } 433 } 434 435 return true; 436 } 437 402 438 void CompositeAnimation::suspendAnimations() 403 439 { -
trunk/Source/WebCore/page/animation/CompositeAnimation.h
r177733 r181515 58 58 Ref<RenderStyle> animate(RenderElement&, RenderStyle* currentStyle, RenderStyle& targetStyle); 59 59 PassRefPtr<RenderStyle> getAnimatedStyle() const; 60 bool computeExtentOfTransformAnimation(LayoutRect&) const; 60 61 61 62 double timeToNextService() const; -
trunk/Source/WebCore/page/animation/ImplicitAnimation.cpp
r174587 r181515 33 33 #include "CompositeAnimation.h" 34 34 #include "EventNames.h" 35 #include "GeometryUtilities.h" 35 36 #include "ImplicitAnimation.h" 36 37 #include "KeyframeAnimation.h" 37 #include "RenderBox ModelObject.h"38 #include "RenderBox.h" 38 39 39 40 namespace WebCore { … … 98 99 99 100 CSSPropertyAnimation::blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); 101 } 102 103 bool ImplicitAnimation::computeExtentOfTransformAnimation(LayoutRect& bounds) const 104 { 105 ASSERT(hasStyle()); 106 107 if (!m_object->isBox()) 108 return false; 109 110 ASSERT(m_animatingProperty == CSSPropertyWebkitTransform); 111 112 RenderBox& box = downcast<RenderBox>(*m_object); 113 FloatRect rendererBox = snapRectToDevicePixels(box.borderBoxRect(), box.document().deviceScaleFactor()); 114 115 LayoutRect startBounds = bounds; 116 LayoutRect endBounds = bounds; 117 118 if (isTransformFunctionListValid()) { 119 if (!computeTransformedExtentViaTransformList(rendererBox, *m_fromStyle, startBounds)) 120 return false; 121 122 if (!computeTransformedExtentViaTransformList(rendererBox, *m_toStyle, endBounds)) 123 return false; 124 } else { 125 if (!computeTransformedExtentViaMatrix(rendererBox, *m_fromStyle, startBounds)) 126 return false; 127 128 if (!computeTransformedExtentViaMatrix(rendererBox, *m_toStyle, endBounds)) 129 return false; 130 } 131 132 bounds = unionRect(startBounds, endBounds); 133 return true; 100 134 } 101 135 -
trunk/Source/WebCore/page/animation/ImplicitAnimation.h
r173268 r181515 59 59 virtual void reset(RenderStyle* to); 60 60 61 bool computeExtentOfTransformAnimation(LayoutRect&) const override; 62 61 63 void setOverridden(bool); 62 64 virtual bool overridden() const override { return m_overridden; } -
trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp
r176423 r181515 35 35 #include "CompositeAnimation.h" 36 36 #include "EventNames.h" 37 #include "RenderBoxModelObject.h" 37 #include "GeometryUtilities.h" 38 #include "RenderBox.h" 38 39 #include "RenderStyle.h" 39 40 #include "StyleResolver.h" … … 160 161 for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { 161 162 // Get the from/to styles and progress between 162 const RenderStyle* fromStyle = 0;163 const RenderStyle* toStyle = 0;164 double progress = 0 .0;163 const RenderStyle* fromStyle = nullptr; 164 const RenderStyle* toStyle = nullptr; 165 double progress = 0; 165 166 fetchIntervalEndpointsForProperty(*it, fromStyle, toStyle, progress); 166 167 … … 190 191 for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { 191 192 // Get the from/to styles and progress between 192 const RenderStyle* fromStyle = 0;193 const RenderStyle* toStyle = 0;194 double progress = 0 .0;193 const RenderStyle* fromStyle = nullptr; 194 const RenderStyle* toStyle = nullptr; 195 double progress = 0; 195 196 fetchIntervalEndpointsForProperty(*it, fromStyle, toStyle, progress); 196 197 197 198 CSSPropertyAnimation::blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress); 198 199 } 200 } 201 202 bool KeyframeAnimation::computeExtentOfTransformAnimation(LayoutRect& bounds) const 203 { 204 ASSERT(m_keyframes.containsProperty(CSSPropertyWebkitTransform)); 205 206 RenderBox& box = downcast<RenderBox>(*m_object); 207 FloatRect rendererBox = snapRectToDevicePixels(box.borderBoxRect(), box.document().deviceScaleFactor()); 208 209 FloatRect cumulativeBounds = bounds; 210 211 size_t numKeyframes = m_keyframes.size(); 212 for (size_t i = 0; i < numKeyframes; ++i) { 213 const KeyframeValue& currKeyFrame = m_keyframes[i]; 214 215 if (!currKeyFrame.containsProperty(CSSPropertyWebkitTransform)) 216 continue; 217 218 LayoutRect keyframeBounds = bounds; 219 220 bool canCompute; 221 if (isTransformFunctionListValid()) 222 canCompute = computeTransformedExtentViaTransformList(rendererBox, *currKeyFrame.style(), keyframeBounds); 223 else 224 canCompute = computeTransformedExtentViaMatrix(rendererBox, *currKeyFrame.style(), keyframeBounds); 225 226 if (!canCompute) 227 return false; 228 229 cumulativeBounds.unite(keyframeBounds); 230 } 231 232 bounds = LayoutRect(cumulativeBounds); 233 return true; 199 234 } 200 235 -
trunk/Source/WebCore/page/animation/KeyframeAnimation.h
r173268 r181515 49 49 virtual void getAnimatedStyle(RefPtr<RenderStyle>&) override; 50 50 51 bool computeExtentOfTransformAnimation(LayoutRect&) const override; 52 51 53 const KeyframeList& keyframes() const { return m_keyframes; } 52 54 … … 78 80 virtual bool affectsProperty(CSSPropertyID) const override; 79 81 82 bool computeExtentOfAnimationForMatrixAnimation(const FloatRect& rendererBox, LayoutRect&) const; 83 84 bool computeExtentOfAnimationForMatchingTransformLists(const FloatRect& rendererBox, LayoutRect&) const; 85 80 86 void validateTransformFunctionList(); 81 87 void checkForMatchingFilterFunctionLists(); -
trunk/Source/WebCore/platform/graphics/GeometryUtilities.cpp
r168392 r181515 28 28 29 29 namespace WebCore { 30 31 float euclidianDistance(const FloatPoint& p1, const FloatPoint& p2) 32 { 33 FloatSize delta = p1 - p2; 34 return sqrt(delta.width() * delta.width() + delta.height() * delta.height()); 35 } 30 36 31 37 float findSlope(const FloatPoint& p1, const FloatPoint& p2, float& c) … … 116 122 } 117 123 124 FloatRect boundsOfRotatingRect(const FloatRect& r) 125 { 126 // Compute the furthest corner from the origin. 127 float maxCornerDistance = euclidianDistance(FloatPoint(), r.minXMinYCorner()); 128 maxCornerDistance = std::max(maxCornerDistance, euclidianDistance(FloatPoint(), r.maxXMinYCorner())); 129 maxCornerDistance = std::max(maxCornerDistance, euclidianDistance(FloatPoint(), r.minXMaxYCorner())); 130 maxCornerDistance = std::max(maxCornerDistance, euclidianDistance(FloatPoint(), r.maxXMaxYCorner())); 131 132 return FloatRect(-maxCornerDistance, -maxCornerDistance, 2 * maxCornerDistance, 2 * maxCornerDistance); 118 133 } 134 135 } -
trunk/Source/WebCore/platform/graphics/GeometryUtilities.h
r179861 r181515 33 33 namespace WebCore { 34 34 35 float euclidianDistance(const FloatPoint&, const FloatPoint&); 36 35 37 float findSlope(const FloatPoint& p1, const FloatPoint& p2, float& c); 36 38 … … 46 48 WEBCORE_EXPORT FloatRect largestRectWithAspectRatioInsideRect(float aspectRatio, const FloatRect&); 47 49 50 // Compute a rect that encloses all points covered by the given rect if it were rotated a full turn around (0,0). 51 FloatRect boundsOfRotatingRect(const FloatRect&); 52 48 53 } 49 54 -
trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h
r174739 r181515 42 42 private: 43 43 virtual bool isIdentity() const override { return m_matrix.isIdentity(); } 44 virtual bool isAffectedByTransformOrigin() const { return !isIdentity(); } 44 45 45 46 virtual OperationType type() const override { return MATRIX_3D; } -
trunk/Source/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
r174739 r181515 47 47 private: 48 48 virtual bool isIdentity() const override { return m_a == 1 && m_b == 0 && m_c == 0 && m_d == 1 && m_e == 0 && m_f == 0; } 49 virtual bool isAffectedByTransformOrigin() const { return !isIdentity(); } 49 50 50 51 virtual OperationType type() const override { return MATRIX; } -
trunk/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
r174739 r181515 44 44 private: 45 45 virtual bool isIdentity() const override { return !floatValueForLength(m_p, 1); } 46 virtual bool isAffectedByTransformOrigin() const { return !isIdentity(); } 47 46 48 virtual OperationType type() const override { return PERSPECTIVE; } 47 49 virtual bool isSameType(const TransformOperation& o) const override { return o.type() == PERSPECTIVE; } -
trunk/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h
r174739 r181515 49 49 private: 50 50 virtual bool isIdentity() const override { return m_angle == 0; } 51 virtual bool isAffectedByTransformOrigin() const { return !isIdentity(); } 51 52 52 53 virtual OperationType type() const override { return m_type; } -
trunk/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h
r174739 r181515 48 48 private: 49 49 virtual bool isIdentity() const override { return m_x == 1 && m_y == 1 && m_z == 1; } 50 virtual bool isAffectedByTransformOrigin() const { return !isIdentity(); } 50 51 51 52 virtual OperationType type() const override { return m_type; } -
trunk/Source/WebCore/platform/graphics/transforms/SkewTransformOperation.h
r174739 r181515 42 42 private: 43 43 virtual bool isIdentity() const override { return m_angleX == 0 && m_angleY == 0; } 44 virtual bool isAffectedByTransformOrigin() const { return !isIdentity(); } 45 44 46 virtual OperationType type() const override { return m_type; } 45 47 virtual bool isSameType(const TransformOperation& o) const override { return o.type() == m_type; } -
trunk/Source/WebCore/platform/graphics/transforms/TransformOperation.h
r174739 r181515 67 67 virtual OperationType type() const = 0; 68 68 virtual bool isSameType(const TransformOperation&) const { return false; } 69 70 virtual bool isAffectedByTransformOrigin() const { return false; } 69 71 70 72 bool is3DOperation() const -
trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.cpp
r159027 r181515 64 64 } 65 65 66 bool TransformOperations::affectedByTransformOrigin() const 67 { 68 for (const auto& operation : m_operations) { 69 if (operation->isAffectedByTransformOrigin()) 70 return true; 71 } 72 return false; 73 } 74 66 75 TransformOperations TransformOperations::blendByMatchingOperations(const TransformOperations& from, const double& progress) const 67 76 { … … 72 81 unsigned size = std::max(fromSize, toSize); 73 82 for (unsigned i = 0; i < size; i++) { 74 RefPtr<TransformOperation> fromOperation = (i < fromSize) ? from.operations()[i].get() : 0;75 RefPtr<TransformOperation> toOperation = (i < toSize) ? operations()[i].get() : 0;76 RefPtr<TransformOperation> blendedOperation = toOperation ? toOperation->blend(fromOperation.get(), progress) : (fromOperation ? fromOperation->blend( 0, progress, true) : 0);83 RefPtr<TransformOperation> fromOperation = (i < fromSize) ? from.operations()[i].get() : nullptr; 84 RefPtr<TransformOperation> toOperation = (i < toSize) ? operations()[i].get() : nullptr; 85 RefPtr<TransformOperation> blendedOperation = toOperation ? toOperation->blend(fromOperation.get(), progress) : (fromOperation ? fromOperation->blend(nullptr, progress, true) : nullptr); 77 86 if (blendedOperation) 78 87 result.operations().append(blendedOperation); -
trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h
r157653 r181515 66 66 m_operations.clear(); 67 67 } 68 69 bool affectedByTransformOrigin() const; 68 70 69 71 Vector<RefPtr<TransformOperation>>& operations() { return m_operations; } -
trunk/Source/WebCore/rendering/RenderBox.cpp
r181505 r181515 1995 1995 LayoutSize adjustmentForSkippedAncestor; 1996 1996 if (ancestorSkipped) { 1997 // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe1998 // to just subtract the delta between the ancestor and o.1997 // There can't be a transform between repaintContainer and container, because transforms create containers, so it should be safe 1998 // to just subtract the delta between the ancestor and container. 1999 1999 adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(*container); 2000 2000 } … … 2004 2004 2005 2005 bool preserve3D = container->style().preserves3D() || style().preserves3D(); 2006 if (shouldUseTransformFromContainer(container) ) {2006 if (shouldUseTransformFromContainer(container) && (geometryMap.mapCoordinatesFlags() & UseTransforms)) { 2007 2007 TransformationMatrix t; 2008 2008 getTransformFromContainer(container, containerOffset, t); -
trunk/Source/WebCore/rendering/RenderGeometryMap.cpp
r180441 r181515 135 135 } 136 136 137 #if !ASSERT_DISABLED138 FloatRect rendererMappedResult = m_mapping.last().m_renderer->localToContainerQuad(rect, container, m_mapCoordinatesFlags).boundingBox();139 // Inspector creates renderers with negative width <https://bugs.webkit.org/show_bug.cgi?id=87194>.140 // Taking FloatQuad bounds avoids spurious assertions because of that.141 ASSERT(enclosingIntRect(rendererMappedResult) == enclosingIntRect(result.boundingBox()));142 #endif143 144 137 return result; 145 138 } … … 179 172 } 180 173 181 void RenderGeometryMap::pushMappingsToAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer) 182 { 174 void RenderGeometryMap::pushMappingsToAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer, bool respectTransforms) 175 { 176 MapCoordinatesFlags newFlags = respectTransforms ? m_mapCoordinatesFlags : m_mapCoordinatesFlags & ~UseTransforms; 177 TemporaryChange<MapCoordinatesFlags> flagsChange(m_mapCoordinatesFlags, newFlags); 178 183 179 const RenderLayerModelObject& renderer = layer->renderer(); 184 180 -
trunk/Source/WebCore/rendering/RenderGeometryMap.h
r181505 r181515 98 98 99 99 // Called by code walking the renderer or layer trees. 100 void pushMappingsToAncestor(const RenderLayer*, const RenderLayer* ancestorLayer );100 void pushMappingsToAncestor(const RenderLayer*, const RenderLayer* ancestorLayer, bool respectTransforms = true); 101 101 void popMappingsToAncestor(const RenderLayer*); 102 102 void pushMappingsToAncestor(const RenderObject*, const RenderLayerModelObject* ancestorRenderer); -
trunk/Source/WebCore/rendering/RenderLayer.cpp
r181505 r181515 5831 5831 if (flags & UseFragmentBoxesIncludingCompositing) 5832 5832 inclusionMode = IncludeCompositedPaginatedLayers; 5833 5833 5834 const RenderLayer* paginationLayer = nullptr; 5834 5835 if (flags & UseFragmentBoxesExcludingCompositing || flags & UseFragmentBoxesIncludingCompositing) … … 5856 5857 result.move(offsetFromRoot); 5857 5858 return result; 5859 } 5860 5861 bool RenderLayer::getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(LayoutRect& bounds) const 5862 { 5863 // The animation will override the display transform, so don't include it. 5864 CalculateLayerBoundsFlags boundsFlags = DefaultCalculateLayerBoundsFlags & ~IncludeSelfTransform; 5865 5866 bounds = calculateLayerBounds(this, LayoutSize(), boundsFlags); 5867 5868 LayoutRect animatedBounds = bounds; 5869 if (renderer().animation().computeExtentOfAnimation(renderer(), animatedBounds)) { 5870 bounds = animatedBounds; 5871 return true; 5872 } 5873 5874 return false; 5858 5875 } 5859 5876 -
trunk/Source/WebCore/rendering/RenderLayer.h
r181166 r181515 488 488 489 489 enum CalculateLayerBoundsFlag { 490 IncludeSelfTransform = 1 << 0,491 UseLocalClipRectIfPossible = 1 << 1,492 IncludeLayerFilterOutsets = 1 << 2,493 ExcludeHiddenDescendants = 1 << 3,494 DontConstrainForMask = 1 << 4,495 IncludeCompositedDescendants = 1 << 5,496 UseFragmentBoxesExcludingCompositing = 1 << 6,497 UseFragmentBoxesIncludingCompositing = 1 << 7,498 DefaultCalculateLayerBoundsFlags =IncludeSelfTransform | UseLocalClipRectIfPossible | IncludeLayerFilterOutsets | UseFragmentBoxesExcludingCompositing490 IncludeSelfTransform = 1 << 0, 491 UseLocalClipRectIfPossible = 1 << 1, 492 IncludeLayerFilterOutsets = 1 << 2, 493 ExcludeHiddenDescendants = 1 << 3, 494 DontConstrainForMask = 1 << 4, 495 IncludeCompositedDescendants = 1 << 5, 496 UseFragmentBoxesExcludingCompositing = 1 << 6, 497 UseFragmentBoxesIncludingCompositing = 1 << 7, 498 DefaultCalculateLayerBoundsFlags = IncludeSelfTransform | UseLocalClipRectIfPossible | IncludeLayerFilterOutsets | UseFragmentBoxesExcludingCompositing 499 499 }; 500 500 typedef unsigned CalculateLayerBoundsFlags; … … 511 511 // Bounds used for layer overlap testing in RenderLayerCompositor. 512 512 LayoutRect overlapBounds() const { return overlapBoundsIncludeChildren() ? calculateLayerBounds(this, LayoutSize()) : localBoundingBox(); } 513 514 // Takes transform animations into account, returning true if they could be cheaply computed. 515 // Unlike overlapBounds, these bounds include descendant layers. 516 bool getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(LayoutRect&) const; 513 517 514 518 // If true, this layer's children are included in its bounds for overlap testing. -
trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp
r181513 r181515 224 224 , subtreeIsCompositing(false) 225 225 , testingOverlap(testOverlap) 226 , ancestorHasTransformAnimation(false) 226 227 #if ENABLE(CSS_COMPOSITING) 227 228 , hasNotIsolatedCompositedBlendingDescendants(false) … … 237 238 , subtreeIsCompositing(other.subtreeIsCompositing) 238 239 , testingOverlap(other.testingOverlap) 240 , ancestorHasTransformAnimation(other.ancestorHasTransformAnimation) 239 241 #if ENABLE(CSS_COMPOSITING) 240 242 , hasNotIsolatedCompositedBlendingDescendants(other.hasNotIsolatedCompositedBlendingDescendants) … … 249 251 bool subtreeIsCompositing; 250 252 bool testingOverlap; 253 bool ancestorHasTransformAnimation; 251 254 #if ENABLE(CSS_COMPOSITING) 252 255 bool hasNotIsolatedCompositedBlendingDescendants; … … 260 263 LayoutRect bounds; 261 264 bool extentComputed { false }; 265 bool hasTransformAnimation { false }; 266 bool animationCausesExtentUncertainty { false }; 267 268 bool knownToBeHaveExtentUncertainty() const { return extentComputed && animationCausesExtentUncertainty; } 262 269 }; 263 270 … … 1142 1149 } 1143 1150 1144 void RenderLayerCompositor::computeExtent(const OverlapMap& overlapMap, RenderLayer& layer, OverlapExtent& extent) const1151 void RenderLayerCompositor::computeExtent(const OverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent) const 1145 1152 { 1146 1153 if (extent.extentComputed) 1147 1154 return; 1148 1155 1149 // FIXME: If this layer's overlap bounds include its children, we don't need to add its 1150 // children's bounds to the overlap map. 1151 extent.bounds = enclosingLayoutRect(overlapMap.geometryMap().absoluteRect(layer.overlapBounds())); 1156 LayoutRect layerBounds; 1157 if (extent.hasTransformAnimation) 1158 extent.animationCausesExtentUncertainty = !layer.getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(layerBounds); 1159 else 1160 layerBounds = layer.overlapBounds(); 1161 1162 // In the animating transform case, we avoid double-accounting for the transform because 1163 // we told pushMappingsToAncestor() to ignore transforms earlier. 1164 extent.bounds = enclosingLayoutRect(overlapMap.geometryMap().absoluteRect(layerBounds)); 1165 1152 1166 // Empty rects never intersect, but we need them to for the purposes of overlap testing. 1153 1167 if (extent.bounds.isEmpty()) … … 1157 1171 } 1158 1172 1159 void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer& layer, OverlapExtent& extent)1173 void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent) 1160 1174 { 1161 1175 if (layer.isRootLayer()) … … 1177 1191 } 1178 1192 1179 void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, RenderLayer& layer,RenderLayer* ancestorLayer)1193 void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, const RenderLayer& layer, const RenderLayer* ancestorLayer) 1180 1194 { 1181 1195 if (!canBeComposited(layer) || overlapMap.contains(&layer)) … … 1190 1204 1191 1205 #if !ASSERT_DISABLED 1192 LayerListMutationDetector mutationChecker( &layer);1206 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(&layer)); 1193 1207 #endif 1194 1208 … … 1256 1270 } 1257 1271 1258 overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer);1259 1260 1272 // Clear the flag 1261 1273 layer.setHasCompositingDescendant(false); … … 1263 1275 1264 1276 // Check if the layer needs to be composited for direct reasons (e.g. 3D transform). 1265 // We use this value to avoid checking the overlap map, if we know for sure the layer1266 // is already going to be composited for other reasons.1267 1277 bool willBeComposited = needsToBeComposited(layer); 1268 bool mayHaveAnimatedTransform = willBeComposited && !layer.isRootLayer(); 1278 1279 OverlapExtent layerExtent; 1280 // Use the fact that we're composited as a hint to check for an animating transform. 1281 // FIXME: Maybe needsToBeComposited() should return a bitmask of reasons, to avoid the need to recompute things. 1282 if (willBeComposited && !layer.isRootLayer()) 1283 layerExtent.hasTransformAnimation = isRunningTransformAnimation(layer.renderer()); 1284 1285 bool respectTransforms = !layerExtent.hasTransformAnimation; 1286 overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer, respectTransforms); 1269 1287 1270 1288 RenderLayer::IndirectCompositingReason compositingReason = compositingState.subtreeIsCompositing ? RenderLayer::IndirectCompositingReason::Stacking : RenderLayer::IndirectCompositingReason::None; 1271 1272 OverlapExtent layerExtent;1273 1289 1274 1290 // If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map … … 1314 1330 // animation running behind this layer, meaning they can rely on the overlap map testing again. 1315 1331 childState.testingOverlap = true; 1332 1333 computeExtent(overlapMap, layer, layerExtent); 1334 childState.ancestorHasTransformAnimation |= layerExtent.hasTransformAnimation; 1335 // Too hard to compute animated bounds if both us and some ancestor is animating transform. 1336 layerExtent.animationCausesExtentUncertainty |= layerExtent.hasTransformAnimation && compositingState.ancestorHasTransformAnimation; 1316 1337 } 1317 1338 … … 1378 1399 // the overlap map. Layers that do not composite will draw into their 1379 1400 // compositing ancestor's backing, and so are still considered for overlap. 1401 // FIXME: When layerExtent has taken animation bounds into account, we also know that the bounds 1402 // include descendants, so we don't need to add them all to the overlap map. 1380 1403 if (childState.compositingAncestor && !childState.compositingAncestor->isRootLayer()) 1381 1404 addToOverlapMap(overlapMap, layer, layerExtent); … … 1406 1429 compositingState.subtreeIsCompositing = true; 1407 1430 1408 // Set the flag to say that this SChas compositing children.1431 // Set the flag to say that this layer has compositing children. 1409 1432 layer.setHasCompositingDescendant(childState.subtreeIsCompositing); 1410 1433 1411 // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping, 1412 // so test that again. 1434 // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping, so test that again. 1413 1435 bool isCompositedClippingLayer = canBeComposited(layer) && clipsCompositingDescendants(layer); 1414 1436 … … 1416 1438 // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because 1417 1439 // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map. 1418 if ((!childState.testingOverlap && !isCompositedClippingLayer) || (mayHaveAnimatedTransform && isRunningAcceleratedTransformAnimation(layer.renderer())))1440 if ((!childState.testingOverlap && !isCompositedClippingLayer) || layerExtent.knownToBeHaveExtentUncertainty()) 1419 1441 compositingState.testingOverlap = false; 1420 1442 … … 2784 2806 #endif 2785 2807 2786 bool RenderLayerCompositor::isRunning AcceleratedTransformAnimation(RenderLayerModelObject& renderer) const2808 bool RenderLayerCompositor::isRunningTransformAnimation(RenderLayerModelObject& renderer) const 2787 2809 { 2788 2810 if (!(m_compositingTriggers & ChromeClient::AnimationTrigger)) 2789 2811 return false; 2790 2812 2791 return renderer.animation().isRunningA cceleratedAnimationOnRenderer(renderer, CSSPropertyWebkitTransform, AnimationBase::Running | AnimationBase::Paused);2813 return renderer.animation().isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform, AnimationBase::Running | AnimationBase::Paused); 2792 2814 } 2793 2815 -
trunk/Source/WebCore/rendering/RenderLayerCompositor.h
r181247 r181515 339 339 void recursiveRepaintLayer(RenderLayer&); 340 340 341 void computeExtent(const OverlapMap&, RenderLayer&, OverlapExtent&) const;342 void addToOverlapMap(OverlapMap&, RenderLayer&, OverlapExtent&);343 void addToOverlapMapRecursive(OverlapMap&, RenderLayer&,RenderLayer* ancestorLayer = nullptr);341 void computeExtent(const OverlapMap&, const RenderLayer&, OverlapExtent&) const; 342 void addToOverlapMap(OverlapMap&, const RenderLayer&, OverlapExtent&); 343 void addToOverlapMapRecursive(OverlapMap&, const RenderLayer&, const RenderLayer* ancestorLayer = nullptr); 344 344 345 345 void updateCompositingLayersTimerFired(); … … 369 369 370 370 bool layerHas3DContent(const RenderLayer&) const; 371 bool isRunning AcceleratedTransformAnimation(RenderLayerModelObject&) const;371 bool isRunningTransformAnimation(RenderLayerModelObject&) const; 372 372 373 373 void appendDocumentOverlayLayers(Vector<GraphicsLayer*>&); -
trunk/Source/WebCore/rendering/style/RenderStyle.cpp
r181189 r181515 989 989 } 990 990 991 // FIXME: use affectedByTransformOrigin(). 991 992 static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin) 992 993 { … … 1002 1003 && type != TransformOperation::TRANSLATE_Y 1003 1004 && type != TransformOperation::TRANSLATE 1004 && type != TransformOperation::TRANSLATE_Z 1005 && type != TransformOperation::TRANSLATE_Z // FIXME: doesn't this depend on transform origin? 1005 1006 && type != TransformOperation::TRANSLATE_3D) 1006 1007 return true;
Note:
See TracChangeset
for help on using the changeset viewer.