DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_layers_AnimationHelper_h
#define mozilla_layers_AnimationHelper_h

#include "mozilla/ComputedTimingFunction.h"  // for ComputedTimingFunction
#include "mozilla/layers/LayersMessages.h"   // for TransformData, etc
#include "mozilla/TimeStamp.h"               // for TimeStamp

namespace mozilla {
struct AnimationValue;
namespace layers {
class Animation;

typedef InfallibleTArray<layers::Animation> AnimationArray;

struct AnimData {
  InfallibleTArray<mozilla::AnimationValue> mStartValues;
  InfallibleTArray<mozilla::AnimationValue> mEndValues;
  InfallibleTArray<Maybe<mozilla::ComputedTimingFunction>> mFunctions;
};

struct AnimationTransform {
  /*
   * This transform is calculated from sampleanimation in device pixel
   * and used by compositor.
   */
  gfx::Matrix4x4 mTransformInDevSpace;
  /*
   * This transform is calculated from frame and used by getOMTAStyle()
   * for OMTA testing.
   */
  gfx::Matrix4x4 mFrameTransform;
  TransformData mData;
};

struct AnimatedValue {
  enum { TRANSFORM, OPACITY, NONE } mType{NONE};

  union {
    AnimationTransform mTransform;
    float mOpacity;
  };

  AnimatedValue(gfx::Matrix4x4&& aTransformInDevSpace,
                gfx::Matrix4x4&& aFrameTransform, const TransformData& aData)
      : mType(AnimatedValue::TRANSFORM) {
    mTransform.mTransformInDevSpace = Move(aTransformInDevSpace);
    mTransform.mFrameTransform = Move(aFrameTransform);
    mTransform.mData = aData;
  }

  explicit AnimatedValue(const float& aValue)
      : mType(AnimatedValue::OPACITY), mOpacity(aValue) {}

  ~AnimatedValue() {}

 private:
  AnimatedValue() = delete;
};

// CompositorAnimationStorage stores the animations and animated values
// keyed by a CompositorAnimationsId. The "animations" are a representation of
// an entire animation over time, while the "animated values" are values sampled
// from the animations at a particular point in time.
//
// There is one CompositorAnimationStorage per CompositorBridgeParent (i.e.
// one per browser window), and the CompositorAnimationsId key is unique within
// a particular CompositorAnimationStorage instance.
//
// Each layer which has animations gets a CompositorAnimationsId key, and reuses
// that key during its lifetime. Likewise, in layers-free webrender, a display
// item that is animated (e.g. nsDisplayTransform) gets a CompositorAnimationsId
// key and reuses that key (it persists the key via the frame user-data
// mechanism).
class CompositorAnimationStorage final {
  typedef nsClassHashtable<nsUint64HashKey, AnimatedValue> AnimatedValueTable;
  typedef nsClassHashtable<nsUint64HashKey, AnimationArray> AnimationsTable;

  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorAnimationStorage)
 public:
  /**
   * Set the animation transform based on the unique id and also
   * set up |aFrameTransform| and |aData| for OMTA testing
   */
  void SetAnimatedValue(uint64_t aId, gfx::Matrix4x4&& aTransformInDevSpace,
                        gfx::Matrix4x4&& aFrameTransform,
                        const TransformData& aData);

  /**
   * Set the animation transform in device pixel based on the unique id
   */
  void SetAnimatedValue(uint64_t aId, gfx::Matrix4x4&& aTransformInDevSpace);

  /**
   * Set the animation opacity based on the unique id
   */
  void SetAnimatedValue(uint64_t aId, const float& aOpacity);

  /**
   * Return the animated value if a given id can map to its animated value
   */
  AnimatedValue* GetAnimatedValue(const uint64_t& aId) const;

  /**
   * Like GetAnimatedValue(), but ensures the value is an opacity and returns
   * the float value if possible, or Nothing() otherwise.
   */
  Maybe<float> GetAnimationOpacity(const uint64_t& aId) const;

  /**
   * Like GetAnimatedValue(), but ensures the value is a transform and returns
   * the transform matrix if possible, or Nothing() otherwise. It also does
   * some post-processing on the transform matrix as well. See the comments
   * inside the function for details.
   */
  Maybe<gfx::Matrix4x4> GetAnimationTransform(const uint64_t& aId) const;

  /**
   * Return the iterator of animated value table
   */
  AnimatedValueTable::Iterator ConstAnimatedValueTableIter() const {
    return mAnimatedValues.ConstIter();
  }

  uint32_t AnimatedValueCount() const { return mAnimatedValues.Count(); }

  /**
   * Set the animations based on the unique id
   */
  void SetAnimations(uint64_t aId, const AnimationArray& aAnimations);

  /**
   * Return the animations if a given id can map to its animations
   */
  AnimationArray* GetAnimations(const uint64_t& aId) const;

  /**
   * Return the iterator of animations table
   */
  AnimationsTable::Iterator ConstAnimationsTableIter() const {
    return mAnimations.ConstIter();
  }

  uint32_t AnimationsCount() const { return mAnimations.Count(); }

  /**
   * Clear AnimatedValues and Animations data
   */
  void Clear();
  void ClearById(const uint64_t& aId);

 private:
  ~CompositorAnimationStorage(){};

 private:
  AnimatedValueTable mAnimatedValues;
  AnimationsTable mAnimations;
};

/**
 * This utility class allows reusing code between the webrender and
 * non-webrender compositor-side implementations. It provides
 * utility functions for sampling animations at particular timestamps.
 */
class AnimationHelper {
 public:
  /**
   * Sample animations based on a given time stamp for a element(layer) with
   * its animation data.
   * Returns true if there exists compositor animation, and stores corresponding
   * animated value in |aAnimationValue|.
   */
  static bool SampleAnimationForEachNode(
      TimeStamp aTime, AnimationArray& aAnimations,
      InfallibleTArray<AnimData>& aAnimationData,
      AnimationValue& aAnimationValue, bool& aHasInEffectAnimations);
  /**
   * Populates AnimData stuctures into |aAnimData| and |aBaseAnimationStyle|
   * based on |aAnimations|.
   */
  static void SetAnimations(AnimationArray& aAnimations,
                            InfallibleTArray<AnimData>& aAnimData,
                            AnimationValue& aBaseAnimationStyle);

  /**
   * Get a unique id to represent the compositor animation between child
   * and parent side. This id will be used as a key to store animation
   * data in the CompositorAnimationStorage per compositor.
   * Each layer on the content side calls this when it gets new animation
   * data.
   */
  static uint64_t GetNextCompositorAnimationsId();

  /**
   * Sample animation based a given time stamp |aTime| and the animation
   * data inside CompositorAnimationStorage |aStorage|. The animated values
   * after sampling will be stored in CompositorAnimationStorage as well.
   */
  static void SampleAnimations(CompositorAnimationStorage* aStorage,
                               TimeStamp aTime);
};

}  // namespace layers
}  // namespace mozilla

#endif  // mozilla_layers_AnimationHelper_h