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; }
bool KeyframeEffect::maybeStartAnimationOnCompositor(int group, double startTime, double currentTime, double animationPlaybackRate) { ASSERT(!hasActiveAnimationsOnCompositor()); if (!isCandidateForAnimationOnCompositor(animationPlaybackRate)) return false; if (!CompositorAnimations::instance()->canStartAnimationOnCompositor(*m_target)) return false; if (!CompositorAnimations::instance()->startAnimationOnCompositor(*m_target, group, startTime, currentTime, specifiedTiming(), *animation(), *model(), m_compositorAnimationIds, animationPlaybackRate)) return false; ASSERT(!m_compositorAnimationIds.isEmpty()); return true; }
bool Animation::maybeStartAnimationOnCompositor(double startTime, double currentTime) { ASSERT(!hasActiveAnimationsOnCompositor()); if (!isCandidateForAnimationOnCompositor()) return false; if (!CompositorAnimations::instance()->canStartAnimationOnCompositor(*m_target)) return false; if (!CompositorAnimations::instance()->startAnimationOnCompositor(*m_target, startTime, currentTime, specifiedTiming(), *effect(), m_compositorAnimationIds)) return false; ASSERT(!m_compositorAnimationIds.isEmpty()); return true; }
bool Animation::maybeStartAnimationOnCompositor() { ASSERT(!hasActiveAnimationsOnCompositor()); if (!isCandidateForAnimationOnCompositor()) return false; if (!CompositorAnimations::instance()->canStartAnimationOnCompositor(*m_target.get())) return false; if (!CompositorAnimations::instance()->startAnimationOnCompositor(*m_target.get(), specified(), *effect(), m_compositorAnimationIds)) return false; ASSERT(!m_compositorAnimationIds.isEmpty()); return true; }
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; }