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

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

Issue 2869183002: Initial implementation of WorkletAnimation (Closed)
Patch Set: DCHECK for threaded animation support Created 3 years, 6 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/DocumentTimeline.h"
8 #include "core/animation/ElementAnimations.h"
9 #include "core/animation/KeyframeEffectModel.h"
10 #include "core/animation/ScrollTimeline.h"
11 #include "core/animation/Timing.h"
12 #include "core/dom/Node.h"
13 #include "core/dom/NodeComputedStyle.h"
14 #include "platform/animation/CompositorAnimationPlayer.h"
15 #include "platform/wtf/text/WTFString.h"
16 #include "public/platform/Platform.h"
17 #include "public/platform/WebCompositorSupport.h"
18
19 namespace blink {
20
21 namespace {
22 bool ValidateEffects(const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
23 String* error_string) {
24 if (effects.IsEmpty()) {
25 *error_string = "Effects array must be non-empty";
26 return false;
27 }
28
29 Document& target_document = effects.at(0)->Target()->GetDocument();
30 for (const auto& effect : effects) {
31 if (effect->Target()->GetDocument() != target_document) {
32 *error_string = "All effects must target elements in the same document";
33 return false;
34 }
35 }
36 return true;
37 }
38
39 bool ValidateTimelines(HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
40 String* error_string) {
41 if (timelines.IsEmpty()) {
42 *error_string = "Timelines array must be non-empty";
43 return false;
44 }
45
46 for (const auto& timeline : timelines) {
47 if (timeline.isScrollTimeline()) {
48 DoubleOrScrollTimelineAutoKeyword time_range;
49 timeline.getAsScrollTimeline()->timeRange(time_range);
50 if (time_range.isScrollTimelineAutoKeyword()) {
51 *error_string = "ScrollTimeline timeRange must have non-auto value";
52 return false;
53 }
54 }
55 }
56 return true;
57 }
58 } // namespace
59
60 WorkletAnimation* WorkletAnimation::Create(
61 String animator_name,
62 const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
63 HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
64 RefPtr<SerializedScriptValue> user_data,
65 ExceptionState& exception_state) {
66 String error_string;
67 if (!ValidateEffects(effects, &error_string)) {
68 exception_state.ThrowDOMException(kNotSupportedError, error_string);
69 return nullptr;
70 }
71
72 if (!ValidateTimelines(timelines, &error_string)) {
73 exception_state.ThrowDOMException(kNotSupportedError, error_string);
74 return nullptr;
75 }
76
77 // TODO(smcgruer): Document.
flackr 2017/06/07 17:21:33 What do you mean by Document? This should maybe ch
smcgruer 2017/06/07 18:23:25 It was a reminder to myself to document this code,
78 Document& document = effects.at(0)->Target()->GetDocument();
79 AnimationTimeline& main_document_timeline = document.Timeline();
majidvp 2017/06/06 16:04:28 nit: s/main_document_timeline/document_timeline/.
smcgruer 2017/06/07 18:23:25 Done.
80
81 WorkletAnimation* animation =
82 new WorkletAnimation(animator_name, effects, timelines,
83 std::move(user_data), main_document_timeline);
84
85 document.RegisterWorkletAnimation(animation);
86 // TODO(smcgruer): Set needs compositing update?
87 animation->AttachCompositorTimeline();
88
89 return animation;
90 }
91
92 WorkletAnimation::WorkletAnimation(
93 String animator_name,
94 const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
95 HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
96 RefPtr<SerializedScriptValue> user_data,
97 AnimationTimeline& main_document_timeline)
98 : animator_name_(animator_name),
99 effects_(effects),
100 timelines_(timelines),
101 user_data_(std::move(user_data)),
102 main_document_timeline_(main_document_timeline),
103 on_compositor_(false) {
104 DCHECK(Platform::Current()->IsThreadedAnimationEnabled());
105 DCHECK(Platform::Current()->CompositorSupport());
106 compositor_player_ = CompositorAnimationPlayerHolder::Create(this);
107 DCHECK(compositor_player_);
108 }
109
110 void WorkletAnimation::Update() {
111 if (!on_compositor_) {
majidvp 2017/06/06 16:04:27 The current logic keeps trying to start the animat
smcgruer 2017/06/07 18:23:25 Any thoughts on how to actually report an error fr
112 int group = 0; // We don't know.
113 double start_time = 0;
114 double current_time = 0;
115 double animation_playback_rate = 1;
116 Element& target = *effects_.at(0)->Target();
117 static_cast<KeyframeEffectModelBase*>(effects_.at(0)->Model())
118 ->SnapshotAllCompositorKeyframes(target, target.ComputedStyleRef(),
119 target.ParentComputedStyle());
120 on_compositor_ = effects_.at(0)->MaybeStartAnimationOnCompositor(
flackr 2017/06/07 17:21:33 Why do we just start the first effect? Does that s
smcgruer 2017/06/07 18:23:25 Well the CL doesn't really *do* anything currently
121 group, start_time, current_time, animation_playback_rate,
122 compositor_player_->Player());
123 }
124 }
125
126 void WorkletAnimation::AttachCompositorTimeline() {
127 if (compositor_player_) {
majidvp 2017/06/06 16:04:28 I agree with flackr@ that we should for now assume
flackr 2017/06/07 17:21:33 I would suggest just removing them. When we add ma
smcgruer 2017/06/07 18:23:25 Done.
128 CompositorAnimationTimeline* timeline =
129 main_document_timeline_ ? main_document_timeline_->CompositorTimeline()
130 : nullptr;
131 if (timeline)
flackr 2017/06/07 17:21:32 It looks like this should always be set as long as
smcgruer 2017/06/07 18:23:25 Done.
132 timeline->PlayerAttached(*this);
133 }
134 }
135
136 void WorkletAnimation::DetachCompositorTimeline() {
137 if (compositor_player_) {
138 CompositorAnimationTimeline* timeline =
139 main_document_timeline_ ? main_document_timeline_->CompositorTimeline()
140 : nullptr;
141 if (timeline)
142 timeline->PlayerDestroyed(*this);
143 }
144 }
145
146 void WorkletAnimation::Dispose() {
147 if (compositor_player_) {
148 DetachCompositorTimeline();
149 compositor_player_->Detach();
150 compositor_player_ = nullptr;
151 }
152 }
153
154 void WorkletAnimation::SetEffectInheritedTimeForTesting(
155 Member<KeyframeEffectReadOnly> effect,
156 double inherited_time) {}
157
158 DEFINE_TRACE(WorkletAnimation) {
159 visitor->Trace(effects_);
160 visitor->Trace(timelines_);
161 visitor->Trace(main_document_timeline_);
162 visitor->Trace(compositor_player_);
163 WorkletAnimationBase::Trace(visitor);
164 }
165
166 WorkletAnimation::CompositorAnimationPlayerHolder*
167 WorkletAnimation::CompositorAnimationPlayerHolder::Create(
168 WorkletAnimation* animation) {
169 return new CompositorAnimationPlayerHolder(animation);
170 }
171
172 WorkletAnimation::CompositorAnimationPlayerHolder::
173 CompositorAnimationPlayerHolder(WorkletAnimation* animation)
174 : animation_(animation) {
175 compositor_player_ = CompositorAnimationPlayer::Create();
176 compositor_player_->SetAnimationDelegate(animation_);
177 }
178
179 void WorkletAnimation::CompositorAnimationPlayerHolder::Dispose() {
180 if (!animation_)
181 return;
182 animation_->Dispose();
183 DCHECK(!animation_);
184 DCHECK(!compositor_player_);
185 }
186
187 void WorkletAnimation::CompositorAnimationPlayerHolder::Detach() {
188 compositor_player_->SetAnimationDelegate(nullptr);
189 animation_ = nullptr;
190 compositor_player_.reset();
191 }
192
193 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698