APZUpdater.h (10312B)
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_APZUpdater_h 8 #define mozilla_layers_APZUpdater_h 9 10 #include <deque> 11 #include <unordered_map> 12 13 #include "base/platform_thread.h" // for PlatformThreadId 14 #include "LayersTypes.h" 15 #include "mozilla/layers/WebRenderScrollData.h" 16 #include "mozilla/StaticMutex.h" 17 #include "mozilla/StaticPtr.h" 18 #include "mozilla/webrender/WebRenderTypes.h" 19 #include "nsThreadUtils.h" 20 #include "Units.h" 21 22 namespace mozilla { 23 24 namespace layers { 25 26 class APZTestData; 27 class APZCTreeManager; 28 class FocusTarget; 29 class WebRenderScrollData; 30 31 /** 32 * This interface is used to send updates or otherwise mutate APZ internal 33 * state. These functions is usually called from the compositor thread in 34 * response to IPC messages. The method implementations internally redispatch 35 * themselves to the updater thread in the case where the compositor thread 36 * is not the updater thread. 37 */ 38 class APZUpdater { 39 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZUpdater) 40 41 public: 42 APZUpdater(const RefPtr<APZCTreeManager>& aApz, bool aConnectedToWebRender); 43 44 bool HasTreeManager(const RefPtr<APZCTreeManager>& aApz); 45 void SetWebRenderWindowId(const wr::WindowId& aWindowId); 46 47 /** 48 * This function is invoked from rust on the scene builder thread when it 49 * is created. It effectively tells the APZUpdater "the current thread is 50 * the updater thread for this window id" and allows APZUpdater to remember 51 * which thread it is. 52 */ 53 static void SetUpdaterThread(const wr::WrWindowId& aWindowId); 54 static void PrepareForSceneSwap(const wr::WrWindowId& aWindowId); 55 static void CompleteSceneSwap(const wr::WrWindowId& aWindowId, 56 const wr::WrPipelineInfo& aInfo); 57 static void ProcessPendingTasks(const wr::WrWindowId& aWindowId); 58 59 void ClearTree(LayersId aRootLayersId); 60 void UpdateFocusState(LayersId aRootLayerTreeId, 61 LayersId aOriginatingLayersId, 62 const FocusTarget& aFocusTarget); 63 /** 64 * This should be called (in the WR-enabled case) when the compositor receives 65 * a new WebRenderScrollData for a layers id. The |aScrollData| parameter is 66 * the scroll data for |aOriginatingLayersId| and |aEpoch| is the 67 * corresponding epoch for the transaction that transferred the scroll data. 68 * This function will store the new scroll data and update the focus state and 69 * hit-testing tree. 70 */ 71 void UpdateScrollDataAndTreeState(LayersId aRootLayerTreeId, 72 LayersId aOriginatingLayersId, 73 const wr::Epoch& aEpoch, 74 WebRenderScrollData&& aScrollData); 75 /** 76 * This is called in the WR-enabled case when we get an empty transaction that 77 * has some scroll offset updates (from paint-skipped scrolling on the content 78 * side). This function will update the stored scroll offsets and the 79 * hit-testing tree. 80 */ 81 void UpdateScrollOffsets(LayersId aRootLayerTreeId, 82 LayersId aOriginatingLayersId, 83 ScrollUpdatesMap&& aUpdates, 84 uint32_t aPaintSequenceNumber); 85 86 void NotifyLayerTreeAdopted(LayersId aLayersId, 87 const RefPtr<APZUpdater>& aOldUpdater); 88 void NotifyLayerTreeRemoved(LayersId aLayersId); 89 90 bool GetAPZTestData(LayersId aLayersId, APZTestData* aOutData); 91 92 void SetTestAsyncScrollOffset(LayersId aLayersId, 93 const ScrollableLayerGuid::ViewID& aScrollId, 94 const CSSPoint& aOffset); 95 void SetTestAsyncZoom(LayersId aLayersId, 96 const ScrollableLayerGuid::ViewID& aScrollId, 97 const LayerToParentLayerScale& aZoom); 98 99 // This can only be called on the updater thread. 100 const WebRenderScrollData* GetScrollData(LayersId aLayersId) const; 101 102 /** 103 * This can be used to assert that the current thread is the 104 * updater thread (which samples the async transform). 105 * This does nothing if thread assertions are disabled. 106 */ 107 void AssertOnUpdaterThread() const; 108 109 enum class DuringShutdown { 110 No, 111 Yes, 112 }; 113 /** 114 * Runs the given task on the APZ "updater thread" for this APZUpdater. If 115 * this function is called from the updater thread itself then the task is 116 * run immediately without getting queued. 117 * 118 * The layers id argument should be the id of the layer tree that is 119 * requesting this task to be run. Conceptually each layer tree has a separate 120 * task queue, so that if one layer tree is blocked waiting for a scene build 121 * then tasks for the other layer trees can still be processed. 122 * 123 * In the case of where |aDuringShutdown| is `Yes` this function doesn't 124 * invoke `WebRenderAPI::WakeSceneBuilder` explicitly. 125 */ 126 void RunOnUpdaterThread(LayersId aLayersId, already_AddRefed<Runnable> aTask, 127 DuringShutdown aDuringShutdown = DuringShutdown::No); 128 129 /** 130 * Returns true if currently on the APZUpdater's "updater thread". 131 */ 132 bool IsUpdaterThread() const; 133 134 /** 135 * Dispatches the given task to the APZ "controller thread", but does it 136 * *from* the updater thread. That is, if the thread on which this function is 137 * called is not the updater thread, the task is first dispatched to the 138 * updater thread. When the updater thread runs it (or if this is called 139 * directly on the updater thread), that is when the task gets dispatched to 140 * the controller thread. The controller thread then actually runs the task. 141 * 142 * See the RunOnUpdaterThread method for details on the layers id argument. 143 */ 144 void RunOnControllerThread(LayersId aLayersId, 145 already_AddRefed<Runnable> aTask); 146 147 void MarkAsDetached(LayersId aLayersId); 148 149 protected: 150 virtual ~APZUpdater(); 151 152 // Return true if the APZUpdater is connected to WebRender and is 153 // using a WebRender scene builder thread as its updater thread. 154 // This is only false during GTests, and a shutdown codepath during 155 // which we create a dummy APZUpdater. 156 bool IsConnectedToWebRender() const; 157 158 static already_AddRefed<APZUpdater> GetUpdater( 159 const wr::WrWindowId& aWindowId); 160 161 void ProcessQueue(); 162 163 private: 164 RefPtr<APZCTreeManager> mApz; 165 bool mDestroyed; 166 bool mConnectedToWebRender; 167 168 // Map from layers id to WebRenderScrollData. This can only be touched on 169 // the updater thread. 170 std::unordered_map<LayersId, WebRenderScrollData, LayersId::HashFn> 171 mScrollData; 172 173 // Stores epoch state for a particular layers id. This structure is only 174 // accessed on the updater thread. 175 struct EpochState { 176 // The epoch for the most recent scroll data sent from the content side. 177 wr::Epoch mRequired; 178 // The epoch for the most recent scene built and swapped in on the WR side. 179 Maybe<wr::Epoch> mBuilt; 180 // True if and only if the layers id is the root layers id for the 181 // compositor 182 bool mIsRoot; 183 184 EpochState(); 185 186 // Whether or not the state for this layers id is such that it blocks 187 // processing of tasks for the layer tree. This happens if the root layers 188 // id or a "visible" layers id has scroll data for an epoch newer than what 189 // has been built. A "visible" layers id is one that is attached to the full 190 // layer tree (i.e. there is a chain of reflayer items from the root layer 191 // tree to the relevant layer subtree). This is not always the case; for 192 // instance a content process may send the compositor layers for a document 193 // before the chrome has attached the remote iframe to the root document. 194 // Since WR only builds pipelines for "visible" layers ids, |mBuilt| being 195 // populated means that the layers id is "visible". 196 bool IsBlocked() const; 197 }; 198 199 // Map from layers id to epoch state. 200 // This data structure can only be touched on the updater thread. 201 std::unordered_map<LayersId, EpochState, LayersId::HashFn> mEpochData; 202 203 // Used to manage the mapping from a WR window id to APZUpdater. These are 204 // only used if WebRender is enabled. Both sWindowIdMap and mWindowId should 205 // only be used while holding the sWindowIdLock. Note that we use a 206 // StaticAutoPtr wrapper on sWindowIdMap to avoid a static initializer for the 207 // unordered_map. This also avoids the initializer/memory allocation in cases 208 // where we're not using WebRender. 209 static StaticMutex sWindowIdLock MOZ_UNANNOTATED; 210 static StaticAutoPtr<std::unordered_map<uint64_t, APZUpdater*>> sWindowIdMap; 211 Maybe<wr::WrWindowId> mWindowId; 212 213 // Lock used to protected mUpdaterThreadId; 214 mutable Mutex mThreadIdLock MOZ_UNANNOTATED; 215 // If WebRender and async scene building are enabled, this holds the thread id 216 // of the scene builder thread (which is the updater thread) for the 217 // compositor associated with this APZUpdater instance. It may be populated 218 // even if async scene building is not enabled, but in that case we don't 219 // care about the contents. 220 Maybe<PlatformThreadId> mUpdaterThreadId; 221 222 // Helper struct that pairs each queued runnable with the layers id that it is 223 // associated with. This allows us to easily implement the conceptual 224 // separation of mUpdaterQueue into independent queues per layers id. 225 struct QueuedTask { 226 LayersId mLayersId; 227 RefPtr<Runnable> mRunnable; 228 }; 229 230 // Lock used to protect mUpdaterQueue 231 Mutex mQueueLock MOZ_UNANNOTATED; 232 // Holds a queue of tasks to be run on the updater thread, when the updater 233 // thread is a WebRender thread, since it won't have a message loop we can 234 // dispatch to. Note that although this is a single queue it is conceptually 235 // separated into multiple ones, one per layers id. Tasks for a given layers 236 // id will always run in FIFO order, but there is no guaranteed ordering for 237 // tasks with different layers ids. 238 std::deque<QueuedTask> mUpdaterQueue; 239 }; 240 241 } // namespace layers 242 } // namespace mozilla 243 244 #endif // mozilla_layers_APZUpdater_h