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