Source code

Revision control

Other Tools

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
13
#include "GLTypes.h"
14
#include "nsISupportsImpl.h"
15
#include "nsRegion.h"
16
17
namespace mozilla {
18
19
namespace gl {
20
class GLContext;
21
} // namespace gl
22
23
namespace layers {
24
25
class NativeLayer;
26
class NativeLayerCA;
27
class NativeLayerRootSnapshotter;
28
class SurfacePoolHandle;
29
30
// NativeLayerRoot and NativeLayer allow building up a flat layer "tree" of
31
// sibling layers. These layers provide a cross-platform abstraction for the
32
// platform's native layers, such as CoreAnimation layers on macOS.
33
// Every layer has a rectangle that describes its position and size in the
34
// window. The native layer root is usually be created by the window, and then
35
// the compositing subsystem uses it to create and place the actual layers.
36
class NativeLayerRoot {
37
public:
38
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NativeLayerRoot)
39
40
virtual already_AddRefed<NativeLayer> CreateLayer(
41
const gfx::IntSize& aSize, bool aIsOpaque,
42
SurfacePoolHandle* aSurfacePoolHandle) = 0;
43
virtual void AppendLayer(NativeLayer* aLayer) = 0;
44
virtual void RemoveLayer(NativeLayer* aLayer) = 0;
45
virtual void SetLayers(const nsTArray<RefPtr<NativeLayer>>& aLayers) = 0;
46
47
// Publish the layer changes to the screen. Returns whether the commit was
48
// successful.
49
virtual bool CommitToScreen() = 0;
50
51
// Returns a new NativeLayerRootSnapshotter that can be used to read back the
52
// visual output of this NativeLayerRoot. The snapshotter needs to be
53
// destroyed on the same thread that CreateSnapshotter() was called on. Only
54
// one snapshotter per NativeLayerRoot can be in existence at any given time.
55
// CreateSnapshotter() makes sure of this and crashes if called at a time at
56
// which there still exists a snapshotter for this NativeLayerRoot.
57
virtual UniquePtr<NativeLayerRootSnapshotter> CreateSnapshotter() {
58
return nullptr;
59
}
60
61
protected:
62
virtual ~NativeLayerRoot() = default;
63
};
64
65
// Allows reading back the visual output of a NativeLayerRoot.
66
// Can only be used on a single thread, unlike NativeLayerRoot.
67
// Holds a strong reference to the NativeLayerRoot that created it.
68
// On Mac, this owns a GLContext, which wants to be created and destroyed on the
69
// same thread.
70
class NativeLayerRootSnapshotter {
71
public:
72
virtual ~NativeLayerRootSnapshotter() = default;
73
74
// Reads the composited result of the NativeLayer tree into aReadbackBuffer,
75
// synchronously. Should only be called right after a call to CommitToScreen()
76
// - in that case it is guaranteed to read back exactly the NativeLayer state
77
// that was committed. If called at other times, this API does not define
78
// whether the observed state includes NativeLayer modifications which have
79
// not been committed. (The macOS implementation will include those pending
80
// modifications by doing an offscreen commit.)
81
// The readback buffer's stride is assumed to be aReadbackSize.width * 4. Only
82
// BGRA is supported.
83
virtual bool ReadbackPixels(const gfx::IntSize& aReadbackSize,
84
gfx::SurfaceFormat aReadbackFormat,
85
const Range<uint8_t>& aReadbackBuffer) = 0;
86
};
87
88
// Represents a native layer. Native layers, such as CoreAnimation layers on
89
// macOS, are used to put pixels on the screen and to refresh and manipulate
90
// the visual contents of a window efficiently. For example, drawing to a layer
91
// once and then displaying the layer for multiple frames while moving it to
92
// different positions will be more efficient than drawing into a window (or a
93
// non-moving layer) multiple times with different internal offsets.
94
// There are two sources of "work" for a given composited frame: 1) Our own
95
// drawing (such as OpenGL compositing into a window or layer) and 2) the
96
// compositing window manager's work to update the screen. Every pixel we draw
97
// needs to be copied to the screen by the window manager. This suggests two
98
// avenues for reducing the work load for a given frame: Drawing fewer pixels
99
// ourselves, and making the window manager copy fewer pixels to the screen.
100
// Smart use of native layers allows reducing both work loads: If a visual
101
// change can be expressed purely as a layer attribute change (such as a change
102
// in the layer's position), this lets us eliminate our own drawing for that
103
// change. And secondly, manipulating a small layer rather than a large layer
104
// will reduce the window manager's work for that frame because it'll only copy
105
// the pixels of the small layer to the screen.
106
class NativeLayer {
107
public:
108
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NativeLayer)
109
110
virtual NativeLayerCA* AsNativeLayerCA() { return nullptr; }
111
112
// The size and opaqueness of a layer are supplied during layer creation and
113
// never change.
114
virtual gfx::IntSize GetSize() = 0;
115
virtual bool IsOpaque() = 0;
116
117
// The location of the layer, in integer device pixels.
118
virtual void SetPosition(const gfx::IntPoint& aPosition) = 0;
119
virtual gfx::IntPoint GetPosition() = 0;
120
121
virtual gfx::IntRect GetRect() = 0;
122
123
// The valid rect is stored here, but applied in the compositor code
124
// by combining it with the surface clip rect.
125
virtual void SetValidRect(const gfx::IntRect& aValidRect) = 0;
126
virtual gfx::IntRect GetValidRect() = 0;
127
128
// Set an optional clip rect on the layer. The clip rect is in the same
129
// coordinate space as the layer rect.
130
virtual void SetClipRect(const Maybe<gfx::IntRect>& aClipRect) = 0;
131
virtual Maybe<gfx::IntRect> ClipRect() = 0;
132
133
// Whether the surface contents are flipped vertically compared to this
134
// layer's coordinate system. Can be set on any thread at any time.
135
virtual void SetSurfaceIsFlipped(bool aIsFlipped) = 0;
136
virtual bool SurfaceIsFlipped() = 0;
137
138
// Returns a DrawTarget. The size of the DrawTarget will be the same as the
139
// size of this layer. The caller should draw to that DrawTarget, then drop
140
// its reference to the DrawTarget, and then call NotifySurfaceReady(). It can
141
// limit its drawing to aUpdateRegion (which is in the DrawTarget's device
142
// space). After a call to NextSurface*, NextSurface* must not be called again
143
// until after NotifySurfaceReady has been called. Can be called on any
144
// thread. When used from multiple threads, callers need to make sure that
145
// they still only call NextSurface* and NotifySurfaceReady alternatingly and
146
// not in any other order. aUpdateRegion must not extend beyond the layer
147
// size.
148
virtual RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
149
const gfx::IntRegion& aUpdateRegion, gfx::BackendType aBackendType) = 0;
150
151
// Returns a GLuint for a framebuffer that can be used for drawing to the
152
// surface. The size of the framebuffer will be the same as the size of this
153
// layer. If aNeedsDepth is true, the framebuffer is created with a depth
154
// buffer.
155
// The framebuffer's depth buffer (if present) may be shared with other
156
// framebuffers of the same size, even from entirely different NativeLayer
157
// objects. The caller should not assume anything about the depth buffer's
158
// existing contents (i.e. it should clear it at the beginning of the draw).
159
// Callers should draw to one layer at a time, such that there is no
160
// interleaved drawing to different framebuffers that could be tripped up by
161
// the sharing.
162
// The caller should draw to the framebuffer, unbind it, and then call
163
// NotifySurfaceReady(). It can limit its drawing to aUpdateRegion (which is
164
// in the framebuffer's device space, possibly "upside down" if
165
// SurfaceIsFlipped()).
166
// The framebuffer will be created in the GLContext that this layer's
167
// SurfacePoolHandle was created for.
168
// After a call to NextSurface*, NextSurface* must not be called again until
169
// after NotifySurfaceReady has been called. Can be called on any thread. When
170
// used from multiple threads, callers need to make sure that they still only
171
// call NextSurface and NotifySurfaceReady alternatingly and not in any other
172
// order.
173
// aUpdateRegion must not extend beyond the layer size.
174
virtual Maybe<GLuint> NextSurfaceAsFramebuffer(
175
const gfx::IntRegion& aUpdateRegion, bool aNeedsDepth) = 0;
176
177
// Indicates that the surface which has been returned from the most recent
178
// call to NextSurface* is now finished being drawn to and can be displayed on
179
// the screen. Resets the invalid region on the surface to the empty region.
180
virtual void NotifySurfaceReady() = 0;
181
182
// If you know that this layer will likely not draw any more frames, then it's
183
// good to call DiscardBackbuffers in order to save memory and allow other
184
// layer's to pick up the released surfaces from the pool.
185
virtual void DiscardBackbuffers() = 0;
186
187
protected:
188
virtual ~NativeLayer() = default;
189
};
190
191
} // namespace layers
192
} // namespace mozilla
193
194
#endif // mozilla_layers_NativeLayer_h