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

Side by Side Diff: third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp

Issue 2869183002: Initial implementation of WorkletAnimation (Closed)
Patch Set: Fix include for new v8 bindings path Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "modules/compositorworker/WorkletAnimation.h"
6
7 #include "core/animation/ElementAnimations.h"
8 #include "core/animation/KeyframeEffectModel.h"
9 #include "core/animation/ScrollTimeline.h"
10 #include "core/animation/Timing.h"
11 #include "core/dom/Node.h"
12 #include "core/dom/NodeComputedStyle.h"
13 #include "platform/wtf/text/WTFString.h"
14 #include "public/platform/Platform.h"
15 #include "public/platform/WebCompositorSupport.h"
16
17 namespace blink {
18
19 namespace {
20 bool ValidateEffects(const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
21 String& error_string) {
22 if (effects.IsEmpty()) {
23 error_string = "Effects array must be non-empty";
24 return false;
25 }
26
27 Document& target_document = effects.at(0)->Target()->GetDocument();
28 for (const auto& effect : effects) {
29 if (effect->Target()->GetDocument() != target_document) {
30 error_string = "All effects must target elements in the same document";
31 return false;
32 }
33 }
34 return true;
35 }
36
37 bool ValidateTimelines(HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
38 String& error_string) {
39 if (timelines.IsEmpty()) {
40 error_string = "Timelines array must be non-empty";
41 return false;
42 }
43
44 for (const auto& timeline : timelines) {
45 if (timeline.isScrollTimeline()) {
46 DoubleOrScrollTimelineAutoKeyword time_range;
47 timeline.getAsScrollTimeline()->timeRange(time_range);
48 if (time_range.isScrollTimelineAutoKeyword()) {
49 error_string = "ScrollTimeline timeRange must have non-auto value";
50 return false;
51 }
52 }
53 }
54 return true;
55 }
56 } // namespace
57
58 WorkletAnimation* WorkletAnimation::Create(
59 String animator_name,
60 const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
61 HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
62 RefPtr<SerializedScriptValue> options,
63 ExceptionState& exception_state) {
64 String error_string;
65 if (!ValidateEffects(effects, error_string)) {
66 exception_state.ThrowDOMException(kNotSupportedError, error_string);
67 return nullptr;
68 }
69
70 if (!ValidateTimelines(timelines, error_string)) {
71 exception_state.ThrowDOMException(kNotSupportedError, error_string);
72 return nullptr;
73 }
74
75 Document& document = effects.at(0)->Target()->GetDocument();
76 WorkletAnimation* animation = new WorkletAnimation(
77 animator_name, document, effects, timelines, std::move(options));
78 document.Timeline().CompositorTimeline()->PlayerAttached(*animation);
79
80 return animation;
81 }
82
83 WorkletAnimation::WorkletAnimation(
84 String animator_name,
nhiroki 2017/09/08 03:58:22 const String& ?
smcgruer 2017/09/11 18:19:00 Done.
85 Document& document,
86 const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
87 HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
88 RefPtr<SerializedScriptValue> options)
89 : animator_name_(animator_name),
90 play_state_(Animation::kIdle),
91 document_(document),
92 effects_(effects),
93 timelines_(timelines),
94 options_(std::move(options)) {
95 DCHECK(Platform::Current()->IsThreadedAnimationEnabled());
96 DCHECK(Platform::Current()->CompositorSupport());
97 compositor_player_ = CompositorAnimationPlayer::Create();
98 compositor_player_->SetAnimationDelegate(this);
99 }
100
101 String WorkletAnimation::playState() {
102 return Animation::PlayStateString(play_state_);
103 }
104
105 void WorkletAnimation::play() {
106 document_->GetWorkletAnimationController().AttachAnimation(*this);
107 play_state_ = Animation::kPending;
haraken 2017/09/08 01:11:23 Is there any restriction about the state transitio
smcgruer 2017/09/11 18:19:00 As of yet, no. It is valid to call play() twice in
108 }
109
110 void WorkletAnimation::cancel() {
111 document_->GetWorkletAnimationController().DetachAnimation(*this);
112 play_state_ = Animation::kIdle;
113 }
114
115 bool WorkletAnimation::StartOnCompositor() {
116 // TODO(smcgruer): We need to start all of the effects, not just the first.
117 double animation_playback_rate = 1;
118 Element& target = *effects_.at(0)->Target();
119 ToKeyframeEffectModelBase(effects_.at(0)->Model())
120 ->SnapshotAllCompositorKeyframes(target, target.ComputedStyleRef(),
121 target.ParentComputedStyle());
122 bool success =
123 effects_.at(0)
124 ->CheckCanStartAnimationOnCompositor(animation_playback_rate)
125 .Ok();
126 // Currently |StartAnimationOnCompositor| is unable to propagate a
127 // WorkletAnimation effect to the compositor, so this method is a no-op.
128 // TODO(smcgruer): Actually create the element animations on the compositor.
129 play_state_ = success ? Animation::kRunning : Animation::kIdle;
130 return success;
131 }
132
133 void WorkletAnimation::Dispose() {
134 document_->Timeline().CompositorTimeline()->PlayerDestroyed(*this);
135 compositor_player_->SetAnimationDelegate(nullptr);
136 compositor_player_ = nullptr;
137 }
138
139 DEFINE_TRACE(WorkletAnimation) {
140 visitor->Trace(document_);
141 visitor->Trace(effects_);
142 visitor->Trace(timelines_);
143 WorkletAnimationBase::Trace(visitor);
144 }
145
146 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698