summaryrefslogtreecommitdiffstats
path: root/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
diff options
context:
space:
mode:
authorajuma@chromium.org <ajuma@chromium.org>2015-01-19 15:47:20 +0000
committerajuma@chromium.org <ajuma@chromium.org>2015-01-19 15:47:20 +0000
commitf150188c9839c45490d28ec2a0459f7bbf634360 (patch)
tree6c0aa79cedf887b699e69774af6cc3c9513c7095 /third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
parent0e5cf152c2d43e5296722c1bebf5e2f038773727 (diff)
downloadchromium_src-f150188c9839c45490d28ec2a0459f7bbf634360.zip
chromium_src-f150188c9839c45490d28ec2a0459f7bbf634360.tar.gz
chromium_src-f150188c9839c45490d28ec2a0459f7bbf634360.tar.bz2
Run CSSOM smooth scroll animations on the compositor when possible
This runs smooth scroll animations on the compositor when a composited layer for scrolling already exists and main-thread scrolling isn't required. This also adds a virtual test suite that runs the fast/scroll-behavior tests with --enable-threaded-compositing and --enable-prefer-compositing-to-lcd-text. Smooth scrolling is behind a runtime flag. BUG=243871 Review URL: https://codereview.chromium.org/802383003 git-svn-id: svn://svn.chromium.org/blink/trunk@188634 bbb929c8-8fbe-4397-9dbb-9b2b20218538
Diffstat (limited to 'third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp')
-rw-r--r--third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp135
1 files changed, 121 insertions, 14 deletions
diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
index 5740180..7b23329 100644
--- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
@@ -6,8 +6,10 @@
#include "platform/scroll/ProgrammaticScrollAnimator.h"
#include "platform/geometry/IntPoint.h"
+#include "platform/graphics/GraphicsLayer.h"
#include "platform/scroll/ScrollableArea.h"
#include "public/platform/Platform.h"
+#include "public/platform/WebCompositorAnimation.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebScrollOffsetAnimationCurve.h"
@@ -21,6 +23,9 @@ PassOwnPtr<ProgrammaticScrollAnimator> ProgrammaticScrollAnimator::create(Scroll
ProgrammaticScrollAnimator::ProgrammaticScrollAnimator(ScrollableArea* scrollableArea)
: m_scrollableArea(scrollableArea)
, m_startTime(0.0)
+ , m_runState(RunState::Idle)
+ , m_compositorAnimationId(0)
+ , m_compositorAnimationGroupId(0)
{
}
@@ -32,6 +37,9 @@ void ProgrammaticScrollAnimator::resetAnimationState()
{
m_animationCurve.clear();
m_startTime = 0.0;
+ m_runState = RunState::Idle;
+ m_compositorAnimationId = 0;
+ m_compositorAnimationGroupId = 0;
}
void ProgrammaticScrollAnimator::animateToOffset(FloatPoint offset)
@@ -46,35 +54,134 @@ void ProgrammaticScrollAnimator::animateToOffset(FloatPoint offset)
resetAnimationState();
m_scrollableArea->notifyScrollPositionChanged(IntPoint(offset.x(), offset.y()));
}
+ m_runState = RunState::WaitingToSendToCompositor;
}
void ProgrammaticScrollAnimator::cancelAnimation()
{
- resetAnimationState();
+ switch (m_runState) {
+ case RunState::Idle:
+ case RunState::WaitingToCancelOnCompositor:
+ break;
+ case RunState::WaitingToSendToCompositor:
+ if (m_compositorAnimationId) {
+ // We still have a previous animation running on the compositor.
+ m_runState = RunState::WaitingToCancelOnCompositor;
+ } else {
+ resetAnimationState();
+ }
+ break;
+ case RunState::RunningOnMainThread:
+ resetAnimationState();
+ break;
+ case RunState::RunningOnCompositor:
+ m_runState = RunState::WaitingToCancelOnCompositor;
+
+ // Get serviced the next time compositor updates are allowed.
+ m_scrollableArea->registerForAnimation();
+ }
}
void ProgrammaticScrollAnimator::tickAnimation(double monotonicTime)
{
- if (m_animationCurve) {
- if (!m_startTime)
- m_startTime = monotonicTime;
- double elapsedTime = monotonicTime - m_startTime;
- bool isFinished = (elapsedTime > m_animationCurve->duration());
- FloatPoint offset = m_animationCurve->getValue(elapsedTime);
- m_scrollableArea->notifyScrollPositionChanged(IntPoint(offset.x(), offset.y()));
+ if (m_runState != RunState::RunningOnMainThread)
+ return;
- if (isFinished) {
- resetAnimationState();
- } else if (!m_scrollableArea->scheduleAnimation()) {
- m_scrollableArea->notifyScrollPositionChanged(IntPoint(m_targetOffset.x(), m_targetOffset.y()));
+ if (!m_startTime)
+ m_startTime = monotonicTime;
+ double elapsedTime = monotonicTime - m_startTime;
+ bool isFinished = (elapsedTime > m_animationCurve->duration());
+ FloatPoint offset = m_animationCurve->getValue(elapsedTime);
+ m_scrollableArea->notifyScrollPositionChanged(IntPoint(offset.x(), offset.y()));
+
+ if (isFinished) {
+ resetAnimationState();
+ } else if (!m_scrollableArea->scheduleAnimation()) {
+ m_scrollableArea->notifyScrollPositionChanged(IntPoint(m_targetOffset.x(), m_targetOffset.y()));
+ resetAnimationState();
+ }
+}
+
+bool ProgrammaticScrollAnimator::hasAnimationThatRequiresService() const
+{
+ switch (m_runState) {
+ case RunState::Idle:
+ case RunState::RunningOnCompositor:
+ return false;
+ case RunState::WaitingToSendToCompositor:
+ case RunState::RunningOnMainThread:
+ case RunState::WaitingToCancelOnCompositor:
+ return true;
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void ProgrammaticScrollAnimator::updateCompositorAnimations()
+{
+ if (m_compositorAnimationId && m_runState != RunState::RunningOnCompositor) {
+ // If the current run state is WaitingToSendToCompositor but we have a
+ // non-zero compositor animation id, there's a currently running
+ // compositor animation that needs to be removed here before the new
+ // animation is added below.
+ ASSERT(m_runState == RunState::WaitingToCancelOnCompositor || m_runState == RunState::WaitingToSendToCompositor);
+ if (GraphicsLayer* layer = m_scrollableArea->layerForScrolling())
+ layer->removeAnimation(m_compositorAnimationId);
+ m_compositorAnimationId = 0;
+ m_compositorAnimationGroupId = 0;
+ if (m_runState == RunState::WaitingToCancelOnCompositor) {
resetAnimationState();
+ return;
+ }
+ }
+
+ if (m_runState == RunState::WaitingToSendToCompositor) {
+ bool sentToCompositor = false;
+
+ if (GraphicsLayer* layer = m_scrollableArea->layerForScrolling()) {
+ if (!layer->platformLayer()->shouldScrollOnMainThread()) {
+ OwnPtr<WebCompositorAnimation> animation = adoptPtr(Platform::current()->compositorSupport()->createAnimation(*m_animationCurve, WebCompositorAnimation::TargetPropertyScrollOffset));
+
+ int animationId = animation->id();
+ int animationGroupId = animation->group();
+ if (m_scrollableArea->layerForScrolling()->addAnimation(animation.release())) {
+ sentToCompositor = true;
+ m_runState = RunState::RunningOnCompositor;
+ m_compositorAnimationId = animationId;
+ m_compositorAnimationGroupId = animationGroupId;
+ }
+ }
+ }
+
+ if (!sentToCompositor) {
+ m_runState = RunState::RunningOnMainThread;
+ if (!m_scrollableArea->scheduleAnimation()) {
+ m_scrollableArea->notifyScrollPositionChanged(IntPoint(m_targetOffset.x(), m_targetOffset.y()));
+ resetAnimationState();
+ }
}
}
}
-bool ProgrammaticScrollAnimator::hasRunningAnimation() const
+void ProgrammaticScrollAnimator::notifyCompositorAnimationFinished(int groupId)
{
- return !!m_animationCurve;
+ if (m_compositorAnimationGroupId != groupId)
+ return;
+
+ m_compositorAnimationId = 0;
+ m_compositorAnimationGroupId = 0;
+
+ switch (m_runState) {
+ case RunState::Idle:
+ case RunState::RunningOnMainThread:
+ ASSERT_NOT_REACHED();
+ break;
+ case RunState::WaitingToSendToCompositor:
+ break;
+ case RunState::RunningOnCompositor:
+ case RunState::WaitingToCancelOnCompositor:
+ resetAnimationState();
+ }
}
} // namespace blink