tor-browser

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

WindowRenderer.h (10645B)


      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_PAINTING_WINDOWRENDERER_H
      8 #define MOZILLA_PAINTING_WINDOWRENDERER_H
      9 
     10 #include "gfxContext.h"
     11 #include "mozilla/ScrollPositionUpdate.h"  // for ScrollPositionUpdate
     12 #include "mozilla/dom/Animation.h"         // for Animation
     13 #include "mozilla/gfx/GPUProcessListener.h"
     14 #include "mozilla/layers/LayersTypes.h"
     15 #include "mozilla/layers/ScrollableLayerGuid.h"  // for ScrollableLayerGuid, ScrollableLayerGuid::ViewID
     16 #include "mozilla/webrender/webrender_ffi.h"
     17 #include "nsRefPtrHashtable.h"  // for nsRefPtrHashtable
     18 
     19 namespace mozilla {
     20 namespace layers {
     21 class LayerManager;
     22 class WebRenderLayerManager;
     23 class KnowsCompositor;
     24 class CompositorBridgeChild;
     25 class FrameUniformityData;
     26 class PersistentBufferProvider;
     27 }  // namespace layers
     28 class FallbackRenderer;
     29 class nsDisplayListBuilder;
     30 class nsDisplayList;
     31 
     32 class FrameRecorder {
     33 public:
     34  /**
     35   * Record (and return) frame-intervals and paint-times for frames which were
     36   * presented between calling StartFrameTimeRecording and
     37   * StopFrameTimeRecording.
     38   *
     39   * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is
     40   *   called too late
     41   *     (elements were overwritten since Start), result is considered invalid
     42   *      and hence empty.)
     43   * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were
     44   *   less frequent).
     45   *     Can be changed (up to 1 hour) via pref:
     46   *     toolkit.framesRecording.bufferSize.
     47   * - Note: the first frame-interval may be longer than expected because last
     48   *   frame
     49   *     might have been presented some time before calling
     50   *     StartFrameTimeRecording.
     51   */
     52 
     53  /**
     54   * Returns a handle which represents current recording start position.
     55   */
     56  virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize);
     57 
     58  /**
     59   *  Clears, then populates aFrameIntervals with the recorded frame timing
     60   *  data. The array will be empty if data was overwritten since
     61   *  aStartIndex was obtained.
     62   */
     63  virtual void StopFrameTimeRecording(uint32_t aStartIndex,
     64                                      nsTArray<float>& aFrameIntervals);
     65 
     66  void RecordFrame();
     67 
     68 private:
     69  struct FramesTimingRecording {
     70    // Stores state and data for frame intervals and paint times recording.
     71    // see LayerManager::StartFrameTimeRecording() at Layers.cpp for more
     72    // details.
     73    FramesTimingRecording()
     74        : mNextIndex(0),
     75          mLatestStartIndex(0),
     76          mCurrentRunStartIndex(0),
     77          mIsPaused(true) {}
     78    nsTArray<float> mIntervals;
     79    TimeStamp mLastFrameTime;
     80    uint32_t mNextIndex;
     81    uint32_t mLatestStartIndex;
     82    uint32_t mCurrentRunStartIndex;
     83    bool mIsPaused;
     84  };
     85  FramesTimingRecording mRecording;
     86 };
     87 
     88 /**
     89 * WindowRenderer is the retained rendering object owned by an nsIWidget for
     90 * drawing the contents of that window, the role previously handled by
     91 * LayerManager.
     92 *
     93 * It can be WebRender, (deprecated) Layers, or an immediate-mode
     94 * FallbackRenderer.
     95 *
     96 * The intention is for LayerManager to be removed entirely in the near future,
     97 * with WebRender inheriting directly from this class. It is likely that more
     98 * cleanup can be done once that happens.
     99 */
    100 class WindowRenderer : public FrameRecorder {
    101  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
    102 
    103 public:
    104  // Cast to implementation types.
    105  virtual layers::WebRenderLayerManager* AsWebRender() { return nullptr; }
    106  virtual FallbackRenderer* AsFallback() { return nullptr; }
    107 
    108  // Required functionality
    109 
    110  /**
    111   * Start a new transaction. Nested transactions are not allowed so
    112   * there must be no transaction currently in progress.
    113   * This transaction will update the state of the window from which
    114   * this LayerManager was obtained.
    115   */
    116  virtual bool BeginTransaction(const nsCString& aURL = nsCString()) = 0;
    117 
    118  enum EndTransactionFlags {
    119    END_DEFAULT = 0,
    120    END_NO_IMMEDIATE_REDRAW = 1 << 0,  // Do not perform the drawing phase
    121    END_NO_COMPOSITE =
    122        1 << 1,  // Do not composite after drawing painted layer contents.
    123    END_NO_REMOTE_COMPOSITE = 1 << 2  // Do not schedule a composition with a
    124                                      // remote Compositor, if one exists.
    125  };
    126 
    127  /**
    128   * Attempts to end an "empty transaction". There must have been no
    129   * changes to the layer tree since the BeginTransaction().
    130   * It's possible for this to fail; PaintedLayers may need to be updated
    131   * due to VRAM data being lost, for example. In such cases this method
    132   * returns false, and the caller must proceed with a normal layer tree
    133   * update and EndTransaction.
    134   */
    135  virtual bool EndEmptyTransaction(
    136      EndTransactionFlags aFlags = END_DEFAULT) = 0;
    137 
    138  virtual void Destroy() {}
    139 
    140  /**
    141   * Type of layer manager this is. This is to be used sparsely in order to
    142   * avoid a lot of Layers backend specific code. It should be used only when
    143   * Layers backend specific functionality is necessary.
    144   */
    145  virtual layers::LayersBackend GetBackendType() = 0;
    146 
    147  /**
    148   * Type of layers backend that will be used to composite this layer tree.
    149   * When compositing is done remotely, then this returns the layers type
    150   * of the compositor.
    151   */
    152  virtual layers::LayersBackend GetCompositorBackendType() {
    153    return GetBackendType();
    154  }
    155 
    156  /**
    157   * Checks if we need to invalidate the OS widget to trigger
    158   * painting when updating this renderer.
    159   */
    160  virtual bool NeedsWidgetInvalidation() { return true; }
    161 
    162  /**
    163   * Make sure that the previous transaction has been entirely
    164   * completed.
    165   *
    166   * Note: This may sychronously wait on a remote compositor
    167   * to complete rendering.
    168   */
    169  virtual void FlushRendering(wr::RenderReasons aReasons) {}
    170 
    171  /**
    172   * Make sure that the previous transaction has been
    173   * received. This will synchronsly wait on a remote compositor.
    174   */
    175  virtual void WaitOnTransactionProcessed() {}
    176 
    177  /**
    178   * returns the maximum texture size on this layer backend, or INT32_MAX
    179   * if there is no maximum
    180   */
    181  virtual int32_t GetMaxTextureSize() const { return INT32_MAX; }
    182 
    183  /**
    184   * Return the name of the layer manager's backend.
    185   */
    186  virtual void GetBackendName(nsAString& aName) = 0;
    187 
    188  virtual void GetFrameUniformity(layers::FrameUniformityData* aOutData) {}
    189 
    190  virtual bool AddPendingScrollUpdateForNextTransaction(
    191      layers::ScrollableLayerGuid::ViewID aScrollId,
    192      const ScrollPositionUpdate& aUpdateInfo) {
    193    return false;
    194  }
    195 
    196  /**
    197   * Creates a PersistentBufferProvider for use with canvas which is optimized
    198   * for inter-operating with this layermanager.
    199   */
    200  virtual already_AddRefed<layers::PersistentBufferProvider>
    201  CreatePersistentBufferProvider(const mozilla::gfx::IntSize& aSize,
    202                                 mozilla::gfx::SurfaceFormat aFormat,
    203                                 bool aWillReadFrequently = false);
    204 
    205  // Helper wrappers around cast to impl and then cast again.
    206 
    207  virtual layers::KnowsCompositor* AsKnowsCompositor() { return nullptr; }
    208 
    209  virtual layers::CompositorBridgeChild* GetCompositorBridgeChild() {
    210    return nullptr;
    211  }
    212 
    213  // Provided functionality
    214 
    215  void AddPartialPrerenderedAnimation(uint64_t aCompositorAnimationId,
    216                                      dom::Animation* aAnimation);
    217  void RemovePartialPrerenderedAnimation(uint64_t aCompositorAnimationId,
    218                                         dom::Animation* aAnimation);
    219  void UpdatePartialPrerenderedAnimations(
    220      const nsTArray<uint64_t>& aJankedAnimations);
    221 
    222 protected:
    223  virtual ~WindowRenderer() = default;
    224 
    225  // Transform animations which are not fully pre-rendered because it's on a
    226  // large frame.  We need to update the pre-rendered area once after we tried
    227  // to composite area which is outside of the pre-rendered area on the
    228  // compositor.
    229  nsRefPtrHashtable<nsUint64HashKey, dom::Animation>
    230      mPartialPrerenderedAnimations;
    231 };
    232 
    233 /**
    234 * FallbackRenderer is non-retained renderer that acts as a direct wrapper
    235 * around calling Paint on the provided DisplayList. This is used for cases
    236 * where initializing WebRender is too costly, and we don't need
    237 * retaining/invalidation (like small popup windows).
    238 *
    239 * It doesn't support any sort of EmptyTransaction, and only draws during
    240 * EndTransaction if a composite is requested (no END_NO_COMPOSITE flag
    241 * provided)
    242 */
    243 class FallbackRenderer : public WindowRenderer {
    244 public:
    245  FallbackRenderer* AsFallback() final { return this; }
    246 
    247  void SetTarget(gfxContext* aContext);
    248 
    249  bool BeginTransaction(const nsCString& aURL = nsCString()) final;
    250 
    251  bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) final {
    252    return false;
    253  }
    254 
    255  layers::LayersBackend GetBackendType() final {
    256    return layers::LayersBackend::LAYERS_NONE;
    257  }
    258 
    259  void GetBackendName(nsAString& name) final { name.AssignLiteral("Fallback"); }
    260 
    261  void EndTransactionWithColor(const nsIntRect& aRect,
    262                               const gfx::DeviceColor& aColor);
    263  void EndTransactionWithList(nsDisplayListBuilder* aBuilder,
    264                              nsDisplayList* aList,
    265                              int32_t aAppUnitsPerDevPixel,
    266                              EndTransactionFlags aFlags);
    267 
    268  gfxContext* mTarget = nullptr;
    269 
    270 protected:
    271  FallbackRenderer() = default;
    272 };
    273 
    274 /**
    275 * DefaultFallbackRenderer is intended to be used when the caller does not want
    276 * it to be destroyed/recreated based on the compositing state.
    277 */
    278 class DefaultFallbackRenderer final : public FallbackRenderer {
    279  NS_INLINE_DECL_REFCOUNTING(DefaultFallbackRenderer, final)
    280 
    281 public:
    282  DefaultFallbackRenderer() = default;
    283 
    284 private:
    285  ~DefaultFallbackRenderer() final = default;
    286 };
    287 
    288 /**
    289 * BackgroundedFallbackRenderer is intended to be used as a placeholder while we
    290 * wait for compositing to be reinstantiated.
    291 */
    292 class BackgroundedFallbackRenderer final : public FallbackRenderer,
    293                                           public gfx::GPUProcessListener {
    294  NS_INLINE_DECL_REFCOUNTING(BackgroundedFallbackRenderer, final)
    295 
    296 public:
    297  explicit BackgroundedFallbackRenderer(nsIWidget* aWidget);
    298 
    299  void Destroy() final;
    300 
    301  void OnCompositorDestroyBackgrounded() final;
    302 
    303 private:
    304  ~BackgroundedFallbackRenderer() final;
    305 
    306  // The widget to notify when compositing is reinstantiated.
    307  nsIWidget* mWidget;
    308 };
    309 
    310 }  // namespace mozilla
    311 
    312 #endif /* MOZILLA_PAINTING_WINDOWRENDERER_H */