1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef MOZILLA_GFX_COMPOSITOR_H
8 #define MOZILLA_GFX_COMPOSITOR_H
9
10 #include "Units.h" // for ScreenPoint
11 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
12 #include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted
13 #include "mozilla/gfx/2D.h" // for DrawTarget
14 #include "mozilla/gfx/MatrixFwd.h" // for Matrix, Matrix4x4
15 #include "mozilla/gfx/Point.h" // for IntSize, Point
16 #include "mozilla/gfx/Polygon.h" // for Polygon
17 #include "mozilla/gfx/Rect.h" // for Rect, IntRect
18 #include "mozilla/gfx/Types.h" // for Float
19 #include "mozilla/gfx/Triangle.h" // for Triangle, TexturedTriangle
20 #include "mozilla/layers/CompositorTypes.h" // for DiagnosticTypes, etc
21 #include "mozilla/layers/LayersTypes.h" // for LayersBackend
22 #include "mozilla/layers/SurfacePool.h" // for SurfacePoolHandle
23 #include "mozilla/layers/TextureSourceProvider.h"
24 #include "mozilla/widget/CompositorWidget.h"
25 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
26 #include "nsRegion.h"
27 #include <vector>
28 #include "mozilla/WidgetUtils.h"
29
30 /**
31 * Different elements of a web pages are rendered into separate "layers" before
32 * they are flattened into the final image that is brought to the screen.
33 * See Layers.h for more informations about layers and why we use retained
34 * structures.
35 * Most of the documentation for layers is directly in the source code in the
36 * form of doc comments. An overview can also be found in the the wiki:
37 * https://wiki.mozilla.org/Gecko:Overview#Graphics
38 *
39 *
40 * # Main interfaces and abstractions
41 *
42 * - CompositableClient and CompositableHost
43 * (client/CompositableClient.h composite/CompositableHost.h)
44 * - TextureClient and TextureHost
45 * (client/TextureClient.h composite/TextureHost.h)
46 * - TextureSource
47 * (composite/TextureHost.h)
48 * - Forwarders
49 * (ipc/CompositableForwarder.h ipc/ShadowLayers.h)
50 * - Compositor
51 * (this file)
52 * - IPDL protocols
53 * (.ipdl files under the gfx/layers/ipc directory)
54 *
55 * The *Client and Shadowable* classes are always used on the content thread.
56 * Forwarders are always used on the content thread.
57 * The *Host and Shadow* classes are always used on the compositor thread.
58 * Compositors, TextureSource, and Effects are always used on the compositor
59 * thread.
60 * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h.
61 *
62 *
63 * # Texture transfer
64 *
65 * Most layer classes own a Compositable plus some extra information like
66 * transforms and clip rects. They are platform independent.
67 * Compositable classes manipulate Texture objects and are reponsible for
68 * things like tiling, buffer rotation or double buffering. Compositables
69 * are also platform-independent. Examples of compositable classes are:
70 * - ImageClient
71 * - CanvasClient
72 * - etc.
73 * Texture classes (TextureClient and TextureHost) are thin abstractions over
74 * platform-dependent texture memory. They are maniplulated by compositables
75 * and don't know about buffer rotations and such. The purposes of TextureClient
76 * and TextureHost are to synchronize, serialize and deserialize texture data.
77 * TextureHosts provide access to TextureSources that are views on the
78 * Texture data providing the necessary api for Compositor backend to composite
79 * them.
80 *
81 * Compositable and Texture clients and hosts are created using factory methods.
82 * They should only be created by using their constructor in exceptional
83 * circumstances. The factory methods are located:
84 * TextureClient - CompositableClient::CreateTextureClient
85 * TextureHost - TextureHost::CreateTextureHost, which calls a
86 * platform-specific function, e.g.,
87 * CreateTextureHostOGL CompositableClient - in the appropriate subclass, e.g.,
88 * CanvasClient::CreateCanvasClient
89 * CompositableHost - CompositableHost::Create
90 *
91 *
92 * # IPDL
93 *
94 * If off-main-thread compositing (OMTC) is enabled, compositing is performed
95 * in a dedicated thread. In some setups compositing happens in a dedicated
96 * process. Documentation may refer to either the compositor thread or the
97 * compositor process.
98 * See explanations in ShadowLayers.h.
99 *
100 *
101 * # Backend implementations
102 *
103 * Compositor backends like OpenGL or flavours of D3D live in their own
104 * directory under gfx/layers/. To add a new backend, implement at least the
105 * following interfaces:
106 * - Compositor (ex. CompositorOGL)
107 * - TextureHost (ex. SurfaceTextureHost)
108 * Depending on the type of data that needs to be serialized, you may need to
109 * add specific TextureClient implementations.
110 */
111
112 class nsIWidget;
113
114 namespace mozilla {
115 namespace gfx {
116 class DrawTarget;
117 class DataSourceSurface;
118 } // namespace gfx
119
120 namespace layers {
121
122 struct Effect;
123 struct EffectChain;
124 class Image;
125 class Layer;
126 class TextureSource;
127 class DataTextureSource;
128 class CompositingRenderTarget;
129 class CompositorBridgeParent;
130 class NativeLayer;
131 class CompositorOGL;
132 class CompositorD3D11;
133 class TextureReadLock;
134 struct GPUStats;
135 class AsyncReadbackBuffer;
136 class RecordedFrame;
137
138 enum SurfaceInitMode { INIT_MODE_NONE, INIT_MODE_CLEAR };
139
140 /**
141 * Common interface for compositor backends.
142 *
143 * Compositor provides a cross-platform interface to a set of operations for
144 * compositing quads. Compositor knows nothing about the layer tree. It must be
145 * told everything about each composited quad - contents, location, transform,
146 * opacity, etc.
147 *
148 * In theory it should be possible for different widgets to use the same
149 * compositor. In practice, we use one compositor per window.
150 *
151 * # Usage
152 *
153 * For an example of a user of Compositor, see LayerManagerComposite.
154 *
155 * Initialization: create a Compositor object, call Initialize().
156 *
157 * Destruction: destroy any resources associated with the compositor, call
158 * Destroy(), delete the Compositor object.
159 *
160 * Composition:
161 * call BeginFrame,
162 * for each quad to be composited:
163 * call MakeCurrent if necessary (not necessary if no other context has been
164 * made current),
165 * take care of any texture upload required to composite the quad, this step
166 * is backend-dependent,
167 * construct an EffectChain for the quad,
168 * call DrawQuad,
169 * call EndFrame.
170 *
171 * By default, the compositor will render to the screen if BeginFrameForWindow
172 * is called. To render to a target, call BeginFrameForTarget or
173 * or SetRenderTarget, the latter with a target created
174 * by CreateRenderTarget or CreateRenderTargetFromSource.
175 *
176 * The target and viewport methods can be called before any DrawQuad call and
177 * affect any subsequent DrawQuad calls.
178 */
179 class Compositor : public TextureSourceProvider {
180 protected:
181 virtual ~Compositor();
182
183 public:
184 explicit Compositor(widget::CompositorWidget* aWidget);
185
IsValid()186 bool IsValid() const override { return true; }
187
188 virtual bool Initialize(nsCString* const out_failureReason) = 0;
189 void Destroy() override;
IsDestroyed()190 bool IsDestroyed() const { return mIsDestroyed; }
191
192 /**
193 * Creates a Surface that can be used as a rendering target by this
194 * compositor.
195 */
196 virtual already_AddRefed<CompositingRenderTarget> CreateRenderTarget(
197 const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0;
198
199 /**
200 * Grab a snapshot of aSource and store it in aDest, so that the pixels can
201 * be read on the CPU by mapping aDest at some point in the future.
202 * aSource and aDest must have the same size.
203 * If this is a GPU compositor, this call must not block on the GPU.
204 * Returns whether the operation was successful.
205 */
206 virtual bool ReadbackRenderTarget(CompositingRenderTarget* aSource,
207 AsyncReadbackBuffer* aDest) = 0;
208
209 /**
210 * Create an AsyncReadbackBuffer of the specified size. Can return null.
211 */
212 virtual already_AddRefed<AsyncReadbackBuffer> CreateAsyncReadbackBuffer(
213 const gfx::IntSize& aSize) = 0;
214
215 /**
216 * Draw a part of aSource into the current render target.
217 * Scaling is done with linear filtering.
218 * Returns whether the operation was successful.
219 */
220 virtual bool BlitRenderTarget(CompositingRenderTarget* aSource,
221 const gfx::IntSize& aSourceSize,
222 const gfx::IntSize& aDestSize) = 0;
223
224 /**
225 * Sets the given surface as the target for subsequent calls to DrawQuad.
226 * Passing null as aSurface sets the screen as the target.
227 */
228 virtual void SetRenderTarget(CompositingRenderTarget* aSurface) = 0;
229
230 /**
231 * Returns the current target for rendering. Will return null if we are
232 * rendering to the screen.
233 */
234 virtual already_AddRefed<CompositingRenderTarget> GetCurrentRenderTarget()
235 const = 0;
236
237 /**
238 * Returns a render target which contains the entire window's drawing.
239 * On platforms where no such render target is used during compositing (e.g.
240 * with buffered BasicCompositor, where only the invalid area is drawn to a
241 * render target), this will return null.
242 */
243 virtual already_AddRefed<CompositingRenderTarget> GetWindowRenderTarget()
244 const = 0;
245
246 /**
247 * Mostly the compositor will pull the size from a widget and this method will
248 * be ignored, but compositor implementations are free to use it if they like.
249 */
250 virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) = 0;
251
252 /**
253 * Tell the compositor to draw a quad. What to do draw and how it is
254 * drawn is specified by aEffectChain. aRect is the quad to draw, in user
255 * space. aTransform transforms from user space to screen space. If texture
256 * coords are required, these will be in the primary effect in the effect
257 * chain. aVisibleRect is used to determine which edges should be antialiased,
258 * without applying the effect to the inner edges of a tiled layer.
259 */
260 virtual void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect,
261 const EffectChain& aEffectChain, gfx::Float aOpacity,
262 const gfx::Matrix4x4& aTransform,
263 const gfx::Rect& aVisibleRect) = 0;
264
SetClearColor(const gfx::DeviceColor & aColor)265 void SetClearColor(const gfx::DeviceColor& aColor) { mClearColor = aColor; }
266
267 /**
268 * Start a new frame for rendering to the window.
269 * Needs to be paired with a call to EndFrame() if the return value is not
270 * Nothing().
271 *
272 * aInvalidRegion is the invalid region of the window.
273 * aClipRect is the clip rect for all drawing (optional).
274 * aRenderBounds is the bounding rect for rendering.
275 * aOpaqueRegion is the area that contains opaque content.
276 * All coordinates are in window space.
277 *
278 * Returns the non-empty render bounds actually used by the compositor in
279 * window space, or Nothing() if composition should be aborted.
280 */
281 virtual Maybe<gfx::IntRect> BeginFrameForWindow(
282 const nsIntRegion& aInvalidRegion, const Maybe<gfx::IntRect>& aClipRect,
283 const gfx::IntRect& aRenderBounds, const nsIntRegion& aOpaqueRegion) = 0;
284
285 /**
286 * Flush the current frame to the screen and tidy up.
287 *
288 * Derived class overriding this should call Compositor::EndFrame.
289 */
290 virtual void EndFrame();
291
292 virtual void CancelFrame(bool aNeedFlush = true) {}
293
294 #ifdef MOZ_DUMP_PAINTING
295 virtual const char* Name() const = 0;
296 #endif // MOZ_DUMP_PAINTING
297
AsCompositorD3D11()298 virtual CompositorD3D11* AsCompositorD3D11() { return nullptr; }
299
AsCompositor()300 Compositor* AsCompositor() override { return this; }
301
GetLastCompositionEndTime()302 TimeStamp GetLastCompositionEndTime() const override {
303 return mLastCompositionEndTime;
304 }
305
306 /**
307 * Notify the compositor that composition is being paused. This allows the
308 * compositor to temporarily release any resources.
309 * Between calling Pause and Resume, compositing may fail.
310 */
Pause()311 virtual void Pause() {}
312 /**
313 * Notify the compositor that composition is being resumed. The compositor
314 * regain any resources it requires for compositing.
315 * Returns true if succeeded.
316 */
Resume()317 virtual bool Resume() { return true; }
318
GetWidget()319 widget::CompositorWidget* GetWidget() const { return mWidget; }
320
321 /**
322 * Request the compositor to allow recording its frames.
323 *
324 * This is a noop on |CompositorOGL|.
325 */
RequestAllowFrameRecording(bool aWillRecord)326 virtual void RequestAllowFrameRecording(bool aWillRecord) {
327 mRecordFrames = aWillRecord;
328 }
329
330 /**
331 * Record the current frame for readback by the |CompositionRecorder|.
332 *
333 * If this compositor does not support this feature, a null pointer is
334 * returned instead.
335 */
336 already_AddRefed<RecordedFrame> RecordFrame(const TimeStamp& aTimeStamp);
337
338 protected:
339 /**
340 * Whether or not the compositor should be prepared to record frames. While
341 * this returns true, compositors are expected to maintain a full window
342 * render target that they return from GetWindowRenderTarget() between
343 * NormalDrawingDone() and EndFrame().
344 *
345 * This will be true when either we are recording a profile with screenshots
346 * enabled or the |LayerManagerComposite| has requested us to record frames
347 * for the |CompositionRecorder|.
348 */
349 bool ShouldRecordFrames() const;
350
351 /**
352 * Last Composition end time.
353 */
354 TimeStamp mLastCompositionEndTime;
355
356 widget::CompositorWidget* mWidget;
357
358 bool mIsDestroyed;
359
360 gfx::DeviceColor mClearColor;
361
362 bool mRecordFrames = false;
363
364 private:
365 static LayersBackend sBackend;
366 };
367
368 // Returns the number of rects. (Up to 4)
369 typedef gfx::Rect decomposedRectArrayT[4];
370 size_t DecomposeIntoNoRepeatRects(const gfx::Rect& aRect,
371 const gfx::Rect& aTexCoordRect,
372 decomposedRectArrayT* aLayerRects,
373 decomposedRectArrayT* aTextureRects);
374
BlendOpIsMixBlendMode(gfx::CompositionOp aOp)375 static inline bool BlendOpIsMixBlendMode(gfx::CompositionOp aOp) {
376 switch (aOp) {
377 case gfx::CompositionOp::OP_MULTIPLY:
378 case gfx::CompositionOp::OP_SCREEN:
379 case gfx::CompositionOp::OP_OVERLAY:
380 case gfx::CompositionOp::OP_DARKEN:
381 case gfx::CompositionOp::OP_LIGHTEN:
382 case gfx::CompositionOp::OP_COLOR_DODGE:
383 case gfx::CompositionOp::OP_COLOR_BURN:
384 case gfx::CompositionOp::OP_HARD_LIGHT:
385 case gfx::CompositionOp::OP_SOFT_LIGHT:
386 case gfx::CompositionOp::OP_DIFFERENCE:
387 case gfx::CompositionOp::OP_EXCLUSION:
388 case gfx::CompositionOp::OP_HUE:
389 case gfx::CompositionOp::OP_SATURATION:
390 case gfx::CompositionOp::OP_COLOR:
391 case gfx::CompositionOp::OP_LUMINOSITY:
392 return true;
393 default:
394 return false;
395 }
396 }
397
398 class AsyncReadbackBuffer {
399 public:
NS_INLINE_DECL_REFCOUNTING(AsyncReadbackBuffer)400 NS_INLINE_DECL_REFCOUNTING(AsyncReadbackBuffer)
401
402 gfx::IntSize GetSize() const { return mSize; }
403 virtual bool MapAndCopyInto(gfx::DataSourceSurface* aSurface,
404 const gfx::IntSize& aReadSize) const = 0;
405
406 protected:
AsyncReadbackBuffer(const gfx::IntSize & aSize)407 explicit AsyncReadbackBuffer(const gfx::IntSize& aSize) : mSize(aSize) {}
408 virtual ~AsyncReadbackBuffer() = default;
409
410 gfx::IntSize mSize;
411 };
412
413 struct TexturedVertex {
414 float position[2];
415 float texCoords[2];
416 };
417
418 nsTArray<TexturedVertex> TexturedTrianglesToVertexArray(
419 const nsTArray<gfx::TexturedTriangle>& aTriangles);
420
421 } // namespace layers
422 } // namespace mozilla
423
424 #endif /* MOZILLA_GFX_COMPOSITOR_H */
425