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