1 /*
2  * Copyright (c) 2013, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
29  */
30 
31 #include "third_party/blink/renderer/core/animation/compositor_animations.h"
32 
33 #include <limits>
34 #include <memory>
35 #include <utility>
36 
37 #include "base/memory/ptr_util.h"
38 #include "base/memory/scoped_refptr.h"
39 #include "cc/animation/animation_host.h"
40 #include "cc/layers/picture_layer.h"
41 #include "cc/trees/transform_node.h"
42 #include "testing/gtest/include/gtest/gtest.h"
43 #include "third_party/blink/public/web/web_settings.h"
44 #include "third_party/blink/renderer/core/animation/animation.h"
45 #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_double.h"
46 #include "third_party/blink/renderer/core/animation/document_timeline.h"
47 #include "third_party/blink/renderer/core/animation/element_animations.h"
48 #include "third_party/blink/renderer/core/animation/keyframe_effect.h"
49 #include "third_party/blink/renderer/core/animation/pending_animations.h"
50 #include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
51 #include "third_party/blink/renderer/core/css/css_paint_value.h"
52 #include "third_party/blink/renderer/core/css/css_syntax_definition.h"
53 #include "third_party/blink/renderer/core/css/css_test_helpers.h"
54 #include "third_party/blink/renderer/core/css/mock_css_paint_image_generator.h"
55 #include "third_party/blink/renderer/core/dom/document.h"
56 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
57 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
58 #include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
59 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
60 #include "third_party/blink/renderer/core/layout/layout_object.h"
61 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
62 #include "third_party/blink/renderer/core/paint/object_paint_properties.h"
63 #include "third_party/blink/renderer/core/paint/paint_layer.h"
64 #include "third_party/blink/renderer/core/style/computed_style.h"
65 #include "third_party/blink/renderer/core/style/filter_operations.h"
66 #include "third_party/blink/renderer/core/style/style_generated_image.h"
67 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
68 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
69 #include "third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h"
70 #include "third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h"
71 #include "third_party/blink/renderer/platform/animation/compositor_float_keyframe.h"
72 #include "third_party/blink/renderer/platform/animation/compositor_keyframe_model.h"
73 #include "third_party/blink/renderer/platform/geometry/float_box.h"
74 #include "third_party/blink/renderer/platform/geometry/int_size.h"
75 #include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
76 #include "third_party/blink/renderer/platform/heap/heap.h"
77 #include "third_party/blink/renderer/platform/testing/histogram_tester.h"
78 #include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
79 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
80 #include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
81 #include "third_party/blink/renderer/platform/transforms/transform_operations.h"
82 #include "third_party/blink/renderer/platform/transforms/translate_transform_operation.h"
83 #include "third_party/blink/renderer/platform/wtf/hash_functions.h"
84 #include "third_party/skia/include/core/SkColor.h"
85 
86 using testing::_;
87 using testing::NiceMock;
88 using testing::Return;
89 using testing::ReturnRef;
90 using testing::Values;
91 
92 namespace blink {
93 
94 namespace {
95 // CSSPaintImageGenerator requires that CSSPaintImageGeneratorCreateFunction be
96 // a static method. As such, it cannot access a class member and so instead we
97 // store a pointer to the overriding generator globally.
98 MockCSSPaintImageGenerator* g_override_generator = nullptr;
ProvideOverrideGenerator(const String &,const Document &,CSSPaintImageGenerator::Observer *)99 CSSPaintImageGenerator* ProvideOverrideGenerator(
100     const String&,
101     const Document&,
102     CSSPaintImageGenerator::Observer*) {
103   return g_override_generator;
104 }
105 }  // namespace
106 
107 using css_test_helpers::RegisterProperty;
108 
109 class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
110                                           public RenderingTest {
111  protected:
112   scoped_refptr<TimingFunction> linear_timing_function_;
113   scoped_refptr<TimingFunction> cubic_ease_timing_function_;
114   scoped_refptr<TimingFunction> cubic_custom_timing_function_;
115   scoped_refptr<TimingFunction> step_timing_function_;
116 
117   Timing timing_;
118   CompositorAnimations::CompositorTiming compositor_timing_;
119   Persistent<HeapVector<Member<StringKeyframe>>> keyframe_vector2_;
120   Persistent<StringKeyframeEffectModel> keyframe_animation_effect2_;
121   Persistent<HeapVector<Member<StringKeyframe>>> keyframe_vector5_;
122   Persistent<StringKeyframeEffectModel> keyframe_animation_effect5_;
123 
124   Persistent<Element> element_;
125   Persistent<Element> inline_;
126   Persistent<DocumentTimeline> timeline_;
127 
SetUp()128   void SetUp() override {
129     EnableCompositing();
130     RenderingTest::SetUp();
131     linear_timing_function_ = LinearTimingFunction::Shared();
132     cubic_ease_timing_function_ = CubicBezierTimingFunction::Preset(
133         CubicBezierTimingFunction::EaseType::EASE);
134     cubic_custom_timing_function_ =
135         CubicBezierTimingFunction::Create(1, 2, 3, 4);
136     step_timing_function_ =
137         StepsTimingFunction::Create(1, StepsTimingFunction::StepPosition::END);
138 
139     timing_ = CreateCompositableTiming();
140     compositor_timing_ = CompositorAnimations::CompositorTiming();
141     // Make sure the CompositableTiming is really compositable, otherwise
142     // most other tests will fail.
143     ASSERT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
144 
145     keyframe_vector2_ = CreateCompositableFloatKeyframeVector(2);
146     keyframe_animation_effect2_ =
147         MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector2_);
148 
149     keyframe_vector5_ = CreateCompositableFloatKeyframeVector(5);
150     keyframe_animation_effect5_ =
151         MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector5_);
152 
153     GetAnimationClock().ResetTimeForTesting();
154 
155     timeline_ = GetDocument().Timeline();
156     timeline_->ResetForTesting();
157 
158     // Using will-change ensures that this object will need paint properties.
159     // Having an animation would normally ensure this but these tests don't
160     // explicitly construct a full animation on the element.
161     SetBodyInnerHTML(R"HTML(
162         <div id='test' style='will-change: opacity,filter,transform; height:100px; background: green;'></div>
163         <span id='inline' style='will-change: opacity,filter,transform;'>text</div>
164     )HTML");
165     element_ = GetDocument().getElementById("test");
166     inline_ = GetDocument().getElementById("inline");
167 
168     helper_.Initialize(nullptr, nullptr, nullptr);
169     base_url_ = "http://www.test.com/";
170   }
171 
172  public:
ConvertTimingForCompositor(const Timing & t,CompositorAnimations::CompositorTiming & out)173   bool ConvertTimingForCompositor(const Timing& t,
174                                   CompositorAnimations::CompositorTiming& out) {
175     return CompositorAnimations::ConvertTimingForCompositor(
176         t, base::TimeDelta(), out, 1);
177   }
178 
CanStartEffectOnCompositor(const Timing & timing,const KeyframeEffectModelBase & effect)179   CompositorAnimations::FailureReasons CanStartEffectOnCompositor(
180       const Timing& timing,
181       const KeyframeEffectModelBase& effect) {
182     // TODO(crbug.com/725385): Remove once compositor uses InterpolationTypes.
183     auto style = GetDocument().EnsureStyleResolver().StyleForElement(element_);
184     effect.SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
185                                                      nullptr);
186     return CheckCanStartEffectOnCompositor(timing, *element_.Get(), nullptr,
187                                            effect);
188   }
CheckCanStartEffectOnCompositor(const Timing & timing,const Element & element,const Animation * animation,const EffectModel & effect_model)189   CompositorAnimations::FailureReasons CheckCanStartEffectOnCompositor(
190       const Timing& timing,
191       const Element& element,
192       const Animation* animation,
193       const EffectModel& effect_model) {
194     const PaintArtifactCompositor* paint_artifact_compositor =
195         GetDocument().View()->GetPaintArtifactCompositor();
196     return CompositorAnimations::CheckCanStartEffectOnCompositor(
197         timing, element, animation, effect_model, paint_artifact_compositor, 1);
198   }
199 
CheckCanStartElementOnCompositor(const Element & element)200   CompositorAnimations::FailureReasons CheckCanStartElementOnCompositor(
201       const Element& element) {
202     return CompositorAnimations::CheckCanStartElementOnCompositor(element);
203   }
204 
GetAnimationOnCompositor(Timing & timing,StringKeyframeEffectModel & effect,Vector<std::unique_ptr<CompositorKeyframeModel>> & keyframe_models,double animation_playback_rate)205   void GetAnimationOnCompositor(
206       Timing& timing,
207       StringKeyframeEffectModel& effect,
208       Vector<std::unique_ptr<CompositorKeyframeModel>>& keyframe_models,
209       double animation_playback_rate) {
210     CompositorAnimations::GetAnimationOnCompositor(
211         *element_, timing, 0, base::nullopt, base::TimeDelta(), effect,
212         keyframe_models, animation_playback_rate);
213   }
214 
215   CompositorAnimations::FailureReasons
DuplicateSingleKeyframeAndTestIsCandidateOnResult(StringKeyframe * frame)216   DuplicateSingleKeyframeAndTestIsCandidateOnResult(StringKeyframe* frame) {
217     EXPECT_EQ(frame->CheckedOffset(), 0);
218     StringKeyframeVector frames;
219     Keyframe* second = frame->CloneWithOffset(1);
220 
221     frames.push_back(frame);
222     frames.push_back(To<StringKeyframe>(second));
223     return CanStartEffectOnCompositor(
224         timing_, *MakeGarbageCollected<StringKeyframeEffectModel>(frames));
225   }
226 
227   // -------------------------------------------------------------------
228 
CreateCompositableTiming()229   Timing CreateCompositableTiming() {
230     Timing timing;
231     timing.start_delay = 0;
232     timing.fill_mode = Timing::FillMode::NONE;
233     timing.iteration_start = 0;
234     timing.iteration_count = 1;
235     timing.iteration_duration = AnimationTimeDelta::FromSecondsD(1);
236     timing.direction = Timing::PlaybackDirection::NORMAL;
237     timing.timing_function = linear_timing_function_;
238     return timing;
239   }
240 
CreateReplaceOpKeyframe(CSSPropertyID id,const String & value,double offset=0)241   StringKeyframe* CreateReplaceOpKeyframe(CSSPropertyID id,
242                                           const String& value,
243                                           double offset = 0) {
244     auto* keyframe = MakeGarbageCollected<StringKeyframe>();
245     keyframe->SetCSSPropertyValue(id, value,
246                                   SecureContextMode::kInsecureContext, nullptr);
247     keyframe->SetComposite(EffectModel::kCompositeReplace);
248     keyframe->SetOffset(offset);
249     keyframe->SetEasing(LinearTimingFunction::Shared());
250     return keyframe;
251   }
252 
CreateReplaceOpKeyframe(const String & property_name,const String & value,double offset=0)253   StringKeyframe* CreateReplaceOpKeyframe(const String& property_name,
254                                           const String& value,
255                                           double offset = 0) {
256     auto* keyframe = MakeGarbageCollected<StringKeyframe>();
257     keyframe->SetCSSPropertyValue(AtomicString(property_name), value,
258                                   GetDocument().GetSecureContextMode(),
259                                   GetDocument().ElementSheet().Contents());
260     keyframe->SetComposite(EffectModel::kCompositeReplace);
261     keyframe->SetOffset(offset);
262     keyframe->SetEasing(LinearTimingFunction::Shared());
263     return keyframe;
264   }
265 
CreateDefaultKeyframe(CSSPropertyID id,EffectModel::CompositeOperation op,double offset=0)266   StringKeyframe* CreateDefaultKeyframe(CSSPropertyID id,
267                                         EffectModel::CompositeOperation op,
268                                         double offset = 0) {
269     String value = "0.1";
270     if (id == CSSPropertyID::kTransform)
271       value = "none";
272     else if (id == CSSPropertyID::kColor)
273       value = "red";
274 
275     StringKeyframe* keyframe = CreateReplaceOpKeyframe(id, value, offset);
276     keyframe->SetComposite(op);
277     return keyframe;
278   }
279 
CreateCompositableFloatKeyframeVector(size_t n)280   HeapVector<Member<StringKeyframe>>* CreateCompositableFloatKeyframeVector(
281       size_t n) {
282     Vector<double> values;
283     for (size_t i = 0; i < n; i++) {
284       values.push_back(static_cast<double>(i));
285     }
286     return CreateCompositableFloatKeyframeVector(values);
287   }
288 
CreateCompositableFloatKeyframeVector(Vector<double> & values)289   HeapVector<Member<StringKeyframe>>* CreateCompositableFloatKeyframeVector(
290       Vector<double>& values) {
291     HeapVector<Member<StringKeyframe>>* frames =
292         MakeGarbageCollected<HeapVector<Member<StringKeyframe>>>();
293     for (wtf_size_t i = 0; i < values.size(); i++) {
294       double offset = 1.0 / (values.size() - 1) * i;
295       String value = String::Number(values[i]);
296       frames->push_back(
297           CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, value, offset));
298     }
299     return frames;
300   }
301 
SetCustomProperty(const String & name,const String & value)302   void SetCustomProperty(const String& name, const String& value) {
303     DummyExceptionStateForTesting exception_state;
304     element_->style()->setProperty(GetDocument().GetExecutionContext(), name,
305                                    value, g_empty_string, exception_state);
306     EXPECT_FALSE(exception_state.HadException());
307     EXPECT_TRUE(element_->style()->getPropertyValue(name));
308   }
309 
310   // This class exists to dodge the interlock between creating compositor
311   // keyframe values iff we can animate them on the compositor, and hence can
312   // start their animations on it. i.e. two far away switch statements have
313   // matching non-default values, preventing us from testing the default.
314   class MockStringKeyframe : public StringKeyframe {
315    public:
Create(double offset)316     static StringKeyframe* Create(double offset) {
317       return MakeGarbageCollected<MockStringKeyframe>(offset);
318     }
319 
MockStringKeyframe(double offset)320     MockStringKeyframe(double offset)
321         : StringKeyframe(),
322           property_specific_(
323               MakeGarbageCollected<MockPropertySpecificStringKeyframe>(
324                   offset)) {
325       SetOffset(offset);
326     }
327 
CreatePropertySpecificKeyframe(const PropertyHandle &,EffectModel::CompositeOperation,double) const328     Keyframe::PropertySpecificKeyframe* CreatePropertySpecificKeyframe(
329         const PropertyHandle&,
330         EffectModel::CompositeOperation,
331         double) const final {
332       return property_specific_;  // We know a shortcut.
333     }
334 
Trace(Visitor * visitor)335     void Trace(Visitor* visitor) override {
336       visitor->Trace(property_specific_);
337       StringKeyframe::Trace(visitor);
338     }
339 
340    private:
341     class MockPropertySpecificStringKeyframe : public PropertySpecificKeyframe {
342      public:
343       // Pretend to have a compositor keyframe value. Pick the offset for pure
344       // convenience: it matters not what it is.
MockPropertySpecificStringKeyframe(double offset)345       MockPropertySpecificStringKeyframe(double offset)
346           : PropertySpecificKeyframe(offset,
347                                      LinearTimingFunction::Shared(),
348                                      EffectModel::kCompositeReplace),
349             compositor_keyframe_value_(
350                 MakeGarbageCollected<CompositorKeyframeDouble>(offset)) {}
IsNeutral() const351       bool IsNeutral() const final { return true; }
CloneWithOffset(double) const352       PropertySpecificKeyframe* CloneWithOffset(double) const final {
353         NOTREACHED();
354         return nullptr;
355       }
PopulateCompositorKeyframeValue(const PropertyHandle &,Element &,const ComputedStyle & base_style,const ComputedStyle * parent_style) const356       bool PopulateCompositorKeyframeValue(
357           const PropertyHandle&,
358           Element&,
359           const ComputedStyle& base_style,
360           const ComputedStyle* parent_style) const final {
361         return true;
362       }
GetCompositorKeyframeValue() const363       const CompositorKeyframeValue* GetCompositorKeyframeValue() const final {
364         return compositor_keyframe_value_;
365       }
NeutralKeyframe(double,scoped_refptr<TimingFunction>) const366       PropertySpecificKeyframe* NeutralKeyframe(
367           double,
368           scoped_refptr<TimingFunction>) const final {
369         NOTREACHED();
370         return nullptr;
371       }
372 
Trace(Visitor * visitor)373       void Trace(Visitor* visitor) override {
374         visitor->Trace(compositor_keyframe_value_);
375         PropertySpecificKeyframe::Trace(visitor);
376       }
377 
378      private:
379       Member<CompositorKeyframeDouble> compositor_keyframe_value_;
380     };
381 
382     Member<PropertySpecificKeyframe> property_specific_;
383   };
384 
CreateMockReplaceKeyframe(CSSPropertyID id,const String & value,double offset)385   StringKeyframe* CreateMockReplaceKeyframe(CSSPropertyID id,
386                                             const String& value,
387                                             double offset) {
388     StringKeyframe* keyframe = MockStringKeyframe::Create(offset);
389     keyframe->SetCSSPropertyValue(id, value,
390                                   SecureContextMode::kInsecureContext, nullptr);
391     keyframe->SetComposite(EffectModel::kCompositeReplace);
392     keyframe->SetEasing(LinearTimingFunction::Shared());
393 
394     return keyframe;
395   }
396 
CreateSVGKeyframe(const QualifiedName & name,const String & value,double offset)397   StringKeyframe* CreateSVGKeyframe(const QualifiedName& name,
398                                     const String& value,
399                                     double offset) {
400     auto* keyframe = MakeGarbageCollected<StringKeyframe>();
401     keyframe->SetSVGAttributeValue(name, value);
402     keyframe->SetComposite(EffectModel::kCompositeReplace);
403     keyframe->SetOffset(offset);
404     keyframe->SetEasing(LinearTimingFunction::Shared());
405 
406     return keyframe;
407   }
408 
CreateKeyframeEffectModel(StringKeyframe * from,StringKeyframe * to,StringKeyframe * c=nullptr,StringKeyframe * d=nullptr)409   StringKeyframeEffectModel* CreateKeyframeEffectModel(
410       StringKeyframe* from,
411       StringKeyframe* to,
412       StringKeyframe* c = nullptr,
413       StringKeyframe* d = nullptr) {
414     EXPECT_EQ(from->CheckedOffset(), 0);
415     StringKeyframeVector frames;
416     frames.push_back(from);
417     EXPECT_LE(from->Offset(), to->Offset());
418     frames.push_back(to);
419     if (c) {
420       EXPECT_LE(to->Offset(), c->Offset());
421       frames.push_back(c);
422     }
423     if (d) {
424       frames.push_back(d);
425       EXPECT_LE(c->Offset(), d->Offset());
426       EXPECT_EQ(d->CheckedOffset(), 1.0);
427     } else {
428       EXPECT_EQ(to->CheckedOffset(), 1.0);
429     }
430     if (!HasFatalFailure()) {
431       return MakeGarbageCollected<StringKeyframeEffectModel>(frames);
432     }
433     return nullptr;
434   }
435 
SimulateFrame(double time)436   void SimulateFrame(double time) {
437     GetAnimationClock().UpdateTime(base::TimeTicks() +
438                                    base::TimeDelta::FromSecondsD(time));
439     GetPendingAnimations().Update(nullptr, false);
440     timeline_->ServiceAnimations(kTimingUpdateForAnimationFrame);
441   }
442 
ConvertToCompositorAnimation(StringKeyframeEffectModel & effect,double animation_playback_rate)443   std::unique_ptr<CompositorKeyframeModel> ConvertToCompositorAnimation(
444       StringKeyframeEffectModel& effect,
445       double animation_playback_rate) {
446     // As the compositor code only understands CompositorKeyframeValues, we must
447     // snapshot the effect to make those available.
448     // TODO(crbug.com/725385): Remove once compositor uses InterpolationTypes.
449     auto style = GetDocument().EnsureStyleResolver().StyleForElement(element_);
450     effect.SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
451                                                      nullptr);
452 
453     Vector<std::unique_ptr<CompositorKeyframeModel>> result;
454     GetAnimationOnCompositor(timing_, effect, result, animation_playback_rate);
455     DCHECK_EQ(1U, result.size());
456     return std::move(result[0]);
457   }
458 
ConvertToCompositorAnimation(StringKeyframeEffectModel & effect)459   std::unique_ptr<CompositorKeyframeModel> ConvertToCompositorAnimation(
460       StringKeyframeEffectModel& effect) {
461     return ConvertToCompositorAnimation(effect, 1.0);
462   }
463 
ExpectKeyframeTimingFunctionCubic(const CompositorFloatKeyframe & keyframe,const CubicBezierTimingFunction::EaseType ease_type)464   void ExpectKeyframeTimingFunctionCubic(
465       const CompositorFloatKeyframe& keyframe,
466       const CubicBezierTimingFunction::EaseType ease_type) {
467     auto keyframe_timing_function = keyframe.GetTimingFunctionForTesting();
468     DCHECK_EQ(keyframe_timing_function->GetType(),
469               TimingFunction::Type::CUBIC_BEZIER);
470     const auto& cubic_timing_function =
471         To<CubicBezierTimingFunction>(*keyframe_timing_function);
472     EXPECT_EQ(cubic_timing_function.GetEaseType(), ease_type);
473   }
474 
LoadTestData(const std::string & file_name)475   void LoadTestData(const std::string& file_name) {
476     String testing_path =
477         test::BlinkRootDir() + "/renderer/core/animation/test_data/";
478     WebURL url = url_test_helpers::RegisterMockedURLLoadFromBase(
479         WebString::FromUTF8(base_url_), testing_path,
480         WebString::FromUTF8(file_name));
481     frame_test_helpers::LoadFrame(helper_.GetWebView()->MainFrameImpl(),
482                                   base_url_ + file_name);
483     ForceFullCompositingUpdate();
484     url_test_helpers::RegisterMockedURLUnregister(url);
485   }
486 
GetFrame() const487   LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); }
488 
BeginFrame()489   void BeginFrame() {
490     helper_.GetWebView()
491         ->MainFrameWidgetBase()
492         ->SynchronouslyCompositeForTesting(base::TimeTicks::Now());
493   }
494 
ForceFullCompositingUpdate()495   void ForceFullCompositingUpdate() {
496     helper_.GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
497         DocumentUpdateReason::kTest);
498   }
499 
500  private:
501   frame_test_helpers::WebViewHelper helper_;
502   std::string base_url_;
503 };
504 
505 class LayoutObjectProxy : public LayoutObject {
506  public:
Create(Node * node)507   static LayoutObjectProxy* Create(Node* node) {
508     return new LayoutObjectProxy(node);
509   }
510 
Dispose(LayoutObjectProxy * proxy)511   static void Dispose(LayoutObjectProxy* proxy) { proxy->Destroy(); }
512 
GetName() const513   const char* GetName() const override { return nullptr; }
UpdateLayout()514   void UpdateLayout() override {}
LocalBoundingBoxRectForAccessibility() const515   FloatRect LocalBoundingBoxRectForAccessibility() const override {
516     return FloatRect();
517   }
518 
EnsureIdForTestingProxy()519   void EnsureIdForTestingProxy() {
520     // We need Ids of proxies to be valid.
521     EnsureIdForTesting();
522   }
523 
524  private:
LayoutObjectProxy(Node * node)525   explicit LayoutObjectProxy(Node* node) : LayoutObject(node) {}
526 };
527 
528 // -----------------------------------------------------------------------
529 // -----------------------------------------------------------------------
530 
531 INSTANTIATE_PAINT_TEST_SUITE_P(AnimationCompositorAnimationsTest);
532 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorKeyframeMultipleCSSProperties)533 TEST_P(AnimationCompositorAnimationsTest,
534        CanStartEffectOnCompositorKeyframeMultipleCSSProperties) {
535   StringKeyframe* keyframe_good_multiple = CreateDefaultKeyframe(
536       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace);
537   keyframe_good_multiple->SetCSSPropertyValue(
538       CSSPropertyID::kTransform, "none", SecureContextMode::kInsecureContext,
539       nullptr);
540   EXPECT_EQ(
541       DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe_good_multiple),
542       CompositorAnimations::kNoFailure);
543 
544   StringKeyframe* keyframe_bad_multiple_id = CreateDefaultKeyframe(
545       CSSPropertyID::kColor, EffectModel::kCompositeReplace);
546   keyframe_bad_multiple_id->SetCSSPropertyValue(
547       CSSPropertyID::kOpacity, "0.1", SecureContextMode::kInsecureContext,
548       nullptr);
549   EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(
550                   keyframe_bad_multiple_id) &
551               CompositorAnimations::kUnsupportedCSSProperty);
552 }
553 
TEST_P(AnimationCompositorAnimationsTest,IsNotCandidateForCompositorAnimationTransformDependsOnBoxSize)554 TEST_P(AnimationCompositorAnimationsTest,
555        IsNotCandidateForCompositorAnimationTransformDependsOnBoxSize) {
556   // Absolute transforms can be animated on the compositor.
557   String transform = "translateX(2px) translateY(2px)";
558   StringKeyframe* good_keyframe =
559       CreateReplaceOpKeyframe(CSSPropertyID::kTransform, transform);
560   EXPECT_EQ(DuplicateSingleKeyframeAndTestIsCandidateOnResult(good_keyframe),
561             CompositorAnimations::kNoFailure);
562 
563   // Transforms that rely on the box size, such as percent calculations, cannot
564   // be animated on the compositor (as the box size may change).
565   String transform2 = "translateX(50%) translateY(2px)";
566   StringKeyframe* bad_keyframe =
567       CreateReplaceOpKeyframe(CSSPropertyID::kTransform, transform2);
568   EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(bad_keyframe) &
569               CompositorAnimations::kTransformRelatedPropertyDependsOnBoxSize);
570 
571   // Similarly, calc transforms cannot be animated on the compositor.
572   String transform3 = "translateX(calc(100% + (0.5 * 100px)))";
573   StringKeyframe* bad_keyframe2 =
574       CreateReplaceOpKeyframe(CSSPropertyID::kTransform, transform3);
575   EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(bad_keyframe2) &
576               CompositorAnimations::kTransformRelatedPropertyDependsOnBoxSize);
577 }
578 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorKeyframeEffectModel)579 TEST_P(AnimationCompositorAnimationsTest,
580        CanStartEffectOnCompositorKeyframeEffectModel) {
581   StringKeyframeVector frames_same;
582   frames_same.push_back(CreateDefaultKeyframe(
583       CSSPropertyID::kColor, EffectModel::kCompositeReplace, 0.0));
584   frames_same.push_back(CreateDefaultKeyframe(
585       CSSPropertyID::kColor, EffectModel::kCompositeReplace, 1.0));
586   EXPECT_TRUE(CanStartEffectOnCompositor(
587                   timing_, *MakeGarbageCollected<StringKeyframeEffectModel>(
588                                frames_same)) &
589               CompositorAnimations::kUnsupportedCSSProperty);
590 
591   StringKeyframeVector frames_mixed_properties;
592   auto* keyframe = MakeGarbageCollected<StringKeyframe>();
593   keyframe->SetOffset(0);
594   keyframe->SetCSSPropertyValue(CSSPropertyID::kColor, "red",
595                                 SecureContextMode::kInsecureContext, nullptr);
596   keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0",
597                                 SecureContextMode::kInsecureContext, nullptr);
598   frames_mixed_properties.push_back(keyframe);
599   keyframe = MakeGarbageCollected<StringKeyframe>();
600   keyframe->SetOffset(1);
601   keyframe->SetCSSPropertyValue(CSSPropertyID::kColor, "green",
602                                 SecureContextMode::kInsecureContext, nullptr);
603   keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1",
604                                 SecureContextMode::kInsecureContext, nullptr);
605   frames_mixed_properties.push_back(keyframe);
606   EXPECT_TRUE(CanStartEffectOnCompositor(
607                   timing_, *MakeGarbageCollected<StringKeyframeEffectModel>(
608                                frames_mixed_properties)) &
609               CompositorAnimations::kUnsupportedCSSProperty);
610 }
611 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorCustomCssProperty)612 TEST_P(AnimationCompositorAnimationsTest,
613        CanStartEffectOnCompositorCustomCssProperty) {
614   ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true);
615   RegisterProperty(GetDocument(), "--foo", "<number>", "0", false);
616   RegisterProperty(GetDocument(), "--bar", "<length>", "10px", false);
617   RegisterProperty(GetDocument(), "--loo", "<color>", "rgb(0, 0, 0)", false);
618   RegisterProperty(GetDocument(), "--x", "<number>", "0", false);
619   SetCustomProperty("--foo", "10");
620   SetCustomProperty("--bar", "10px");
621   SetCustomProperty("--loo", "rgb(0, 255, 0)");
622   SetCustomProperty("--x", "5");
623 
624   auto style = GetDocument().EnsureStyleResolver().StyleForElement(element_);
625   EXPECT_TRUE(style->NonInheritedVariables());
626   EXPECT_TRUE(style->NonInheritedVariables()
627                   ->GetData(AtomicString("--foo"))
628                   .value_or(nullptr));
629   EXPECT_TRUE(style->NonInheritedVariables()
630                   ->GetData(AtomicString("--bar"))
631                   .value_or(nullptr));
632   EXPECT_TRUE(style->NonInheritedVariables()
633                   ->GetData(AtomicString("--loo"))
634                   .value_or(nullptr));
635   EXPECT_TRUE(style->NonInheritedVariables()
636                   ->GetData(AtomicString("--x"))
637                   .value_or(nullptr));
638 
639   NiceMock<MockCSSPaintImageGenerator>* mock_generator =
640       MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
641   base::AutoReset<MockCSSPaintImageGenerator*> scoped_override_generator(
642       &g_override_generator, mock_generator);
643   base::AutoReset<CSSPaintImageGenerator::CSSPaintImageGeneratorCreateFunction>
644       scoped_create_function(
645           CSSPaintImageGenerator::GetCreateFunctionForTesting(),
646           ProvideOverrideGenerator);
647 
648   mock_generator->AddCustomProperty("--foo");
649   mock_generator->AddCustomProperty("--bar");
650   mock_generator->AddCustomProperty("--loo");
651   auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("foopainter");
652   CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
653   paint_value->CreateGeneratorForTesting(GetDocument());
654   StyleGeneratedImage* style_image =
655       MakeGarbageCollected<StyleGeneratedImage>(*paint_value);
656   style->AddPaintImage(style_image);
657   element_->GetLayoutObject()->SetStyle(style);
658   // The image is added for testing off-thread paint worklet supporting
659   // custom property animation case. The style doesn't have a real
660   // PaintImage, so we cannot call UpdateAllLifecyclePhasesForTest. But the
661   // PaintArtifactCompositor requires NeedsUpdate to be false.
662   // In the real world when a PaintImage does exist in the style, the life
663   // cycle will be updated automatically and we don't have to worry about
664   // this.
665   auto* paint_artifact_compositor =
666       GetDocument().View()->GetPaintArtifactCompositor();
667   paint_artifact_compositor->ClearNeedsUpdateForTesting();
668 
669   ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true));
670   StringKeyframe* keyframe = CreateReplaceOpKeyframe("--foo", "10");
671   EXPECT_EQ(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe),
672             CompositorAnimations::kNoFailure);
673 
674   // Color-valued properties are supported
675   StringKeyframe* color_keyframe =
676       CreateReplaceOpKeyframe("--loo", "rgb(0, 255, 0)");
677   EXPECT_EQ(DuplicateSingleKeyframeAndTestIsCandidateOnResult(color_keyframe),
678             CompositorAnimations::kNoFailure);
679 
680   // Length-valued properties are not compositable.
681   StringKeyframe* non_animatable_keyframe =
682       CreateReplaceOpKeyframe("--bar", "10px");
683   EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(
684                   non_animatable_keyframe) &
685               CompositorAnimations::kUnsupportedCSSProperty);
686 
687   // Cannot composite due to side effect.
688   SetCustomProperty("opacity", "var(--foo)");
689   EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe) &
690               CompositorAnimations::kUnsupportedCSSProperty);
691 
692   // Cannot composite because "--x" is not used by the paint worklet.
693   StringKeyframe* non_used_keyframe = CreateReplaceOpKeyframe("--x", "5");
694   EXPECT_EQ(
695       DuplicateSingleKeyframeAndTestIsCandidateOnResult(non_used_keyframe),
696       CompositorAnimations::kUnsupportedCSSProperty);
697 }
698 
TEST_P(AnimationCompositorAnimationsTest,ConvertTimingForCompositorStartDelay)699 TEST_P(AnimationCompositorAnimationsTest,
700        ConvertTimingForCompositorStartDelay) {
701   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(20);
702 
703   timing_.start_delay = 2.0;
704   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
705   EXPECT_DOUBLE_EQ(-2.0, compositor_timing_.scaled_time_offset.InSecondsF());
706 
707   timing_.start_delay = -2.0;
708   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
709   EXPECT_DOUBLE_EQ(2.0, compositor_timing_.scaled_time_offset.InSecondsF());
710 }
711 
TEST_P(AnimationCompositorAnimationsTest,ConvertTimingForCompositorIterationStart)712 TEST_P(AnimationCompositorAnimationsTest,
713        ConvertTimingForCompositorIterationStart) {
714   timing_.iteration_start = 2.2;
715   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
716 }
717 
TEST_P(AnimationCompositorAnimationsTest,ConvertTimingForCompositorIterationCount)718 TEST_P(AnimationCompositorAnimationsTest,
719        ConvertTimingForCompositorIterationCount) {
720   timing_.iteration_count = 5.0;
721   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
722   EXPECT_EQ(5, compositor_timing_.adjusted_iteration_count);
723 
724   timing_.iteration_count = 5.5;
725   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
726   EXPECT_EQ(5.5, compositor_timing_.adjusted_iteration_count);
727 
728   timing_.iteration_count = std::numeric_limits<double>::infinity();
729   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
730   EXPECT_EQ(std::numeric_limits<double>::infinity(),
731             compositor_timing_.adjusted_iteration_count);
732 
733   timing_.iteration_count = std::numeric_limits<double>::infinity();
734   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(5);
735   timing_.start_delay = -6.0;
736   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
737   EXPECT_DOUBLE_EQ(6.0, compositor_timing_.scaled_time_offset.InSecondsF());
738   EXPECT_EQ(std::numeric_limits<double>::infinity(),
739             compositor_timing_.adjusted_iteration_count);
740 }
741 
TEST_P(AnimationCompositorAnimationsTest,ConvertTimingForCompositorIterationsAndStartDelay)742 TEST_P(AnimationCompositorAnimationsTest,
743        ConvertTimingForCompositorIterationsAndStartDelay) {
744   timing_.iteration_count = 4.0;
745   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(5);
746 
747   timing_.start_delay = 6.0;
748   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
749   EXPECT_DOUBLE_EQ(-6.0, compositor_timing_.scaled_time_offset.InSecondsF());
750   EXPECT_DOUBLE_EQ(4.0, compositor_timing_.adjusted_iteration_count);
751 
752   timing_.start_delay = -6.0;
753   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
754   EXPECT_DOUBLE_EQ(6.0, compositor_timing_.scaled_time_offset.InSecondsF());
755   EXPECT_DOUBLE_EQ(4.0, compositor_timing_.adjusted_iteration_count);
756 
757   timing_.start_delay = 21.0;
758   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
759 }
760 
TEST_P(AnimationCompositorAnimationsTest,ConvertTimingForCompositorDirection)761 TEST_P(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirection) {
762   timing_.direction = Timing::PlaybackDirection::NORMAL;
763   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
764   EXPECT_EQ(compositor_timing_.direction, Timing::PlaybackDirection::NORMAL);
765 
766   timing_.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
767   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
768   EXPECT_EQ(compositor_timing_.direction,
769             Timing::PlaybackDirection::ALTERNATE_NORMAL);
770 
771   timing_.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
772   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
773   EXPECT_EQ(compositor_timing_.direction,
774             Timing::PlaybackDirection::ALTERNATE_REVERSE);
775 
776   timing_.direction = Timing::PlaybackDirection::REVERSE;
777   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
778   EXPECT_EQ(compositor_timing_.direction, Timing::PlaybackDirection::REVERSE);
779 }
780 
TEST_P(AnimationCompositorAnimationsTest,ConvertTimingForCompositorDirectionIterationsAndStartDelay)781 TEST_P(AnimationCompositorAnimationsTest,
782        ConvertTimingForCompositorDirectionIterationsAndStartDelay) {
783   timing_.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
784   timing_.iteration_count = 4.0;
785   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(5);
786   timing_.start_delay = -6.0;
787   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
788   EXPECT_DOUBLE_EQ(6.0, compositor_timing_.scaled_time_offset.InSecondsF());
789   EXPECT_EQ(4, compositor_timing_.adjusted_iteration_count);
790   EXPECT_EQ(compositor_timing_.direction,
791             Timing::PlaybackDirection::ALTERNATE_NORMAL);
792 
793   timing_.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
794   timing_.iteration_count = 4.0;
795   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(5);
796   timing_.start_delay = -11.0;
797   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
798   EXPECT_DOUBLE_EQ(11.0, compositor_timing_.scaled_time_offset.InSecondsF());
799   EXPECT_EQ(4, compositor_timing_.adjusted_iteration_count);
800   EXPECT_EQ(compositor_timing_.direction,
801             Timing::PlaybackDirection::ALTERNATE_NORMAL);
802 
803   timing_.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
804   timing_.iteration_count = 4.0;
805   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(5);
806   timing_.start_delay = -6.0;
807   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
808   EXPECT_DOUBLE_EQ(6.0, compositor_timing_.scaled_time_offset.InSecondsF());
809   EXPECT_EQ(4, compositor_timing_.adjusted_iteration_count);
810   EXPECT_EQ(compositor_timing_.direction,
811             Timing::PlaybackDirection::ALTERNATE_REVERSE);
812 
813   timing_.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
814   timing_.iteration_count = 4.0;
815   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(5);
816   timing_.start_delay = -11.0;
817   EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
818   EXPECT_DOUBLE_EQ(11.0, compositor_timing_.scaled_time_offset.InSecondsF());
819   EXPECT_EQ(4, compositor_timing_.adjusted_iteration_count);
820   EXPECT_EQ(compositor_timing_.direction,
821             Timing::PlaybackDirection::ALTERNATE_REVERSE);
822 }
823 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorTimingFunctionLinear)824 TEST_P(AnimationCompositorAnimationsTest,
825        CanStartEffectOnCompositorTimingFunctionLinear) {
826   timing_.timing_function = linear_timing_function_;
827   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
828             CompositorAnimations::kNoFailure);
829   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
830             CompositorAnimations::kNoFailure);
831 }
832 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorTimingFunctionCubic)833 TEST_P(AnimationCompositorAnimationsTest,
834        CanStartEffectOnCompositorTimingFunctionCubic) {
835   timing_.timing_function = cubic_ease_timing_function_;
836   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
837             CompositorAnimations::kNoFailure);
838   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
839             CompositorAnimations::kNoFailure);
840 
841   timing_.timing_function = cubic_custom_timing_function_;
842   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
843             CompositorAnimations::kNoFailure);
844   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
845             CompositorAnimations::kNoFailure);
846 }
847 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorTimingFunctionSteps)848 TEST_P(AnimationCompositorAnimationsTest,
849        CanStartEffectOnCompositorTimingFunctionSteps) {
850   timing_.timing_function = step_timing_function_;
851   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
852             CompositorAnimations::kNoFailure);
853   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
854             CompositorAnimations::kNoFailure);
855 }
856 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorTimingFunctionChainedLinear)857 TEST_P(AnimationCompositorAnimationsTest,
858        CanStartEffectOnCompositorTimingFunctionChainedLinear) {
859   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
860             CompositorAnimations::kNoFailure);
861   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
862             CompositorAnimations::kNoFailure);
863 }
864 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorNonLinearTimingFunctionOnFirstOrLastFrame)865 TEST_P(AnimationCompositorAnimationsTest,
866        CanStartEffectOnCompositorNonLinearTimingFunctionOnFirstOrLastFrame) {
867   keyframe_vector2_->at(0)->SetEasing(cubic_ease_timing_function_.get());
868   keyframe_animation_effect2_ =
869       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector2_);
870 
871   keyframe_vector5_->at(3)->SetEasing(cubic_ease_timing_function_.get());
872   keyframe_animation_effect5_ =
873       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector5_);
874 
875   timing_.timing_function = cubic_ease_timing_function_;
876   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
877             CompositorAnimations::kNoFailure);
878   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
879             CompositorAnimations::kNoFailure);
880 
881   timing_.timing_function = cubic_custom_timing_function_;
882   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
883             CompositorAnimations::kNoFailure);
884   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
885             CompositorAnimations::kNoFailure);
886 }
887 
TEST_P(AnimationCompositorAnimationsTest,CanStartElementOnCompositorEffectOpacity)888 TEST_P(AnimationCompositorAnimationsTest,
889        CanStartElementOnCompositorEffectOpacity) {
890   // Check that we got something effectively different.
891   StringKeyframeVector key_frames;
892   key_frames.push_back(CreateDefaultKeyframe(
893       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 0.0));
894   key_frames.push_back(CreateDefaultKeyframe(
895       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 1.0));
896   KeyframeEffectModelBase* animation_effect =
897       MakeGarbageCollected<StringKeyframeEffectModel>(key_frames);
898 
899   Timing timing;
900   timing.iteration_duration = AnimationTimeDelta::FromSecondsD(1);
901 
902   // The first animation for opacity is ok to run on compositor.
903   auto* keyframe_effect1 =
904       MakeGarbageCollected<KeyframeEffect>(element_, animation_effect, timing);
905   Animation* animation = timeline_->Play(keyframe_effect1);
906   auto style = ComputedStyle::Create();
907   animation_effect->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(),
908                                                               *style, nullptr);
909 
910   // Now we can check that we are set up correctly.
911   EXPECT_EQ(CheckCanStartEffectOnCompositor(timing, *element_.Get(), animation,
912                                             *animation_effect),
913             CompositorAnimations::kNoFailure);
914 
915   // Timings have to be convertible for compositor.
916   EXPECT_EQ(CheckCanStartEffectOnCompositor(timing, *element_.Get(), animation,
917                                             *animation_effect),
918             CompositorAnimations::kNoFailure);
919   timing.end_delay = 1.0;
920   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing, *element_.Get(),
921                                               animation, *animation_effect) &
922               CompositorAnimations::kEffectHasUnsupportedTimingParameters);
923   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing, *element_.Get(),
924                                               animation, *animation_effect) &
925               (CompositorAnimations::kTargetHasInvalidCompositingState |
926                CompositorAnimations::kEffectHasUnsupportedTimingParameters));
927 }
928 
TEST_P(AnimationCompositorAnimationsTest,CanStartElementOnCompositorEffectInvalid)929 TEST_P(AnimationCompositorAnimationsTest,
930        CanStartElementOnCompositorEffectInvalid) {
931   auto style = ComputedStyle::Create();
932 
933   // Check that we notice the value is not animatable correctly.
934   const CSSProperty& target_property1(GetCSSPropertyOutlineStyle());
935   PropertyHandle target_property1h(target_property1);
936   StringKeyframeEffectModel* effect1 = CreateKeyframeEffectModel(
937       CreateReplaceOpKeyframe(target_property1.PropertyID(), "dotted", 0),
938       CreateReplaceOpKeyframe(target_property1.PropertyID(), "dashed", 1.0));
939 
940   auto* keyframe_effect1 =
941       MakeGarbageCollected<KeyframeEffect>(element_.Get(), effect1, timing_);
942 
943   Animation* animation1 = timeline_->Play(keyframe_effect1);
944   effect1->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
945                                                      nullptr);
946 
947   const auto& keyframes1 =
948       *effect1->GetPropertySpecificKeyframes(target_property1h);
949   EXPECT_EQ(2u, keyframes1.size());
950   EXPECT_FALSE(keyframes1[0]->GetCompositorKeyframeValue());
951   EXPECT_EQ(1u, effect1->Properties().size());
952   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing_, *element_.Get(),
953                                               animation1, *effect1) &
954               CompositorAnimations::kUnsupportedCSSProperty);
955 
956   // Check that we notice transform is not animatable correctly on an inline.
957   const CSSProperty& target_property2(GetCSSPropertyScale());
958   PropertyHandle target_property2h(target_property2);
959   StringKeyframeEffectModel* effect2 = CreateKeyframeEffectModel(
960       CreateReplaceOpKeyframe(target_property2.PropertyID(), "1", 0),
961       CreateReplaceOpKeyframe(target_property2.PropertyID(), "3", 1.0));
962 
963   auto* keyframe_effect2 =
964       MakeGarbageCollected<KeyframeEffect>(inline_.Get(), effect2, timing_);
965 
966   Animation* animation2 = timeline_->Play(keyframe_effect2);
967   effect2->SnapshotAllCompositorKeyframesIfNecessary(*inline_.Get(), *style,
968                                                      nullptr);
969 
970   const auto& keyframes2 =
971       *effect2->GetPropertySpecificKeyframes(target_property2h);
972   EXPECT_EQ(2u, keyframes2.size());
973   EXPECT_TRUE(keyframes2[0]->GetCompositorKeyframeValue());
974   EXPECT_EQ(1u, effect2->Properties().size());
975   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing_, *inline_.Get(),
976                                               animation2, *effect2) &
977               CompositorAnimations::
978                   kTransformRelatedPropertyCannotBeAcceleratedOnTarget);
979 
980   // Check that we notice the Property is not animatable correctly.
981   // These ones claim to have animatable values, but we can't composite
982   // the property. We also don't know the ID domain.
983   const CSSProperty& target_property3(GetCSSPropertyWidth());
984   PropertyHandle target_property3h(target_property3);
985   StringKeyframeEffectModel* effect3 = CreateKeyframeEffectModel(
986       CreateMockReplaceKeyframe(target_property3.PropertyID(), "10px", 0.0),
987       CreateMockReplaceKeyframe(target_property3.PropertyID(), "20px", 1.0));
988 
989   auto* keyframe_effect3 =
990       MakeGarbageCollected<KeyframeEffect>(element_.Get(), effect3, timing_);
991 
992   Animation* animation3 = timeline_->Play(keyframe_effect3);
993   effect3->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
994                                                      nullptr);
995 
996   const auto& keyframes3 =
997       *effect3->GetPropertySpecificKeyframes(target_property3h);
998   EXPECT_EQ(2u, keyframes3.size());
999   EXPECT_TRUE(keyframes3[0]->GetCompositorKeyframeValue());
1000   EXPECT_EQ(1u, effect3->Properties().size());
1001   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing_, *element_.Get(),
1002                                               animation3, *effect3) &
1003               CompositorAnimations::kUnsupportedCSSProperty);
1004 }
1005 
TEST_P(AnimationCompositorAnimationsTest,CanStartElementOnCompositorEffectFilter)1006 TEST_P(AnimationCompositorAnimationsTest,
1007        CanStartElementOnCompositorEffectFilter) {
1008   // TODO(https://crbug.com/960953): Create a filter effect node when
1009   // will-change: filter is specified so that filter effects can be tested
1010   // without compositing changes.
1011   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
1012     return;
1013 
1014   // Filter Properties use a different ID namespace
1015   StringKeyframeEffectModel* effect1 = CreateKeyframeEffectModel(
1016       CreateReplaceOpKeyframe(CSSPropertyID::kFilter, "none", 0),
1017       CreateReplaceOpKeyframe(CSSPropertyID::kFilter, "sepia(50%)", 1.0));
1018 
1019   auto* keyframe_effect1 =
1020       MakeGarbageCollected<KeyframeEffect>(element_.Get(), effect1, timing_);
1021 
1022   Animation* animation1 = timeline_->Play(keyframe_effect1);
1023   auto style = ComputedStyle::Create();
1024   effect1->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
1025                                                      nullptr);
1026 
1027   // Now we can check that we are set up correctly.
1028   EXPECT_EQ(CheckCanStartEffectOnCompositor(timing_, *element_.Get(),
1029                                             animation1, *effect1),
1030             CompositorAnimations::kNoFailure);
1031 
1032   // Filters that affect neighboring pixels can't be composited.
1033   StringKeyframeEffectModel* effect2 = CreateKeyframeEffectModel(
1034       CreateReplaceOpKeyframe(CSSPropertyID::kFilter, "none", 0),
1035       CreateReplaceOpKeyframe(CSSPropertyID::kFilter, "blur(10px)", 1.0));
1036 
1037   auto* keyframe_effect2 =
1038       MakeGarbageCollected<KeyframeEffect>(element_.Get(), effect2, timing_);
1039 
1040   Animation* animation2 = timeline_->Play(keyframe_effect2);
1041   effect2->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
1042                                                      nullptr);
1043   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing_, *element_.Get(),
1044                                               animation2, *effect2) &
1045               CompositorAnimations::kFilterRelatedPropertyMayMovePixels);
1046 
1047   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing_, *element_.Get(),
1048                                               animation2, *effect2) &
1049               (CompositorAnimations::kFilterRelatedPropertyMayMovePixels |
1050                CompositorAnimations::kTargetHasInvalidCompositingState));
1051 }
1052 
TEST_P(AnimationCompositorAnimationsTest,CanStartElementOnCompositorEffectTransform)1053 TEST_P(AnimationCompositorAnimationsTest,
1054        CanStartElementOnCompositorEffectTransform) {
1055   auto style = ComputedStyle::Create();
1056 
1057   StringKeyframeEffectModel* effect1 = CreateKeyframeEffectModel(
1058       CreateReplaceOpKeyframe(CSSPropertyID::kTransform, "none", 0),
1059       CreateReplaceOpKeyframe(CSSPropertyID::kTransform, "rotate(45deg)", 1.0));
1060 
1061   auto* keyframe_effect1 =
1062       MakeGarbageCollected<KeyframeEffect>(element_.Get(), effect1, timing_);
1063 
1064   Animation* animation1 = timeline_->Play(keyframe_effect1);
1065   effect1->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
1066                                                      nullptr);
1067 
1068   // Check if our layout object is not TransformApplicable
1069   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing_, *inline_.Get(),
1070                                               animation1, *effect1) &
1071               CompositorAnimations::
1072                   kTransformRelatedPropertyCannotBeAcceleratedOnTarget);
1073 
1074   StringKeyframeEffectModel* effect2 = CreateKeyframeEffectModel(
1075       CreateReplaceOpKeyframe(CSSPropertyID::kTransform, "translateX(-45px)",
1076                               0),
1077       CreateReplaceOpKeyframe(CSSPropertyID::kRotate, "none", 0),
1078       CreateReplaceOpKeyframe(CSSPropertyID::kTransform, "translateX(45px)",
1079                               1.0),
1080       CreateReplaceOpKeyframe(CSSPropertyID::kRotate, "45deg", 1.0));
1081 
1082   auto* keyframe_effect2 =
1083       MakeGarbageCollected<KeyframeEffect>(element_.Get(), effect2, timing_);
1084 
1085   Animation* animation2 = timeline_->Play(keyframe_effect2);
1086   effect2->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
1087                                                      nullptr);
1088 
1089   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing_, *element_.Get(),
1090                                               animation2, *effect2) &
1091               CompositorAnimations::kMultipleTransformAnimationsOnSameTarget);
1092 }
1093 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorTimingFunctionChainedCubicMatchingOffsets)1094 TEST_P(AnimationCompositorAnimationsTest,
1095        CanStartEffectOnCompositorTimingFunctionChainedCubicMatchingOffsets) {
1096   keyframe_vector2_->at(0)->SetEasing(cubic_ease_timing_function_.get());
1097   keyframe_animation_effect2_ =
1098       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector2_);
1099   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
1100             CompositorAnimations::kNoFailure);
1101 
1102   keyframe_vector2_->at(0)->SetEasing(cubic_custom_timing_function_.get());
1103   keyframe_animation_effect2_ =
1104       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector2_);
1105   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
1106             CompositorAnimations::kNoFailure);
1107 
1108   keyframe_vector5_->at(0)->SetEasing(cubic_ease_timing_function_.get());
1109   keyframe_vector5_->at(1)->SetEasing(cubic_custom_timing_function_.get());
1110   keyframe_vector5_->at(2)->SetEasing(cubic_custom_timing_function_.get());
1111   keyframe_vector5_->at(3)->SetEasing(cubic_custom_timing_function_.get());
1112   keyframe_animation_effect5_ =
1113       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector5_);
1114   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
1115             CompositorAnimations::kNoFailure);
1116 }
1117 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorTimingFunctionMixedGood)1118 TEST_P(AnimationCompositorAnimationsTest,
1119        CanStartEffectOnCompositorTimingFunctionMixedGood) {
1120   keyframe_vector5_->at(0)->SetEasing(linear_timing_function_.get());
1121   keyframe_vector5_->at(1)->SetEasing(cubic_ease_timing_function_.get());
1122   keyframe_vector5_->at(2)->SetEasing(cubic_ease_timing_function_.get());
1123   keyframe_vector5_->at(3)->SetEasing(linear_timing_function_.get());
1124   keyframe_animation_effect5_ =
1125       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector5_);
1126   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
1127             CompositorAnimations::kNoFailure);
1128 }
1129 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorTimingFunctionWithStepOrFrameOkay)1130 TEST_P(AnimationCompositorAnimationsTest,
1131        CanStartEffectOnCompositorTimingFunctionWithStepOrFrameOkay) {
1132   keyframe_vector2_->at(0)->SetEasing(step_timing_function_.get());
1133   keyframe_animation_effect2_ =
1134       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector2_);
1135   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_),
1136             CompositorAnimations::kNoFailure);
1137 
1138   keyframe_vector5_->at(0)->SetEasing(step_timing_function_.get());
1139   keyframe_vector5_->at(1)->SetEasing(linear_timing_function_.get());
1140   keyframe_vector5_->at(2)->SetEasing(cubic_ease_timing_function_.get());
1141   keyframe_animation_effect5_ =
1142       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector5_);
1143   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
1144             CompositorAnimations::kNoFailure);
1145 
1146   keyframe_vector5_->at(1)->SetEasing(step_timing_function_.get());
1147   keyframe_vector5_->at(2)->SetEasing(cubic_ease_timing_function_.get());
1148   keyframe_vector5_->at(3)->SetEasing(linear_timing_function_.get());
1149   keyframe_animation_effect5_ =
1150       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector5_);
1151   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
1152             CompositorAnimations::kNoFailure);
1153 
1154   keyframe_vector5_->at(0)->SetEasing(linear_timing_function_.get());
1155   keyframe_vector5_->at(2)->SetEasing(cubic_ease_timing_function_.get());
1156   keyframe_vector5_->at(3)->SetEasing(step_timing_function_.get());
1157   keyframe_animation_effect5_ =
1158       MakeGarbageCollected<StringKeyframeEffectModel>(*keyframe_vector5_);
1159   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_),
1160             CompositorAnimations::kNoFailure);
1161 }
1162 
TEST_P(AnimationCompositorAnimationsTest,CanStartEffectOnCompositorBasic)1163 TEST_P(AnimationCompositorAnimationsTest, CanStartEffectOnCompositorBasic) {
1164   StringKeyframeVector basic_frames_vector;
1165   basic_frames_vector.push_back(CreateDefaultKeyframe(
1166       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 0.0));
1167   basic_frames_vector.push_back(CreateDefaultKeyframe(
1168       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 1.0));
1169 
1170   StringKeyframeVector non_basic_frames_vector;
1171   non_basic_frames_vector.push_back(CreateDefaultKeyframe(
1172       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 0.0));
1173   non_basic_frames_vector.push_back(CreateDefaultKeyframe(
1174       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 0.5));
1175   non_basic_frames_vector.push_back(CreateDefaultKeyframe(
1176       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 1.0));
1177 
1178   basic_frames_vector[0]->SetEasing(linear_timing_function_.get());
1179   auto* basic_frames =
1180       MakeGarbageCollected<StringKeyframeEffectModel>(basic_frames_vector);
1181   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *basic_frames),
1182             CompositorAnimations::kNoFailure);
1183 
1184   basic_frames_vector[0]->SetEasing(CubicBezierTimingFunction::Preset(
1185       CubicBezierTimingFunction::EaseType::EASE_IN));
1186   basic_frames =
1187       MakeGarbageCollected<StringKeyframeEffectModel>(basic_frames_vector);
1188   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *basic_frames),
1189             CompositorAnimations::kNoFailure);
1190 
1191   non_basic_frames_vector[0]->SetEasing(linear_timing_function_.get());
1192   non_basic_frames_vector[1]->SetEasing(CubicBezierTimingFunction::Preset(
1193       CubicBezierTimingFunction::EaseType::EASE_IN));
1194   auto* non_basic_frames =
1195       MakeGarbageCollected<StringKeyframeEffectModel>(non_basic_frames_vector);
1196   EXPECT_EQ(CanStartEffectOnCompositor(timing_, *non_basic_frames),
1197             CompositorAnimations::kNoFailure);
1198 
1199   StringKeyframeVector non_allowed_frames_vector;
1200   non_allowed_frames_vector.push_back(CreateDefaultKeyframe(
1201       CSSPropertyID::kOpacity, EffectModel::kCompositeAdd, 0.1));
1202   non_allowed_frames_vector.push_back(CreateDefaultKeyframe(
1203       CSSPropertyID::kOpacity, EffectModel::kCompositeAdd, 0.25));
1204   auto* non_allowed_frames = MakeGarbageCollected<StringKeyframeEffectModel>(
1205       non_allowed_frames_vector);
1206   EXPECT_TRUE(CanStartEffectOnCompositor(timing_, *non_allowed_frames) &
1207               CompositorAnimations::kEffectHasNonReplaceCompositeMode);
1208 
1209   // Set SVGAttribute keeps a pointer to this thing for the lifespan of
1210   // the Keyframe.  This is ugly but sufficient to work around it.
1211   QualifiedName fake_name("prefix", "local", "uri");
1212 
1213   StringKeyframeVector non_css_frames_vector;
1214   non_css_frames_vector.push_back(CreateSVGKeyframe(fake_name, "cargo", 0.0));
1215   non_css_frames_vector.push_back(CreateSVGKeyframe(fake_name, "cargo", 1.0));
1216   auto* non_css_frames =
1217       MakeGarbageCollected<StringKeyframeEffectModel>(non_css_frames_vector);
1218   EXPECT_TRUE(CanStartEffectOnCompositor(timing_, *non_css_frames) &
1219               CompositorAnimations::kAnimationAffectsNonCSSProperties);
1220   // NB: Important that non_css_frames_vector goes away and cleans up
1221   // before fake_name.
1222 }
1223 
1224 // -----------------------------------------------------------------------
1225 // -----------------------------------------------------------------------
1226 
TEST_P(AnimationCompositorAnimationsTest,CreateSimpleOpacityAnimation)1227 TEST_P(AnimationCompositorAnimationsTest, CreateSimpleOpacityAnimation) {
1228   // KeyframeEffect to convert
1229   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1230       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0),
1231       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1232 
1233   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1234       ConvertToCompositorAnimation(*effect);
1235   EXPECT_EQ(compositor_target_property::OPACITY,
1236             keyframe_model->TargetProperty());
1237   EXPECT_EQ(1.0, keyframe_model->Iterations());
1238   EXPECT_EQ(0, keyframe_model->TimeOffset());
1239   EXPECT_EQ(CompositorKeyframeModel::Direction::NORMAL,
1240             keyframe_model->GetDirection());
1241   EXPECT_EQ(1.0, keyframe_model->PlaybackRate());
1242 
1243   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1244       keyframe_model->FloatCurveForTesting();
1245 
1246   CompositorFloatAnimationCurve::Keyframes keyframes =
1247       keyframed_float_curve->KeyframesForTesting();
1248   ASSERT_EQ(2UL, keyframes.size());
1249 
1250   EXPECT_EQ(0, keyframes[0]->Time());
1251   EXPECT_EQ(0.2f, keyframes[0]->Value());
1252   EXPECT_EQ(TimingFunction::Type::LINEAR,
1253             keyframes[0]->GetTimingFunctionForTesting()->GetType());
1254 
1255   EXPECT_EQ(1.0, keyframes[1]->Time());
1256   EXPECT_EQ(0.5f, keyframes[1]->Value());
1257   EXPECT_EQ(TimingFunction::Type::LINEAR,
1258             keyframes[1]->GetTimingFunctionForTesting()->GetType());
1259 }
1260 
TEST_P(AnimationCompositorAnimationsTest,CreateSimpleOpacityAnimationDuration)1261 TEST_P(AnimationCompositorAnimationsTest,
1262        CreateSimpleOpacityAnimationDuration) {
1263   // KeyframeEffect to convert
1264   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1265       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0),
1266       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1267 
1268   const AnimationTimeDelta kDuration = AnimationTimeDelta::FromSecondsD(10);
1269   timing_.iteration_duration = kDuration;
1270 
1271   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1272       ConvertToCompositorAnimation(*effect);
1273   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1274       keyframe_model->FloatCurveForTesting();
1275 
1276   CompositorFloatAnimationCurve::Keyframes keyframes =
1277       keyframed_float_curve->KeyframesForTesting();
1278   ASSERT_EQ(2UL, keyframes.size());
1279 
1280   EXPECT_EQ(kDuration, keyframes[1]->Time() * kDuration);
1281 }
1282 
TEST_P(AnimationCompositorAnimationsTest,CreateMultipleKeyframeOpacityAnimationLinear)1283 TEST_P(AnimationCompositorAnimationsTest,
1284        CreateMultipleKeyframeOpacityAnimationLinear) {
1285   // KeyframeEffect to convert
1286   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1287       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0),
1288       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.0", 0.25),
1289       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.25", 0.5),
1290       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1291 
1292   timing_.iteration_count = 5;
1293   timing_.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
1294 
1295   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1296       ConvertToCompositorAnimation(*effect, 2.0);
1297   EXPECT_EQ(compositor_target_property::OPACITY,
1298             keyframe_model->TargetProperty());
1299   EXPECT_EQ(5.0, keyframe_model->Iterations());
1300   EXPECT_EQ(0, keyframe_model->TimeOffset());
1301   EXPECT_EQ(CompositorKeyframeModel::Direction::ALTERNATE_NORMAL,
1302             keyframe_model->GetDirection());
1303   EXPECT_EQ(2.0, keyframe_model->PlaybackRate());
1304 
1305   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1306       keyframe_model->FloatCurveForTesting();
1307 
1308   CompositorFloatAnimationCurve::Keyframes keyframes =
1309       keyframed_float_curve->KeyframesForTesting();
1310   ASSERT_EQ(4UL, keyframes.size());
1311 
1312   EXPECT_EQ(0, keyframes[0]->Time());
1313   EXPECT_EQ(0.2f, keyframes[0]->Value());
1314   EXPECT_EQ(TimingFunction::Type::LINEAR,
1315             keyframes[0]->GetTimingFunctionForTesting()->GetType());
1316 
1317   EXPECT_EQ(0.25, keyframes[1]->Time());
1318   EXPECT_EQ(0, keyframes[1]->Value());
1319   EXPECT_EQ(TimingFunction::Type::LINEAR,
1320             keyframes[1]->GetTimingFunctionForTesting()->GetType());
1321 
1322   EXPECT_EQ(0.5, keyframes[2]->Time());
1323   EXPECT_EQ(0.25f, keyframes[2]->Value());
1324   EXPECT_EQ(TimingFunction::Type::LINEAR,
1325             keyframes[2]->GetTimingFunctionForTesting()->GetType());
1326 
1327   EXPECT_EQ(1.0, keyframes[3]->Time());
1328   EXPECT_EQ(0.5f, keyframes[3]->Value());
1329   EXPECT_EQ(TimingFunction::Type::LINEAR,
1330             keyframes[3]->GetTimingFunctionForTesting()->GetType());
1331 }
1332 
TEST_P(AnimationCompositorAnimationsTest,CreateSimpleOpacityAnimationStartDelay)1333 TEST_P(AnimationCompositorAnimationsTest,
1334        CreateSimpleOpacityAnimationStartDelay) {
1335   // KeyframeEffect to convert
1336   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1337       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0),
1338       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1339 
1340   const double kStartDelay = 3.25;
1341 
1342   timing_.iteration_count = 5.0;
1343   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(1.75);
1344   timing_.start_delay = kStartDelay;
1345 
1346   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1347       ConvertToCompositorAnimation(*effect);
1348 
1349   EXPECT_EQ(compositor_target_property::OPACITY,
1350             keyframe_model->TargetProperty());
1351   EXPECT_EQ(5.0, keyframe_model->Iterations());
1352   EXPECT_EQ(-kStartDelay, keyframe_model->TimeOffset());
1353 
1354   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1355       keyframe_model->FloatCurveForTesting();
1356 
1357   CompositorFloatAnimationCurve::Keyframes keyframes =
1358       keyframed_float_curve->KeyframesForTesting();
1359   ASSERT_EQ(2UL, keyframes.size());
1360 
1361   EXPECT_EQ(1.75,
1362             keyframes[1]->Time() * timing_.iteration_duration->InSecondsF());
1363   EXPECT_EQ(0.5f, keyframes[1]->Value());
1364 }
1365 
TEST_P(AnimationCompositorAnimationsTest,CreateMultipleKeyframeOpacityAnimationChained)1366 TEST_P(AnimationCompositorAnimationsTest,
1367        CreateMultipleKeyframeOpacityAnimationChained) {
1368   // KeyframeEffect to convert
1369   StringKeyframeVector frames;
1370   frames.push_back(CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0));
1371   frames.push_back(
1372       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.0", 0.25));
1373   frames.push_back(
1374       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.35", 0.5));
1375   frames.push_back(
1376       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1377   frames[0]->SetEasing(cubic_ease_timing_function_.get());
1378   frames[1]->SetEasing(linear_timing_function_.get());
1379   frames[2]->SetEasing(cubic_custom_timing_function_.get());
1380   auto* effect = MakeGarbageCollected<StringKeyframeEffectModel>(frames);
1381 
1382   timing_.timing_function = linear_timing_function_.get();
1383   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(2);
1384   timing_.iteration_count = 10;
1385   timing_.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
1386 
1387   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1388       ConvertToCompositorAnimation(*effect);
1389   EXPECT_EQ(compositor_target_property::OPACITY,
1390             keyframe_model->TargetProperty());
1391   EXPECT_EQ(10.0, keyframe_model->Iterations());
1392   EXPECT_EQ(0, keyframe_model->TimeOffset());
1393   EXPECT_EQ(CompositorKeyframeModel::Direction::ALTERNATE_NORMAL,
1394             keyframe_model->GetDirection());
1395   EXPECT_EQ(1.0, keyframe_model->PlaybackRate());
1396 
1397   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1398       keyframe_model->FloatCurveForTesting();
1399 
1400   CompositorFloatAnimationCurve::Keyframes keyframes =
1401       keyframed_float_curve->KeyframesForTesting();
1402   ASSERT_EQ(4UL, keyframes.size());
1403 
1404   EXPECT_EQ(0, keyframes[0]->Time() * timing_.iteration_duration->InSecondsF());
1405   EXPECT_EQ(0.2f, keyframes[0]->Value());
1406   ExpectKeyframeTimingFunctionCubic(*keyframes[0],
1407                                     CubicBezierTimingFunction::EaseType::EASE);
1408 
1409   EXPECT_EQ(0.5,
1410             keyframes[1]->Time() * timing_.iteration_duration->InSecondsF());
1411   EXPECT_EQ(0, keyframes[1]->Value());
1412   EXPECT_EQ(TimingFunction::Type::LINEAR,
1413             keyframes[1]->GetTimingFunctionForTesting()->GetType());
1414 
1415   EXPECT_EQ(1.0,
1416             keyframes[2]->Time() * timing_.iteration_duration->InSecondsF());
1417   EXPECT_EQ(0.35f, keyframes[2]->Value());
1418   ExpectKeyframeTimingFunctionCubic(
1419       *keyframes[2], CubicBezierTimingFunction::EaseType::CUSTOM);
1420 
1421   EXPECT_EQ(2.0,
1422             keyframes[3]->Time() * timing_.iteration_duration->InSecondsF());
1423   EXPECT_EQ(0.5f, keyframes[3]->Value());
1424   EXPECT_EQ(TimingFunction::Type::LINEAR,
1425             keyframes[3]->GetTimingFunctionForTesting()->GetType());
1426 }
1427 
TEST_P(AnimationCompositorAnimationsTest,CreateReversedOpacityAnimation)1428 TEST_P(AnimationCompositorAnimationsTest, CreateReversedOpacityAnimation) {
1429   scoped_refptr<TimingFunction> cubic_easy_flip_timing_function =
1430       CubicBezierTimingFunction::Create(0.0, 0.0, 0.0, 1.0);
1431 
1432   // KeyframeEffect to convert
1433   StringKeyframeVector frames;
1434   frames.push_back(CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0));
1435   frames.push_back(
1436       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.0", 0.25));
1437   frames.push_back(
1438       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.25", 0.5));
1439   frames.push_back(
1440       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1441   frames[0]->SetEasing(CubicBezierTimingFunction::Preset(
1442       CubicBezierTimingFunction::EaseType::EASE_IN));
1443   frames[1]->SetEasing(linear_timing_function_.get());
1444   frames[2]->SetEasing(cubic_easy_flip_timing_function.get());
1445   auto* effect = MakeGarbageCollected<StringKeyframeEffectModel>(frames);
1446 
1447   timing_.timing_function = linear_timing_function_.get();
1448   timing_.iteration_count = 10;
1449   timing_.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
1450 
1451   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1452       ConvertToCompositorAnimation(*effect);
1453   EXPECT_EQ(compositor_target_property::OPACITY,
1454             keyframe_model->TargetProperty());
1455   EXPECT_EQ(10.0, keyframe_model->Iterations());
1456   EXPECT_EQ(0, keyframe_model->TimeOffset());
1457   EXPECT_EQ(CompositorKeyframeModel::Direction::ALTERNATE_REVERSE,
1458             keyframe_model->GetDirection());
1459   EXPECT_EQ(1.0, keyframe_model->PlaybackRate());
1460 
1461   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1462       keyframe_model->FloatCurveForTesting();
1463 
1464   CompositorFloatAnimationCurve::Keyframes keyframes =
1465       keyframed_float_curve->KeyframesForTesting();
1466   ASSERT_EQ(4UL, keyframes.size());
1467 
1468   EXPECT_EQ(keyframed_float_curve->GetTimingFunctionForTesting()->GetType(),
1469             TimingFunction::Type::LINEAR);
1470 
1471   EXPECT_EQ(0, keyframes[0]->Time());
1472   EXPECT_EQ(0.2f, keyframes[0]->Value());
1473   ExpectKeyframeTimingFunctionCubic(
1474       *keyframes[0], CubicBezierTimingFunction::EaseType::EASE_IN);
1475 
1476   EXPECT_EQ(0.25, keyframes[1]->Time());
1477   EXPECT_EQ(0, keyframes[1]->Value());
1478   EXPECT_EQ(TimingFunction::Type::LINEAR,
1479             keyframes[1]->GetTimingFunctionForTesting()->GetType());
1480 
1481   EXPECT_EQ(0.5, keyframes[2]->Time());
1482   EXPECT_EQ(0.25f, keyframes[2]->Value());
1483   ExpectKeyframeTimingFunctionCubic(
1484       *keyframes[2], CubicBezierTimingFunction::EaseType::CUSTOM);
1485 
1486   EXPECT_EQ(1.0, keyframes[3]->Time());
1487   EXPECT_EQ(0.5f, keyframes[3]->Value());
1488   EXPECT_EQ(TimingFunction::Type::LINEAR,
1489             keyframes[3]->GetTimingFunctionForTesting()->GetType());
1490 }
1491 
TEST_P(AnimationCompositorAnimationsTest,CreateReversedOpacityAnimationNegativeStartDelay)1492 TEST_P(AnimationCompositorAnimationsTest,
1493        CreateReversedOpacityAnimationNegativeStartDelay) {
1494   // KeyframeEffect to convert
1495   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1496       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0),
1497       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1498 
1499   const double kNegativeStartDelay = -3;
1500 
1501   timing_.iteration_count = 5.0;
1502   timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(1.5);
1503   timing_.start_delay = kNegativeStartDelay;
1504   timing_.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
1505 
1506   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1507       ConvertToCompositorAnimation(*effect);
1508   EXPECT_EQ(compositor_target_property::OPACITY,
1509             keyframe_model->TargetProperty());
1510   EXPECT_EQ(5.0, keyframe_model->Iterations());
1511   EXPECT_EQ(-kNegativeStartDelay, keyframe_model->TimeOffset());
1512   EXPECT_EQ(CompositorKeyframeModel::Direction::ALTERNATE_REVERSE,
1513             keyframe_model->GetDirection());
1514   EXPECT_EQ(1.0, keyframe_model->PlaybackRate());
1515 
1516   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1517       keyframe_model->FloatCurveForTesting();
1518 
1519   CompositorFloatAnimationCurve::Keyframes keyframes =
1520       keyframed_float_curve->KeyframesForTesting();
1521   ASSERT_EQ(2UL, keyframes.size());
1522 }
1523 
TEST_P(AnimationCompositorAnimationsTest,CreateSimpleOpacityAnimationFillModeNone)1524 TEST_P(AnimationCompositorAnimationsTest,
1525        CreateSimpleOpacityAnimationFillModeNone) {
1526   // KeyframeEffect to convert
1527   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1528       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0),
1529       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1530 
1531   timing_.fill_mode = Timing::FillMode::NONE;
1532 
1533   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1534       ConvertToCompositorAnimation(*effect);
1535   EXPECT_EQ(CompositorKeyframeModel::FillMode::NONE,
1536             keyframe_model->GetFillMode());
1537 }
1538 
TEST_P(AnimationCompositorAnimationsTest,CreateSimpleOpacityAnimationFillModeAuto)1539 TEST_P(AnimationCompositorAnimationsTest,
1540        CreateSimpleOpacityAnimationFillModeAuto) {
1541   // KeyframeEffect to convert
1542   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1543       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0),
1544       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1545 
1546   timing_.fill_mode = Timing::FillMode::AUTO;
1547 
1548   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1549       ConvertToCompositorAnimation(*effect);
1550   EXPECT_EQ(compositor_target_property::OPACITY,
1551             keyframe_model->TargetProperty());
1552   EXPECT_EQ(1.0, keyframe_model->Iterations());
1553   EXPECT_EQ(0, keyframe_model->TimeOffset());
1554   EXPECT_EQ(CompositorKeyframeModel::Direction::NORMAL,
1555             keyframe_model->GetDirection());
1556   EXPECT_EQ(1.0, keyframe_model->PlaybackRate());
1557   EXPECT_EQ(CompositorKeyframeModel::FillMode::NONE,
1558             keyframe_model->GetFillMode());
1559 }
1560 
TEST_P(AnimationCompositorAnimationsTest,CreateSimpleOpacityAnimationWithTimingFunction)1561 TEST_P(AnimationCompositorAnimationsTest,
1562        CreateSimpleOpacityAnimationWithTimingFunction) {
1563   // KeyframeEffect to convert
1564   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1565       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.2", 0),
1566       CreateReplaceOpKeyframe(CSSPropertyID::kOpacity, "0.5", 1.0));
1567 
1568   timing_.timing_function = cubic_custom_timing_function_;
1569 
1570   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1571       ConvertToCompositorAnimation(*effect);
1572 
1573   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1574       keyframe_model->FloatCurveForTesting();
1575 
1576   auto curve_timing_function =
1577       keyframed_float_curve->GetTimingFunctionForTesting();
1578   EXPECT_EQ(curve_timing_function->GetType(),
1579             TimingFunction::Type::CUBIC_BEZIER);
1580   const auto& cubic_timing_function =
1581       To<CubicBezierTimingFunction>(*curve_timing_function);
1582   EXPECT_EQ(cubic_timing_function.GetEaseType(),
1583             CubicBezierTimingFunction::EaseType::CUSTOM);
1584   EXPECT_EQ(cubic_timing_function.X1(), 1.0);
1585   EXPECT_EQ(cubic_timing_function.Y1(), 2.0);
1586   EXPECT_EQ(cubic_timing_function.X2(), 3.0);
1587   EXPECT_EQ(cubic_timing_function.Y2(), 4.0);
1588 
1589   CompositorFloatAnimationCurve::Keyframes keyframes =
1590       keyframed_float_curve->KeyframesForTesting();
1591   ASSERT_EQ(2UL, keyframes.size());
1592 
1593   EXPECT_EQ(0, keyframes[0]->Time());
1594   EXPECT_EQ(0.2f, keyframes[0]->Value());
1595   EXPECT_EQ(TimingFunction::Type::LINEAR,
1596             keyframes[0]->GetTimingFunctionForTesting()->GetType());
1597 
1598   EXPECT_EQ(1.0, keyframes[1]->Time());
1599   EXPECT_EQ(0.5f, keyframes[1]->Value());
1600   EXPECT_EQ(TimingFunction::Type::LINEAR,
1601             keyframes[1]->GetTimingFunctionForTesting()->GetType());
1602 }
1603 
TEST_P(AnimationCompositorAnimationsTest,CreateCustomFloatPropertyAnimationWithNonAsciiName)1604 TEST_P(AnimationCompositorAnimationsTest,
1605        CreateCustomFloatPropertyAnimationWithNonAsciiName) {
1606   ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true);
1607 
1608   String property_name = "--東京都";
1609   RegisterProperty(GetDocument(), property_name, "<number>", "0", false);
1610   SetCustomProperty(property_name, "10");
1611 
1612   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1613       CreateReplaceOpKeyframe(property_name, "10", 0),
1614       CreateReplaceOpKeyframe(property_name, "20", 1.0));
1615 
1616   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1617       ConvertToCompositorAnimation(*effect);
1618   EXPECT_EQ(compositor_target_property::CSS_CUSTOM_PROPERTY,
1619             keyframe_model->TargetProperty());
1620   EXPECT_EQ(keyframe_model->GetCustomPropertyNameForTesting(),
1621             property_name.Utf8().data());
1622 }
1623 
TEST_P(AnimationCompositorAnimationsTest,CreateSimpleCustomFloatPropertyAnimation)1624 TEST_P(AnimationCompositorAnimationsTest,
1625        CreateSimpleCustomFloatPropertyAnimation) {
1626   ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true);
1627 
1628   RegisterProperty(GetDocument(), "--foo", "<number>", "0", false);
1629   SetCustomProperty("--foo", "10");
1630 
1631   StringKeyframeEffectModel* effect =
1632       CreateKeyframeEffectModel(CreateReplaceOpKeyframe("--foo", "10", 0),
1633                                 CreateReplaceOpKeyframe("--foo", "20", 1.0));
1634 
1635   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1636       ConvertToCompositorAnimation(*effect);
1637   EXPECT_EQ(compositor_target_property::CSS_CUSTOM_PROPERTY,
1638             keyframe_model->TargetProperty());
1639 
1640   std::unique_ptr<CompositorFloatAnimationCurve> keyframed_float_curve =
1641       keyframe_model->FloatCurveForTesting();
1642 
1643   CompositorFloatAnimationCurve::Keyframes keyframes =
1644       keyframed_float_curve->KeyframesForTesting();
1645   ASSERT_EQ(2UL, keyframes.size());
1646 
1647   EXPECT_EQ(0, keyframes[0]->Time());
1648   EXPECT_EQ(10, keyframes[0]->Value());
1649   EXPECT_EQ(TimingFunction::Type::LINEAR,
1650             keyframes[0]->GetTimingFunctionForTesting()->GetType());
1651 
1652   EXPECT_EQ(1.0, keyframes[1]->Time());
1653   EXPECT_EQ(20, keyframes[1]->Value());
1654   EXPECT_EQ(TimingFunction::Type::LINEAR,
1655             keyframes[1]->GetTimingFunctionForTesting()->GetType());
1656 }
1657 
TEST_P(AnimationCompositorAnimationsTest,CreateSimpleCustomColorPropertyAnimation)1658 TEST_P(AnimationCompositorAnimationsTest,
1659        CreateSimpleCustomColorPropertyAnimation) {
1660   ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true);
1661 
1662   RegisterProperty(GetDocument(), "--foo", "<color>", "rgb(0, 0, 0)", false);
1663   SetCustomProperty("--foo", "rgb(0, 0, 0)");
1664 
1665   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1666       CreateReplaceOpKeyframe("--foo", "rgb(0, 0, 0)", 0),
1667       CreateReplaceOpKeyframe("--foo", "rgb(0, 255, 0)", 1.0));
1668 
1669   std::unique_ptr<CompositorKeyframeModel> keyframe_model =
1670       ConvertToCompositorAnimation(*effect);
1671   EXPECT_EQ(compositor_target_property::CSS_CUSTOM_PROPERTY,
1672             keyframe_model->TargetProperty());
1673 
1674   std::unique_ptr<CompositorColorAnimationCurve> keyframed_color_curve =
1675       keyframe_model->ColorCurveForTesting();
1676 
1677   CompositorColorAnimationCurve::Keyframes keyframes =
1678       keyframed_color_curve->KeyframesForTesting();
1679   ASSERT_EQ(2UL, keyframes.size());
1680 
1681   EXPECT_EQ(0, keyframes[0]->Time());
1682   EXPECT_EQ(SkColorSetRGB(0, 0, 0), keyframes[0]->Value());
1683   EXPECT_EQ(TimingFunction::Type::LINEAR,
1684             keyframes[0]->GetTimingFunctionForTesting()->GetType());
1685 
1686   EXPECT_EQ(1.0, keyframes[1]->Time());
1687   EXPECT_EQ(SkColorSetRGB(0, 0xFF, 0), keyframes[1]->Value());
1688   EXPECT_EQ(TimingFunction::Type::LINEAR,
1689             keyframes[1]->GetTimingFunctionForTesting()->GetType());
1690 }
1691 
TEST_P(AnimationCompositorAnimationsTest,MixedCustomPropertyAnimation)1692 TEST_P(AnimationCompositorAnimationsTest, MixedCustomPropertyAnimation) {
1693   ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true);
1694 
1695   RegisterProperty(GetDocument(), "--foo", "<number> | <color>", "0", false);
1696   SetCustomProperty("--foo", "0");
1697 
1698   StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
1699       CreateReplaceOpKeyframe("--foo", "20", 0),
1700       CreateReplaceOpKeyframe("--foo", "rgb(0, 255, 0)", 1.0));
1701 
1702   EXPECT_TRUE(CanStartEffectOnCompositor(timing_, *effect) &
1703               CompositorAnimations::kMixedKeyframeValueTypes);
1704 }
1705 
TEST_P(AnimationCompositorAnimationsTest,CancelIncompatibleCompositorAnimations)1706 TEST_P(AnimationCompositorAnimationsTest,
1707        CancelIncompatibleCompositorAnimations) {
1708   Persistent<HeapVector<Member<StringKeyframe>>> key_frames =
1709       MakeGarbageCollected<HeapVector<Member<StringKeyframe>>>();
1710   key_frames->push_back(CreateDefaultKeyframe(
1711       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 0.0));
1712   key_frames->push_back(CreateDefaultKeyframe(
1713       CSSPropertyID::kOpacity, EffectModel::kCompositeReplace, 1.0));
1714   KeyframeEffectModelBase* animation_effect1 =
1715       MakeGarbageCollected<StringKeyframeEffectModel>(*key_frames);
1716   KeyframeEffectModelBase* animation_effect2 =
1717       MakeGarbageCollected<StringKeyframeEffectModel>(*key_frames);
1718 
1719   Timing timing;
1720   timing.iteration_duration = AnimationTimeDelta::FromSecondsD(1);
1721 
1722   // The first animation for opacity is ok to run on compositor.
1723   auto* keyframe_effect1 = MakeGarbageCollected<KeyframeEffect>(
1724       element_.Get(), animation_effect1, timing);
1725   Animation* animation1 = timeline_->Play(keyframe_effect1);
1726   auto style = ComputedStyle::Create();
1727   animation_effect1->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(),
1728                                                                *style, nullptr);
1729   EXPECT_EQ(CheckCanStartEffectOnCompositor(timing, *element_.Get(), animation1,
1730                                             *animation_effect1),
1731             CompositorAnimations::kNoFailure);
1732 
1733   // The second animation for opacity is not ok to run on compositor.
1734   auto* keyframe_effect2 = MakeGarbageCollected<KeyframeEffect>(
1735       element_.Get(), animation_effect2, timing);
1736   Animation* animation2 = timeline_->Play(keyframe_effect2);
1737   animation_effect2->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(),
1738                                                                *style, nullptr);
1739   EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing, *element_.Get(),
1740                                               animation2, *animation_effect2) &
1741               CompositorAnimations::kTargetHasIncompatibleAnimations);
1742   EXPECT_FALSE(animation2->HasActiveAnimationsOnCompositor());
1743 
1744   // A fallback to blink implementation needed, so cancel all compositor-side
1745   // opacity animations for this element.
1746   animation2->CancelIncompatibleAnimationsOnCompositor();
1747 
1748   EXPECT_FALSE(animation1->HasActiveAnimationsOnCompositor());
1749   EXPECT_FALSE(animation2->HasActiveAnimationsOnCompositor());
1750 
1751   SimulateFrame(0);
1752   EXPECT_EQ(2U, element_->GetElementAnimations()->Animations().size());
1753 
1754   // After finishing and collecting garbage there should be no
1755   // ElementAnimations on the element.
1756   SimulateFrame(1.);
1757   ThreadState::Current()->CollectAllGarbageForTesting();
1758   EXPECT_TRUE(element_->GetElementAnimations()->Animations().IsEmpty());
1759 }
1760 
1761 namespace {
1762 
UpdateDummyTransformNode(ObjectPaintProperties & properties,CompositingReasons reasons)1763 void UpdateDummyTransformNode(ObjectPaintProperties& properties,
1764                               CompositingReasons reasons) {
1765   // Initialize with TransformationMatrix() to avoid 2d translation optimization
1766   // in case of transform animation.
1767   TransformPaintPropertyNode::State state{TransformationMatrix()};
1768   state.direct_compositing_reasons = reasons;
1769   properties.UpdateTransform(TransformPaintPropertyNode::Root(),
1770                              std::move(state));
1771 }
1772 
UpdateDummyEffectNode(ObjectPaintProperties & properties,CompositingReasons reasons)1773 void UpdateDummyEffectNode(ObjectPaintProperties& properties,
1774                            CompositingReasons reasons) {
1775   EffectPaintPropertyNode::State state;
1776   state.direct_compositing_reasons = reasons;
1777   properties.UpdateEffect(EffectPaintPropertyNode::Root(), std::move(state));
1778 }
1779 
1780 }  // namespace
1781 
TEST_P(AnimationCompositorAnimationsTest,CanStartElementOnCompositorTransformBasedOnPaintProperties)1782 TEST_P(AnimationCompositorAnimationsTest,
1783        CanStartElementOnCompositorTransformBasedOnPaintProperties) {
1784   Persistent<Element> element = GetDocument().CreateElementForBinding("shared");
1785   LayoutObjectProxy* layout_object = LayoutObjectProxy::Create(element.Get());
1786   layout_object->EnsureIdForTestingProxy();
1787   element->SetLayoutObject(layout_object);
1788 
1789   auto& properties = layout_object->GetMutableForPainting()
1790                          .FirstFragment()
1791                          .EnsurePaintProperties();
1792 
1793   // Add a transform with a compositing reason, which should allow starting
1794   // animation.
1795   UpdateDummyTransformNode(properties,
1796                            CompositingReason::kActiveTransformAnimation);
1797   EXPECT_EQ(CheckCanStartElementOnCompositor(*element),
1798             CompositorAnimations::kNoFailure);
1799 
1800   // Setting to CompositingReasonNone should produce false.
1801   UpdateDummyTransformNode(properties, CompositingReason::kNone);
1802   EXPECT_TRUE(CheckCanStartElementOnCompositor(*element) &
1803               CompositorAnimations::kTargetHasInvalidCompositingState);
1804 
1805   // Clearing the transform node entirely should also produce false.
1806   properties.ClearTransform();
1807   EXPECT_TRUE(CheckCanStartElementOnCompositor(*element) &
1808               CompositorAnimations::kTargetHasInvalidCompositingState);
1809 
1810   element->SetLayoutObject(nullptr);
1811   LayoutObjectProxy::Dispose(layout_object);
1812 }
1813 
TEST_P(AnimationCompositorAnimationsTest,CanStartElementOnCompositorEffectBasedOnPaintProperties)1814 TEST_P(AnimationCompositorAnimationsTest,
1815        CanStartElementOnCompositorEffectBasedOnPaintProperties) {
1816   Persistent<Element> element = GetDocument().CreateElementForBinding("shared");
1817   LayoutObjectProxy* layout_object = LayoutObjectProxy::Create(element.Get());
1818   layout_object->EnsureIdForTestingProxy();
1819   element->SetLayoutObject(layout_object);
1820 
1821   auto& properties = layout_object->GetMutableForPainting()
1822                          .FirstFragment()
1823                          .EnsurePaintProperties();
1824 
1825   // Add an effect with a compositing reason, which should allow starting
1826   // animation.
1827   UpdateDummyEffectNode(properties,
1828                         CompositingReason::kActiveTransformAnimation);
1829   EXPECT_EQ(CheckCanStartElementOnCompositor(*element),
1830             CompositorAnimations::kNoFailure);
1831 
1832   // Setting to CompositingReasonNone should produce false.
1833   UpdateDummyEffectNode(properties, CompositingReason::kNone);
1834   EXPECT_TRUE(CheckCanStartElementOnCompositor(*element) &
1835               CompositorAnimations::kTargetHasInvalidCompositingState);
1836 
1837   // Clearing the effect node entirely should also produce false.
1838   properties.ClearEffect();
1839   EXPECT_TRUE(CheckCanStartElementOnCompositor(*element) &
1840               CompositorAnimations::kTargetHasInvalidCompositingState);
1841 
1842   element->SetLayoutObject(nullptr);
1843   LayoutObjectProxy::Dispose(layout_object);
1844 }
1845 
TEST_P(AnimationCompositorAnimationsTest,TrackRafAnimation)1846 TEST_P(AnimationCompositorAnimationsTest, TrackRafAnimation) {
1847   LoadTestData("raf-countdown.html");
1848 
1849   cc::AnimationHost* host =
1850       GetFrame()->GetDocument()->View()->GetCompositorAnimationHost();
1851 
1852   // The test file registers two rAF 'animations'; one which ends after 5
1853   // iterations and the other that ends after 10.
1854   for (int i = 0; i < 9; i++) {
1855     BeginFrame();
1856     EXPECT_TRUE(host->CurrentFrameHadRAF());
1857     EXPECT_TRUE(host->NextFrameHasPendingRAF());
1858   }
1859 
1860   // On the 10th iteration, there should be a current rAF, but no more pending
1861   // rAFs.
1862   BeginFrame();
1863   EXPECT_TRUE(host->CurrentFrameHadRAF());
1864   EXPECT_FALSE(host->NextFrameHasPendingRAF());
1865 
1866   // On the 11th iteration, there should be no more rAFs firing.
1867   BeginFrame();
1868   EXPECT_FALSE(host->CurrentFrameHadRAF());
1869   EXPECT_FALSE(host->NextFrameHasPendingRAF());
1870 }
1871 
TEST_P(AnimationCompositorAnimationsTest,TrackRafAnimationTimeout)1872 TEST_P(AnimationCompositorAnimationsTest, TrackRafAnimationTimeout) {
1873   LoadTestData("raf-timeout.html");
1874 
1875   cc::AnimationHost* host =
1876       GetFrame()->GetDocument()->View()->GetCompositorAnimationHost();
1877 
1878   // The test file executes a rAF, which fires a setTimeout for the next rAF.
1879   // Even with setTimeout(func, 0), the next rAF is not considered pending.
1880   BeginFrame();
1881   EXPECT_TRUE(host->CurrentFrameHadRAF());
1882   EXPECT_FALSE(host->NextFrameHasPendingRAF());
1883 }
1884 
TEST_P(AnimationCompositorAnimationsTest,TrackRafAnimationNoneRegistered)1885 TEST_P(AnimationCompositorAnimationsTest, TrackRafAnimationNoneRegistered) {
1886   SetBodyInnerHTML("<div id='box'></div>");
1887 
1888   // Run a full frame after loading the test data so that scripted animations
1889   // are serviced and data propagated.
1890   BeginFrame();
1891 
1892   // The HTML does not have any rAFs.
1893   cc::AnimationHost* host =
1894       GetFrame()->GetDocument()->View()->GetCompositorAnimationHost();
1895   EXPECT_FALSE(host->CurrentFrameHadRAF());
1896   EXPECT_FALSE(host->NextFrameHasPendingRAF());
1897 
1898   // And still shouldn't after another frame.
1899   BeginFrame();
1900   EXPECT_FALSE(host->CurrentFrameHadRAF());
1901   EXPECT_FALSE(host->NextFrameHasPendingRAF());
1902 }
1903 
TEST_P(AnimationCompositorAnimationsTest,CompositedTransformAnimation)1904 TEST_P(AnimationCompositorAnimationsTest, CompositedTransformAnimation) {
1905   // TODO(wangxianzhu): Fix this test for CompositeAfterPaint.
1906   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
1907     return;
1908 
1909   LoadTestData("transform-animation.html");
1910   Document* document = GetFrame()->GetDocument();
1911   Element* target = document->getElementById("target");
1912   const ObjectPaintProperties* properties =
1913       target->GetLayoutObject()->FirstFragment().PaintProperties();
1914   ASSERT_NE(nullptr, properties);
1915   const auto* transform = properties->Transform();
1916   ASSERT_NE(nullptr, transform);
1917   EXPECT_TRUE(transform->HasDirectCompositingReasons());
1918   EXPECT_TRUE(transform->HasActiveTransformAnimation());
1919 
1920   // Make sure the animation state is initialized in paint properties.
1921   auto* property_trees =
1922       document->View()->RootCcLayer()->layer_tree_host()->property_trees();
1923   auto* cc_transform = property_trees->transform_tree.Node(
1924       property_trees->element_id_to_transform_node_index
1925           [transform->GetCompositorElementId()]);
1926   ASSERT_NE(nullptr, cc_transform);
1927   EXPECT_TRUE(cc_transform->has_potential_animation);
1928   EXPECT_TRUE(cc_transform->is_currently_animating);
1929   EXPECT_EQ(cc::kNotScaled, cc_transform->starting_animation_scale);
1930   EXPECT_EQ(cc::kNotScaled, cc_transform->maximum_animation_scale);
1931 
1932   // Make sure the animation is started on the compositor.
1933   EXPECT_EQ(CheckCanStartElementOnCompositor(*target),
1934             CompositorAnimations::kNoFailure);
1935   EXPECT_EQ(document->Timeline().AnimationsNeedingUpdateCount(), 1u);
1936   cc::AnimationHost* host = document->View()->GetCompositorAnimationHost();
1937   EXPECT_EQ(host->MainThreadAnimationsCount(), 0u);
1938   EXPECT_EQ(host->CompositedAnimationsCount(), 1u);
1939 }
1940 
TEST_P(AnimationCompositorAnimationsTest,CompositedScaleAnimation)1941 TEST_P(AnimationCompositorAnimationsTest, CompositedScaleAnimation) {
1942   // TODO(wangxianzhu): Fix this test for CompositeAfterPaint.
1943   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
1944     return;
1945 
1946   LoadTestData("scale-animation.html");
1947   Document* document = GetFrame()->GetDocument();
1948   Element* target = document->getElementById("target");
1949   const ObjectPaintProperties* properties =
1950       target->GetLayoutObject()->FirstFragment().PaintProperties();
1951   ASSERT_NE(nullptr, properties);
1952   const auto* transform = properties->Transform();
1953   ASSERT_NE(nullptr, transform);
1954   EXPECT_TRUE(transform->HasDirectCompositingReasons());
1955   EXPECT_TRUE(transform->HasActiveTransformAnimation());
1956 
1957   // Make sure the animation state is initialized in paint properties.
1958   auto* property_trees =
1959       document->View()->RootCcLayer()->layer_tree_host()->property_trees();
1960   auto* cc_transform = property_trees->transform_tree.Node(
1961       property_trees->element_id_to_transform_node_index
1962           [transform->GetCompositorElementId()]);
1963   ASSERT_NE(nullptr, cc_transform);
1964   EXPECT_TRUE(cc_transform->has_potential_animation);
1965   EXPECT_TRUE(cc_transform->is_currently_animating);
1966   EXPECT_EQ(2.f, cc_transform->starting_animation_scale);
1967   EXPECT_EQ(5.f, cc_transform->maximum_animation_scale);
1968 
1969   // Make sure the animation is started on the compositor.
1970   EXPECT_EQ(CheckCanStartElementOnCompositor(*target),
1971             CompositorAnimations::kNoFailure);
1972   EXPECT_EQ(document->Timeline().AnimationsNeedingUpdateCount(), 1u);
1973   cc::AnimationHost* host = document->View()->GetCompositorAnimationHost();
1974   EXPECT_EQ(host->MainThreadAnimationsCount(), 0u);
1975   EXPECT_EQ(host->CompositedAnimationsCount(), 1u);
1976 }
1977 
TEST_P(AnimationCompositorAnimationsTest,NonAnimatedTransformPropertyChangeGetsUpdated)1978 TEST_P(AnimationCompositorAnimationsTest,
1979        NonAnimatedTransformPropertyChangeGetsUpdated) {
1980   // TODO(wangxianzhu): Fix this test for CompositeAfterPaint.
1981   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
1982     return;
1983 
1984   LoadTestData("transform-animation-update.html");
1985   Document* document = GetFrame()->GetDocument();
1986   Element* target = document->getElementById("target");
1987   const ObjectPaintProperties* properties =
1988       target->GetLayoutObject()->FirstFragment().PaintProperties();
1989   ASSERT_NE(nullptr, properties);
1990   const auto* transform = properties->Transform();
1991   ASSERT_NE(nullptr, transform);
1992   // Make sure composited animation is running on #target.
1993   EXPECT_TRUE(transform->HasDirectCompositingReasons());
1994   EXPECT_TRUE(transform->HasActiveTransformAnimation());
1995   EXPECT_EQ(CheckCanStartElementOnCompositor(*target),
1996             CompositorAnimations::kNoFailure);
1997   // Make sure the animation state is initialized in paint properties.
1998   auto* property_trees =
1999       document->View()->RootCcLayer()->layer_tree_host()->property_trees();
2000   auto* cc_transform = property_trees->transform_tree.Node(
2001       property_trees->element_id_to_transform_node_index
2002           [transform->GetCompositorElementId()]);
2003   ASSERT_NE(nullptr, cc_transform);
2004   EXPECT_TRUE(cc_transform->has_potential_animation);
2005   EXPECT_TRUE(cc_transform->is_currently_animating);
2006   // Make sure the animation is started on the compositor.
2007   EXPECT_EQ(document->Timeline().AnimationsNeedingUpdateCount(), 1u);
2008   cc::AnimationHost* host = document->View()->GetCompositorAnimationHost();
2009   EXPECT_EQ(host->MainThreadAnimationsCount(), 0u);
2010   EXPECT_EQ(host->CompositedAnimationsCount(), 1u);
2011   // Make sure the backface-visibility is correctly set, both in blink and on
2012   // the cc::Layer.
2013   EXPECT_FALSE(transform->Matrix().IsIdentity());  // Rotated
2014   EXPECT_EQ(transform->GetBackfaceVisibilityForTesting(),
2015             TransformPaintPropertyNode::BackfaceVisibility::kVisible);
2016   const CompositedLayerMapping* composited_layer_mapping =
2017       ToLayoutBoxModelObject(target->GetLayoutObject())
2018           ->Layer()
2019           ->GetCompositedLayerMapping();
2020   ASSERT_NE(nullptr, composited_layer_mapping);
2021   const cc::PictureLayer* layer =
2022       composited_layer_mapping->MainGraphicsLayer()->CcLayer();
2023   ASSERT_NE(nullptr, layer);
2024   EXPECT_TRUE(layer->double_sided());
2025 
2026   // Change the backface visibility, while the compositor animation is
2027   // happening.
2028   target->setAttribute(html_names::kClassAttr, "backface-hidden");
2029   ForceFullCompositingUpdate();
2030   // Make sure the setting made it to both blink and all the way to CC.
2031   EXPECT_EQ(transform->GetBackfaceVisibilityForTesting(),
2032             TransformPaintPropertyNode::BackfaceVisibility::kHidden);
2033   EXPECT_FALSE(layer->double_sided())
2034       << "Change to hidden did not get propagated to CC";
2035   // Make sure the animation state is initialized in paint properties after
2036   // blink pushing new paint properties without animation state change.
2037   property_trees =
2038       document->View()->RootCcLayer()->layer_tree_host()->property_trees();
2039   cc_transform = property_trees->transform_tree.Node(
2040       property_trees->element_id_to_transform_node_index
2041           [transform->GetCompositorElementId()]);
2042   ASSERT_NE(nullptr, cc_transform);
2043   EXPECT_TRUE(cc_transform->has_potential_animation);
2044   EXPECT_TRUE(cc_transform->is_currently_animating);
2045 }
2046 
2047 // Regression test for https://crbug.com/781305. When we have a transform
2048 // animation on a SVG element, the effect can be started on compositor but the
2049 // element itself cannot.
TEST_P(AnimationCompositorAnimationsTest,CannotStartElementOnCompositorEffectSVG)2050 TEST_P(AnimationCompositorAnimationsTest,
2051        CannotStartElementOnCompositorEffectSVG) {
2052   LoadTestData("transform-animation-on-svg.html");
2053   Document* document = GetFrame()->GetDocument();
2054   Element* target = document->getElementById("dots");
2055   EXPECT_TRUE(CheckCanStartElementOnCompositor(*target) &
2056               CompositorAnimations::kTargetHasInvalidCompositingState);
2057   EXPECT_EQ(document->Timeline().AnimationsNeedingUpdateCount(), 4u);
2058   cc::AnimationHost* host = document->View()->GetCompositorAnimationHost();
2059   EXPECT_EQ(host->MainThreadAnimationsCount(), 4u);
2060   EXPECT_EQ(host->CompositedAnimationsCount(), 0u);
2061 }
2062 
2063 // Regression test for https://crbug.com/999333. We were relying on the Document
2064 // always having Settings, which will not be the case if it is not attached to a
2065 // Frame.
TEST_P(AnimationCompositorAnimationsTest,DocumentWithoutSettingShouldNotCauseCrash)2066 TEST_P(AnimationCompositorAnimationsTest,
2067        DocumentWithoutSettingShouldNotCauseCrash) {
2068   SetBodyInnerHTML("<div id='target'></div>");
2069   Element* target = GetElementById("target");
2070   ASSERT_TRUE(target);
2071 
2072   // Move the target element to another Document, that does not have a frame
2073   // (and thus no Settings).
2074   Document* another_document = MakeGarbageCollected<Document>();
2075   ASSERT_FALSE(another_document->GetSettings());
2076 
2077   another_document->adoptNode(target, ASSERT_NO_EXCEPTION);
2078 
2079   // This should not crash.
2080   EXPECT_NE(CheckCanStartElementOnCompositor(*target),
2081             CompositorAnimations::kNoFailure);
2082 }
2083 
2084 }  // namespace blink
2085