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

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

Powered by Google App Engine
This is Rietveld 408576698