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