tor-browser

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

NativeLayerWayland.h (13547B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef mozilla_layers_NativeLayerWayland_h
      7 #define mozilla_layers_NativeLayerWayland_h
      8 
      9 #include <deque>
     10 
     11 #include "mozilla/Mutex.h"
     12 #include "mozilla/layers/NativeLayer.h"
     13 #include "mozilla/layers/SurfacePoolWayland.h"
     14 #include "mozilla/widget/DMABufFormats.h"
     15 #include "nsRegion.h"
     16 #include "nsTArray.h"
     17 
     18 namespace mozilla::wr {
     19 class RenderDMABUFTextureHost;
     20 }  // namespace mozilla::wr
     21 
     22 namespace mozilla::widget {
     23 class WaylandSurfaceLock;
     24 }  // namespace mozilla::widget
     25 
     26 namespace mozilla::layers {
     27 class NativeLayerWaylandExternal;
     28 class NativeLayerWaylandRender;
     29 
     30 struct LayerState {
     31  // Layer is visible (has correct size/position), we should paint it
     32  bool mIsVisible : 1;
     33  // Layer has been rendered and it's visible
     34  bool mIsRendered : 1;
     35 
     36  // Layer visibility has been changed
     37  bool mMutatedVisibility : 1;
     38  // Layer stacking order was changed (layer was added/removed/mapped/unmapped)
     39  bool mMutatedStackingOrder : 1;
     40  // Layer placement (size/position/scale etc.) was changed
     41  bool mMutatedPlacement : 1;
     42  // mFrontBuffer was changed and we need to commit it to Wayland compositor
     43  // to show new content.
     44  bool mMutatedFrontBuffer : 1;
     45  // Was rendered in last cycle.
     46  bool mRenderedLastCycle : 1;
     47 
     48  // For debugging purposse. Resets the layer state
     49  // to force full init.
     50  void InvalidateAll() {
     51    mIsVisible = false;
     52    mIsRendered = false;
     53 
     54    mMutatedVisibility = true;
     55    mMutatedStackingOrder = true;
     56    mMutatedPlacement = true;
     57    mMutatedFrontBuffer = true;
     58    mRenderedLastCycle = false;
     59  }
     60 };
     61 
     62 class NativeLayerRootWayland final : public NativeLayerRoot {
     63 public:
     64  static already_AddRefed<NativeLayerRootWayland> Create(
     65      RefPtr<widget::WaylandSurface> aWaylandSurface);
     66 
     67  // Overridden methods
     68  already_AddRefed<NativeLayer> CreateLayer(
     69      const gfx::IntSize& aSize, bool aIsOpaque,
     70      SurfacePoolHandle* aSurfacePoolHandle) override;
     71  already_AddRefed<NativeLayer> CreateLayerForExternalTexture(
     72      bool aIsOpaque) override;
     73 
     74  void AppendLayer(NativeLayer* aLayer) override;
     75  void RemoveLayer(NativeLayer* aLayer) override;
     76  void SetLayers(const nsTArray<RefPtr<NativeLayer>>& aLayers) override;
     77 
     78  void PrepareForCommit() override { mFrameInProcess = true; };
     79  bool CommitToScreen() override;
     80 
     81  // Main thread only
     82  GdkWindow* GetGdkWindow() const;
     83 
     84  RefPtr<widget::WaylandSurface> GetRootWaylandSurface() {
     85    return mRootSurface;
     86  }
     87 
     88  RefPtr<widget::DRMFormat> GetDRMFormat() { return mDRMFormat; }
     89 
     90  void FrameCallbackHandler(uint32_t aTime);
     91 
     92  RefPtr<widget::WaylandBuffer> BorrowExternalBuffer(
     93      RefPtr<DMABufSurface> aDMABufSurface);
     94 
     95 #ifdef MOZ_LOGGING
     96  nsAutoCString GetDebugTag() const;
     97  void* GetLoggingWidget() const;
     98 #endif
     99 
    100  void Init();
    101  void Shutdown();
    102 
    103  void UpdateLayersOnMainThread();
    104  void RequestUpdateOnMainThreadLocked(
    105      const widget::WaylandSurfaceLock& aProofOfLock);
    106 
    107  explicit NativeLayerRootWayland(
    108      RefPtr<widget::WaylandSurface> aWaylandSurface);
    109 
    110  void NotifyFullscreenChanged(bool aIsFullscreen) {
    111    mIsFullscreen = aIsFullscreen;
    112  }
    113 
    114 private:
    115  ~NativeLayerRootWayland();
    116 
    117  // Map NativeLayerRootWayland and all child surfaces.
    118  // Returns true if we're set.
    119  bool MapLocked(const widget::WaylandSurfaceLock& aProofOfLock);
    120  bool IsEmptyLocked(const widget::WaylandSurfaceLock& aProofOfLock);
    121  void ClearLayersLocked(const widget::WaylandSurfaceLock& aProofOfLock);
    122 
    123 #ifdef MOZ_LOGGING
    124  void LogStatsLocked(const widget::WaylandSurfaceLock& aProofOfLock);
    125 #endif
    126 
    127 #ifdef MOZ_LOGGING
    128  void* mLoggingWidget = nullptr;
    129 #endif
    130 
    131  // WaylandSurface of nsWindow (our root window).
    132  // This WaylandSurface is owned by nsWindow so we don't map/unmap it
    133  // or handle any callbacks.
    134  // We also use widget::WaylandSurfaceLock for locking whole layer for
    135  // read/write.
    136  RefPtr<widget::WaylandSurface> mRootSurface;
    137 
    138  // Copy of DRM format we use to create DMABuf surfaces
    139  RefPtr<widget::DRMFormat> mDRMFormat;
    140 
    141  // Empty buffer attached to mSurface. We need to have something
    142  // attached to make mSurface and all child visible.
    143  RefPtr<widget::WaylandBufferSHM> mTmpBuffer;
    144 
    145  // Child layers attached to this root, they're all on the same level
    146  // so all child layers are attached to mContainer as subsurfaces.
    147  // Layer visibility is sorted by Z-order, mSublayers[0] is on bottom.
    148  nsTArray<RefPtr<NativeLayerWayland>> mSublayers;
    149 
    150  // Child layers which needs to be updated on main thread,
    151  // they have been added or removed.
    152  nsTArray<RefPtr<NativeLayerWayland>> mMainThreadUpdateSublayers;
    153 
    154  // Child layers which has been removed and are
    155  // waiting to be unmapped. We do that in sync with root surface to avoid
    156  // flickering. When unmapped they're moved to mMainThreadUpdateSublayers
    157  // for final clean up at main thread.
    158  nsTArray<RefPtr<NativeLayerWayland>> mRemovedSublayers;
    159 
    160  // External buffers (DMABuf) used by the layers.
    161  // We want to cache and reuse wl_buffer of external images.
    162  nsTArray<widget::WaylandBufferDMABUFHolder> mExternalBuffers;
    163 
    164  // We're between CompositorBeginFrame() / CompositorEndFrame() calls.
    165  mozilla::Atomic<bool, mozilla::Relaxed> mFrameInProcess{false};
    166 
    167  uint32_t mLastFrameCallbackTime = 0;
    168 
    169  // State flags used for optimizations
    170  // Layers have been added/removed
    171  bool mRootMutatedStackingOrder = false;
    172  // All layers has been rendered
    173  bool mRootAllLayersRendered = false;
    174  bool mMainThreadUpdateQueued = false;
    175  bool mIsFullscreen = false;
    176 };
    177 
    178 class NativeLayerWayland : public NativeLayer {
    179 public:
    180  NativeLayerWayland* AsNativeLayerWayland() override { return this; }
    181  virtual NativeLayerWaylandExternal* AsNativeLayerWaylandExternal() {
    182    return nullptr;
    183  }
    184  virtual NativeLayerWaylandRender* AsNativeLayerWaylandRender() {
    185    return nullptr;
    186  }
    187 
    188  // Overridden methods
    189  gfx::IntSize GetSize() override;
    190  void SetPosition(const gfx::IntPoint& aPosition) override;
    191  gfx::IntPoint GetPosition() override;
    192  void SetTransform(const gfx::Matrix4x4& aTransform) override;
    193  gfx::Matrix4x4 GetTransform() override;
    194  gfx::IntRect GetRect() override;
    195  void SetSamplingFilter(gfx::SamplingFilter aSamplingFilter) override;
    196 
    197  bool IsOpaque() override;
    198  void SetClipRect(const Maybe<gfx::IntRect>& aClipRect) override;
    199  Maybe<gfx::IntRect> ClipRect() override;
    200  void SetRoundedClipRect(const Maybe<gfx::RoundedRect>& aClip) override;
    201  Maybe<gfx::RoundedRect> RoundedClipRect() override;
    202  gfx::IntRect CurrentSurfaceDisplayRect() override;
    203  void SetSurfaceIsFlipped(bool aIsFlipped) override;
    204  bool SurfaceIsFlipped() override;
    205 
    206  void RenderLayer(double aScale);
    207  // TODO
    208  GpuFence* GetGpuFence() override { return nullptr; }
    209 
    210  RefPtr<widget::WaylandSurface> GetWaylandSurface() { return mSurface; }
    211 
    212  // Surface Map/Unamp happens on rendering thread.
    213  //
    214  // We can use surface right after map but we need to finish mapping
    215  // on main thread to render it correctly.
    216  //
    217  // Also Unmap() needs to be finished on main thread.
    218  bool IsMapped();
    219  bool Map(widget::WaylandSurfaceLock* aParentWaylandSurfaceLock);
    220  void Unmap();
    221 
    222  void UpdateOnMainThread();
    223  void MainThreadMap();
    224  void MainThreadUnmap();
    225 
    226  void ForceCommit();
    227 
    228  void PlaceAbove(NativeLayerWayland* aLowerLayer);
    229 
    230 #ifdef MOZ_LOGGING
    231  nsAutoCString GetDebugTag() const;
    232 #endif
    233 
    234  void SetFrameCallbackState(bool aState);
    235 
    236  virtual void DiscardBackbuffersLocked(
    237      const widget::WaylandSurfaceLock& aProofOfLock, bool aForce = false) = 0;
    238  void DiscardBackbuffers() override;
    239 
    240  NativeLayerWayland(NativeLayerRootWayland* aRootLayer,
    241                     const gfx::IntSize& aSize, bool aIsOpaque);
    242 
    243  // No need to lock as we used it when new layers are added only
    244  constexpr static int sLayerClear = 0;
    245  constexpr static int sLayerRemoved = 1;
    246  constexpr static int sLayerAdded = 2;
    247 
    248  void MarkClear() { mUsageCount = sLayerClear; }
    249  void MarkRemoved() { mUsageCount = sLayerRemoved; }
    250  void MarkAdded() { mUsageCount += sLayerAdded; }
    251 
    252  bool IsRemoved() const { return mUsageCount == sLayerRemoved; }
    253  bool IsNew() const { return mUsageCount == sLayerAdded; }
    254 
    255  LayerState* State() { return &mState; }
    256 
    257 protected:
    258  void SetScalelocked(const widget::WaylandSurfaceLock& aProofOfLock,
    259                      double aScale);
    260  void UpdateLayerPlacementLocked(
    261      const widget::WaylandSurfaceLock& aProofOfLock);
    262  virtual bool CommitFrontBufferToScreenLocked(
    263      const widget::WaylandSurfaceLock& aProofOfLock) = 0;
    264  virtual bool IsFrontBufferChanged() = 0;
    265 
    266 protected:
    267  ~NativeLayerWayland();
    268 
    269  // There's a cycle dependency here as NativeLayerRootWayland holds strong
    270  // reference to NativeLayerWayland and vice versa.
    271  //
    272  // Shutdown sequence is:
    273  //
    274  // 1) NativeLayerRootWayland is released by GtkCompositorWidget
    275  // 2) NativeLayerRootWayland calls childs NativeLayerWayland release code and
    276  //    unrefs them.
    277  // 3) Child NativeLayerWayland register main thread callback to clean up
    278  //    and release itself.
    279  // 4) Child NativeLayerWayland unref itself and parent NativeLayerRootWayland.
    280  // 5) NativeLayerRootWayland is released when there isn't any
    281  //    NativeLayerWayland left.
    282  //
    283  RefPtr<NativeLayerRootWayland> mRootLayer;
    284 
    285  RefPtr<widget::WaylandSurface> mSurface;
    286 
    287  // Final buffer which we attach to WaylandSurface
    288  RefPtr<widget::WaylandBuffer> mFrontBuffer;
    289 
    290  const bool mIsOpaque = false;
    291 
    292  // Used at SetLayers() when we need to identify removed layers, new layers
    293  // and layers removed but returned back.
    294  // We're adding respective constants to mUsageCount for each layer
    295  // so removed layers have usage count 1, newly added 2 and removed+added 3.
    296  int mUsageCount = 0;
    297 
    298  gfx::IntSize mSize;
    299  gfx::IntPoint mPosition;
    300  gfx::Matrix4x4 mTransform;
    301  gfx::IntRect mDisplayRect;
    302  Maybe<gfx::IntRect> mClipRect;
    303  Maybe<gfx::RoundedRect> mRoundedClipRect;
    304  gfx::SamplingFilter mSamplingFilter = gfx::SamplingFilter::POINT;
    305  double mScale = 1.0f;
    306  LayerState mState{};
    307  bool mSurfaceIsFlipped = false;
    308  bool mIsHDR = false;
    309 
    310  enum class MainThreadUpdate {
    311    None,
    312    Map,
    313    Unmap,
    314  };
    315 
    316  // Indicate that we need to finish surface map/unmap
    317  // on main thread.
    318  // We need to perform main thread unmap even if mapping on main thread
    319  // is not finished, some main thread resources are created
    320  // by WaylandSurface itself.
    321  Atomic<MainThreadUpdate, mozilla::Relaxed> mNeedsMainThreadUpdate{
    322      MainThreadUpdate::None};
    323 };
    324 
    325 class NativeLayerWaylandRender final : public NativeLayerWayland {
    326 public:
    327  NativeLayerWaylandRender* AsNativeLayerWaylandRender() override {
    328    return this;
    329  }
    330 
    331  RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
    332      const gfx::IntRect& aDisplayRect, const gfx::IntRegion& aUpdateRegion,
    333      gfx::BackendType aBackendType) override;
    334  Maybe<GLuint> NextSurfaceAsFramebuffer(const gfx::IntRect& aDisplayRect,
    335                                         const gfx::IntRegion& aUpdateRegion,
    336                                         bool aNeedsDepth) override;
    337  void NotifySurfaceReady() override;
    338  void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
    339  bool IsFrontBufferChanged() override;
    340 
    341  NativeLayerWaylandRender(NativeLayerRootWayland* aRootLayer,
    342                           const gfx::IntSize& aSize, bool aIsOpaque,
    343                           SurfacePoolHandleWayland* aSurfacePoolHandle);
    344 
    345 private:
    346  ~NativeLayerWaylandRender() override;
    347 
    348  void DiscardBackbuffersLocked(const widget::WaylandSurfaceLock& aProofOfLock,
    349                                bool aForce) override;
    350  void ReadBackFrontBuffer(const widget::WaylandSurfaceLock& aProofOfLock);
    351  bool CommitFrontBufferToScreenLocked(
    352      const widget::WaylandSurfaceLock& aProofOfLock) override;
    353 
    354  const RefPtr<SurfacePoolHandleWayland> mSurfacePoolHandle;
    355  RefPtr<widget::WaylandBuffer> mInProgressBuffer;
    356  gfx::IntRegion mDirtyRegion;
    357 };
    358 
    359 class NativeLayerWaylandExternal final : public NativeLayerWayland {
    360 public:
    361  // Overridden methods
    362  NativeLayerWaylandExternal* AsNativeLayerWaylandExternal() override {
    363    return this;
    364  }
    365  RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
    366      const gfx::IntRect& aDisplayRect, const gfx::IntRegion& aUpdateRegion,
    367      gfx::BackendType aBackendType) override;
    368  Maybe<GLuint> NextSurfaceAsFramebuffer(const gfx::IntRect& aDisplayRect,
    369                                         const gfx::IntRegion& aUpdateRegion,
    370                                         bool aNeedsDepth) override;
    371  void NotifySurfaceReady() override {};
    372  void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
    373  bool IsFrontBufferChanged() override;
    374  RefPtr<DMABufSurface> GetSurface();
    375 
    376  NativeLayerWaylandExternal(NativeLayerRootWayland* aRootLayer,
    377                             bool aIsOpaque);
    378 
    379 private:
    380  ~NativeLayerWaylandExternal() override;
    381 
    382  void DiscardBackbuffersLocked(const widget::WaylandSurfaceLock& aProofOfLock,
    383                                bool aForce) override;
    384  void FreeUnusedBackBuffers();
    385  bool CommitFrontBufferToScreenLocked(
    386      const widget::WaylandSurfaceLock& aProofOfLock) override;
    387 
    388  RefPtr<wr::RenderDMABUFTextureHost> mTextureHost;
    389 };
    390 
    391 }  // namespace mozilla::layers
    392 
    393 #endif  // mozilla_layers_NativeLayerWayland_h