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

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

Issue 1218943002: Compositor animations for Independent CSS Transform Properties (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Clean up Created 5 years, 5 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 return true; 86 return true;
87 case Animation::Paused: 87 case Animation::Paused:
88 case Animation::Finished: 88 case Animation::Finished:
89 return Animation::hasLowerPriority(&animationToAdd, &animation); 89 return Animation::hasLowerPriority(&animationToAdd, &animation);
90 default: 90 default:
91 ASSERT_NOT_REACHED(); 91 ASSERT_NOT_REACHED();
92 return true; 92 return true;
93 } 93 }
94 } 94 }
95 95
96 bool isTransformRelatedCSSProperty(const PropertyHandle property)
97 {
98 return property.isCSSProperty()
99 && property.cssProperty() != CSSPropertyRotate
100 && property.cssProperty() != CSSPropertyScale
101 && property.cssProperty() != CSSPropertyTransform
102 && property.cssProperty() != CSSPropertyTranslate;
103 }
104
105 bool isTransformRelatedEffect(const EffectModel& effect)
106 {
107 return effect.affects(PropertyHandle(CSSPropertyTransform))
108 || effect.affects(PropertyHandle(CSSPropertyRotate))
109 || effect.affects(PropertyHandle(CSSPropertyScale))
110 || effect.affects(PropertyHandle(CSSPropertyTranslate));
111 }
112
113 bool isTransformRelatedAnimation(const Element& targetElement, const Animation* animation)
114 {
115 return animation->affects(targetElement, CSSPropertyTransform)
116 || animation->affects(targetElement, CSSPropertyRotate)
117 || animation->affects(targetElement, CSSPropertyScale)
118 || animation->affects(targetElement, CSSPropertyTranslate);
119 }
120
96 bool hasIncompatibleAnimations(const Element& targetElement, const Animation& an imationToAdd, const EffectModel& effectToAdd) 121 bool hasIncompatibleAnimations(const Element& targetElement, const Animation& an imationToAdd, const EffectModel& effectToAdd)
97 { 122 {
98 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp acity)); 123 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp acity));
99 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty Transform)); 124 const bool affectsTransform = isTransformRelatedEffect(effectToAdd);
100 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb kitFilter)); 125 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb kitFilter));
101 126
102 if (!targetElement.hasAnimations()) 127 if (!targetElement.hasAnimations())
103 return false; 128 return false;
104 129
105 ElementAnimations* elementAnimations = targetElement.elementAnimations(); 130 ElementAnimations* elementAnimations = targetElement.elementAnimations();
106 ASSERT(elementAnimations); 131 ASSERT(elementAnimations);
107 132
108 for (const auto& entry : elementAnimations->animations()) { 133 for (const auto& entry : elementAnimations->animations()) {
109 const Animation* attachedAnimation = entry.key; 134 const Animation* attachedAnimation = entry.key;
110 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd) ) 135 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd) )
111 continue; 136 continue;
112 137
113 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp ertyOpacity)) 138 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp ertyOpacity))
114 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyTransform)) 139 || (affectsTransform && isTransformRelatedAnimation(targetElement, a ttachedAnimation))
115 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr opertyWebkitFilter))) 140 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr opertyWebkitFilter)))
116 return true; 141 return true;
117 } 142 }
118 143
119 return false; 144 return false;
120 } 145 }
121 146
122 } 147 }
123 148
124 CSSPropertyID CompositorAnimations::CompositableProperties[3] = { 149 bool CompositorAnimations::isCompositableProperty(CSSPropertyID property)
125 CSSPropertyOpacity, CSSPropertyTransform, CSSPropertyWebkitFilter 150 {
151 for (CSSPropertyID id : compositableProperties) {
152 if (property == id)
153 return true;
154 }
155 return false;
156 }
157
158 const CSSPropertyID CompositorAnimations::compositableProperties[6] = {
159 CSSPropertyOpacity,
160 CSSPropertyRotate,
161 CSSPropertyScale,
162 CSSPropertyTransform,
163 CSSPropertyTranslate,
164 CSSPropertyWebkitFilter
126 }; 165 };
127 166
128 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const EffectMod el& effect, double minValue, double maxValue) const 167 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const EffectMod el& effect, double minValue, double maxValue) const
129 { 168 {
130 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect); 169 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect);
131 170
132 PropertyHandleSet properties = keyframeEffect.properties(); 171 PropertyHandleSet properties = keyframeEffect.properties();
133 172
134 if (properties.isEmpty()) 173 if (properties.isEmpty())
135 return true; 174 return true;
136 175
137 minValue = std::min(minValue, 0.0); 176 minValue = std::min(minValue, 0.0);
138 maxValue = std::max(maxValue, 1.0); 177 maxValue = std::max(maxValue, 1.0);
139 178
140 for (const auto& property : properties) { 179 for (const auto& property : properties) {
141 if (!property.isCSSProperty()) 180 if (!property.isCSSProperty())
142 continue; 181 continue;
143 182
144 // TODO: Add the ability to get expanded bounds for filters as well. 183 // TODO: Add the ability to get expanded bounds for filters as well.
145 if (property.cssProperty() != CSSPropertyTransform) 184 if (isTransformRelatedCSSProperty(property))
146 continue; 185 continue;
147 186
148 const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropert ySpecificKeyframes(property); 187 const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropert ySpecificKeyframes(property);
149 if (frames.isEmpty() || frames.size() < 2) 188 if (frames.isEmpty() || frames.size() < 2)
150 continue; 189 continue;
151 190
152 FloatBox originalBox(box); 191 FloatBox originalBox(box);
153 192
154 for (size_t j = 0; j < frames.size() - 1; ++j) { 193 for (size_t j = 0; j < frames.size() - 1; ++j) {
155 const AnimatableTransform* startTransform = toAnimatableTransform(fr ames[j]->getAnimatableValue().get()); 194 const AnimatableTransform* startTransform = toAnimatableTransform(fr ames[j]->getAnimatableValue().get());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 // ----------------------------------------------------------------------- 232 // -----------------------------------------------------------------------
194 233
195 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim ing, const Element& targetElement, const Animation* animationToAdd, const Effect Model& effect, double animationPlaybackRate) 234 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim ing, const Element& targetElement, const Animation* animationToAdd, const Effect Model& effect, double animationPlaybackRate)
196 { 235 {
197 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect); 236 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect);
198 237
199 PropertyHandleSet properties = keyframeEffect.properties(); 238 PropertyHandleSet properties = keyframeEffect.properties();
200 if (properties.isEmpty()) 239 if (properties.isEmpty())
201 return false; 240 return false;
202 241
242 unsigned transformPropertyCount = 0;
203 for (const auto& property : properties) { 243 for (const auto& property : properties) {
204 if (!property.isCSSProperty()) 244 if (!property.isCSSProperty())
205 return false; 245 return false;
206 246
247 if (isTransformRelatedCSSProperty(property))
248 transformPropertyCount++;
249
207 const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getProp ertySpecificKeyframes(property); 250 const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getProp ertySpecificKeyframes(property);
208 ASSERT(keyframes.size() >= 2); 251 ASSERT(keyframes.size() >= 2);
209 for (const auto& keyframe : keyframes) { 252 for (const auto& keyframe : keyframes) {
210 // FIXME: Determine candidacy based on the CSSValue instead of a sna pshot AnimatableValue. 253 // FIXME: Determine candidacy based on the CSSValue instead of a sna pshot AnimatableValue.
211 bool isNeutralKeyframe = keyframe->isCSSPropertySpecificKeyframe() & & !toCSSPropertySpecificKeyframe(keyframe.get())->value() && keyframe->composite () == EffectModel::CompositeAdd; 254 bool isNeutralKeyframe = keyframe->isCSSPropertySpecificKeyframe() & & !toCSSPropertySpecificKeyframe(keyframe.get())->value() && keyframe->composite () == EffectModel::CompositeAdd;
212 if ((keyframe->composite() != EffectModel::CompositeReplace && !isNe utralKeyframe) || !keyframe->getAnimatableValue()) 255 if ((keyframe->composite() != EffectModel::CompositeReplace && !isNe utralKeyframe) || !keyframe->getAnimatableValue())
213 return false; 256 return false;
214 257
215 switch (property.cssProperty()) { 258 switch (property.cssProperty()) {
216 case CSSPropertyOpacity: 259 case CSSPropertyOpacity:
217 break; 260 break;
261 case CSSPropertyRotate:
262 case CSSPropertyScale:
263 case CSSPropertyTranslate:
218 case CSSPropertyTransform: 264 case CSSPropertyTransform:
219 if (toAnimatableTransform(keyframe->getAnimatableValue().get())- >transformOperations().dependsOnBoxSize()) 265 if (toAnimatableTransform(keyframe->getAnimatableValue().get())- >transformOperations().dependsOnBoxSize())
220 return false; 266 return false;
221 break; 267 break;
222 case CSSPropertyWebkitFilter: { 268 case CSSPropertyWebkitFilter: {
223 const FilterOperations& operations = toAnimatableFilterOperation s(keyframe->getAnimatableValue().get())->operations(); 269 const FilterOperations& operations = toAnimatableFilterOperation s(keyframe->getAnimatableValue().get())->operations();
224 if (operations.hasFilterThatMovesPixels()) 270 if (operations.hasFilterThatMovesPixels())
225 return false; 271 return false;
226 break; 272 break;
227 } 273 }
228 default: 274 default:
229 // any other types are not allowed to run on compositor. 275 // any other types are not allowed to run on compositor.
230 return false; 276 return false;
231 } 277 }
232 } 278 }
233 } 279 }
234 280
281 // TODO: Support multiple transform property animations on the compositor
282 if (transformPropertyCount > 1)
283 return false;
284
235 if (animationToAdd && hasIncompatibleAnimations(targetElement, *animationToA dd, effect)) 285 if (animationToAdd && hasIncompatibleAnimations(targetElement, *animationToA dd, effect))
236 return false; 286 return false;
237 287
238 CompositorAnimationsImpl::CompositorTiming out; 288 CompositorAnimationsImpl::CompositorTiming out;
239 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, an imationPlaybackRate)) 289 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, an imationPlaybackRate))
240 return false; 290 return false;
241 291
242 return true; 292 return true;
243 } 293 }
244 294
245 void CompositorAnimations::cancelIncompatibleAnimationsOnCompositor(const Elemen t& targetElement, const Animation& animationToAdd, const EffectModel& effectToAd d) 295 void CompositorAnimations::cancelIncompatibleAnimationsOnCompositor(const Elemen t& targetElement, const Animation& animationToAdd, const EffectModel& effectToAd d)
246 { 296 {
247 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp acity)); 297 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp acity));
248 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty Transform)); 298 const bool affectsTransform = isTransformRelatedEffect(effectToAdd);
249 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb kitFilter)); 299 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb kitFilter));
250 300
251 if (!targetElement.hasAnimations()) 301 if (!targetElement.hasAnimations())
252 return; 302 return;
253 303
254 ElementAnimations* elementAnimations = targetElement.elementAnimations(); 304 ElementAnimations* elementAnimations = targetElement.elementAnimations();
255 ASSERT(elementAnimations); 305 ASSERT(elementAnimations);
256 306
257 for (const auto& entry : elementAnimations->animations()) { 307 for (const auto& entry : elementAnimations->animations()) {
258 Animation* attachedAnimation = entry.key; 308 Animation* attachedAnimation = entry.key;
259 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd) ) 309 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd) )
260 continue; 310 continue;
261 311
262 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp ertyOpacity)) 312 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp ertyOpacity))
263 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyTransform)) 313 || (affectsTransform && isTransformRelatedAnimation(targetElement, a ttachedAnimation))
264 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr opertyWebkitFilter))) 314 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr opertyWebkitFilter)))
265 attachedAnimation->cancelAnimationOnCompositor(); 315 attachedAnimation->cancelAnimationOnCompositor();
266 } 316 }
267 } 317 }
268 318
269 bool CompositorAnimations::canStartAnimationOnCompositor(const Element& element) 319 bool CompositorAnimations::canStartAnimationOnCompositor(const Element& element)
270 { 320 {
271 return element.layoutObject() && element.layoutObject()->compositingState() == PaintsIntoOwnBacking; 321 return element.layoutObject() && element.layoutObject()->compositingState() == PaintsIntoOwnBacking;
272 } 322 }
273 323
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 break; 673 break;
624 } 674 }
625 case CSSPropertyWebkitFilter: { 675 case CSSPropertyWebkitFilter: {
626 targetProperty = WebCompositorAnimation::TargetPropertyFilter; 676 targetProperty = WebCompositorAnimation::TargetPropertyFilter;
627 WebFilterAnimationCurve* filterCurve = Platform::current()->composit orSupport()->createFilterAnimationCurve(); 677 WebFilterAnimationCurve* filterCurve = Platform::current()->composit orSupport()->createFilterAnimationCurve();
628 addKeyframesToCurve(*filterCurve, values, timing); 678 addKeyframesToCurve(*filterCurve, values, timing);
629 setTimingFunctionOnCurve(*filterCurve, timing.timingFunction.get()); 679 setTimingFunctionOnCurve(*filterCurve, timing.timingFunction.get());
630 curve = adoptPtr(filterCurve); 680 curve = adoptPtr(filterCurve);
631 break; 681 break;
632 } 682 }
683 case CSSPropertyRotate:
684 case CSSPropertyScale:
685 case CSSPropertyTranslate:
633 case CSSPropertyTransform: { 686 case CSSPropertyTransform: {
634 targetProperty = WebCompositorAnimation::TargetPropertyTransform; 687 targetProperty = WebCompositorAnimation::TargetPropertyTransform;
635 WebTransformAnimationCurve* transformCurve = Platform::current()->co mpositorSupport()->createTransformAnimationCurve(); 688 WebTransformAnimationCurve* transformCurve = Platform::current()->co mpositorSupport()->createTransformAnimationCurve();
636 addKeyframesToCurve(*transformCurve, values, timing); 689 addKeyframesToCurve(*transformCurve, values, timing);
637 setTimingFunctionOnCurve(*transformCurve, timing.timingFunction.get( )); 690 setTimingFunctionOnCurve(*transformCurve, timing.timingFunction.get( ));
638 curve = adoptPtr(transformCurve); 691 curve = adoptPtr(transformCurve);
639 break; 692 break;
640 } 693 }
641 default: 694 default:
642 ASSERT_NOT_REACHED(); 695 ASSERT_NOT_REACHED();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 break; 739 break;
687 default: 740 default:
688 ASSERT_NOT_REACHED(); 741 ASSERT_NOT_REACHED();
689 } 742 }
690 animations.append(animation.release()); 743 animations.append(animation.release());
691 } 744 }
692 ASSERT(!animations.isEmpty()); 745 ASSERT(!animations.isEmpty());
693 } 746 }
694 747
695 } // namespace blink 748 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698