bool CompositorAnimations::startAnimationOnCompositor(const Element& element, int group, double startTime, double timeOffset, const Timing& timing, const AnimationPlayer& player, const AnimationEffect& effect, Vector<int>& startedAnimationIds, double playerPlaybackRate) { ASSERT(startedAnimationIds.isEmpty()); ASSERT(isCandidateForAnimationOnCompositor(timing, element, &player, effect, playerPlaybackRate)); ASSERT(canStartAnimationOnCompositor(element)); const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(effect); DeprecatedPaintLayer* layer = toLayoutBoxModelObject(element.layoutObject())->layer(); ASSERT(layer); Vector<OwnPtr<WebCompositorAnimation>> animations; CompositorAnimationsImpl::getAnimationOnCompositor(timing, group, startTime, timeOffset, keyframeEffect, animations, playerPlaybackRate); ASSERT(!animations.isEmpty()); for (auto& animation : animations) { int id = animation->id(); if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) { WebCompositorAnimationPlayer* compositorPlayer = player.compositorPlayer(); ASSERT(compositorPlayer); compositorPlayer->addAnimation(animation.leakPtr()); } else if (!layer->compositedDeprecatedPaintLayerMapping()->mainGraphicsLayer()->addAnimation(animation.release())) { // FIXME: We should know ahead of time whether these animations can be started. for (int startedAnimationId : startedAnimationIds) cancelAnimationOnCompositor(element, player, startedAnimationId); startedAnimationIds.clear(); return false; } startedAnimationIds.append(id); } ASSERT(!startedAnimationIds.isEmpty()); return true; }
bool CompositorAnimations::startAnimationOnCompositor(const Element& element, const Timing& timing, const AnimationEffect& effect, Vector<int>& startedAnimationIds) { ASSERT(startedAnimationIds.isEmpty()); ASSERT(isCandidateForAnimationOnCompositor(timing, effect)); ASSERT(canStartAnimationOnCompositor(element)); const KeyframeEffectModel& keyframeEffect = *toKeyframeEffectModel(&effect); RenderLayer* layer = toRenderBoxModelObject(element.renderer())->layer(); ASSERT(layer); Vector<OwnPtr<blink::WebAnimation> > animations; CompositorAnimationsImpl::getAnimationOnCompositor(timing, keyframeEffect, animations); ASSERT(!animations.isEmpty()); for (size_t i = 0; i < animations.size(); ++i) { int id = animations[i]->id(); if (!layer->compositedLayerMapping()->mainGraphicsLayer()->addAnimation(animations[i].release())) { // FIXME: We should know ahead of time whether these animations can be started. for (size_t j = 0; j < startedAnimationIds.size(); ++j) cancelAnimationOnCompositor(element, startedAnimationIds[j]); startedAnimationIds.clear(); return false; } startedAnimationIds.append(id); } ASSERT(!startedAnimationIds.isEmpty()); return true; }
void AnimationPlayer::preCommit(bool startOnCompositor) { if (m_compositorState && m_compositorState->pendingAction == Start) { // Still waiting for a start time. return; } bool softChange = m_compositorState && (paused() || m_compositorState->playbackRate != m_playbackRate); bool hardChange = m_compositorState && (m_compositorState->sourceChanged || (m_compositorState->startTime != m_startTime && !std::isnan(m_compositorState->startTime) && !std::isnan(m_startTime))); // FIXME: softChange && !hardChange should generate a Pause/ThenStart, // not a Cancel, but we can't communicate these to the compositor yet. bool changed = softChange || hardChange; bool shouldCancel = (!playing() && m_compositorState) || changed; bool shouldStart = playing() && (!m_compositorState || changed); if (shouldCancel) { cancelAnimationOnCompositor(); m_compositorState = nullptr; } if (!shouldStart) { m_currentTimePending = false; } if (shouldStart && startOnCompositor && maybeStartAnimationOnCompositor()) { m_compositorState = adoptPtr(new CompositorState(*this)); } }
void AnimationPlayer::pause() { if (m_paused) return; m_paused = true; updateTimingState(currentTime()); // FIXME: resume compositor animation rather than pull back to main-thread cancelAnimationOnCompositor(); }
void Animation::specifiedTimingChanged() { cancelAnimationOnCompositor(); if (player()) { // FIXME: Needs to consider groups when added. ASSERT(player()->source() == this); player()->schedulePendingAnimationOnCompositor(); } }
void Animation::clearEffects() { ASSERT(player()); ASSERT(m_sampledEffect); m_sampledEffect->clear(); m_sampledEffect = nullptr; cancelAnimationOnCompositor(); m_target->setNeedsAnimationStyleRecalc(); invalidate(); }
void Animation::clearEffects() { ASSERT(player()); ASSERT(m_activeInAnimationStack); ensureAnimationStack(m_target.get()).remove(this); cancelAnimationOnCompositor(); m_activeInAnimationStack = false; m_compositableValues.clear(); m_target->setNeedsAnimationStyleRecalc(); invalidate(); }
void Player::setPausedImpl(bool newValue) { if (pausedInternal() == newValue) return; if (newValue) { // FIXME: resume compositor animation rather than pull back to main-thread cancelAnimationOnCompositor(); m_pauseStartTime = currentTime(); } else { m_timeDrift = pausedTimeDrift(); m_pauseStartTime = nullValue(); } }
bool Animation::preCommit(int compositorGroup, bool startOnCompositor) { PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending); bool softChange = m_compositorState && (paused() || m_compositorState->playbackRate != m_playbackRate); bool hardChange = m_compositorState && (m_compositorState->effectChanged || m_compositorState->startTime != m_startTime); // FIXME: softChange && !hardChange should generate a Pause/ThenStart, // not a Cancel, but we can't communicate these to the compositor yet. bool changed = softChange || hardChange; bool shouldCancel = (!playing() && m_compositorState) || changed; bool shouldStart = playing() && (!m_compositorState || changed); if (startOnCompositor && shouldCancel && shouldStart && m_compositorState && m_compositorState->pendingAction == Start) { // Restarting but still waiting for a start time. return false; } if (shouldCancel) { cancelAnimationOnCompositor(); m_compositorState = nullptr; } ASSERT(!m_compositorState || !std::isnan(m_compositorState->startTime)); if (!shouldStart) { m_currentTimePending = false; } if (shouldStart) { m_compositorGroup = compositorGroup; if (startOnCompositor) { if (isCandidateForAnimationOnCompositor()) createCompositorPlayer(); if (maybeStartAnimationOnCompositor()) m_compositorState = adoptPtr(new CompositorState(*this)); else cancelIncompatibleAnimationsOnCompositor(); } } return true; }
void KeyframeEffectReadOnly::restartAnimationOnCompositor() { if (cancelAnimationOnCompositor()) animation()->setCompositorPending(true); }
void Animation::disableCompositedAnimationForTesting() { m_isCompositedAnimationDisabledForTesting = true; cancelAnimationOnCompositor(); }