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

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

Issue 2869183002: Initial implementation of WorkletAnimation (Closed)
Patch Set: Add more DCHECKs 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 DCHECK(IsMainThread());
65
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 Document& document = effects.at(0)->Target()->GetDocument();
78 WorkletAnimation* animation = new WorkletAnimation(
79 animator_name, document, effects, timelines, std::move(options));
80 document.Timeline().CompositorTimeline()->PlayerAttached(*animation);
81
82 return animation;
83 }
84
85 WorkletAnimation::WorkletAnimation(
86 const String& animator_name,
87 Document& document,
88 const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
89 HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
90 RefPtr<SerializedScriptValue> options)
91 : animator_name_(animator_name),
92 play_state_(Animation::kIdle),
93 document_(document),
94 effects_(effects),
95 timelines_(timelines),
96 options_(std::move(options)) {
97 DCHECK(IsMainThread());
98 DCHECK(Platform::Current()->IsThreadedAnimationEnabled());
99 DCHECK(Platform::Current()->CompositorSupport());
100 compositor_player_ = CompositorAnimationPlayer::Create();
101 compositor_player_->SetAnimationDelegate(this);
102 }
103
104 String WorkletAnimation::playState() {
105 DCHECK(IsMainThread());
106 return Animation::PlayStateString(play_state_);
107 }
108
109 void WorkletAnimation::play() {
110 DCHECK(IsMainThread());
111 if (play_state_ != Animation::kPending) {
112 document_->GetWorkletAnimationController().AttachAnimation(*this);
113 play_state_ = Animation::kPending;
114 }
115 }
116
117 void WorkletAnimation::cancel() {
118 DCHECK(IsMainThread());
119 if (play_state_ != Animation::kIdle) {
120 document_->GetWorkletAnimationController().DetachAnimation(*this);
121 play_state_ = Animation::kIdle;
122 }
123 }
124
125 bool WorkletAnimation::StartOnCompositor() {
126 DCHECK(IsMainThread());
127 // TODO(smcgruer): We need to start all of the effects, not just the first.
128 double animation_playback_rate = 1;
129 Element& target = *effects_.at(0)->Target();
130 ToKeyframeEffectModelBase(effects_.at(0)->Model())
131 ->SnapshotAllCompositorKeyframes(target, target.ComputedStyleRef(),
132 target.ParentComputedStyle());
133 bool success =
134 effects_.at(0)
135 ->CheckCanStartAnimationOnCompositor(animation_playback_rate)
136 .Ok();
137 // Currently |StartAnimationOnCompositor| is unable to propagate a
138 // WorkletAnimation effect to the compositor, so this method is a no-op.
139 // TODO(smcgruer): Actually create the element animations on the compositor.
140 play_state_ = success ? Animation::kRunning : Animation::kIdle;
141 return success;
142 }
143
144 void WorkletAnimation::Dispose() {
145 DCHECK(IsMainThread());
146 document_->Timeline().CompositorTimeline()->PlayerDestroyed(*this);
147 compositor_player_->SetAnimationDelegate(nullptr);
148 compositor_player_ = nullptr;
149 }
150
151 DEFINE_TRACE(WorkletAnimation) {
152 visitor->Trace(document_);
153 visitor->Trace(effects_);
154 visitor->Trace(timelines_);
155 WorkletAnimationBase::Trace(visitor);
156 }
157
158 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698