tor-browser

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

NativeLayer.h (12570B)


      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_NativeLayer_h
      7 #define mozilla_layers_NativeLayer_h
      8 
      9 #include "mozilla/Maybe.h"
     10 #include "mozilla/Range.h"
     11 #include "mozilla/UniquePtr.h"
     12 #include "mozilla/gfx/Types.h"
     13 #include "mozilla/layers/ScreenshotGrabber.h"
     14 
     15 #include "GLTypes.h"
     16 #include "nsISupportsImpl.h"
     17 #include "nsRegion.h"
     18 
     19 namespace mozilla {
     20 
     21 namespace gl {
     22 class GLContext;
     23 }  // namespace gl
     24 
     25 namespace wr {
     26 class RenderTextureHost;
     27 }
     28 
     29 namespace layers {
     30 
     31 class GpuFence;
     32 class NativeLayer;
     33 class NativeLayerCA;
     34 class NativeLayerRemoteMac;
     35 class NativeLayerWayland;
     36 class NativeLayerRootCA;
     37 class NativeLayerRootWayland;
     38 class NativeLayerRootSnapshotter;
     39 class NativeLayerWayland;
     40 class SurfacePoolHandle;
     41 
     42 // NativeLayerRoot and NativeLayer allow building up a flat layer "tree" of
     43 // sibling layers. These layers provide a cross-platform abstraction for the
     44 // platform's native layers, such as CoreAnimation layers on macOS.
     45 // Every layer has a rectangle that describes its position and size in the
     46 // window. The native layer root is usually be created by the window, and then
     47 // the compositing subsystem uses it to create and place the actual layers.
     48 class NativeLayerRoot {
     49 public:
     50  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NativeLayerRoot)
     51 
     52  virtual NativeLayerRootCA* AsNativeLayerRootCA() { return nullptr; }
     53  virtual NativeLayerRootWayland* AsNativeLayerRootWayland() { return nullptr; }
     54 
     55  virtual already_AddRefed<NativeLayer> CreateLayer(
     56      const gfx::IntSize& aSize, bool aIsOpaque,
     57      SurfacePoolHandle* aSurfacePoolHandle) = 0;
     58  virtual already_AddRefed<NativeLayer> CreateLayerForExternalTexture(
     59      bool aIsOpaque) = 0;
     60  virtual already_AddRefed<NativeLayer> CreateLayerForColor(
     61      gfx::DeviceColor aColor) {
     62    return nullptr;
     63  }
     64 
     65  virtual void LayerDestroyed(NativeLayer* aLayer) {}
     66 
     67  virtual void AppendLayer(NativeLayer* aLayer) = 0;
     68  virtual void RemoveLayer(NativeLayer* aLayer) = 0;
     69  virtual void SetLayers(const nsTArray<RefPtr<NativeLayer>>& aLayers) = 0;
     70 
     71  // Called before any layer content changes
     72  virtual void PrepareForCommit() {}
     73 
     74  // Publish the layer changes to the screen. Returns whether the commit was
     75  // successful.
     76  virtual bool CommitToScreen() = 0;
     77 
     78  // When called on a remote instance, synchronously wait until the other side
     79  // has processed any previous commits.
     80  virtual void WaitUntilCommitToScreenHasBeenProcessed() {}
     81 
     82  // Returns a new NativeLayerRootSnapshotter that can be used to read back the
     83  // visual output of this NativeLayerRoot. The snapshotter needs to be
     84  // destroyed on the same thread that CreateSnapshotter() was called on. Only
     85  // one snapshotter per NativeLayerRoot can be in existence at any given time.
     86  // CreateSnapshotter() makes sure of this and crashes if called at a time at
     87  // which there still exists a snapshotter for this NativeLayerRoot.
     88  virtual UniquePtr<NativeLayerRootSnapshotter> CreateSnapshotter() {
     89    return nullptr;
     90  }
     91 
     92 protected:
     93  virtual ~NativeLayerRoot() = default;
     94 };
     95 
     96 // Allows reading back the visual output of a NativeLayerRoot.
     97 // Can only be used on a single thread, unlike NativeLayerRoot.
     98 // Holds a strong reference to the NativeLayerRoot that created it.
     99 // On Mac, this owns a GLContext, which wants to be created and destroyed on the
    100 // same thread.
    101 class NativeLayerRootSnapshotter : public profiler_screenshots::Window {
    102 public:
    103  virtual ~NativeLayerRootSnapshotter() = default;
    104 
    105  // Reads the composited result of the NativeLayer tree into aReadbackBuffer,
    106  // synchronously. Should only be called right after a call to CommitToScreen()
    107  // - in that case it is guaranteed to read back exactly the NativeLayer state
    108  // that was committed. If called at other times, this API does not define
    109  // whether the observed state includes NativeLayer modifications which have
    110  // not been committed. (The macOS implementation will include those pending
    111  // modifications by doing an offscreen commit.)
    112  // The readback buffer's stride is assumed to be aReadbackSize.width * 4. Only
    113  // BGRA is supported.
    114  virtual bool ReadbackPixels(const gfx::IntSize& aReadbackSize,
    115                              gfx::SurfaceFormat aReadbackFormat,
    116                              const Range<uint8_t>& aReadbackBuffer) = 0;
    117 };
    118 
    119 // Represents a native layer. Native layers, such as CoreAnimation layers on
    120 // macOS, are used to put pixels on the screen and to refresh and manipulate
    121 // the visual contents of a window efficiently. For example, drawing to a layer
    122 // once and then displaying the layer for multiple frames while moving it to
    123 // different positions will be more efficient than drawing into a window (or a
    124 // non-moving layer) multiple times with different internal offsets.
    125 // There are two sources of "work" for a given composited frame: 1) Our own
    126 // drawing (such as OpenGL compositing into a window or layer) and 2) the
    127 // compositing window manager's work to update the screen. Every pixel we draw
    128 // needs to be copied to the screen by the window manager. This suggests two
    129 // avenues for reducing the work load for a given frame: Drawing fewer pixels
    130 // ourselves, and making the window manager copy fewer pixels to the screen.
    131 // Smart use of native layers allows reducing both work loads: If a visual
    132 // change can be expressed purely as a layer attribute change (such as a change
    133 // in the layer's position), this lets us eliminate our own drawing for that
    134 // change. And secondly, manipulating a small layer rather than a large layer
    135 // will reduce the window manager's work for that frame because it'll only copy
    136 // the pixels of the small layer to the screen.
    137 class NativeLayer {
    138 public:
    139  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NativeLayer)
    140 
    141  virtual NativeLayerCA* AsNativeLayerCA() { return nullptr; }
    142  virtual NativeLayerRemoteMac* AsNativeLayerRemoteMac() { return nullptr; }
    143  virtual NativeLayerWayland* AsNativeLayerWayland() { return nullptr; }
    144 
    145  // The size and opaqueness of a layer are supplied during layer creation and
    146  // never change.
    147  virtual gfx::IntSize GetSize() = 0;
    148  virtual bool IsOpaque() = 0;
    149 
    150  // The location of the layer, in integer device pixels.
    151  // This is applied to the layer, before the transform is applied.
    152  virtual void SetPosition(const gfx::IntPoint& aPosition) = 0;
    153  virtual gfx::IntPoint GetPosition() = 0;
    154 
    155  // Sets a transformation to apply to the Layer. This gets applied to
    156  // coordinates with the position applied, but before clipping is
    157  // applied.
    158  virtual void SetTransform(const gfx::Matrix4x4& aTransform) = 0;
    159  virtual gfx::Matrix4x4 GetTransform() = 0;
    160 
    161  virtual gfx::IntRect GetRect() = 0;
    162 
    163  // Set an optional clip rect on the layer. The clip rect is in post-transform
    164  // coordinate space
    165  virtual void SetClipRect(const Maybe<gfx::IntRect>& aClipRect) = 0;
    166  virtual Maybe<gfx::IntRect> ClipRect() = 0;
    167 
    168  // Set an optional rounded clip rect on the layer. The clip rect is in
    169  // post-transform coordinate space
    170  virtual void SetRoundedClipRect(const Maybe<gfx::RoundedRect>& aClip) = 0;
    171  virtual Maybe<gfx::RoundedRect> RoundedClipRect() = 0;
    172 
    173  // Returns the "display rect", in content coordinates, of the current front
    174  // surface. This rect acts as an extra clip and prevents invalid content from
    175  // getting to the screen. The display rect starts out empty before the first
    176  // call to NextSurface*. Note the different coordinate space from the regular
    177  // clip rect: the clip rect is "outside" the layer position, the display rect
    178  // is "inside" the layer position (moves with the layer).
    179  virtual gfx::IntRect CurrentSurfaceDisplayRect() = 0;
    180 
    181  // Whether the surface contents are flipped vertically compared to this
    182  // layer's coordinate system. Can be set on any thread at any time.
    183  virtual void SetSurfaceIsFlipped(bool aIsFlipped) = 0;
    184  virtual bool SurfaceIsFlipped() = 0;
    185 
    186  virtual void SetSamplingFilter(gfx::SamplingFilter aSamplingFilter) = 0;
    187  virtual gfx::SamplingFilter SamplingFilter() {
    188    return gfx::SamplingFilter::POINT;
    189  };
    190 
    191  // Returns a DrawTarget. The size of the DrawTarget will be the same as the
    192  // size of this layer. The caller should draw to that DrawTarget, then drop
    193  // its reference to the DrawTarget, and then call NotifySurfaceReady(). It can
    194  // limit its drawing to aUpdateRegion (which is in the DrawTarget's device
    195  // space). After a call to NextSurface*, NextSurface* must not be called again
    196  // until after NotifySurfaceReady has been called. Can be called on any
    197  // thread. When used from multiple threads, callers need to make sure that
    198  // they still only call NextSurface* and NotifySurfaceReady alternatingly and
    199  // not in any other order. aUpdateRegion and aDisplayRect are in "content
    200  // coordinates" and must not extend beyond the layer size. If aDisplayRect
    201  // contains parts that were not valid before, then those parts must be updated
    202  // (must be part of aUpdateRegion), so that the entirety of aDisplayRect is
    203  // valid after the update. The display rect determines the parts of the
    204  // surface that will be shown; this allows using surfaces with only
    205  // partially-valid content, as long as none of the invalid content is included
    206  // in the display rect.
    207  virtual RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
    208      const gfx::IntRect& aDisplayRect, const gfx::IntRegion& aUpdateRegion,
    209      gfx::BackendType aBackendType) = 0;
    210 
    211  // Returns a GLuint for a framebuffer that can be used for drawing to the
    212  // surface. The size of the framebuffer will be the same as the size of this
    213  // layer. If aNeedsDepth is true, the framebuffer is created with a depth
    214  // buffer.
    215  // The framebuffer's depth buffer (if present) may be shared with other
    216  // framebuffers of the same size, even from entirely different NativeLayer
    217  // objects. The caller should not assume anything about the depth buffer's
    218  // existing contents (i.e. it should clear it at the beginning of the draw).
    219  // Callers should draw to one layer at a time, such that there is no
    220  // interleaved drawing to different framebuffers that could be tripped up by
    221  // the sharing.
    222  // The caller should draw to the framebuffer, unbind it, and then call
    223  // NotifySurfaceReady(). It can limit its drawing to aUpdateRegion (which is
    224  // in the framebuffer's device space, possibly "upside down" if
    225  // SurfaceIsFlipped()).
    226  // The framebuffer will be created in the GLContext that this layer's
    227  // SurfacePoolHandle was created for.
    228  // After a call to NextSurface*, NextSurface* must not be called again until
    229  // after NotifySurfaceReady has been called. Can be called on any thread. When
    230  // used from multiple threads, callers need to make sure that they still only
    231  // call NextSurface and NotifySurfaceReady alternatingly and not in any other
    232  // order.
    233  // aUpdateRegion and aDisplayRect are in "content coordinates" and must not
    234  // extend beyond the layer size. If aDisplayRect contains parts that were not
    235  // valid before, then those parts must be updated (must be part of
    236  // aUpdateRegion), so that the entirety of aDisplayRect is valid after the
    237  // update. The display rect determines the parts of the surface that will be
    238  // shown; this allows using surfaces with only partially-valid content, as
    239  // long as none of the invalid content is included in the display rect.
    240  virtual Maybe<GLuint> NextSurfaceAsFramebuffer(
    241      const gfx::IntRect& aDisplayRect, const gfx::IntRegion& aUpdateRegion,
    242      bool aNeedsDepth) = 0;
    243 
    244  // Indicates that the surface which has been returned from the most recent
    245  // call to NextSurface* is now finished being drawn to and can be displayed on
    246  // the screen. Resets the invalid region on the surface to the empty region.
    247  virtual void NotifySurfaceReady() = 0;
    248 
    249  // If you know that this layer will likely not draw any more frames, then it's
    250  // good to call DiscardBackbuffers in order to save memory and allow other
    251  // layer's to pick up the released surfaces from the pool.
    252  virtual void DiscardBackbuffers() = 0;
    253 
    254  virtual void AttachExternalImage(wr::RenderTextureHost* aExternalImage) = 0;
    255 
    256  virtual GpuFence* GetGpuFence() = 0;
    257 
    258 protected:
    259  virtual ~NativeLayer() = default;
    260 };
    261 
    262 }  // namespace layers
    263 }  // namespace mozilla
    264 
    265 #endif  // mozilla_layers_NativeLayer_h