1 /* -*- Mode: C++; tab-width: 20; 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_GFX_COMPOSITOR_H
7 #define MOZILLA_GFX_COMPOSITOR_H
9 #include "Units.h" // for ScreenPoint
10 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
11 #include "mozilla/RefPtr.h" // for TemporaryRef, RefCounted
12 #include "mozilla/gfx/2D.h" // for DrawTarget
13 #include "mozilla/gfx/Point.h" // for IntSize, Point
14 #include "mozilla/gfx/Rect.h" // for Rect, IntRect
15 #include "mozilla/gfx/Types.h" // for Float
16 #include "mozilla/layers/CompositorTypes.h" // for DiagnosticTypes, etc
17 #include "mozilla/layers/FenceUtils.h" // for FenceHandle
18 #include "mozilla/layers/LayersTypes.h" // for LayersBackend
19 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
22 #include "mozilla/WidgetUtils.h"
25 * Different elements of a web pages are rendered into separate "layers" before
26 * they are flattened into the final image that is brought to the screen.
27 * See Layers.h for more informations about layers and why we use retained
29 * Most of the documentation for layers is directly in the source code in the
30 * form of doc comments. An overview can also be found in the the wiki:
31 * https://wiki.mozilla.org/Gecko:Overview#Graphics
34 * # Main interfaces and abstractions
36 * - Layer, ShadowableLayer and LayerComposite
37 * (see Layers.h and ipc/ShadowLayers.h)
38 * - CompositableClient and CompositableHost
39 * (client/CompositableClient.h composite/CompositableHost.h)
40 * - TextureClient and TextureHost
41 * (client/TextureClient.h composite/TextureHost.h)
43 * (composite/TextureHost.h)
45 * (ipc/CompositableForwarder.h ipc/ShadowLayers.h)
49 * (.ipdl files under the gfx/layers/ipc directory)
51 * The *Client and Shadowable* classes are always used on the content thread.
52 * Forwarders are always used on the content thread.
53 * The *Host and Shadow* classes are always used on the compositor thread.
54 * Compositors, TextureSource, and Effects are always used on the compositor
56 * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h.
61 * Most layer classes own a Compositable plus some extra information like
62 * transforms and clip rects. They are platform independent.
63 * Compositable classes manipulate Texture objects and are reponsible for
64 * things like tiling, buffer rotation or double buffering. Compositables
65 * are also platform-independent. Examples of compositable classes are:
70 * Texture classes (TextureClient and TextureHost) are thin abstractions over
71 * platform-dependent texture memory. They are maniplulated by compositables
72 * and don't know about buffer rotations and such. The purposes of TextureClient
73 * and TextureHost are to synchronize, serialize and deserialize texture data.
74 * TextureHosts provide access to TextureSources that are views on the
75 * Texture data providing the necessary api for Compositor backend to composite
78 * Compositable and Texture clients and hosts are created using factory methods.
79 * They should only be created by using their constructor in exceptional
80 * circumstances. The factory methods are located:
81 * TextureClient - CompositableClient::CreateTextureClient
82 * TextureHost - TextureHost::CreateTextureHost, which calls a
83 * platform-specific function, e.g., CreateTextureHostOGL
84 * CompositableClient - in the appropriate subclass, e.g.,
85 * CanvasClient::CreateCanvasClient
86 * CompositableHost - CompositableHost::Create
91 * If off-main-thread compositing (OMTC) is enabled, compositing is performed
92 * in a dedicated thread. In some setups compositing happens in a dedicated
93 * process. Documentation may refer to either the compositor thread or the
95 * See explanations in ShadowLayers.h.
98 * # Backend implementations
100 * Compositor backends like OpenGL or flavours of D3D live in their own directory
101 * under gfx/layers/. To add a new backend, implement at least the following
103 * - Compositor (ex. CompositorOGL)
104 * - TextureHost (ex. SurfaceTextureHost)
105 * Depending on the type of data that needs to be serialized, you may need to
106 * add specific TextureClient implementations.
125 class ISurfaceAllocator
;
128 class DataTextureSource
;
129 class CompositingRenderTarget
;
130 class PCompositorParent
;
131 class LayerManagerComposite
;
140 * Common interface for compositor backends.
142 * Compositor provides a cross-platform interface to a set of operations for
143 * compositing quads. Compositor knows nothing about the layer tree. It must be
144 * told everything about each composited quad - contents, location, transform,
147 * In theory it should be possible for different widgets to use the same
148 * compositor. In practice, we use one compositor per window.
152 * For an example of a user of Compositor, see LayerManagerComposite.
154 * Initialization: create a Compositor object, call Initialize().
156 * Destruction: destroy any resources associated with the compositor, call
157 * Destroy(), delete the Compositor object.
161 * for each quad to be composited:
162 * call MakeCurrent if necessary (not necessary if no other context has been
164 * take care of any texture upload required to composite the quad, this step
165 * is backend-dependent,
166 * construct an EffectChain for the quad,
169 * If the compositor is usually used for compositing but compositing is
170 * temporarily done without the compositor, call EndFrameForExternalComposition
171 * after compositing each frame so the compositor can remain internally
174 * By default, the compositor will render to the screen, to render to a target,
175 * call SetTargetContext or SetRenderTarget, the latter with a target created
176 * by CreateRenderTarget or CreateRenderTargetFromSource.
178 * The target and viewport methods can be called before any DrawQuad call and
179 * affect any subsequent DrawQuad calls.
184 virtual ~Compositor() {}
187 NS_INLINE_DECL_REFCOUNTING(Compositor
)
189 explicit Compositor(PCompositorParent
* aParent
= nullptr)
191 , mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC
)
193 , mScreenRotation(ROTATION_0
)
197 virtual TemporaryRef
<DataTextureSource
> CreateDataTextureSource(TextureFlags aFlags
= TextureFlags::NO_FLAGS
) = 0;
198 virtual bool Initialize() = 0;
199 virtual void Destroy() = 0;
202 * Return true if the effect type is supported.
204 * By default Compositor implementations should support all effects but in
205 * some rare cases it is not possible to support an effect efficiently.
206 * This is the case for BasicCompositor with EffectYCbCr.
208 virtual bool SupportsEffect(EffectTypes aEffect
) { return true; }
211 * Request a texture host identifier that may be used for creating textures
212 * across process or thread boundaries that are compatible with this
215 virtual TextureFactoryIdentifier
GetTextureFactoryIdentifier() = 0;
218 * Properties of the compositor.
220 virtual bool CanUseCanvasLayerForSize(const gfx::IntSize
& aSize
) = 0;
221 virtual int32_t GetMaxTextureSize() const = 0;
224 * Set the target for rendering. Results will have been written to aTarget by
225 * the time that EndFrame returns.
227 * If this method is not used, or we pass in nullptr, we target the compositor's
228 * usual swap chain and render to the screen.
230 void SetTargetContext(gfx::DrawTarget
* aTarget
, const nsIntRect
& aRect
)
233 mTargetBounds
= aRect
;
235 void ClearTargetContext()
240 typedef uint32_t MakeCurrentFlags
;
241 static const MakeCurrentFlags ForceMakeCurrent
= 0x1;
243 * Make this compositor's rendering context the current context for the
244 * underlying graphics API. This may be a global operation, depending on the
245 * API. Our context will remain the current one until someone else changes it.
247 * Clients of the compositor should call this at the start of the compositing
248 * process, it might be required by texture uploads etc.
250 * If aFlags == ForceMakeCurrent then we will (re-)set our context on the
251 * underlying API even if it is already the current context.
253 virtual void MakeCurrent(MakeCurrentFlags aFlags
= 0) = 0;
256 * Creates a Surface that can be used as a rendering target by this
259 virtual TemporaryRef
<CompositingRenderTarget
>
260 CreateRenderTarget(const gfx::IntRect
& aRect
, SurfaceInitMode aInit
) = 0;
263 * Creates a Surface that can be used as a rendering target by this
264 * compositor, and initializes the surface by copying from aSource.
265 * If aSource is null, then the current screen buffer is used as source.
267 * aSourcePoint specifies the point in aSource to copy data from.
269 virtual TemporaryRef
<CompositingRenderTarget
>
270 CreateRenderTargetFromSource(const gfx::IntRect
& aRect
,
271 const CompositingRenderTarget
* aSource
,
272 const gfx::IntPoint
& aSourcePoint
) = 0;
275 * Sets the given surface as the target for subsequent calls to DrawQuad.
276 * Passing null as aSurface sets the screen as the target.
278 virtual void SetRenderTarget(CompositingRenderTarget
* aSurface
) = 0;
281 * Returns the current target for rendering. Will return null if we are
282 * rendering to the screen.
284 virtual CompositingRenderTarget
* GetCurrentRenderTarget() const = 0;
287 * Mostly the compositor will pull the size from a widget and this method will
288 * be ignored, but compositor implementations are free to use it if they like.
290 virtual void SetDestinationSurfaceSize(const gfx::IntSize
& aSize
) = 0;
293 * Declare an offset to use when rendering layers. This will be ignored when
294 * rendering to a target instead of the screen.
296 virtual void SetScreenRenderOffset(const ScreenPoint
& aOffset
) = 0;
299 * Tell the compositor to draw a quad. What to do draw and how it is
300 * drawn is specified by aEffectChain. aRect is the quad to draw, in user space.
301 * aTransform transforms from user space to screen space. If texture coords are
302 * required, these will be in the primary effect in the effect chain.
304 virtual void DrawQuad(const gfx::Rect
& aRect
, const gfx::Rect
& aClipRect
,
305 const EffectChain
& aEffectChain
,
306 gfx::Float aOpacity
, const gfx::Matrix4x4
&aTransform
) = 0;
309 * Clear aRect on current render target.
311 virtual void ClearRect(const gfx::Rect
& aRect
) = 0;
316 * aInvalidRect is the invalid region of the screen; it can be ignored for
317 * compositors where the performance for compositing the entire window is
320 * aClipRectIn is the clip rect for the window in window space (optional).
321 * aTransform is the transform from user space to window space.
322 * aRenderBounds bounding rect for rendering, in user space.
324 * If aClipRectIn is null, this method sets *aClipRectOut to the clip rect
325 * actually used for rendering (if aClipRectIn is non-null, we will use that
326 * for the clip rect).
328 * If aRenderBoundsOut is non-null, it will be set to the render bounds
329 * actually used by the compositor in window space. If aRenderBoundsOut
330 * is returned empty, composition should be aborted.
332 virtual void BeginFrame(const nsIntRegion
& aInvalidRegion
,
333 const gfx::Rect
* aClipRectIn
,
334 const gfx::Rect
& aRenderBounds
,
335 gfx::Rect
* aClipRectOut
= nullptr,
336 gfx::Rect
* aRenderBoundsOut
= nullptr) = 0;
339 * Flush the current frame to the screen and tidy up.
341 virtual void EndFrame() = 0;
343 virtual void SetFBAcquireFence(Layer
* aLayer
) {}
345 virtual FenceHandle
GetReleaseFence()
347 return FenceHandle();
351 * Post-rendering stuff if the rendering is done outside of this Compositor
352 * e.g., by Composer2D.
353 * aTransform is the transform from user space to window space.
355 virtual void EndFrameForExternalComposition(const gfx::Matrix
& aTransform
) = 0;
358 * Setup the viewport and projection matrix for rendering to a target of the
359 * given dimensions. The size and transform here will override those set in
360 * BeginFrame. BeginFrame sets a size and transform for the default render
361 * target, usually the screen. Calling this method prepares the compositor to
362 * render using a different viewport (that is, size and transform), usually
363 * associated with a new render target.
365 virtual void PrepareViewport(const gfx::IntSize
& aSize
) = 0;
368 * Whether textures created by this compositor can receive partial updates.
370 virtual bool SupportsPartialTextureUpdate() = 0;
372 void SetDiagnosticTypes(DiagnosticTypes aDiagnostics
)
374 mDiagnosticTypes
= aDiagnostics
;
377 DiagnosticTypes
GetDiagnosticTypes() const
379 return mDiagnosticTypes
;
382 void DrawDiagnostics(DiagnosticFlags aFlags
,
383 const gfx::Rect
& visibleRect
,
384 const gfx::Rect
& aClipRect
,
385 const gfx::Matrix4x4
& transform
,
386 uint32_t aFlashCounter
= DIAGNOSTIC_FLASH_COUNTER_MAX
);
388 void DrawDiagnostics(DiagnosticFlags aFlags
,
389 const nsIntRegion
& visibleRegion
,
390 const gfx::Rect
& aClipRect
,
391 const gfx::Matrix4x4
& transform
,
392 uint32_t aFlashCounter
= DIAGNOSTIC_FLASH_COUNTER_MAX
);
394 #ifdef MOZ_DUMP_PAINTING
395 virtual const char* Name() const = 0;
396 #endif // MOZ_DUMP_PAINTING
398 virtual LayersBackend
GetBackendType() const = 0;
401 * Each Compositor has a unique ID.
402 * This ID is used to keep references to each Compositor in a map accessed
403 * from the compositor thread only, so that async compositables can find
404 * the right compositor parent and schedule compositing even if the compositor
407 uint32_t GetCompositorID() const
409 return mCompositorID
;
411 void SetCompositorID(uint32_t aID
)
413 MOZ_ASSERT(mCompositorID
== 0, "The compositor ID must be set only once.");
418 * Notify the compositor that composition is being paused. This allows the
419 * compositor to temporarily release any resources.
420 * Between calling Pause and Resume, compositing may fail.
422 virtual void Pause() {}
424 * Notify the compositor that composition is being resumed. The compositor
425 * regain any resources it requires for compositing.
426 * Returns true if succeeded.
428 virtual bool Resume() { return true; }
431 * Call before rendering begins to ensure the compositor is ready to
432 * composite. Returns false if rendering should be aborted.
434 virtual bool Ready() { return true; }
436 // XXX I expect we will want to move mWidget into this class and implement
437 // these methods properly.
438 virtual nsIWidget
* GetWidget() const { return nullptr; }
441 * Debug-build assertion that can be called to ensure code is running on the
444 static void AssertOnCompositorThread();
447 * We enforce that there can only be one Compositor backend type off the main
448 * thread at the same time. The backend type in use can be checked with this
449 * static method. We need this for creating texture clients/hosts etc. when we
450 * don't have a reference to a Compositor.
452 * This can only be used from the compositor thread!
454 static LayersBackend
GetBackend();
456 size_t GetFillRatio() {
458 if (mPixelsFilled
> 0 && mPixelsPerFrame
> 0) {
459 fillRatio
= 100.0f
* float(mPixelsFilled
) / float(mPixelsPerFrame
);
460 if (fillRatio
> 999.0f
) {
467 ScreenRotation
GetScreenRotation() const {
468 return mScreenRotation
;
471 void SetScreenRotation(ScreenRotation aRotation
) {
472 mScreenRotation
= aRotation
;
476 void DrawDiagnosticsInternal(DiagnosticFlags aFlags
,
477 const gfx::Rect
& aVisibleRect
,
478 const gfx::Rect
& aClipRect
,
479 const gfx::Matrix4x4
& transform
,
480 uint32_t aFlashCounter
);
482 bool ShouldDrawDiagnostics(DiagnosticFlags
);
485 * Set the global Compositor backend, checking that one isn't already set.
487 static void SetBackend(LayersBackend backend
);
489 uint32_t mCompositorID
;
490 DiagnosticTypes mDiagnosticTypes
;
491 PCompositorParent
* mParent
;
494 * We keep track of the total number of pixels filled as we composite the
495 * current frame. This value is an approximation and is not accurate,
496 * especially in the presence of transforms.
498 size_t mPixelsPerFrame
;
499 size_t mPixelsFilled
;
501 ScreenRotation mScreenRotation
;
503 virtual gfx::IntSize
GetWidgetSize() const = 0;
505 RefPtr
<gfx::DrawTarget
> mTarget
;
506 nsIntRect mTargetBounds
;
509 static LayersBackend sBackend
;
513 // Returns the number of rects. (Up to 4)
514 typedef gfx::Rect decomposedRectArrayT
[4];
515 size_t DecomposeIntoNoRepeatRects(const gfx::Rect
& aRect
,
516 const gfx::Rect
& aTexCoordRect
,
517 decomposedRectArrayT
* aLayerRects
,
518 decomposedRectArrayT
* aTextureRects
);
520 } // namespace layers
521 } // namespace mozilla
523 #endif /* MOZILLA_GFX_COMPOSITOR_H */