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

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 test 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 hasIncompatibleAnimations(const Element& targetElement, const Animation& an imationToAdd, const EffectModel& effectToAdd) 96 bool hasIncompatibleAnimations(const Element& targetElement, const Animation& an imationToAdd, const EffectModel& effectToAdd)
97 { 97 {
98 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp acity)); 98 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp acity));
99 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty Transform)); 99 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty Rotate))
100 || effectToAdd.affects(PropertyHandle(CSSPropertyScale))
101 || effectToAdd.affects(PropertyHandle(CSSPropertyTransform))
dstockwell 2015/07/03 01:53:23 transform should be first (as most common)
soonm 2015/07/03 06:34:29 Done.
102 || effectToAdd.affects(PropertyHandle(CSSPropertyTranslate));
100 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb kitFilter)); 103 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb kitFilter));
101 104
102 if (!targetElement.hasAnimations()) 105 if (!targetElement.hasAnimations())
103 return false; 106 return false;
104 107
105 ElementAnimations* elementAnimations = targetElement.elementAnimations(); 108 ElementAnimations* elementAnimations = targetElement.elementAnimations();
106 ASSERT(elementAnimations); 109 ASSERT(elementAnimations);
107 110
108 for (const auto& entry : elementAnimations->animations()) { 111 for (const auto& entry : elementAnimations->animations()) {
109 const Animation* attachedAnimation = entry.key; 112 const Animation* attachedAnimation = entry.key;
110 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd) ) 113 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd) )
111 continue; 114 continue;
112 115
113 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp ertyOpacity)) 116 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp ertyOpacity))
117 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyRotate))
118 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyScale))
114 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyTransform)) 119 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyTransform))
dstockwell 2015/07/03 01:53:23 transform should come first
soonm 2015/07/03 06:34:29 Done - As well for the same code below.
120 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyTranslate))
115 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr opertyWebkitFilter))) 121 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr opertyWebkitFilter)))
116 return true; 122 return true;
117 } 123 }
118 124
119 return false; 125 return false;
120 } 126 }
121 127
122 } 128 }
123 129
124 CSSPropertyID CompositorAnimations::CompositableProperties[3] = { 130 bool CompositorAnimations::isCompositableProperty(CSSPropertyID property)
125 CSSPropertyOpacity, CSSPropertyTransform, CSSPropertyWebkitFilter 131 {
132 for (CSSPropertyID id : compositableProperties) {
133 if (property == id)
134 return true;
135 }
136 return false;
137 }
138
139 const CSSPropertyID CompositorAnimations::compositableProperties[6] = {
140 CSSPropertyOpacity,
141 CSSPropertyRotate,
142 CSSPropertyScale,
143 CSSPropertyTransform,
144 CSSPropertyTranslate,
145 CSSPropertyWebkitFilter
126 }; 146 };
127 147
128 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const EffectMod el& effect, double minValue, double maxValue) const 148 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const EffectMod el& effect, double minValue, double maxValue) const
129 { 149 {
130 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect); 150 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect);
131 151
132 PropertyHandleSet properties = keyframeEffect.properties(); 152 PropertyHandleSet properties = keyframeEffect.properties();
133 153
134 if (properties.isEmpty()) 154 if (properties.isEmpty())
135 return true; 155 return true;
136 156
137 minValue = std::min(minValue, 0.0); 157 minValue = std::min(minValue, 0.0);
138 maxValue = std::max(maxValue, 1.0); 158 maxValue = std::max(maxValue, 1.0);
139 159
140 for (const auto& property : properties) { 160 for (const auto& property : properties) {
141 if (!property.isCSSProperty()) 161 if (!property.isCSSProperty())
142 continue; 162 continue;
143 163
144 // TODO: Add the ability to get expanded bounds for filters as well. 164 // TODO: Add the ability to get expanded bounds for filters as well.
145 if (property.cssProperty() != CSSPropertyTransform) 165 if (property.cssProperty() != CSSPropertyRotate
166 && property.cssProperty() != CSSPropertyScale
167 && property.cssProperty() != CSSPropertyTransform
168 && property.cssProperty() != CSSPropertyTranslate)
146 continue; 169 continue;
147 170
148 const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropert ySpecificKeyframes(property); 171 const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropert ySpecificKeyframes(property);
149 if (frames.isEmpty() || frames.size() < 2) 172 if (frames.isEmpty() || frames.size() < 2)
150 continue; 173 continue;
151 174
152 FloatBox originalBox(box); 175 FloatBox originalBox(box);
153 176
154 for (size_t j = 0; j < frames.size() - 1; ++j) { 177 for (size_t j = 0; j < frames.size() - 1; ++j) {
155 const AnimatableTransform* startTransform = toAnimatableTransform(fr ames[j]->getAnimatableValue().get()); 178 const AnimatableTransform* startTransform = toAnimatableTransform(fr ames[j]->getAnimatableValue().get());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 // ----------------------------------------------------------------------- 216 // -----------------------------------------------------------------------
194 217
195 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim ing, const Element& targetElement, const Animation* animationToAdd, const Effect Model& effect, double animationPlaybackRate) 218 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim ing, const Element& targetElement, const Animation* animationToAdd, const Effect Model& effect, double animationPlaybackRate)
196 { 219 {
197 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect); 220 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef fect);
198 221
199 PropertyHandleSet properties = keyframeEffect.properties(); 222 PropertyHandleSet properties = keyframeEffect.properties();
200 if (properties.isEmpty()) 223 if (properties.isEmpty())
201 return false; 224 return false;
202 225
226 unsigned transformOperationsCount = 0;
dstockwell 2015/07/03 01:58:40 transformPropertyCount?
soonm 2015/07/03 06:34:29 Yep that sounds better.
203 for (const auto& property : properties) { 227 for (const auto& property : properties) {
204 if (!property.isCSSProperty()) 228 if (!property.isCSSProperty())
205 return false; 229 return false;
206 230
231 if (property.cssProperty() == CSSPropertyRotate
loyso (OOO) 2015/07/03 03:50:07 You have similar patterns repeated everywhere. Cou
soonm 2015/07/03 06:34:29 Did some clean up and abstracted out common checks
232 || property.cssProperty() == CSSPropertyScale
233 || property.cssProperty() == CSSPropertyTransform
234 || property.cssProperty() == CSSPropertyTranslate)
235 transformOperationsCount++;
236
207 const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getProp ertySpecificKeyframes(property); 237 const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getProp ertySpecificKeyframes(property);
208 ASSERT(keyframes.size() >= 2); 238 ASSERT(keyframes.size() >= 2);
209 for (const auto& keyframe : keyframes) { 239 for (const auto& keyframe : keyframes) {
210 // FIXME: Determine candidacy based on the CSSValue instead of a sna pshot AnimatableValue. 240 // 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; 241 bool isNeutralKeyframe = keyframe->isCSSPropertySpecificKeyframe() & & !toCSSPropertySpecificKeyframe(keyframe.get())->value() && keyframe->composite () == EffectModel::CompositeAdd;
212 if ((keyframe->composite() != EffectModel::CompositeReplace && !isNe utralKeyframe) || !keyframe->getAnimatableValue()) 242 if ((keyframe->composite() != EffectModel::CompositeReplace && !isNe utralKeyframe) || !keyframe->getAnimatableValue())
213 return false; 243 return false;
214 244
215 switch (property.cssProperty()) { 245 switch (property.cssProperty()) {
216 case CSSPropertyOpacity: 246 case CSSPropertyOpacity:
217 break; 247 break;
248 case CSSPropertyRotate:
249 case CSSPropertyScale:
250 case CSSPropertyTranslate:
218 case CSSPropertyTransform: 251 case CSSPropertyTransform:
219 if (toAnimatableTransform(keyframe->getAnimatableValue().get())- >transformOperations().dependsOnBoxSize()) 252 if (toAnimatableTransform(keyframe->getAnimatableValue().get())- >transformOperations().dependsOnBoxSize())
220 return false; 253 return false;
221 break; 254 break;
222 case CSSPropertyWebkitFilter: { 255 case CSSPropertyWebkitFilter: {
223 const FilterOperations& operations = toAnimatableFilterOperation s(keyframe->getAnimatableValue().get())->operations(); 256 const FilterOperations& operations = toAnimatableFilterOperation s(keyframe->getAnimatableValue().get())->operations();
224 if (operations.hasFilterThatMovesPixels()) 257 if (operations.hasFilterThatMovesPixels())
225 return false; 258 return false;
226 break; 259 break;
227 } 260 }
228 default: 261 default:
229 // any other types are not allowed to run on compositor. 262 // any other types are not allowed to run on compositor.
230 return false; 263 return false;
231 } 264 }
232 } 265 }
233 } 266 }
234 267
268 // TODO: Support multiple transform property animations on the compositor
269 if (transformOperationsCount > 1)
270 return false;
271
235 if (animationToAdd && hasIncompatibleAnimations(targetElement, *animationToA dd, effect)) 272 if (animationToAdd && hasIncompatibleAnimations(targetElement, *animationToA dd, effect))
236 return false; 273 return false;
237 274
238 CompositorAnimationsImpl::CompositorTiming out; 275 CompositorAnimationsImpl::CompositorTiming out;
239 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, an imationPlaybackRate)) 276 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, an imationPlaybackRate))
240 return false; 277 return false;
241 278
242 return true; 279 return true;
243 } 280 }
244 281
245 void CompositorAnimations::cancelIncompatibleAnimationsOnCompositor(const Elemen t& targetElement, const Animation& animationToAdd, const EffectModel& effectToAd d) 282 void CompositorAnimations::cancelIncompatibleAnimationsOnCompositor(const Elemen t& targetElement, const Animation& animationToAdd, const EffectModel& effectToAd d)
246 { 283 {
247 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp acity)); 284 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp acity));
248 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty Transform)); 285 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty Rotate))
286 || effectToAdd.affects(PropertyHandle(CSSPropertyScale))
287 || effectToAdd.affects(PropertyHandle(CSSPropertyTransform))
dstockwell 2015/07/03 01:58:40 transform first
soonm 2015/07/03 06:34:29 Done.
288 || effectToAdd.affects(PropertyHandle(CSSPropertyTranslate));
249 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb kitFilter)); 289 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb kitFilter));
250 290
251 if (!targetElement.hasAnimations()) 291 if (!targetElement.hasAnimations())
252 return; 292 return;
253 293
254 ElementAnimations* elementAnimations = targetElement.elementAnimations(); 294 ElementAnimations* elementAnimations = targetElement.elementAnimations();
255 ASSERT(elementAnimations); 295 ASSERT(elementAnimations);
256 296
257 for (const auto& entry : elementAnimations->animations()) { 297 for (const auto& entry : elementAnimations->animations()) {
258 Animation* attachedAnimation = entry.key; 298 Animation* attachedAnimation = entry.key;
259 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd) ) 299 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd) )
260 continue; 300 continue;
261 301
262 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp ertyOpacity)) 302 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp ertyOpacity))
303 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyRotate))
304 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyScale))
263 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyTransform)) 305 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyTransform))
dstockwell 2015/07/03 01:58:40 transform first
soonm 2015/07/03 06:34:29 Done.
306 || (affectsTransform && attachedAnimation->affects(targetElement, CS SPropertyTranslate))
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

Powered by Google App Engine
This is Rietveld 408576698