Changeset 222129 in webkit
- Timestamp:
- Sep 16, 2017 5:33:04 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r222127 r222129 1 2017-09-16 Antti Koivisto <antti@apple.com> 2 3 Computing animated style should not require renderers 4 https://bugs.webkit.org/show_bug.cgi?id=171926 5 <rdar://problem/34428035> 6 7 Reviewed by Sam Weinig. 8 9 * transitions/transition-display-property-2-expected.html: Added. 10 * transitions/transition-display-property-2.html: Added. 11 * transitions/transition-display-property.html: 12 1 13 2017-09-16 Carlos Garcia Campos <cgarcia@igalia.com> 2 14 -
trunk/LayoutTests/transitions/transition-display-property.html
r222104 r222129 6 6 <script> 7 7 var test = document.querySelector("test"); 8 var count = 0;9 function testUntilComplete()10 {11 if (test.offsetWidth == 10 || ++count == 10)12 testRunner.notifyDone();13 else14 setTimeout(testUntilComplete, 0.1);15 }16 8 17 9 if (window.testRunner) { 18 10 testRunner.waitUntilDone(); 19 test UntilComplete();11 test.ontransitionend = () => testRunner.notifyDone(); 20 12 } 21 13 test.offsetWidth; -
trunk/Source/WebCore/ChangeLog
r222126 r222129 1 2017-09-16 Antti Koivisto <antti@apple.com> 2 3 Computing animated style should not require renderers 4 https://bugs.webkit.org/show_bug.cgi?id=171926 5 <rdar://problem/34428035> 6 7 Reviewed by Sam Weinig. 8 9 CSS animation system is now element rather than renderer based. This allows cleaning up 10 style resolution and render tree update code. 11 12 This also fixes bug animation doesn't run if display property is animated from one rendered type 13 to another. Added a test case for this. 14 15 Test: transitions/transition-display-property-2.html 16 17 * page/animation/CSSAnimationController.cpp: 18 (WebCore::CSSAnimationController::updateAnimations): 19 20 Pass in the old style instead of getting it from the renderer. 21 Factor to return the animated style as a return value. 22 23 * page/animation/CSSAnimationController.h: 24 * rendering/RenderElement.cpp: 25 (WebCore::RenderElement::RenderElement): 26 (WebCore::RenderElement::willBeDestroyed): 27 28 Animation are now canceled by RenderTreeUpdater::tearDownRenderers. 29 30 * rendering/RenderElement.h: 31 (WebCore::RenderElement::hasInitialAnimatedStyle const): Deleted. 32 (WebCore::RenderElement::setHasInitialAnimatedStyle): Deleted. 33 34 We no longer need to this concept. 35 36 * style/RenderTreeUpdater.cpp: 37 (WebCore::RenderTreeUpdater::updateElementRenderer): 38 (WebCore::RenderTreeUpdater::createRenderer): 39 40 We now get correct animated style from style resolution in all cases so we don't need to compute 41 it separately for new renderers. 42 43 (WebCore::RenderTreeUpdater::tearDownRenderers): 44 45 Cancel animations when render tree is fully torn down. Keep them when updating style. 46 47 * style/RenderTreeUpdater.h: 48 * style/StyleTreeResolver.cpp: 49 (WebCore::Style::TreeResolver::createAnimatedElementUpdate): 50 51 We can now compute animated style without renderer. Special cases dealing with rendererless case 52 can be removed. 53 1 54 2017-09-15 Carlos Garcia Campos <cgarcia@igalia.com> 2 55 -
trunk/Source/WebCore/page/animation/CSSAnimationController.cpp
r222104 r222129 638 638 } 639 639 640 bool CSSAnimationController::updateAnimations(Element& element, const RenderStyle& newStyle, std::unique_ptr<RenderStyle>& animatedStyle) 641 { 642 auto* renderer = element.renderer(); 643 auto* oldStyle = (renderer && renderer->hasInitializedStyle()) ? &renderer->style() : nullptr; 644 if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle.animations() && !newStyle.transitions())) 645 return false; 640 AnimationUpdate CSSAnimationController::updateAnimations(Element& element, const RenderStyle& newStyle, const RenderStyle* oldStyle) 641 { 642 bool hasOrHadAnimations = (oldStyle && oldStyle->hasAnimationsOrTransitions()) || newStyle.hasAnimationsOrTransitions(); 643 if (!hasOrHadAnimations) 644 return { }; 646 645 647 646 if (element.document().pageCacheState() != Document::NotInPageCache) 648 return false;647 return { }; 649 648 650 649 // Don't run transitions when printing. 651 650 if (element.document().renderView()->printing()) 652 return false;651 return { }; 653 652 654 653 // Fetch our current set of implicit animations from a hashtable. We then compare them … … 658 657 659 658 CompositeAnimation& compositeAnimation = m_data->ensureCompositeAnimation(element); 660 bool animationStateChanged = compositeAnimation.animate(element, oldStyle, newStyle, animatedStyle); 661 659 auto update = compositeAnimation.animate(element, oldStyle, newStyle); 660 661 auto* renderer = element.renderer(); 662 662 if ((renderer && renderer->parent()) || newStyle.animations() || (oldStyle && oldStyle->animations())) { 663 663 auto& frameView = *element.document().view(); … … 668 668 } 669 669 670 return animationStateChanged;670 return update; 671 671 } 672 672 -
trunk/Source/WebCore/page/animation/CSSAnimationController.h
r222104 r222129 31 31 #include "AnimationBase.h" 32 32 #include "CSSPropertyNames.h" 33 #include "RenderStyle.h" 33 34 #include <wtf/Forward.h> 34 35 … … 41 42 class LayoutRect; 42 43 class RenderElement; 43 class RenderStyle; 44 45 struct AnimationUpdate { 46 #if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES) 47 AnimationUpdate() = default; 48 AnimationUpdate(std::unique_ptr<RenderStyle> style, bool stateChanged) 49 : style(WTFMove(style)) 50 , stateChanged(stateChanged) 51 { } 52 #endif 53 std::unique_ptr<RenderStyle> style; 54 bool stateChanged { false }; 55 }; 44 56 45 57 class CSSAnimationController { … … 50 62 51 63 void cancelAnimations(Element&); 52 bool updateAnimations(Element&, const RenderStyle& newStyle, std::unique_ptr<RenderStyle>& animatedStyle);64 AnimationUpdate updateAnimations(Element&, const RenderStyle& newStyle, const RenderStyle* oldStyle); 53 65 std::unique_ptr<RenderStyle> animatedStyleForRenderer(RenderElement&); 54 66 -
trunk/Source/WebCore/page/animation/CompositeAnimation.cpp
r222104 r222129 288 288 } 289 289 290 bool CompositeAnimation::animate(Element& element, const RenderStyle* currentStyle, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& blendedStyle)290 AnimationUpdate CompositeAnimation::animate(Element& element, const RenderStyle* currentStyle, const RenderStyle& targetStyle) 291 291 { 292 292 // We don't do any transitions if we don't have a currentStyle (on startup). … … 298 298 bool forceStackingContext = false; 299 299 300 std::unique_ptr<RenderStyle> animatedStyle; 301 300 302 if (currentStyle) { 301 303 // Now that we have transition objects ready, let them know about the new goal state. We want them … … 304 306 for (auto& transition : m_transitions.values()) { 305 307 bool didBlendStyle = false; 306 if (transition->animate(*this, targetStyle, blendedStyle, didBlendStyle))308 if (transition->animate(*this, targetStyle, animatedStyle, didBlendStyle)) 307 309 animationStateChanged = true; 308 310 … … 311 313 } 312 314 313 if ( blendedStyle && checkForStackingContext) {315 if (animatedStyle && checkForStackingContext) { 314 316 // Note that this is similar to code in StyleResolver::adjustRenderStyle() but only needs to consult 315 317 // animatable properties that can trigger stacking context. 316 if ( blendedStyle->opacity() < 1.0f317 || blendedStyle->hasTransformRelatedProperty()318 || blendedStyle->hasMask()319 || blendedStyle->clipPath()320 || blendedStyle->boxReflect()321 || blendedStyle->hasFilter()318 if (animatedStyle->opacity() < 1.0f 319 || animatedStyle->hasTransformRelatedProperty() 320 || animatedStyle->hasMask() 321 || animatedStyle->clipPath() 322 || animatedStyle->boxReflect() 323 || animatedStyle->hasFilter() 322 324 #if ENABLE(FILTERS_LEVEL_2) 323 || blendedStyle->hasBackdropFilter()325 || animatedStyle->hasBackdropFilter() 324 326 #endif 325 327 ) … … 334 336 if (keyframeAnim) { 335 337 bool didBlendStyle = false; 336 if (keyframeAnim->animate(*this, targetStyle, blendedStyle, didBlendStyle))338 if (keyframeAnim->animate(*this, targetStyle, animatedStyle, didBlendStyle)) 337 339 animationStateChanged = true; 338 340 … … 346 348 // the user agent must act as if the will-change property ([css-will-change-1]) on the element additionally 347 349 // includes all the properties animated by the animation. 348 if (forceStackingContext && blendedStyle) {349 if ( blendedStyle->hasAutoZIndex())350 blendedStyle->setZIndex(0);351 } 352 353 return animationStateChanged;350 if (forceStackingContext && animatedStyle) { 351 if (animatedStyle->hasAutoZIndex()) 352 animatedStyle->setZIndex(0); 353 } 354 355 return { WTFMove(animatedStyle), animationStateChanged }; 354 356 } 355 357 -
trunk/Source/WebCore/page/animation/CompositeAnimation.h
r222104 r222129 29 29 #pragma once 30 30 31 #include "CSSAnimationController.h" 31 32 #include "ImplicitAnimation.h" 32 33 #include "KeyframeAnimation.h" … … 55 56 void clearElement(); 56 57 57 bool animate(Element&, const RenderStyle* currentStyle, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& blendedStyle);58 AnimationUpdate animate(Element&, const RenderStyle* currentStyle, const RenderStyle& targetStyle); 58 59 std::unique_ptr<RenderStyle> getAnimatedStyle() const; 59 60 bool computeExtentOfTransformAnimation(LayoutRect&) const; -
trunk/Source/WebCore/rendering/RenderElement.cpp
r222104 r222129 27 27 28 28 #include "AXObjectCache.h" 29 #include "CSSAnimationController.h"30 29 #include "ContentData.h" 31 30 #include "CursorList.h" … … 103 102 , m_ancestorLineBoxDirty(false) 104 103 , m_hasInitializedStyle(false) 105 , m_hasInitialAnimatedStyle(false)106 104 , m_renderInlineAlwaysCreatesLineBoxes(false) 107 105 , m_renderBoxNeedsLazyRepaint(false) … … 1105 1103 view().frameView().removeSlowRepaintObject(this); 1106 1104 1107 if (element())1108 animation().cancelAnimations(*element());1109 1110 1105 destroyLeftoverChildren(); 1111 1106 -
trunk/Source/WebCore/rendering/RenderElement.h
r222104 r222129 132 132 void setStyleInternal(RenderStyle&& style) { m_style = WTFMove(style); } 133 133 134 bool hasInitialAnimatedStyle() const { return m_hasInitialAnimatedStyle; }135 void setHasInitialAnimatedStyle(bool b) { m_hasInitialAnimatedStyle = b; }136 137 134 // Repaint only if our old bounds and new bounds are different. The caller may pass in newBounds and newOutlineBox if they are known. 138 135 bool repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr = nullptr, const LayoutRect* newOutlineBoxPtr = nullptr); … … 330 327 unsigned m_ancestorLineBoxDirty : 1; 331 328 unsigned m_hasInitializedStyle : 1; 332 unsigned m_hasInitialAnimatedStyle : 1;333 329 334 330 unsigned m_renderInlineAlwaysCreatesLineBoxes : 1; -
trunk/Source/WebCore/style/RenderTreeUpdater.cpp
r222104 r222129 308 308 renderTreePosition().invalidateNextSibling(); 309 309 } 310 tearDownRenderers(element, TeardownType::KeepHoverAndActive); 310 311 // display:none cancels animations. 312 auto teardownType = update.style->display() == NONE ? TeardownType::RendererUpdateCancelingAnimations : TeardownType::RendererUpdate; 313 tearDownRenderers(element, teardownType); 311 314 } 312 315 … … 396 399 397 400 element.setRenderer(newRenderer); 398 399 auto& initialStyle = newRenderer->style();400 std::unique_ptr<RenderStyle> animatedStyle;401 newRenderer->animation().updateAnimations(element, initialStyle, animatedStyle);402 if (animatedStyle) {403 newRenderer->setStyleInternal(WTFMove(*animatedStyle));404 newRenderer->setHasInitialAnimatedStyle(true);405 }406 401 407 402 newRenderer->initializeStyle(); … … 526 521 } 527 522 523 void RenderTreeUpdater::tearDownRenderers(Element& root) 524 { 525 tearDownRenderers(root, TeardownType::Full); 526 } 527 528 528 void RenderTreeUpdater::tearDownRenderers(Element& root, TeardownType teardownType) 529 529 { … … 538 538 }; 539 539 540 auto& animationController = root.document().frame()->animation(); 541 540 542 auto pop = [&] (unsigned depth) { 541 543 while (teardownStack.size() > depth) { 542 544 auto& element = *teardownStack.takeLast(); 543 545 544 if (teardownType != TeardownType::KeepHoverAndActive) 546 if (teardownType == TeardownType::Full || teardownType == TeardownType::RendererUpdateCancelingAnimations) 547 animationController.cancelAnimations(element); 548 549 if (teardownType == TeardownType::Full) 545 550 element.clearHoverAndActiveStatusBeforeDetachingRenderer(); 551 546 552 element.clearStyleDerivedDataBeforeDetachingRenderer(); 547 553 -
trunk/Source/WebCore/style/RenderTreeUpdater.h
r222104 r222129 48 48 void commit(std::unique_ptr<const Style::Update>); 49 49 50 enum class TeardownType { Normal, KeepHoverAndActive }; 51 static void tearDownRenderers(Element&, TeardownType = TeardownType::Normal); 50 static void tearDownRenderers(Element&); 52 51 static void tearDownRenderer(Text&); 53 52 … … 84 83 void popParentsToDepth(unsigned depth); 85 84 85 enum class TeardownType { Full, RendererUpdate, RendererUpdateCancelingAnimations }; 86 static void tearDownRenderers(Element&, TeardownType); 87 86 88 RenderView& renderView(); 87 89 -
trunk/Source/WebCore/style/StyleTreeResolver.cpp
r222104 r222129 242 242 ElementUpdate TreeResolver::createAnimatedElementUpdate(std::unique_ptr<RenderStyle> newStyle, Element& element, Change parentChange) 243 243 { 244 auto& animationController = element.document().frame()->animation(); 245 246 auto* oldStyle = renderOrDisplayContentsStyle(element); 247 auto animationUpdate = animationController.updateAnimations(element, *newStyle, oldStyle); 248 249 if (animationUpdate.style) 250 newStyle = WTFMove(animationUpdate.style); 251 252 auto change = oldStyle ? determineChange(*oldStyle, *newStyle) : Detach; 253 244 254 auto validity = element.styleValidity(); 245 bool recompositeLayer = element.styleResolutionShouldRecompositeLayer(); 246 247 auto makeUpdate = [&] (std::unique_ptr<RenderStyle> style, Change change) { 248 if (validity >= Validity::SubtreeInvalid) 249 change = std::max(change, validity == Validity::SubtreeAndRenderersInvalid ? Detach : Force); 250 if (parentChange >= Force) 251 change = std::max(change, parentChange); 252 return ElementUpdate { WTFMove(style), change, recompositeLayer }; 253 }; 254 255 auto* renderer = element.renderer(); 256 257 bool shouldReconstruct = validity >= Validity::SubtreeAndRenderersInvalid || parentChange == Detach; 258 if (shouldReconstruct) 259 return makeUpdate(WTFMove(newStyle), Detach); 260 261 if (!renderer) { 262 auto change = Detach; 263 if (auto* oldStyle = renderOrDisplayContentsStyle(element)) 264 change = determineChange(*oldStyle, *newStyle); 265 return makeUpdate(WTFMove(newStyle), change); 266 } 267 268 std::unique_ptr<RenderStyle> animatedStyle; 269 if (element.document().frame()->animation().updateAnimations(element, *newStyle, animatedStyle)) 270 recompositeLayer = true; 271 272 if (animatedStyle) { 273 auto change = determineChange(renderer->style(), *animatedStyle); 274 if (renderer->hasInitialAnimatedStyle()) { 275 renderer->setHasInitialAnimatedStyle(false); 276 // When we initialize a newly created renderer with initial animated style we don't inherit it to descendants. 277 // The first animation frame needs to correct this. 278 // FIXME: We should compute animated style correctly during initial style resolution when we don't have renderers yet. 279 // https://bugs.webkit.org/show_bug.cgi?id=171926 280 change = std::max(change, Inherit); 281 } 282 // If animation forces render tree reconstruction pass the original style. The animation will be applied on renderer construction. 283 // FIXME: We should always use the animated style here. 284 auto style = change == Detach ? WTFMove(newStyle) : WTFMove(animatedStyle); 285 return makeUpdate(WTFMove(style), change); 286 } 287 288 auto change = determineChange(renderer->style(), *newStyle); 289 return makeUpdate(WTFMove(newStyle), change); 255 if (validity >= Validity::SubtreeInvalid) 256 change = std::max(change, validity == Validity::SubtreeAndRenderersInvalid ? Detach : Force); 257 if (parentChange >= Force) 258 change = std::max(change, parentChange); 259 260 bool shouldRecompositeLayer = element.styleResolutionShouldRecompositeLayer() || animationUpdate.stateChanged; 261 262 return { WTFMove(newStyle), change, shouldRecompositeLayer }; 290 263 } 291 264
Note: See TracChangeset
for help on using the changeset viewer.