tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AnimationHelper.h (7398B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_layers_AnimationHelper_h
      8 #define mozilla_layers_AnimationHelper_h
      9 
     10 #include "mozilla/dom/Nullable.h"
     11 #include "mozilla/layers/AnimationStorageData.h"
     12 #include "mozilla/layers/LayersMessages.h"     // for TransformData, etc
     13 #include "mozilla/webrender/WebRenderTypes.h"  // for RenderRoot
     14 #include "mozilla/TimeStamp.h"                 // for TimeStamp
     15 #include "mozilla/TimingParams.h"
     16 #include "X11UndefineNone.h"
     17 
     18 namespace mozilla::layers {
     19 class Animation;
     20 class APZSampler;
     21 class CompositorAnimationStorage;
     22 struct AnimatedValue;
     23 
     24 using AnimationArray = nsTArray<layers::Animation>;
     25 using SampledAnimationArray = AutoTArray<RefPtr<StyleAnimationValue>, 1>;
     26 
     27 /**
     28 * This utility class allows reusing code between the webrender and
     29 * non-webrender compositor-side implementations. It provides
     30 * utility functions for sampling animations at particular timestamps.
     31 */
     32 class AnimationHelper {
     33 public:
     34  struct SampleResult {
     35    enum class Type : uint8_t { None, Skipped, Sampled };
     36    enum class Reason : uint8_t { None, ScrollToDelayPhase };
     37    Type mType = Type::None;
     38    Reason mReason = Reason::None;
     39 
     40    SampleResult() = default;
     41    SampleResult(Type aType, Reason aReason) : mType(aType), mReason(aReason) {}
     42 
     43    static SampleResult Skipped() { return {Type::Skipped, Reason::None}; }
     44    static SampleResult Sampled() { return {Type::Sampled, Reason::None}; }
     45 
     46    bool IsNone() { return mType == Type::None; }
     47    bool IsSkipped() { return mType == Type::Skipped; }
     48    bool IsSampled() { return mType == Type::Sampled; }
     49  };
     50 
     51  /**
     52   * Sample animations based on a given time stamp for a element(layer) with
     53   * its animation data.
     54   * Generally |aPreviousFrameTime| is used for the sampling if it's
     55   * supplied to make the animation more in sync with other animations on the
     56   * main-thread.  But in the case where the animation just started at the time
     57   * when the animation was sent to the compositor, |aCurrentFrameTime| is used
     58   * for sampling instead to avoid flicker.
     59   *
     60   * Returns SampleResult::None if none of the animations are producing a result
     61   * (e.g. they are in the delay phase with no backwards fill),
     62   * SampleResult::Skipped if the animation output did not change since the last
     63   * call of this function,
     64   * SampleResult::Sampled if the animation output was updated.
     65   *
     66   * The only exception is the scroll-driven animation. When the user move the
     67   * scrollbar to make the animations go from active phase to delay phase, this
     68   * returns SampleResult::None but sets its |mReason| to
     69   * Reason::ScrollToDelayPhase. The caller can check this flag so we can store
     70   * the base style into the hash table to make sure we have the correct
     71   * rendering result. The base style stays in the hash table until we sync with
     72   * main thread.
     73   *
     74   * Using the same example from ExtractAnimations (below):
     75   *
     76   * Input |aPropertyAnimationGroups| (ignoring the base animation style):
     77   *
     78   * [
     79   *   Group A: [ { rotate, Animation A }, { rotate, Animation B } ],
     80   *   Group B: [ { scale, Animation B } ],
     81   *   Group C: [ { transform, Animation A }, { transform, Animation B } ],
     82   * ]
     83   *
     84   * For each property group, this function interpolates each animation in turn,
     85   * using the result of interpolating one animation as input for the next such
     86   * that it reduces each property group to a single output value:
     87   *
     88   * [
     89   *   { rotate, StyleAnimationValue },
     90   *   { scale, StyleAnimationValue },
     91   *   { transform, StyleAnimationValue },
     92   * ]
     93   *
     94   * For transform animations, the caller (SampleAnimations) will combine the
     95   * result of the various transform properties into a final matrix.
     96   */
     97  static SampleResult SampleAnimationForEachNode(
     98      const APZSampler* aAPZSampler, const LayersId& aLayersId,
     99      const MutexAutoLock& aProofOfMapLock, TimeStamp aPreviousFrameTime,
    100      TimeStamp aCurrentFrameTime, const AnimatedValue* aPreviousValue,
    101      nsTArray<PropertyAnimationGroup>& aPropertyAnimationGroups,
    102      SampledAnimationArray& aAnimationValues /* output */);
    103 
    104  /**
    105   * Extract organized animation data by property into an array of
    106   * PropertyAnimationGroup objects.
    107   *
    108   * For example, suppose we have the following animations:
    109   *
    110   *   Animation A: [ transform, rotate ]
    111   *   Animation B: [ rotate, scale ]
    112   *   Animation C: [ transform ]
    113   *   Animation D: [ opacity ]
    114   *
    115   * When we go to send transform-like properties to the compositor, we
    116   * sort them as follows:
    117   *
    118   *   [
    119   *     { rotate: Animation A (rotate segments only) },
    120   *     { rotate: Animation B ( " " ) },
    121   *     { scale: Animation B (scale segments only) },
    122   *     { transform: Animation A (transform segments only) },
    123   *     { transform: Animation C ( " " ) },
    124   *   ]
    125   *
    126   * In this function, we group these animations together by property producing
    127   * output such as the following:
    128   *
    129   *   [
    130   *     [ { rotate, Animation A }, { rotate, Animation B } ],
    131   *     [ { scale, Animation B } ],
    132   *     [ { transform, Animation A }, { transform, Animation B } ],
    133   *   ]
    134   *
    135   * In the process of grouping these animations, we also convert their values
    136   * from the rather compact representation we use for transferring across the
    137   * IPC boundary into something we can readily use for sampling.
    138   *
    139   * Note: the animation groups:
    140   * 1. transform-like properties: transfrom, translate, rotate, scale,
    141   *                               offset-*.
    142   * 2. opacity property: opacity.
    143   * 3. background color property: background-color.
    144   */
    145  static AnimationStorageData ExtractAnimations(
    146      const LayersId& aLayersId, const AnimationArray& aAnimations,
    147      const CompositorAnimationStorage* aStorage,
    148      const TimeStamp& aPreviousSampleTime);
    149 
    150  /**
    151   * Get a unique id to represent the compositor animation between child
    152   * and parent side. This id will be used as a key to store animation
    153   * data in the CompositorAnimationStorage per compositor.
    154   * Each layer on the content side calls this when it gets new animation
    155   * data.
    156   */
    157  static uint64_t GetNextCompositorAnimationsId();
    158 
    159  /**
    160   * Convert an array of animation values into a matrix given the corresponding
    161   * transform parameters. |aValue| must be a transform-like value
    162   * (e.g. transform, translate etc.).
    163   */
    164  static gfx::Matrix4x4 ServoAnimationValueToMatrix4x4(
    165      const SampledAnimationArray& aValue, const TransformData& aTransformData,
    166      gfx::Path* aCachedMotionPath);
    167 
    168  /**
    169   * Returns true if |aPrerenderedRect| transformed by |aTransform| were
    170   * composited in |aClipRect| there appears area which wasn't pre-rendered
    171   * on the main-thread. I.e. checkerboarding.
    172   */
    173  static bool ShouldBeJank(const LayoutDeviceRect& aPrerenderedRect,
    174                           SideBits aOverflowedSides,
    175                           const gfx::Matrix4x4& aTransform,
    176                           const ParentLayerRect& aClipRect);
    177 };
    178 
    179 }  // namespace mozilla::layers
    180 
    181 #endif  // mozilla_layers_AnimationHelper_h