summaryrefslogtreecommitdiffstats
path: root/gfx/layers/wr/OMTASampler.h
blob: 513c905fa144a80a08cb7e64afaf75646142cc02 (plain)
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
/* -*- 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_OMTASampler_h
#define mozilla_layers_OMTASampler_h

#include <unordered_map>
#include <queue>

#include "base/platform_thread.h"           // for PlatformThreadId
#include "mozilla/layers/OMTAController.h"  // for OMTAController
#include "mozilla/Atomics.h"
#include "mozilla/Maybe.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/webrender/WebRenderTypes.h"  // For WrWindowId, WrEpoch, etc.

namespace mozilla {

class TimeStamp;

namespace wr {
struct Transaction;
class TransactionWrapper;
}  // namespace wr

namespace layers {
class Animation;
class CompositorAnimationStorage;
class OMTAValue;
struct CompositorAnimationIdsForEpoch;
struct LayersId;
struct WrAnimations;

/**
 * This interface exposes OMTA methods related to "sampling" (i.e. calculating
 * animating values) and "". All sampling methods should be called on the
 * sampler thread, all some of them should be called on the compositor thread.
 */
class OMTASampler final {
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OMTASampler)

 public:
  OMTASampler(const RefPtr<CompositorAnimationStorage>& aAnimStorage,
              LayersId aRootLayersId);

  // Whoever creates this sampler is responsible for calling Destroy() on it
  // before releasing the owning refptr.
  void Destroy();

  void SetWebRenderWindowId(const wr::WrWindowId& aWindowId);

  /**
   * This function is invoked from rust on the render backend thread when it
   * is created. It effectively tells the OMTASampler "the current thread is
   * the sampler thread for this window id" and allows OMTASampler to remember
   * which thread it is.
   */
  static void SetSamplerThread(const wr::WrWindowId& aWindowId);

  static void Sample(const wr::WrWindowId& aWindowId, wr::Transaction* aTxn);

  /**
   * Sample all animations, called on the sampler thread.
   */
  void Sample(wr::TransactionWrapper& aTxn);

  /**
   * These funtions get called on the the compositor thread.
   */
  void SetSampleTime(const TimeStamp& aSampleTime);
  void ResetPreviousSampleTime();
  void SetAnimations(uint64_t aId, const LayersId& aLayersId,
                     const nsTArray<layers::Animation>& aAnimations);
  bool HasAnimations() const;

  /**
   * Clear AnimatedValues and Animations data, called on the compositor
   * thread.
   */
  void ClearActiveAnimations(
      std::unordered_map<uint64_t, wr::Epoch>& aActiveAnimations);
  void RemoveEpochDataPriorTo(
      std::queue<CompositorAnimationIdsForEpoch>& aCompositorAnimationsToDelete,
      std::unordered_map<uint64_t, wr::Epoch>& aActiveAnimations,
      const wr::Epoch& aRenderedEpoch);

  // Those two methods are for testing called on the compositor thread.
  OMTAValue GetOMTAValue(const uint64_t& aId) const;
  /**
   * There are two possibilities when this function gets called, either 1) in
   * testing refesh driver mode or 2) in normal refresh driver mode. In the case
   * of 2) |aTestingSampleTime| should be Nothing() so that we can use
   * |mPreviousSampleTime| and |mSampleTime| for sampling animations.
   */
  void SampleForTesting(const Maybe<TimeStamp>& aTestingSampleTime);

  /**
   * Returns true if currently on the "sampler thread".
   */
  bool IsSamplerThread() const;

  void EnterTestMode() { mIsInTestMode = true; }
  void LeaveTestMode() { mIsInTestMode = false; }

 protected:
  ~OMTASampler() = default;

  static already_AddRefed<OMTASampler> GetSampler(
      const wr::WrWindowId& aWindowId);

 private:
  WrAnimations SampleAnimations(const TimeStamp& aPreviousSampleTime,
                                const TimeStamp& aSampleTime);

  RefPtr<OMTAController> mController;
  // Can only be accessed or modified while holding mStorageLock.
  RefPtr<CompositorAnimationStorage> mAnimStorage;
  mutable Mutex mStorageLock MOZ_UNANNOTATED;

  // Used to manage the mapping from a WR window id to OMTASampler. These are
  // only used if WebRender is enabled. Both sWindowIdMap and mWindowId should
  // only be used while holding the sWindowIdLock. Note that we use a
  // StaticAutoPtr wrapper on sWindowIdMap to avoid a static initializer for the
  // unordered_map. This also avoids the initializer/memory allocation in cases
  // where we're not using WebRender.
  static StaticMutex sWindowIdLock MOZ_UNANNOTATED;
  static StaticAutoPtr<std::unordered_map<uint64_t, RefPtr<OMTASampler>>>
      sWindowIdMap;
  Maybe<wr::WrWindowId> mWindowId;

  // Lock used to protected mSamplerThreadId
  mutable Mutex mThreadIdLock MOZ_UNANNOTATED;
  // If WebRender is enabled, this holds the thread id of the render backend
  // thread (which is the sampler thread) for the compositor associated with
  // this OMTASampler instance.
  Maybe<PlatformThreadId> mSamplerThreadId;

  Mutex mSampleTimeLock MOZ_UNANNOTATED;
  // Can only be accessed or modified while holding mSampleTimeLock.
  TimeStamp mSampleTime;
  // Same as |mSampleTime|, can only be accessed or modified while holding
  // mSampleTimeLock.
  // We basically use this time stamp instead of |mSampleTime| to make
  // animations more in sync with other animations on the main thread.
  TimeStamp mPreviousSampleTime;
  Atomic<bool> mIsInTestMode;
};

}  // namespace layers
}  // namespace mozilla

#endif  // mozilla_layers_OMTASampler_h