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/Point.h" // for IntSize, Point
13 #include "mozilla/gfx/Rect.h" // for Rect, IntRect
14 #include "mozilla/gfx/Types.h" // for Float
15 #include "mozilla/layers/CompositorTypes.h" // for DiagnosticTypes, etc
16 #include "mozilla/layers/LayersTypes.h" // for LayersBackend
17 #include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
20 * Different elements of a web pages are rendered into separate "layers" before
21 * they are flattened into the final image that is brought to the screen.
22 * See Layers.h for more informations about layers and why we use retained
24 * Most of the documentation for layers is directly in the source code in the
25 * form of doc comments. An overview can also be found in the the wiki:
26 * https://wiki.mozilla.org/Gecko:Overview#Graphics
29 * # Main interfaces and abstractions
31 * - Layer, ShadowableLayer and LayerComposite
32 * (see Layers.h and ipc/ShadowLayers.h)
33 * - CompositableClient and CompositableHost
34 * (client/CompositableClient.h composite/CompositableHost.h)
35 * - TextureClient and TextureHost
36 * (client/TextureClient.h composite/TextureHost.h)
38 * (composite/TextureHost.h)
40 * (ipc/CompositableForwarder.h ipc/ShadowLayers.h)
44 * (.ipdl files under the gfx/layers/ipc directory)
46 * The *Client and Shadowable* classes are always used on the content thread.
47 * Forwarders are always used on the content thread.
48 * The *Host and Shadow* classes are always used on the compositor thread.
49 * Compositors, TextureSource, and Effects are always used on the compositor
51 * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h.
56 * Most layer classes own a Compositable plus some extra information like
57 * transforms and clip rects. They are platform independent.
58 * Compositable classes manipulate Texture objects and are reponsible for
59 * things like tiling, buffer rotation or double buffering. Compositables
60 * are also platform-independent. Examples of compositable classes are:
65 * Texture classes (TextureClient and TextureHost) are thin abstractions over
66 * platform-dependent texture memory. They are maniplulated by compositables
67 * and don't know about buffer rotations and such. The purposes of TextureClient
68 * and TextureHost are to synchronize, serialize and deserialize texture data.
69 * TextureHosts provide access to TextureSources that are views on the
70 * Texture data providing the necessary api for Compositor backend to composite
73 * Compositable and Texture clients and hosts are created using factory methods.
74 * They should only be created by using their constructor in exceptional
75 * circumstances. The factory methods are located:
76 * TextureClient - CompositableClient::CreateTextureClient
77 * TextureHost - TextureHost::CreateTextureHost, which calls a
78 * platform-specific function, e.g., CreateTextureHostOGL
79 * CompositableClient - in the appropriate subclass, e.g.,
80 * CanvasClient::CreateCanvasClient
81 * CompositableHost - CompositableHost::Create
86 * If off-main-thread compositing (OMTC) is enabled, compositing is performed
87 * in a dedicated thread. In some setups compositing happens in a dedicated
88 * process. Documentation may refer to either the compositor thread or the
90 * See explanations in ShadowLayers.h.
93 * # Backend implementations
95 * Compositor backends like OpenGL or flavours of D3D live in their own directory
96 * under gfx/layers/. To add a new backend, implement at least the following
98 * - Compositor (ex. CompositorOGL)
99 * - TextureHost (ex. SharedTextureHostOGL)
100 * Depending on the type of data that needs to be serialized, you may need to
101 * add specific TextureClient implementations.
120 class ISurfaceAllocator
;
121 class NewTextureSource
;
122 class DataTextureSource
;
123 class CompositingRenderTarget
;
133 * Common interface for compositor backends.
135 * Compositor provides a cross-platform interface to a set of operations for
136 * compositing quads. Compositor knows nothing about the layer tree. It must be
137 * told everything about each composited quad - contents, location, transform,
140 * In theory it should be possible for different widgets to use the same
141 * compositor. In practice, we use one compositor per window.
145 * For an example of a user of Compositor, see LayerManagerComposite.
147 * Initialization: create a Compositor object, call Initialize().
149 * Destruction: destroy any resources associated with the compositor, call
150 * Destroy(), delete the Compositor object.
154 * for each quad to be composited:
155 * call MakeCurrent if necessary (not necessary if no other context has been
157 * take care of any texture upload required to composite the quad, this step
158 * is backend-dependent,
159 * construct an EffectChain for the quad,
162 * If the user has to stop compositing at any point before EndFrame, call
164 * If the compositor is usually used for compositing but compositing is
165 * temporarily done without the compositor, call EndFrameForExternalComposition
166 * after compositing each frame so the compositor can remain internally
169 * By default, the compositor will render to the screen, to render to a target,
170 * call SetTargetContext or SetRenderTarget, the latter with a target created
171 * by CreateRenderTarget or CreateRenderTargetFromSource.
173 * The target and viewport methods can be called before any DrawQuad call and
174 * affect any subsequent DrawQuad calls.
176 class Compositor
: public RefCounted
<Compositor
>
181 , mDiagnosticTypes(DIAGNOSTIC_NONE
)
183 MOZ_COUNT_CTOR(Compositor
);
185 virtual ~Compositor()
187 MOZ_COUNT_DTOR(Compositor
);
190 virtual TemporaryRef
<DataTextureSource
> CreateDataTextureSource(TextureFlags aFlags
= 0) = 0;
191 virtual bool Initialize() = 0;
192 virtual void Destroy() = 0;
195 * Return true if the effect type is supported.
197 * By default Compositor implementations should support all effects but in
198 * some rare cases it is not possible to support an effect efficiently.
199 * This is the case for BasicCompositor with EffectYCbCr.
201 virtual bool SupportsEffect(EffectTypes aEffect
) { return true; }
204 * Request a texture host identifier that may be used for creating textures
205 * across process or thread boundaries that are compatible with this
208 virtual TextureFactoryIdentifier
GetTextureFactoryIdentifier() = 0;
211 * Properties of the compositor.
213 virtual bool CanUseCanvasLayerForSize(const gfx::IntSize
& aSize
) = 0;
214 virtual int32_t GetMaxTextureSize() const = 0;
217 * Set the target for rendering. Results will have been written to aTarget by
218 * the time that EndFrame returns.
220 * If this method is not used, or we pass in nullptr, we target the compositor's
221 * usual swap chain and render to the screen.
223 virtual void SetTargetContext(gfx::DrawTarget
* aTarget
) = 0;
225 typedef uint32_t MakeCurrentFlags
;
226 static const MakeCurrentFlags ForceMakeCurrent
= 0x1;
228 * Make this compositor's rendering context the current context for the
229 * underlying graphics API. This may be a global operation, depending on the
230 * API. Our context will remain the current one until someone else changes it.
232 * Clients of the compositor should call this at the start of the compositing
233 * process, it might be required by texture uploads etc.
235 * If aFlags == ForceMakeCurrent then we will (re-)set our context on the
236 * underlying API even if it is already the current context.
238 virtual void MakeCurrent(MakeCurrentFlags aFlags
= 0) = 0;
241 * Creates a Surface that can be used as a rendering target by this
244 virtual TemporaryRef
<CompositingRenderTarget
>
245 CreateRenderTarget(const gfx::IntRect
& aRect
, SurfaceInitMode aInit
) = 0;
248 * Creates a Surface that can be used as a rendering target by this
249 * compositor, and initializes the surface by copying from aSource.
250 * If aSource is null, then the current screen buffer is used as source.
252 virtual TemporaryRef
<CompositingRenderTarget
>
253 CreateRenderTargetFromSource(const gfx::IntRect
& aRect
,
254 const CompositingRenderTarget
* aSource
) = 0;
257 * Sets the given surface as the target for subsequent calls to DrawQuad.
258 * Passing null as aSurface sets the screen as the target.
260 virtual void SetRenderTarget(CompositingRenderTarget
* aSurface
) = 0;
263 * Returns the current target for rendering. Will return null if we are
264 * rendering to the screen.
266 virtual CompositingRenderTarget
* GetCurrentRenderTarget() = 0;
269 * Mostly the compositor will pull the size from a widget and this method will
270 * be ignored, but compositor implementations are free to use it if they like.
272 virtual void SetDestinationSurfaceSize(const gfx::IntSize
& aSize
) = 0;
275 * Declare an offset to use when rendering layers. This will be ignored when
276 * rendering to a target instead of the screen.
278 virtual void SetScreenRenderOffset(const ScreenPoint
& aOffset
) = 0;
281 * Tell the compositor to actually draw a quad. What to do draw and how it is
282 * drawn is specified by aEffectChain. aRect is the quad to draw, in user space.
283 * aTransform transforms from user space to screen space. aOffset is the
284 * offset of the render target from 0,0 of the screen. If texture coords are
285 * required, these will be in the primary effect in the effect chain.
287 virtual void DrawQuad(const gfx::Rect
& aRect
, const gfx::Rect
& aClipRect
,
288 const EffectChain
& aEffectChain
,
289 gfx::Float aOpacity
, const gfx::Matrix4x4
&aTransform
,
290 const gfx::Point
& aOffset
) = 0;
294 * aClipRectIn is the clip rect for the window in window space (optional).
295 * aTransform is the transform from user space to window space.
296 * aRenderBounds bounding rect for rendering, in user space.
297 * If aClipRectIn is null, this method sets *aClipRectOut to the clip rect
298 * actually used for rendering (if aClipRectIn is non-null, we will use that
299 * for the clip rect).
300 * If aRenderBoundsOut is non-null, it will be set to the render bounds
301 * actually used by the compositor in window space.
303 virtual void BeginFrame(const gfx::Rect
* aClipRectIn
,
304 const gfxMatrix
& aTransform
,
305 const gfx::Rect
& aRenderBounds
,
306 gfx::Rect
* aClipRectOut
= nullptr,
307 gfx::Rect
* aRenderBoundsOut
= nullptr) = 0;
310 * Flush the current frame to the screen and tidy up.
312 virtual void EndFrame() = 0;
315 * Post-rendering stuff if the rendering is done outside of this Compositor
316 * e.g., by Composer2D.
317 * aTransform is the transform from user space to window space.
319 virtual void EndFrameForExternalComposition(const gfxMatrix
& aTransform
) = 0;
322 * Tidy up if BeginFrame has been called, but EndFrame won't be.
324 virtual void AbortFrame() = 0;
327 * Setup the viewport and projection matrix for rendering to a target of the
328 * given dimensions. The size and transform here will override those set in
329 * BeginFrame. BeginFrame sets a size and transform for the default render
330 * target, usually the screen. Calling this method prepares the compositor to
331 * render using a different viewport (that is, size and transform), usually
332 * associated with a new render target.
333 * aWorldTransform is the transform from user space to the new viewport's
336 virtual void PrepareViewport(const gfx::IntSize
& aSize
,
337 const gfxMatrix
& aWorldTransform
) = 0;
340 * Whether textures created by this compositor can receive partial updates.
342 virtual bool SupportsPartialTextureUpdate() = 0;
344 void SetDiagnosticTypes(DiagnosticTypes aDiagnostics
)
346 mDiagnosticTypes
= aDiagnostics
;
349 void DrawDiagnostics(DiagnosticFlags aFlags
,
350 const gfx::Rect
& visibleRect
,
351 const gfx::Rect
& aClipRect
,
352 const gfx::Matrix4x4
& transform
,
353 const gfx::Point
& aOffset
);
355 void DrawDiagnostics(DiagnosticFlags aFlags
,
356 const nsIntRegion
& visibleRegion
,
357 const gfx::Rect
& aClipRect
,
358 const gfx::Matrix4x4
& transform
,
359 const gfx::Point
& aOffset
);
362 #ifdef MOZ_DUMP_PAINTING
363 virtual const char* Name() const = 0;
364 #endif // MOZ_DUMP_PAINTING
368 * Each Compositor has a unique ID.
369 * This ID is used to keep references to each Compositor in a map accessed
370 * from the compositor thread only, so that async compositables can find
371 * the right compositor parent and schedule compositing even if the compositor
374 uint32_t GetCompositorID() const
376 return mCompositorID
;
378 void SetCompositorID(uint32_t aID
)
380 MOZ_ASSERT(mCompositorID
== 0, "The compositor ID must be set only once.");
385 * Notify the compositor that a layers transaction has occured. This is only
386 * used for FPS information at the moment.
387 * XXX: surely there is a better way to do this?
389 virtual void NotifyLayersTransaction() = 0;
392 * Notify the compositor that composition is being paused. This allows the
393 * compositor to temporarily release any resources.
394 * Between calling Pause and Resume, compositing may fail.
396 virtual void Pause() {}
398 * Notify the compositor that composition is being resumed. The compositor
399 * regain any resources it requires for compositing.
400 * Returns true if succeeded.
402 virtual bool Resume() { return true; }
404 // XXX I expect we will want to move mWidget into this class and implement
405 // these methods properly.
406 virtual nsIWidget
* GetWidget() const { return nullptr; }
407 virtual const nsIntSize
& GetWidgetSize() = 0;
409 // Call before and after any rendering not done by this compositor but which
410 // might affect the compositor's internal state or the state of any APIs it
411 // uses. For example, internal GL state.
412 virtual void SaveState() {}
413 virtual void RestoreState() {}
416 * Debug-build assertion that can be called to ensure code is running on the
419 static void AssertOnCompositorThread();
422 * We enforce that there can only be one Compositor backend type off the main
423 * thread at the same time. The backend type in use can be checked with this
424 * static method. We need this for creating texture clients/hosts etc. when we
425 * don't have a reference to a Compositor.
427 * This can only be used from the compositor thread!
429 static LayersBackend
GetBackend();
432 void DrawDiagnosticsInternal(DiagnosticFlags aFlags
,
433 const gfx::Rect
& aVisibleRect
,
434 const gfx::Rect
& aClipRect
,
435 const gfx::Matrix4x4
& transform
,
436 const gfx::Point
& aOffset
);
438 bool ShouldDrawDiagnostics(DiagnosticFlags
);
440 uint32_t mCompositorID
;
441 static LayersBackend sBackend
;
442 DiagnosticTypes mDiagnosticTypes
;
445 * We keep track of the total number of pixels filled as we composite the
446 * current frame. This value is an approximation and is not accurate,
447 * especially in the presence of transforms.
449 size_t mPixelsPerFrame
;
450 size_t mPixelsFilled
;
453 } // namespace layers
454 } // namespace mozilla
456 #endif /* MOZILLA_GFX_COMPOSITOR_H */