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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp
diff --git a/third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp b/third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..80dc850bd5c13ec0e12c2eccaebaefb8f8771db3
--- /dev/null
+++ b/third_party/WebKit/Source/modules/compositorworker/WorkletAnimation.cpp
@@ -0,0 +1,193 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/compositorworker/WorkletAnimation.h"
+
+#include "core/animation/DocumentTimeline.h"
+#include "core/animation/ElementAnimations.h"
+#include "core/animation/KeyframeEffectModel.h"
+#include "core/animation/ScrollTimeline.h"
+#include "core/animation/Timing.h"
+#include "core/dom/Node.h"
+#include "core/dom/NodeComputedStyle.h"
+#include "platform/animation/CompositorAnimationPlayer.h"
+#include "platform/wtf/text/WTFString.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebCompositorSupport.h"
+
+namespace blink {
+
+namespace {
+bool ValidateEffects(const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
+ String* error_string) {
+ if (effects.IsEmpty()) {
+ *error_string = "Effects array must be non-empty";
+ return false;
+ }
+
+ Document& target_document = effects.at(0)->Target()->GetDocument();
+ for (const auto& effect : effects) {
+ if (effect->Target()->GetDocument() != target_document) {
+ *error_string = "All effects must target elements in the same document";
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateTimelines(HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
+ String* error_string) {
+ if (timelines.IsEmpty()) {
+ *error_string = "Timelines array must be non-empty";
+ return false;
+ }
+
+ for (const auto& timeline : timelines) {
+ if (timeline.isScrollTimeline()) {
+ DoubleOrScrollTimelineAutoKeyword time_range;
+ timeline.getAsScrollTimeline()->timeRange(time_range);
+ if (time_range.isScrollTimelineAutoKeyword()) {
+ *error_string = "ScrollTimeline timeRange must have non-auto value";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+} // namespace
+
+WorkletAnimation* WorkletAnimation::Create(
+ String animator_name,
+ const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
+ HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
+ RefPtr<SerializedScriptValue> user_data,
+ ExceptionState& exception_state) {
+ String error_string;
+ if (!ValidateEffects(effects, &error_string)) {
+ exception_state.ThrowDOMException(kNotSupportedError, error_string);
+ return nullptr;
+ }
+
+ if (!ValidateTimelines(timelines, &error_string)) {
+ exception_state.ThrowDOMException(kNotSupportedError, error_string);
+ return nullptr;
+ }
+
+ // 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,
+ Document& document = effects.at(0)->Target()->GetDocument();
+ 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.
+
+ WorkletAnimation* animation =
+ new WorkletAnimation(animator_name, effects, timelines,
+ std::move(user_data), main_document_timeline);
+
+ document.RegisterWorkletAnimation(animation);
+ // TODO(smcgruer): Set needs compositing update?
+ animation->AttachCompositorTimeline();
+
+ return animation;
+}
+
+WorkletAnimation::WorkletAnimation(
+ String animator_name,
+ const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
+ HeapVector<DocumentTimelineOrScrollTimeline>& timelines,
+ RefPtr<SerializedScriptValue> user_data,
+ AnimationTimeline& main_document_timeline)
+ : animator_name_(animator_name),
+ effects_(effects),
+ timelines_(timelines),
+ user_data_(std::move(user_data)),
+ main_document_timeline_(main_document_timeline),
+ on_compositor_(false) {
+ DCHECK(Platform::Current()->IsThreadedAnimationEnabled());
+ DCHECK(Platform::Current()->CompositorSupport());
+ compositor_player_ = CompositorAnimationPlayerHolder::Create(this);
+ DCHECK(compositor_player_);
+}
+
+void WorkletAnimation::Update() {
+ 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
+ int group = 0; // We don't know.
+ double start_time = 0;
+ double current_time = 0;
+ double animation_playback_rate = 1;
+ Element& target = *effects_.at(0)->Target();
+ static_cast<KeyframeEffectModelBase*>(effects_.at(0)->Model())
+ ->SnapshotAllCompositorKeyframes(target, target.ComputedStyleRef(),
+ target.ParentComputedStyle());
+ 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
+ group, start_time, current_time, animation_playback_rate,
+ compositor_player_->Player());
+ }
+}
+
+void WorkletAnimation::AttachCompositorTimeline() {
+ 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.
+ CompositorAnimationTimeline* timeline =
+ main_document_timeline_ ? main_document_timeline_->CompositorTimeline()
+ : nullptr;
+ 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.
+ timeline->PlayerAttached(*this);
+ }
+}
+
+void WorkletAnimation::DetachCompositorTimeline() {
+ if (compositor_player_) {
+ CompositorAnimationTimeline* timeline =
+ main_document_timeline_ ? main_document_timeline_->CompositorTimeline()
+ : nullptr;
+ if (timeline)
+ timeline->PlayerDestroyed(*this);
+ }
+}
+
+void WorkletAnimation::Dispose() {
+ if (compositor_player_) {
+ DetachCompositorTimeline();
+ compositor_player_->Detach();
+ compositor_player_ = nullptr;
+ }
+}
+
+void WorkletAnimation::SetEffectInheritedTimeForTesting(
+ Member<KeyframeEffectReadOnly> effect,
+ double inherited_time) {}
+
+DEFINE_TRACE(WorkletAnimation) {
+ visitor->Trace(effects_);
+ visitor->Trace(timelines_);
+ visitor->Trace(main_document_timeline_);
+ visitor->Trace(compositor_player_);
+ WorkletAnimationBase::Trace(visitor);
+}
+
+WorkletAnimation::CompositorAnimationPlayerHolder*
+WorkletAnimation::CompositorAnimationPlayerHolder::Create(
+ WorkletAnimation* animation) {
+ return new CompositorAnimationPlayerHolder(animation);
+}
+
+WorkletAnimation::CompositorAnimationPlayerHolder::
+ CompositorAnimationPlayerHolder(WorkletAnimation* animation)
+ : animation_(animation) {
+ compositor_player_ = CompositorAnimationPlayer::Create();
+ compositor_player_->SetAnimationDelegate(animation_);
+}
+
+void WorkletAnimation::CompositorAnimationPlayerHolder::Dispose() {
+ if (!animation_)
+ return;
+ animation_->Dispose();
+ DCHECK(!animation_);
+ DCHECK(!compositor_player_);
+}
+
+void WorkletAnimation::CompositorAnimationPlayerHolder::Detach() {
+ compositor_player_->SetAnimationDelegate(nullptr);
+ animation_ = nullptr;
+ compositor_player_.reset();
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698