tor-browser

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

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