Example #1
0
void ScrollAnimator::createAnimationCurve() {
  DCHECK(!m_animationCurve);
  m_animationCurve = CompositorScrollOffsetAnimationCurve::create(
      compositorOffsetFromBlinkOffset(m_targetOffset),
      m_lastGranularity == ScrollByPixel
          ? CompositorScrollOffsetAnimationCurve::ScrollDurationInverseDelta
          : CompositorScrollOffsetAnimationCurve::ScrollDurationConstant);
  m_animationCurve->setInitialValue(
      compositorOffsetFromBlinkOffset(currentOffset()));
}
Example #2
0
void ProgrammaticScrollAnimator::updateCompositorAnimations() {
  if (m_runState == RunState::PostAnimationCleanup) {
    // No special cleanup, simply reset animation state. We have this state
    // here because the state machine is shared with ScrollAnimator which
    // has to do some cleanup that requires the compositing state to be clean.
    return resetAnimationState();
  }

  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);

    removeAnimation();

    m_compositorAnimationId = 0;
    m_compositorAnimationGroupId = 0;
    if (m_runState == RunState::WaitingToCancelOnCompositor) {
      resetAnimationState();
      return;
    }
  }

  if (m_runState == RunState::WaitingToSendToCompositor) {
    if (!m_compositorAnimationAttachedToElementId)
      reattachCompositorPlayerIfNeeded(
          getScrollableArea()->compositorAnimationTimeline());

    bool sentToCompositor = false;

    if (!m_scrollableArea->shouldScrollOnMainThread()) {
      std::unique_ptr<CompositorAnimation> animation =
          CompositorAnimation::create(
              *m_animationCurve, CompositorTargetProperty::SCROLL_OFFSET, 0, 0);

      int animationId = animation->id();
      int animationGroupId = animation->group();

      if (addAnimation(std::move(animation))) {
        sentToCompositor = true;
        m_runState = RunState::RunningOnCompositor;
        m_compositorAnimationId = animationId;
        m_compositorAnimationGroupId = animationGroupId;
      }
    }

    if (!sentToCompositor) {
      m_runState = RunState::RunningOnMainThread;
      m_animationCurve->setInitialValue(
          compositorOffsetFromBlinkOffset(m_scrollableArea->getScrollOffset()));
      if (!m_scrollableArea->scheduleAnimation()) {
        notifyOffsetChanged(m_targetOffset);
        resetAnimationState();
      }
    }
  }
}
Example #3
0
bool ScrollAnimator::willAnimateToOffset(const ScrollOffset& targetOffset) {
  if (m_runState == RunState::PostAnimationCleanup)
    resetAnimationState();

  if (m_runState == RunState::WaitingToCancelOnCompositor ||
      m_runState == RunState::WaitingToCancelOnCompositorButNewScroll) {
    ASSERT(m_animationCurve);
    m_targetOffset = targetOffset;
    if (registerAndScheduleAnimation())
      m_runState = RunState::WaitingToCancelOnCompositorButNewScroll;
    return true;
  }

  if (m_animationCurve) {
    if ((targetOffset - m_targetOffset).isZero())
      return true;

    m_targetOffset = targetOffset;
    ASSERT(m_runState == RunState::RunningOnMainThread ||
           m_runState == RunState::RunningOnCompositor ||
           m_runState == RunState::RunningOnCompositorButNeedsUpdate ||
           m_runState == RunState::RunningOnCompositorButNeedsTakeover);

    // Running on the main thread, simply update the target offset instead
    // of sending to the compositor.
    if (m_runState == RunState::RunningOnMainThread) {
      m_animationCurve->updateTarget(
          m_timeFunction() - m_startTime,
          compositorOffsetFromBlinkOffset(targetOffset));
      return true;
    }

    if (registerAndScheduleAnimation())
      m_runState = RunState::RunningOnCompositorButNeedsUpdate;
    return true;
  }

  if ((targetOffset - currentOffset()).isZero())
    return false;

  m_targetOffset = targetOffset;
  m_startTime = m_timeFunction();

  if (registerAndScheduleAnimation())
    m_runState = RunState::WaitingToSendToCompositor;

  return true;
}
Example #4
0
void ProgrammaticScrollAnimator::animateToOffset(const ScrollOffset& offset) {
  if (m_runState == RunState::PostAnimationCleanup)
    resetAnimationState();

  m_startTime = 0.0;
  m_targetOffset = offset;
  m_animationCurve = CompositorScrollOffsetAnimationCurve::create(
      compositorOffsetFromBlinkOffset(m_targetOffset),
      CompositorScrollOffsetAnimationCurve::ScrollDurationDeltaBased);

  m_scrollableArea->registerForAnimation();
  if (!m_scrollableArea->scheduleAnimation()) {
    resetAnimationState();
    notifyOffsetChanged(offset);
  }
  m_runState = RunState::WaitingToSendToCompositor;
}
Example #5
0
void ProgrammaticScrollAnimator::layerForCompositedScrollingDidChange(
    CompositorAnimationTimeline* timeline) {
  reattachCompositorPlayerIfNeeded(timeline);

  // If the composited scrolling layer is lost during a composited animation,
  // continue the animation on the main thread.
  if (m_runState == RunState::RunningOnCompositor &&
      !m_scrollableArea->layerForScrolling()) {
    m_runState = RunState::RunningOnMainThread;
    m_compositorAnimationId = 0;
    m_compositorAnimationGroupId = 0;
    m_animationCurve->setInitialValue(
        compositorOffsetFromBlinkOffset(m_scrollableArea->getScrollOffset()));
    m_scrollableArea->registerForAnimation();
    if (!m_scrollableArea->scheduleAnimation()) {
      resetAnimationState();
      notifyOffsetChanged(m_targetOffset);
    }
  }
}
Example #6
0
void ScrollAnimator::updateCompositorAnimations() {
  ScrollAnimatorCompositorCoordinator::updateCompositorAnimations();

  if (m_runState == RunState::PostAnimationCleanup) {
    postAnimationCleanupAndReset();
    return;
  }

  if (m_runState == RunState::WaitingToCancelOnCompositor) {
    DCHECK(m_compositorAnimationId);
    abortAnimation();
    postAnimationCleanupAndReset();
    return;
  }

  if (m_runState == RunState::RunningOnCompositorButNeedsTakeover) {
    // The call to ::takeOverCompositorAnimation aborted the animation and
    // put us in this state. The assumption is that takeOver is called
    // because a main thread scrolling reason is added, and simply trying
    // to ::sendAnimationToCompositor will fail and we will run on the main
    // thread.
    resetAnimationIds();
    m_runState = RunState::WaitingToSendToCompositor;
  }

  if (m_runState == RunState::RunningOnCompositorButNeedsUpdate ||
      m_runState == RunState::WaitingToCancelOnCompositorButNewScroll ||
      m_runState == RunState::RunningOnCompositorButNeedsAdjustment) {
    // Abort the running animation before a new one with an updated
    // target is added.
    abortAnimation();
    resetAnimationIds();

    if (m_runState != RunState::RunningOnCompositorButNeedsAdjustment) {
      // When in RunningOnCompositorButNeedsAdjustment, the call to
      // ::adjustScrollOffsetAnimation should have made the necessary
      // adjustment to the curve.
      m_animationCurve->updateTarget(
          m_timeFunction() - m_startTime,
          compositorOffsetFromBlinkOffset(m_targetOffset));
    }

    if (m_runState == RunState::WaitingToCancelOnCompositorButNewScroll) {
      m_animationCurve->setInitialValue(
          compositorOffsetFromBlinkOffset(currentOffset()));
    }

    m_runState = RunState::WaitingToSendToCompositor;
  }

  if (m_runState == RunState::WaitingToSendToCompositor) {
    if (!m_compositorAnimationAttachedToElementId)
      reattachCompositorPlayerIfNeeded(
          getScrollableArea()->compositorAnimationTimeline());

    if (!m_animationCurve)
      createAnimationCurve();

    bool runningOnMainThread = false;
    bool sentToCompositor = sendAnimationToCompositor();
    if (!sentToCompositor) {
      runningOnMainThread = registerAndScheduleAnimation();
      if (runningOnMainThread)
        m_runState = RunState::RunningOnMainThread;
    }

    // Main thread should deal with the scroll animations it started.
    if (sentToCompositor || runningOnMainThread)
      addMainThreadScrollingReason();
    else
      removeMainThreadScrollingReason();
  }
}