zoukankan      html  css  js  c++  java
  • cc/animation

    cc/animation

    Overview

    cc/animation provides animation support - generating output values (usually
    visual properties) based on a predefined function and changing input values.
    Currently the main clients of cc/animation are Blink and ui/, targeting
    composited layers, but the code is intended to be agnostic of the client it is
    supporting. Aspirationally we could eventually merge cc/animation and Blink
    animation and have only a single animation system for all of Chromium.

    This document covers two main topics. The first section explains how
    cc/animation actually works: how animations are ticked, what animation curves
    are, what the ownership model is, etc. Later sections document how other parts
    of Chromium interact with cc/animation, most prominently Blink and ui/.

    cc/animation terminology

    Animation
    A cc::Animation is responsible for managing animating properties for a set of
    targets. Each target is represented by a [KeyframeEffect][] and can be animating
    multiple properties on that target; see KeyframeEffect below.

    A particular Animation may not own all the KeyframeEffects for a given
    target. Animation is only a grouping mechanism for related effects, and the
    grouping relationship is defined by the client. It is also the client's
    responsibility to deal with any conflicts that arise from animating the same
    property of the same target across multiple Animations.

    Each Animation has a copy on the impl thread, and will take care of
    synchronizing to/from the impl thread when requested.

    There is a 1:1 relationship between Animation and KeyframeEffect.

    Keyframe model
    KeyframeModels contain the state necessary to 'play' (interpolate values from) an

    animation curve,
    which is a function that returns a value given an input time. Aside from the
    animation curve itself, a keyframe model's state includes the run state (playing,
    paused, etc), the start time, the current direction (forwards, reverse), etc.
    An animation does not know or care what property is being animated, and holds
    only an opaque identifier for the property to allow clients to map output values
    to the correct properties.

    [Keyframe effect][]
    A KeyframeEffect owns a group of KeyframeModels for a single target (identified
    by [PropertyToElementIdMap][]). It is responsible for managing the KeyframeModels'
    running states (starting, running, paused, etc), as well as ticking the
    KeyframeModels when it is requested to produce new outputs for a given time.

    Note that a single KeyframeEffect may not own all the KeyframeModels for a
    given target. KeyframeEffect is only a grouping mechanism for related
    KeyframeModels. The commonality between keyframe models on the same target is
    found via ElementAnimations - there is only one ElementAnimations for a given
    target.

    Group:
    KeyframeModels that must be run together are called 'grouped' and have the same
    group id. Grouped KeyframeModels are guaranteed to start at the same time and no
    other KeyframeModels may animate any of the group's target properties until all
    KeyframeModels in the group have finished animating. It's also guaranteed that
    no two keyframe models within a keyframe effect that have both the same group id
    and property id.

    In general, KeyframeModels are grouped together based on their
    animation target
    (the entity whose property is being animated) and each such group is owned by an
    animation.
    Note that there may be multiple animations with the same target (each
    with a set of KeyframeModels for that target); the
    ElementAnimations
    class wraps the multiple animations and has a 1:1 relationship with
    target entities.

    TODO(smcgruer): Why are ElementAnimations and Animations separate?

    In order to play an animation, input time values must be provided to the
    animation curve and output values fed back into the animating entity. This is
    called 'ticking' an animation and is the responsibility of the
    animation host.
    The animation host has a list of currently ticking animations (i.e. those that have
    any non-deleted animations), which it iterates through whenever it receives a
    tick call from the client (along with a corresponding input time). The
    animations then call into their non-deleted animations, retrieving the
    value from the animation curve. As they are computed, output values are sent to
    the target which is responsible for passing them to the client entity that is
    being animated.

    Types of Animation Curve

    As noted above, an animation curve is simply a function which converts an input
    time value into some output value. Animation curves are categorized based on
    their output type, and each such category can have multiple implementations that
    provide different conversion functions. There are many categories of animation
    curve, but some common ones are FloatAnimationCurve, ColorAnimationCurve,
    and TransformAnimationCurve.

    The most common implementation of the various animation curve categories are the
    keyframed animation curves.
    These curves each have a set of keyframes which map a specific time to a
    specific output value. Producing an output value for a given input time is then
    a matter of identifying the two keyframes the time lies between, and
    interpolating between the keyframe output values. (Or simply using a keyframe
    output value directly, if the input time happens to line up exactly.) Exact
    details of how each animation curve category is interpolated can be found in the
    implementations.

    There is one category of animation curve that stands somewhat apart, the
    scroll offset animation curve.
    This curve converts the input time into a scroll offset, interpolating between
    an initial scroll offset and an updateable target scroll offset. It has logic to
    handle different types of scrolling such as programmatic, keyboard, and mouse
    wheel scrolls.

    Animation Timelines

    cc/animation has a concept of an
    animation timeline.
    This should not be confused with the identically named Blink concept. In
    cc/animation, animation timelines are an implementation detail - they hold the
    animations and are responsible for syncing them to the impl thread (see
    below), but do not participate in the ticking process in any way.

    Main/Impl Threads

    One part of cc/animation that is not client agnostic is its support for the
    Chromium compositor thread.
    Most of the cc/animation classes have a PushPropertiesTo method, in which they
    synchronize necessary state from the main thread to the impl thread. It is
    feasible that such support could be abstracted if necessary, but so far it has
    not been required.

    Current cc/animation Clients

    As noted above, the main clients of cc/animation are currently Blink for
    accelerated web animations, and ui/ for accelerated user interface animations.
    Both of these clients utilize
    cc::Layer
    as their animation entity and interact with cc/animation via the
    MutatorHostClient
    interface (which is implemented by cc::LayerTreeHost and cc::LayerTreeHostImpl).
    Recently a third client, chrome/browser/vr/, has started using cc/animations as
    well. The vr/ client does not use cc::Layer as its animation entity.

    TODO(smcgruer): Summarize how vr/ uses cc/animation.

    Supported Animatable Properties

    As cc::Layers are just textures which are reused for performance, clients that
    use composited layers as their animation entities are limited to animating
    properties that do not cause content to be redrawn. For example, a composited
    layer's opacity can be animated as promoted layers are aware of the content
    behind them. On the other hand we cannot animate layer width as changing the
    width could modify layout - which then requires redrawing.

    Blink is able to move compatible animations off the main thread by promoting
    the animating element into a layer. The Blink
    Lifetime of a compositor animation
    document describes how composited animations are created in blink. Once a
    compositor animation is created it is pushed through the commit cycle.

    new animation

    The lifetime of a newly started cc::Animation is roughly the following:

    1. An update to style or a new animation triggers a new BeginMainFrame via
      ScheduleVisualUpdate.
    2. blink::DocumentAnimations::UpdateAnimations calls [blink::Animation::PreCommit][]
      on each pending blink::Animation constructing the corresponding
      cc::Animation via [blink::Animation::CreateCompositorAnimation][] (attaching
      the animation to the cc::AnimationTimeline resulting in it being later pushed).
      The KeyframeEffects are constructed via [blink::Animation::StartAnimationOnCompositor][].
    3. [AnimationHost::RegisterKeyframeEffectForElement][] creates a
      cc::ElementAnimations for the target element_id if one does not already
      exist. This ElementAnimations instance is shared by all animations with
      the same target and tracks the existence of the target.
    4. During the commit, [cc::ElementAnimations::ElementRegistered][] is called on the
      main thread's AnimationHost either:
      • Before BlinkGenPropertyTrees, when a layer with the target element_id is
        registered.
      • After BlinkGenPropertyTrees, after a property tree node with the target
        element_id is created on the main thread LayerTreeHost's property_trees_.
        This begins ticking the attached KeyframeEffects and tracks that the element
        exists in the active layer / property tree.
    5. [cc::LayerTreeHost::FinishCommitOnImplThread][] calls
      [cc::AnimationHost::PushPropertiesTo][] which results in
      [cc::AnimationTimeline::PushAttachedAnimationsToImplThread][] creating a
      cc::Animation on the compositor thread's AnimationTimeline for each animation
      missing from the compositor thread.
    6. [cc::Animation::PushPropertiesTo][] is called on every animation on the timeline.
      When the element_id is pushed by [cc::KeyframeEffect::PushPropertiesTo][]
      [cc::Animation::AttachElementForKeyframeEffect][] creates a compositor side
      cc::ElementAnimations instance to track the existence of the element on the
      compositor. Since animations are pushed after the layer and property trees,
      the element should already exist on the pending tree. This will result in the
      animation being added to the ticking animations list.
    7. Now the animation is ticking, meaning that [cc::Animation::Tick][] will be called
      every frame and update the pending property tree nodes.
    8. When the pending tree is activated,
      [cc::AnimationHost::ActivateAnimations][] updates the keyframe effects and
      [cc::ElementAnimations::ElementRegistered][]
      is called for the newly added element id on the active tree, setting
      has_element_in_active_list_.
    9. Subsequent animation ticks will now update the property nodes on the active
      tree.

    [blink::Animation::PreCommit]: https://cs.chromium.org/search?q=function:blink::PendingAnimations::Update+->PreCommit%5C(&g=0&l=57
    [blink::Animation::CreateCompositorAnimation]: https://cs.chromium.org/search?q=function:blink::Animation::CreateCompositorAnimation+^[+]*AttachCompositorTimeline
    [blink::Animation::StartAnimationOnCompositor]: https://cs.chromium.org/search?q=function:blink::Animation::StartAnimationOnCompositor+->StartAnimationOnCompositor
    [AnimationHost::RegisterKeyframeEffectForElement]: https://cs.chromium.org/search?q=function:cc::AnimationHost::RegisterKeyframeEffectForElement+ElementAnimations::Create
    [cc::ElementAnimations::ElementRegistered]: https://cs.chromium.org/search?q=function:cc::ElementAnimations::ElementRegistered+!has_element_in_any_list
    [cc::LayerTreeHost::FinishCommitOnImplThread]: https://cs.chromium.org/search?q=cc::LayerTreeHost::FinishCommitOnImplThread+file:.cc
    [cc::AnimationHost::PushPropertiesTo]: https://cs.chromium.org/search/?q=function:cc::LayerTreeHost::FinishCommitOnImplThread+->PushPropertiesTo
    [cc::AnimationTimeline::PushAttachedAnimationsToImplThread]: https://cs.chromium.org/search?q=function:cc::AnimationTimeline::PushAttachedAnimationsToImplThread+animation->CreateImplInstance
    [cc::Animation::PushPropertiesTo]: https://cs.chromium.org/search?q=cc::Animation::PushPropertiesTo+file:.cc
    [cc::KeyframeEffect::PushPropertiesTo]: https://cs.chromium.org/search?q=cc::KeyframeEffect::PushPropertiesTo+file:.cc
    [cc::Animation::AttachElementForKeyframeEffect]: https://cs.chromium.org/search?q=cc::Animation::AttachElementForKeyframeEffect+file:.cc
    [cc::Animation::Tick]: https://cs.chromium.org/search?q=cc::Animation::Tick+file:.cc
    [cc::AnimationHost::ActivateAnimations]: https://cs.chromium.org/search?q=cc::AnimationHost::ActivateAnimations+ActivateKeyframeEffects
    [cc::ElementAnimations::ElementRegistered]: https://cs.chromium.org/search?q=cc::ElementAnimations::ElementRegistered+file:.cc
    [KeyframeEffect]: https://cs.chromium.org/chromium/src/cc/animation/keyframe_effect.h
    [PropertyToElementIdMap]: https://cs.chromium.org/chromium/src/cc/trees/target_property.h?type=cs&g=0&l=42

    Animation Events

    The purpose of animation events (cc::AnimationEvent, not to confuse with
    blink::AnimationEvent) is to synchronize animation state from cc::animation
    to its client. The typical life cycle of the events is:

    1. Event Generation.
      Events are generated on IMPL thread and collected into cc::AnimationEvents
      container. cc::AnimationEvents are passed to the MAIN thread as part of
      BeginMainFrame arguments.
    2. Event Dispatch.
      On the MAIN thread events are dispatched to cc::KeyframeModels to ensure
      they are synchronized to their counterparts on the IMPL side. TIME_UPDATED
      events skip this step since cc::KeyframeModels of worklet animations
      don't participate in generating and reacting to these events.
    3. Event Delegation.
      After the events are dispatched, they are delegated to
      cc::AnimationDelegate, the final destination of the events on cc:animation's
      client.

    There is a special type of events called impl_only events. They are generated by
    animations that are running on IMPL thread only. These events are not passed to
    the MAIN thread and skip dispatch stage. They are delegated to the
    cc::AnimationDelegate on the IMPL thread.

    TODO(flackr): Document finishing / cancel / abort.

    Interaction between cc/animation and ui/

    TODO(smcgruer): Write this.

    Additional References

    The Compositor Property Trees talk slides
    includes discussion on compositor animations.

    The Project Heaviside design document
    and slides provide history on the Chromium
    and Blink animation system. The slides in particular include helpful
    software architecture diagrams.

    Smooth scrolling is implemented via animations. See also references to
    "scroll offset" animations in the cc code
    base. Smooth Scrolling in Chromium provides
    an overview of smooth scrolling. There is further class header
    documentation in
    Blink's
    platform/scroll
    directory.

  • 相关阅读:
    《SQL Server 2008从入门到精通》--20180628
    2019国赛
    [蓝桥杯2020] 湖北省省赛
    2019第十届蓝桥杯B组决赛题解第五题
    试题 算法提高 分解质因数
    大数相加减
    试题 算法提高 汉诺塔
    试题 算法提高 欧拉函数
    试题 算法提高 天天向上-dp
    算法训练 猴子吃包子-构造
  • 原文地址:https://www.cnblogs.com/bigben0123/p/15061724.html
Copyright © 2011-2022 走看看