OMTASampler.h (5617B)
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_OMTASampler_h 8 #define mozilla_layers_OMTASampler_h 9 10 #include <unordered_map> 11 #include <queue> 12 13 #include "base/platform_thread.h" // for PlatformThreadId 14 #include "mozilla/layers/OMTAController.h" // for OMTAController 15 #include "mozilla/Atomics.h" 16 #include "mozilla/Maybe.h" 17 #include "mozilla/StaticMutex.h" 18 #include "mozilla/StaticPtr.h" 19 #include "mozilla/webrender/WebRenderTypes.h" // For WrWindowId, WrEpoch, etc. 20 21 namespace mozilla { 22 23 class TimeStamp; 24 25 namespace wr { 26 struct Transaction; 27 class TransactionWrapper; 28 } // namespace wr 29 30 namespace layers { 31 class Animation; 32 class CompositorAnimationStorage; 33 class OMTAValue; 34 struct CompositorAnimationIdsForEpoch; 35 struct LayersId; 36 struct WrAnimations; 37 38 /** 39 * This interface exposes OMTA methods related to "sampling" (i.e. calculating 40 * animating values) and "". All sampling methods should be called on the 41 * sampler thread, all some of them should be called on the compositor thread. 42 */ 43 class OMTASampler final { 44 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OMTASampler) 45 46 public: 47 OMTASampler(const RefPtr<CompositorAnimationStorage>& aAnimStorage, 48 LayersId aRootLayersId); 49 50 // Whoever creates this sampler is responsible for calling Destroy() on it 51 // before releasing the owning refptr. 52 void Destroy(); 53 54 void SetWebRenderWindowId(const wr::WrWindowId& aWindowId); 55 56 /** 57 * This function is invoked from rust on the render backend thread when it 58 * is created. It effectively tells the OMTASampler "the current thread is 59 * the sampler thread for this window id" and allows OMTASampler to remember 60 * which thread it is. 61 */ 62 static void SetSamplerThread(const wr::WrWindowId& aWindowId); 63 64 static void Sample(const wr::WrWindowId& aWindowId, wr::Transaction* aTxn); 65 66 /** 67 * Sample all animations, called on the sampler thread. 68 */ 69 void Sample(wr::TransactionWrapper& aTxn); 70 71 /** 72 * These funtions get called on the the compositor thread. 73 */ 74 void SetSampleTime(const TimeStamp& aSampleTime); 75 void ResetPreviousSampleTime(); 76 void SetAnimations(uint64_t aId, const LayersId& aLayersId, 77 const nsTArray<layers::Animation>& aAnimations); 78 bool HasAnimations() const; 79 80 /** 81 * Clear AnimatedValues and Animations data, called on the compositor 82 * thread. 83 */ 84 void ClearActiveAnimations( 85 std::unordered_map<uint64_t, wr::Epoch>& aActiveAnimations); 86 void RemoveEpochDataPriorTo( 87 std::queue<CompositorAnimationIdsForEpoch>& aCompositorAnimationsToDelete, 88 std::unordered_map<uint64_t, wr::Epoch>& aActiveAnimations, 89 const wr::Epoch& aRenderedEpoch); 90 91 // Those two methods are for testing called on the compositor thread. 92 OMTAValue GetOMTAValue(const uint64_t& aId) const; 93 /** 94 * There are two possibilities when this function gets called, either 1) in 95 * testing refesh driver mode or 2) in normal refresh driver mode. In the case 96 * of 2) |aTestingSampleTime| should be Nothing() so that we can use 97 * |mPreviousSampleTime| and |mSampleTime| for sampling animations. 98 */ 99 void SampleForTesting(const Maybe<TimeStamp>& aTestingSampleTime); 100 101 /** 102 * Returns true if currently on the "sampler thread". 103 */ 104 bool IsSamplerThread() const; 105 106 void EnterTestMode() { mIsInTestMode = true; } 107 void LeaveTestMode() { mIsInTestMode = false; } 108 109 protected: 110 ~OMTASampler() = default; 111 112 static already_AddRefed<OMTASampler> GetSampler( 113 const wr::WrWindowId& aWindowId); 114 115 private: 116 WrAnimations SampleAnimations(const TimeStamp& aPreviousSampleTime, 117 const TimeStamp& aSampleTime); 118 119 RefPtr<OMTAController> mController; 120 // Can only be accessed or modified while holding mStorageLock. 121 RefPtr<CompositorAnimationStorage> mAnimStorage; 122 mutable Mutex mStorageLock MOZ_UNANNOTATED; 123 124 // Used to manage the mapping from a WR window id to OMTASampler. These are 125 // only used if WebRender is enabled. Both sWindowIdMap and mWindowId should 126 // only be used while holding the sWindowIdLock. Note that we use a 127 // StaticAutoPtr wrapper on sWindowIdMap to avoid a static initializer for the 128 // unordered_map. This also avoids the initializer/memory allocation in cases 129 // where we're not using WebRender. 130 static StaticMutex sWindowIdLock MOZ_UNANNOTATED; 131 static StaticAutoPtr<std::unordered_map<uint64_t, RefPtr<OMTASampler>>> 132 sWindowIdMap; 133 Maybe<wr::WrWindowId> mWindowId; 134 135 // Lock used to protected mSamplerThreadId 136 mutable Mutex mThreadIdLock MOZ_UNANNOTATED; 137 // If WebRender is enabled, this holds the thread id of the render backend 138 // thread (which is the sampler thread) for the compositor associated with 139 // this OMTASampler instance. 140 Maybe<PlatformThreadId> mSamplerThreadId; 141 142 Mutex mSampleTimeLock MOZ_UNANNOTATED; 143 // Can only be accessed or modified while holding mSampleTimeLock. 144 TimeStamp mSampleTime; 145 // Same as |mSampleTime|, can only be accessed or modified while holding 146 // mSampleTimeLock. 147 // We basically use this time stamp instead of |mSampleTime| to make 148 // animations more in sync with other animations on the main thread. 149 TimeStamp mPreviousSampleTime; 150 Atomic<bool> mIsInTestMode; 151 }; 152 153 } // namespace layers 154 } // namespace mozilla 155 156 #endif // mozilla_layers_OMTASampler_h