Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: Source/core/animation/CompositorAnimations.cpp

Issue 881183003: Animation: Cancel same-property animations on compositor (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "core/animation/CompositorAnimations.h" 32 #include "core/animation/CompositorAnimations.h"
33 33
34 #include "core/animation/ActiveAnimations.h"
34 #include "core/animation/AnimationNode.h" 35 #include "core/animation/AnimationNode.h"
35 #include "core/animation/AnimationTranslationUtil.h" 36 #include "core/animation/AnimationTranslationUtil.h"
36 #include "core/animation/CompositorAnimationsImpl.h" 37 #include "core/animation/CompositorAnimationsImpl.h"
37 #include "core/animation/animatable/AnimatableDouble.h" 38 #include "core/animation/animatable/AnimatableDouble.h"
38 #include "core/animation/animatable/AnimatableFilterOperations.h" 39 #include "core/animation/animatable/AnimatableFilterOperations.h"
39 #include "core/animation/animatable/AnimatableTransform.h" 40 #include "core/animation/animatable/AnimatableTransform.h"
40 #include "core/animation/animatable/AnimatableValue.h" 41 #include "core/animation/animatable/AnimatableValue.h"
41 #include "core/rendering/RenderBoxModelObject.h" 42 #include "core/rendering/RenderBoxModelObject.h"
42 #include "core/rendering/RenderLayer.h" 43 #include "core/rendering/RenderLayer.h"
43 #include "core/rendering/RenderObject.h" 44 #include "core/rendering/RenderObject.h"
(...skipping 19 matching lines...) Expand all
63 void getKeyframeValuesForProperty(const KeyframeEffectModelBase* effect, CSSProp ertyID id, double scale, PropertySpecificKeyframeVector& values) 64 void getKeyframeValuesForProperty(const KeyframeEffectModelBase* effect, CSSProp ertyID id, double scale, PropertySpecificKeyframeVector& values)
64 { 65 {
65 ASSERT(values.isEmpty()); 66 ASSERT(values.isEmpty());
66 67
67 for (const auto& keyframe : effect->getPropertySpecificKeyframes(id)) { 68 for (const auto& keyframe : effect->getPropertySpecificKeyframes(id)) {
68 double offset = keyframe->offset() * scale; 69 double offset = keyframe->offset() * scale;
69 values.append(keyframe->cloneWithOffset(offset)); 70 values.append(keyframe->cloneWithOffset(offset));
70 } 71 }
71 } 72 }
72 73
74 bool alreadyActiveAnimationsBlockProperties(const Element& targetElement, const AnimationPlayer& playerToAdd, const AnimationEffect& effectToAdd)
dstockwell 2015/01/28 05:44:05 I think this would be better written as: bool aff
loyso (OOO) 2015/01/28 06:33:31 Good point. That's also will be more efficient.
75 {
76 bool propertyOpacityBlocked = false;
77 bool propertyTransformBlocked = false;
78 bool propertyFilterBlocked = false;
79
80 if (targetElement.hasActiveAnimations()) {
81 ActiveAnimations* activeAnimations = targetElement.activeAnimations();
82 ASSERT(activeAnimations);
83
84 for (const auto& entry : activeAnimations->players()) {
85 const AnimationPlayer* attachedPlayer = entry.key;
dstockwell 2015/01/28 05:44:05 Is it possible to skip consideration of earlier pl
loyso (OOO) 2015/01/29 01:08:54 What do you mean? Players with fill=forwards will
dstockwell 2015/01/29 01:14:07 Yes. Hmm, also players which are idle or finished
loyso (OOO) 2015/01/29 04:35:59 Is that a problem? Should we address it?
86 if (attachedPlayer == &playerToAdd)
87 continue;
88
89 if (attachedPlayer->affects(CSSPropertyOpacity))
90 propertyOpacityBlocked = true;
91 else if (attachedPlayer->affects(CSSPropertyTransform))
92 propertyTransformBlocked = true;
93 else if (attachedPlayer->affects(CSSPropertyWebkitFilter))
94 propertyFilterBlocked = true;
95 }
96 }
97
98 if ((propertyOpacityBlocked && effectToAdd.affects(CSSPropertyOpacity))
99 || (propertyTransformBlocked && effectToAdd.affects(CSSPropertyTransform ))
100 || (propertyFilterBlocked && effectToAdd.affects(CSSPropertyWebkitFilter )))
101 return true;
102
103 return false;
104 }
73 } 105 }
74 106
75 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const Animation Effect& effect, double minValue, double maxValue) const 107 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const Animation Effect& effect, double minValue, double maxValue) const
76 { 108 {
77 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect); 109 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect);
78 110
79 PropertySet properties = keyframeEffect.properties(); 111 PropertySet properties = keyframeEffect.properties();
80 112
81 if (properties.isEmpty()) 113 if (properties.isEmpty())
82 return true; 114 return true;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 box.expandTo(bounds); 158 box.expandTo(bounds);
127 } 159 }
128 } 160 }
129 return true; 161 return true;
130 } 162 }
131 163
132 // ----------------------------------------------------------------------- 164 // -----------------------------------------------------------------------
133 // CompositorAnimations public API 165 // CompositorAnimations public API
134 // ----------------------------------------------------------------------- 166 // -----------------------------------------------------------------------
135 167
136 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim ing, const AnimationEffect& effect, double playerPlaybackRate) 168 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim ing, const Element* targetElement, const AnimationPlayer* playerToAdd, const Ani mationEffect& effect, double playerPlaybackRate)
dstockwell 2015/01/28 05:44:05 When can targetElement be null?
loyso (OOO) 2015/01/28 06:33:31 Unit tests. I could setup a fake one there if we n
loyso (OOO) 2015/01/28 23:18:34 Do we need it?
dstockwell 2015/01/29 01:14:07 Unless it's non-trivial to create an Element in th
137 { 169 {
170 if (targetElement && playerToAdd && alreadyActiveAnimationsBlockProperties(* targetElement, *playerToAdd, effect))
171 return false;
172
138 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect); 173 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect);
139 174
140 PropertySet properties = keyframeEffect.properties(); 175 PropertySet properties = keyframeEffect.properties();
141
142 if (properties.isEmpty()) 176 if (properties.isEmpty())
143 return false; 177 return false;
144 178
145 for (const auto& property : properties) { 179 for (const auto& property : properties) {
146 const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getProp ertySpecificKeyframes(property); 180 const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getProp ertySpecificKeyframes(property);
147 ASSERT(keyframes.size() >= 2); 181 ASSERT(keyframes.size() >= 2);
148 for (const auto& keyframe : keyframes) { 182 for (const auto& keyframe : keyframes) {
149 // FIXME: Determine candidacy based on the CSSValue instead of a sna pshot AnimatableValue. 183 // FIXME: Determine candidacy based on the CSSValue instead of a sna pshot AnimatableValue.
150 if (keyframe->composite() != AnimationEffect::CompositeReplace || !k eyframe->getAnimatableValue()) 184 if (keyframe->composite() != AnimationEffect::CompositeReplace || !k eyframe->getAnimatableValue())
151 return false; 185 return false;
152 186
153 switch (property) { 187 switch (property) {
154 case CSSPropertyOpacity: 188 case CSSPropertyOpacity:
155 break; 189 break;
156 case CSSPropertyTransform: 190 case CSSPropertyTransform:
157 if (toAnimatableTransform(keyframe->getAnimatableValue().get())- >transformOperations().dependsOnBoxSize()) 191 if (toAnimatableTransform(keyframe->getAnimatableValue().get())- >transformOperations().dependsOnBoxSize())
158 return false; 192 return false;
159 break; 193 break;
160 case CSSPropertyWebkitFilter: { 194 case CSSPropertyWebkitFilter: {
161 const FilterOperations& operations = toAnimatableFilterOperation s(keyframe->getAnimatableValue().get())->operations(); 195 const FilterOperations& operations = toAnimatableFilterOperation s(keyframe->getAnimatableValue().get())->operations();
162 if (operations.hasFilterThatMovesPixels()) 196 if (operations.hasFilterThatMovesPixels())
163 return false; 197 return false;
164 break; 198 break;
165 } 199 }
166 default: 200 default:
201 // any other types are not allowed to run on compositor.
167 return false; 202 return false;
168 } 203 }
169 } 204 }
170 } 205 }
171 206
172 CompositorAnimationsImpl::CompositorTiming out; 207 CompositorAnimationsImpl::CompositorTiming out;
173 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, pl ayerPlaybackRate)) 208 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, pl ayerPlaybackRate))
174 return false; 209 return false;
175 210
176 return true; 211 return true;
177 } 212 }
178 213
214 void CompositorAnimations::cancelAffectedAnimationsOnCompositor(const Element& t argetElement, const AnimationPlayer& playerToAdd, const AnimationEffect& effectT oAdd)
215 {
216 const bool propertyOpacityCancel = effectToAdd.affects(CSSPropertyOpacity);
217 const bool propertyTransformCancel = effectToAdd.affects(CSSPropertyTransfor m);
218 const bool propertyFilterCancel = effectToAdd.affects(CSSPropertyWebkitFilte r);
219
220 if (!targetElement.hasActiveAnimations())
221 return;
222
223 ActiveAnimations* activeAnimations = targetElement.activeAnimations();
224 ASSERT(activeAnimations);
225
226 for (const auto& entry : activeAnimations->players()) {
227 AnimationPlayer* attachedPlayer = entry.key;
228 if (attachedPlayer == &playerToAdd)
229 continue;
230
231 if ((propertyOpacityCancel && attachedPlayer->affects(CSSPropertyOpacity ))
232 || (propertyTransformCancel && attachedPlayer->affects(CSSPropertyTr ansform))
233 || (propertyFilterCancel && attachedPlayer->affects(CSSPropertyWebki tFilter)))
234 attachedPlayer->cancelAnimationOnCompositor();
235 }
236 }
237
179 bool CompositorAnimations::canStartAnimationOnCompositor(const Element& element) 238 bool CompositorAnimations::canStartAnimationOnCompositor(const Element& element)
180 { 239 {
181 return element.renderer() && element.renderer()->compositingState() == Paint sIntoOwnBacking; 240 return element.renderer() && element.renderer()->compositingState() == Paint sIntoOwnBacking;
182 } 241 }
183 242
184 bool CompositorAnimations::startAnimationOnCompositor(const Element& element, in t group, double startTime, double timeOffset, const Timing& timing, const Animat ionEffect& effect, Vector<int>& startedAnimationIds, double playerPlaybackRate) 243 bool CompositorAnimations::startAnimationOnCompositor(const Element& element, in t group, double startTime, double timeOffset, const Timing& timing, const Animat ionPlayer* player, const AnimationEffect& effect, Vector<int>& startedAnimationI ds, double playerPlaybackRate)
185 { 244 {
186 ASSERT(startedAnimationIds.isEmpty()); 245 ASSERT(startedAnimationIds.isEmpty());
187 ASSERT(isCandidateForAnimationOnCompositor(timing, effect, playerPlaybackRat e)); 246 ASSERT(isCandidateForAnimationOnCompositor(timing, &element, player, effect, playerPlaybackRate));
188 ASSERT(canStartAnimationOnCompositor(element)); 247 ASSERT(canStartAnimationOnCompositor(element));
189 248
190 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect); 249 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect);
191 250
192 RenderLayer* layer = toRenderBoxModelObject(element.renderer())->layer(); 251 RenderLayer* layer = toRenderBoxModelObject(element.renderer())->layer();
193 ASSERT(layer); 252 ASSERT(layer);
194 253
195 Vector<OwnPtr<WebCompositorAnimation>> animations; 254 Vector<OwnPtr<WebCompositorAnimation>> animations;
196 CompositorAnimationsImpl::getAnimationOnCompositor(timing, group, startTime, timeOffset, keyframeEffect, animations, playerPlaybackRate); 255 CompositorAnimationsImpl::getAnimationOnCompositor(timing, group, startTime, timeOffset, keyframeEffect, animations, playerPlaybackRate);
197 ASSERT(!animations.isEmpty()); 256 ASSERT(!animations.isEmpty());
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 break; 601 break;
543 default: 602 default:
544 ASSERT_NOT_REACHED(); 603 ASSERT_NOT_REACHED();
545 } 604 }
546 animations.append(animation.release()); 605 animations.append(animation.release());
547 } 606 }
548 ASSERT(!animations.isEmpty()); 607 ASSERT(!animations.isEmpty());
549 } 608 }
550 609
551 } // namespace blink 610 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698