|
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/. */ |
|
5 |
|
6 #ifndef MOZILLA_GFX_COMPOSITOR_H |
|
7 #define MOZILLA_GFX_COMPOSITOR_H |
|
8 |
|
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 "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc |
|
18 #include "nsRegion.h" |
|
19 #include <vector> |
|
20 #include "mozilla/WidgetUtils.h" |
|
21 |
|
22 /** |
|
23 * Different elements of a web pages are rendered into separate "layers" before |
|
24 * they are flattened into the final image that is brought to the screen. |
|
25 * See Layers.h for more informations about layers and why we use retained |
|
26 * structures. |
|
27 * Most of the documentation for layers is directly in the source code in the |
|
28 * form of doc comments. An overview can also be found in the the wiki: |
|
29 * https://wiki.mozilla.org/Gecko:Overview#Graphics |
|
30 * |
|
31 * |
|
32 * # Main interfaces and abstractions |
|
33 * |
|
34 * - Layer, ShadowableLayer and LayerComposite |
|
35 * (see Layers.h and ipc/ShadowLayers.h) |
|
36 * - CompositableClient and CompositableHost |
|
37 * (client/CompositableClient.h composite/CompositableHost.h) |
|
38 * - TextureClient and TextureHost |
|
39 * (client/TextureClient.h composite/TextureHost.h) |
|
40 * - TextureSource |
|
41 * (composite/TextureHost.h) |
|
42 * - Forwarders |
|
43 * (ipc/CompositableForwarder.h ipc/ShadowLayers.h) |
|
44 * - Compositor |
|
45 * (this file) |
|
46 * - IPDL protocols |
|
47 * (.ipdl files under the gfx/layers/ipc directory) |
|
48 * |
|
49 * The *Client and Shadowable* classes are always used on the content thread. |
|
50 * Forwarders are always used on the content thread. |
|
51 * The *Host and Shadow* classes are always used on the compositor thread. |
|
52 * Compositors, TextureSource, and Effects are always used on the compositor |
|
53 * thread. |
|
54 * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h. |
|
55 * |
|
56 * |
|
57 * # Texture transfer |
|
58 * |
|
59 * Most layer classes own a Compositable plus some extra information like |
|
60 * transforms and clip rects. They are platform independent. |
|
61 * Compositable classes manipulate Texture objects and are reponsible for |
|
62 * things like tiling, buffer rotation or double buffering. Compositables |
|
63 * are also platform-independent. Examples of compositable classes are: |
|
64 * - ImageClient |
|
65 * - CanvasClient |
|
66 * - ContentHost |
|
67 * - etc. |
|
68 * Texture classes (TextureClient and TextureHost) are thin abstractions over |
|
69 * platform-dependent texture memory. They are maniplulated by compositables |
|
70 * and don't know about buffer rotations and such. The purposes of TextureClient |
|
71 * and TextureHost are to synchronize, serialize and deserialize texture data. |
|
72 * TextureHosts provide access to TextureSources that are views on the |
|
73 * Texture data providing the necessary api for Compositor backend to composite |
|
74 * them. |
|
75 * |
|
76 * Compositable and Texture clients and hosts are created using factory methods. |
|
77 * They should only be created by using their constructor in exceptional |
|
78 * circumstances. The factory methods are located: |
|
79 * TextureClient - CompositableClient::CreateTextureClient |
|
80 * TextureHost - TextureHost::CreateTextureHost, which calls a |
|
81 * platform-specific function, e.g., CreateTextureHostOGL |
|
82 * CompositableClient - in the appropriate subclass, e.g., |
|
83 * CanvasClient::CreateCanvasClient |
|
84 * CompositableHost - CompositableHost::Create |
|
85 * |
|
86 * |
|
87 * # IPDL |
|
88 * |
|
89 * If off-main-thread compositing (OMTC) is enabled, compositing is performed |
|
90 * in a dedicated thread. In some setups compositing happens in a dedicated |
|
91 * process. Documentation may refer to either the compositor thread or the |
|
92 * compositor process. |
|
93 * See explanations in ShadowLayers.h. |
|
94 * |
|
95 * |
|
96 * # Backend implementations |
|
97 * |
|
98 * Compositor backends like OpenGL or flavours of D3D live in their own directory |
|
99 * under gfx/layers/. To add a new backend, implement at least the following |
|
100 * interfaces: |
|
101 * - Compositor (ex. CompositorOGL) |
|
102 * - TextureHost (ex. SharedTextureHostOGL) |
|
103 * Depending on the type of data that needs to be serialized, you may need to |
|
104 * add specific TextureClient implementations. |
|
105 */ |
|
106 |
|
107 class nsIWidget; |
|
108 struct nsIntSize; |
|
109 class nsIntRegion; |
|
110 |
|
111 namespace mozilla { |
|
112 namespace gfx { |
|
113 class Matrix; |
|
114 class Matrix4x4; |
|
115 class DrawTarget; |
|
116 } |
|
117 |
|
118 namespace layers { |
|
119 |
|
120 struct Effect; |
|
121 struct EffectChain; |
|
122 class Image; |
|
123 class ISurfaceAllocator; |
|
124 class Layer; |
|
125 class NewTextureSource; |
|
126 class DataTextureSource; |
|
127 class CompositingRenderTarget; |
|
128 class PCompositorParent; |
|
129 class LayerManagerComposite; |
|
130 |
|
131 enum SurfaceInitMode |
|
132 { |
|
133 INIT_MODE_NONE, |
|
134 INIT_MODE_CLEAR |
|
135 }; |
|
136 |
|
137 /** |
|
138 * A base class for a platform-dependent helper for use by TextureHost. |
|
139 */ |
|
140 class CompositorBackendSpecificData |
|
141 { |
|
142 NS_INLINE_DECL_REFCOUNTING(CompositorBackendSpecificData) |
|
143 |
|
144 protected: |
|
145 virtual ~CompositorBackendSpecificData() {} |
|
146 }; |
|
147 |
|
148 /** |
|
149 * Common interface for compositor backends. |
|
150 * |
|
151 * Compositor provides a cross-platform interface to a set of operations for |
|
152 * compositing quads. Compositor knows nothing about the layer tree. It must be |
|
153 * told everything about each composited quad - contents, location, transform, |
|
154 * opacity, etc. |
|
155 * |
|
156 * In theory it should be possible for different widgets to use the same |
|
157 * compositor. In practice, we use one compositor per window. |
|
158 * |
|
159 * # Usage |
|
160 * |
|
161 * For an example of a user of Compositor, see LayerManagerComposite. |
|
162 * |
|
163 * Initialization: create a Compositor object, call Initialize(). |
|
164 * |
|
165 * Destruction: destroy any resources associated with the compositor, call |
|
166 * Destroy(), delete the Compositor object. |
|
167 * |
|
168 * Composition: |
|
169 * call BeginFrame, |
|
170 * for each quad to be composited: |
|
171 * call MakeCurrent if necessary (not necessary if no other context has been |
|
172 * made current), |
|
173 * take care of any texture upload required to composite the quad, this step |
|
174 * is backend-dependent, |
|
175 * construct an EffectChain for the quad, |
|
176 * call DrawQuad, |
|
177 * call EndFrame. |
|
178 * If the user has to stop compositing at any point before EndFrame, call |
|
179 * AbortFrame. |
|
180 * If the compositor is usually used for compositing but compositing is |
|
181 * temporarily done without the compositor, call EndFrameForExternalComposition |
|
182 * after compositing each frame so the compositor can remain internally |
|
183 * consistent. |
|
184 * |
|
185 * By default, the compositor will render to the screen, to render to a target, |
|
186 * call SetTargetContext or SetRenderTarget, the latter with a target created |
|
187 * by CreateRenderTarget or CreateRenderTargetFromSource. |
|
188 * |
|
189 * The target and viewport methods can be called before any DrawQuad call and |
|
190 * affect any subsequent DrawQuad calls. |
|
191 */ |
|
192 class Compositor |
|
193 { |
|
194 protected: |
|
195 virtual ~Compositor() {} |
|
196 |
|
197 public: |
|
198 NS_INLINE_DECL_REFCOUNTING(Compositor) |
|
199 |
|
200 Compositor(PCompositorParent* aParent = nullptr) |
|
201 : mCompositorID(0) |
|
202 , mDiagnosticTypes(DIAGNOSTIC_NONE) |
|
203 , mParent(aParent) |
|
204 , mScreenRotation(ROTATION_0) |
|
205 { |
|
206 } |
|
207 |
|
208 virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = 0) = 0; |
|
209 virtual bool Initialize() = 0; |
|
210 virtual void Destroy() = 0; |
|
211 |
|
212 /** |
|
213 * Return true if the effect type is supported. |
|
214 * |
|
215 * By default Compositor implementations should support all effects but in |
|
216 * some rare cases it is not possible to support an effect efficiently. |
|
217 * This is the case for BasicCompositor with EffectYCbCr. |
|
218 */ |
|
219 virtual bool SupportsEffect(EffectTypes aEffect) { return true; } |
|
220 |
|
221 /** |
|
222 * Request a texture host identifier that may be used for creating textures |
|
223 * across process or thread boundaries that are compatible with this |
|
224 * compositor. |
|
225 */ |
|
226 virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() = 0; |
|
227 |
|
228 /** |
|
229 * Properties of the compositor. |
|
230 */ |
|
231 virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) = 0; |
|
232 virtual int32_t GetMaxTextureSize() const = 0; |
|
233 |
|
234 /** |
|
235 * Set the target for rendering. Results will have been written to aTarget by |
|
236 * the time that EndFrame returns. |
|
237 * |
|
238 * If this method is not used, or we pass in nullptr, we target the compositor's |
|
239 * usual swap chain and render to the screen. |
|
240 */ |
|
241 virtual void SetTargetContext(gfx::DrawTarget* aTarget) = 0; |
|
242 |
|
243 typedef uint32_t MakeCurrentFlags; |
|
244 static const MakeCurrentFlags ForceMakeCurrent = 0x1; |
|
245 /** |
|
246 * Make this compositor's rendering context the current context for the |
|
247 * underlying graphics API. This may be a global operation, depending on the |
|
248 * API. Our context will remain the current one until someone else changes it. |
|
249 * |
|
250 * Clients of the compositor should call this at the start of the compositing |
|
251 * process, it might be required by texture uploads etc. |
|
252 * |
|
253 * If aFlags == ForceMakeCurrent then we will (re-)set our context on the |
|
254 * underlying API even if it is already the current context. |
|
255 */ |
|
256 virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) = 0; |
|
257 |
|
258 /** |
|
259 * Creates a Surface that can be used as a rendering target by this |
|
260 * compositor. |
|
261 */ |
|
262 virtual TemporaryRef<CompositingRenderTarget> |
|
263 CreateRenderTarget(const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0; |
|
264 |
|
265 /** |
|
266 * Creates a Surface that can be used as a rendering target by this |
|
267 * compositor, and initializes the surface by copying from aSource. |
|
268 * If aSource is null, then the current screen buffer is used as source. |
|
269 * |
|
270 * aSourcePoint specifies the point in aSource to copy data from. |
|
271 */ |
|
272 virtual TemporaryRef<CompositingRenderTarget> |
|
273 CreateRenderTargetFromSource(const gfx::IntRect& aRect, |
|
274 const CompositingRenderTarget* aSource, |
|
275 const gfx::IntPoint& aSourcePoint) = 0; |
|
276 |
|
277 /** |
|
278 * Sets the given surface as the target for subsequent calls to DrawQuad. |
|
279 * Passing null as aSurface sets the screen as the target. |
|
280 */ |
|
281 virtual void SetRenderTarget(CompositingRenderTarget* aSurface) = 0; |
|
282 |
|
283 /** |
|
284 * Returns the current target for rendering. Will return null if we are |
|
285 * rendering to the screen. |
|
286 */ |
|
287 virtual CompositingRenderTarget* GetCurrentRenderTarget() const = 0; |
|
288 |
|
289 /** |
|
290 * Mostly the compositor will pull the size from a widget and this method will |
|
291 * be ignored, but compositor implementations are free to use it if they like. |
|
292 */ |
|
293 virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) = 0; |
|
294 |
|
295 /** |
|
296 * Declare an offset to use when rendering layers. This will be ignored when |
|
297 * rendering to a target instead of the screen. |
|
298 */ |
|
299 virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) = 0; |
|
300 |
|
301 /** |
|
302 * Tell the compositor to draw a quad. What to do draw and how it is |
|
303 * drawn is specified by aEffectChain. aRect is the quad to draw, in user space. |
|
304 * aTransform transforms from user space to screen space. If texture coords are |
|
305 * required, these will be in the primary effect in the effect chain. |
|
306 */ |
|
307 virtual void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, |
|
308 const EffectChain& aEffectChain, |
|
309 gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform) = 0; |
|
310 |
|
311 /** |
|
312 * Tell the compositor to draw lines connecting the points. Behaves like |
|
313 * DrawQuad. |
|
314 */ |
|
315 virtual void DrawLines(const std::vector<gfx::Point>& aLines, const gfx::Rect& aClipRect, |
|
316 const gfx::Color& aColor, |
|
317 gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform) |
|
318 { /* Should turn into pure virtual once implemented in D3D */ } |
|
319 |
|
320 /* |
|
321 * Clear aRect on current render target. |
|
322 */ |
|
323 virtual void ClearRect(const gfx::Rect& aRect) { } |
|
324 |
|
325 /** |
|
326 * Start a new frame. |
|
327 * |
|
328 * aInvalidRect is the invalid region of the screen; it can be ignored for |
|
329 * compositors where the performance for compositing the entire window is |
|
330 * sufficient. |
|
331 * |
|
332 * aClipRectIn is the clip rect for the window in window space (optional). |
|
333 * aTransform is the transform from user space to window space. |
|
334 * aRenderBounds bounding rect for rendering, in user space. |
|
335 * |
|
336 * If aClipRectIn is null, this method sets *aClipRectOut to the clip rect |
|
337 * actually used for rendering (if aClipRectIn is non-null, we will use that |
|
338 * for the clip rect). |
|
339 * |
|
340 * If aRenderBoundsOut is non-null, it will be set to the render bounds |
|
341 * actually used by the compositor in window space. If aRenderBoundsOut |
|
342 * is returned empty, composition should be aborted. |
|
343 */ |
|
344 virtual void BeginFrame(const nsIntRegion& aInvalidRegion, |
|
345 const gfx::Rect* aClipRectIn, |
|
346 const gfx::Matrix& aTransform, |
|
347 const gfx::Rect& aRenderBounds, |
|
348 gfx::Rect* aClipRectOut = nullptr, |
|
349 gfx::Rect* aRenderBoundsOut = nullptr) = 0; |
|
350 |
|
351 /** |
|
352 * Flush the current frame to the screen and tidy up. |
|
353 */ |
|
354 virtual void EndFrame() = 0; |
|
355 |
|
356 virtual void SetFBAcquireFence(Layer* aLayer) {} |
|
357 |
|
358 /** |
|
359 * Post-rendering stuff if the rendering is done outside of this Compositor |
|
360 * e.g., by Composer2D. |
|
361 * aTransform is the transform from user space to window space. |
|
362 */ |
|
363 virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0; |
|
364 |
|
365 /** |
|
366 * Tidy up if BeginFrame has been called, but EndFrame won't be. |
|
367 */ |
|
368 virtual void AbortFrame() = 0; |
|
369 |
|
370 /** |
|
371 * Setup the viewport and projection matrix for rendering to a target of the |
|
372 * given dimensions. The size and transform here will override those set in |
|
373 * BeginFrame. BeginFrame sets a size and transform for the default render |
|
374 * target, usually the screen. Calling this method prepares the compositor to |
|
375 * render using a different viewport (that is, size and transform), usually |
|
376 * associated with a new render target. |
|
377 * aWorldTransform is the transform from user space to the new viewport's |
|
378 * coordinate space. |
|
379 */ |
|
380 virtual void PrepareViewport(const gfx::IntSize& aSize, |
|
381 const gfx::Matrix& aWorldTransform) = 0; |
|
382 |
|
383 /** |
|
384 * Whether textures created by this compositor can receive partial updates. |
|
385 */ |
|
386 virtual bool SupportsPartialTextureUpdate() = 0; |
|
387 |
|
388 void SetDiagnosticTypes(DiagnosticTypes aDiagnostics) |
|
389 { |
|
390 mDiagnosticTypes = aDiagnostics; |
|
391 } |
|
392 |
|
393 DiagnosticTypes GetDiagnosticTypes() const |
|
394 { |
|
395 return mDiagnosticTypes; |
|
396 } |
|
397 |
|
398 void DrawDiagnostics(DiagnosticFlags aFlags, |
|
399 const gfx::Rect& visibleRect, |
|
400 const gfx::Rect& aClipRect, |
|
401 const gfx::Matrix4x4& transform, |
|
402 uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX); |
|
403 |
|
404 void DrawDiagnostics(DiagnosticFlags aFlags, |
|
405 const nsIntRegion& visibleRegion, |
|
406 const gfx::Rect& aClipRect, |
|
407 const gfx::Matrix4x4& transform, |
|
408 uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX); |
|
409 |
|
410 #ifdef MOZ_DUMP_PAINTING |
|
411 virtual const char* Name() const = 0; |
|
412 #endif // MOZ_DUMP_PAINTING |
|
413 |
|
414 virtual LayersBackend GetBackendType() const = 0; |
|
415 |
|
416 /** |
|
417 * Each Compositor has a unique ID. |
|
418 * This ID is used to keep references to each Compositor in a map accessed |
|
419 * from the compositor thread only, so that async compositables can find |
|
420 * the right compositor parent and schedule compositing even if the compositor |
|
421 * changed. |
|
422 */ |
|
423 uint32_t GetCompositorID() const |
|
424 { |
|
425 return mCompositorID; |
|
426 } |
|
427 void SetCompositorID(uint32_t aID) |
|
428 { |
|
429 MOZ_ASSERT(mCompositorID == 0, "The compositor ID must be set only once."); |
|
430 mCompositorID = aID; |
|
431 } |
|
432 |
|
433 /** |
|
434 * Notify the compositor that composition is being paused. This allows the |
|
435 * compositor to temporarily release any resources. |
|
436 * Between calling Pause and Resume, compositing may fail. |
|
437 */ |
|
438 virtual void Pause() {} |
|
439 /** |
|
440 * Notify the compositor that composition is being resumed. The compositor |
|
441 * regain any resources it requires for compositing. |
|
442 * Returns true if succeeded. |
|
443 */ |
|
444 virtual bool Resume() { return true; } |
|
445 |
|
446 /** |
|
447 * Call before rendering begins to ensure the compositor is ready to |
|
448 * composite. Returns false if rendering should be aborted. |
|
449 */ |
|
450 virtual bool Ready() { return true; } |
|
451 |
|
452 // XXX I expect we will want to move mWidget into this class and implement |
|
453 // these methods properly. |
|
454 virtual nsIWidget* GetWidget() const { return nullptr; } |
|
455 |
|
456 /** |
|
457 * Debug-build assertion that can be called to ensure code is running on the |
|
458 * compositor thread. |
|
459 */ |
|
460 static void AssertOnCompositorThread(); |
|
461 |
|
462 /** |
|
463 * We enforce that there can only be one Compositor backend type off the main |
|
464 * thread at the same time. The backend type in use can be checked with this |
|
465 * static method. We need this for creating texture clients/hosts etc. when we |
|
466 * don't have a reference to a Compositor. |
|
467 * |
|
468 * This can only be used from the compositor thread! |
|
469 */ |
|
470 static LayersBackend GetBackend(); |
|
471 |
|
472 size_t GetFillRatio() { |
|
473 float fillRatio = 0; |
|
474 if (mPixelsFilled > 0 && mPixelsPerFrame > 0) { |
|
475 fillRatio = 100.0f * float(mPixelsFilled) / float(mPixelsPerFrame); |
|
476 if (fillRatio > 999.0f) { |
|
477 fillRatio = 999.0f; |
|
478 } |
|
479 } |
|
480 return fillRatio; |
|
481 } |
|
482 |
|
483 virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() { |
|
484 return nullptr; |
|
485 } |
|
486 |
|
487 ScreenRotation GetScreenRotation() const { |
|
488 return mScreenRotation; |
|
489 } |
|
490 |
|
491 void SetScreenRotation(ScreenRotation aRotation) { |
|
492 mScreenRotation = aRotation; |
|
493 } |
|
494 |
|
495 // On b2g the clip rect is in the coordinate space of the physical screen |
|
496 // independently of its rotation, while the coordinate space of the layers, |
|
497 // on the other hand, depends on the screen orientation. |
|
498 // This only applies to b2g as with other platforms, orientation is handled |
|
499 // at the OS level rather than in Gecko. |
|
500 // In addition, the clip rect needs to be offset by the rendering origin. |
|
501 // This becomes important if intermediate surfaces are used. |
|
502 gfx::Rect ClipRectInLayersCoordinates(gfx::Rect aClip) const; |
|
503 |
|
504 protected: |
|
505 void DrawDiagnosticsInternal(DiagnosticFlags aFlags, |
|
506 const gfx::Rect& aVisibleRect, |
|
507 const gfx::Rect& aClipRect, |
|
508 const gfx::Matrix4x4& transform, |
|
509 uint32_t aFlashCounter); |
|
510 |
|
511 bool ShouldDrawDiagnostics(DiagnosticFlags); |
|
512 |
|
513 /** |
|
514 * Set the global Compositor backend, checking that one isn't already set. |
|
515 */ |
|
516 static void SetBackend(LayersBackend backend); |
|
517 |
|
518 uint32_t mCompositorID; |
|
519 DiagnosticTypes mDiagnosticTypes; |
|
520 PCompositorParent* mParent; |
|
521 |
|
522 /** |
|
523 * We keep track of the total number of pixels filled as we composite the |
|
524 * current frame. This value is an approximation and is not accurate, |
|
525 * especially in the presence of transforms. |
|
526 */ |
|
527 size_t mPixelsPerFrame; |
|
528 size_t mPixelsFilled; |
|
529 |
|
530 ScreenRotation mScreenRotation; |
|
531 |
|
532 virtual gfx::IntSize GetWidgetSize() const = 0; |
|
533 |
|
534 private: |
|
535 static LayersBackend sBackend; |
|
536 |
|
537 }; |
|
538 |
|
539 } // namespace layers |
|
540 } // namespace mozilla |
|
541 |
|
542 #endif /* MOZILLA_GFX_COMPOSITOR_H */ |