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 already_AddRefed, RefCounted
12 #include "mozilla/gfx/2D.h" // for DrawTarget
13 #include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
14 #include "mozilla/gfx/Point.h" // for IntSize, Point
15 #include "mozilla/gfx/Polygon.h" // for Polygon3D
16 #include "mozilla/gfx/Rect.h" // for Rect, IntRect
17 #include "mozilla/gfx/Types.h" // for Float
18 #include "mozilla/gfx/Triangle.h" // for Triangle, TexturedTriangle
19 #include "mozilla/layers/CompositorTypes.h" // for DiagnosticTypes, etc
20 #include "mozilla/layers/LayersTypes.h" // for LayersBackend
21 #include "mozilla/widget/CompositorWidget.h"
22 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
23 #include "nsRegion.h"
24 #include <vector>
25 #include "mozilla/WidgetUtils.h"
26
27 /**
28 * Different elements of a web pages are rendered into separate "layers" before
29 * they are flattened into the final image that is brought to the screen.
30 * See Layers.h for more informations about layers and why we use retained
31 * structures.
32 * Most of the documentation for layers is directly in the source code in the
33 * form of doc comments. An overview can also be found in the the wiki:
34 * https://wiki.mozilla.org/Gecko:Overview#Graphics
35 *
36 *
37 * # Main interfaces and abstractions
38 *
39 * - Layer, ShadowableLayer and LayerComposite
40 * (see Layers.h and ipc/ShadowLayers.h)
41 * - CompositableClient and CompositableHost
42 * (client/CompositableClient.h composite/CompositableHost.h)
43 * - TextureClient and TextureHost
44 * (client/TextureClient.h composite/TextureHost.h)
45 * - TextureSource
46 * (composite/TextureHost.h)
47 * - Forwarders
48 * (ipc/CompositableForwarder.h ipc/ShadowLayers.h)
49 * - Compositor
50 * (this file)
51 * - IPDL protocols
52 * (.ipdl files under the gfx/layers/ipc directory)
53 *
54 * The *Client and Shadowable* classes are always used on the content thread.
55 * Forwarders are always used on the content thread.
56 * The *Host and Shadow* classes are always used on the compositor thread.
57 * Compositors, TextureSource, and Effects are always used on the compositor
58 * thread.
59 * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h.
60 *
61 *
62 * # Texture transfer
63 *
64 * Most layer classes own a Compositable plus some extra information like
65 * transforms and clip rects. They are platform independent.
66 * Compositable classes manipulate Texture objects and are reponsible for
67 * things like tiling, buffer rotation or double buffering. Compositables
68 * are also platform-independent. Examples of compositable classes are:
69 * - ImageClient
70 * - CanvasClient
71 * - ContentHost
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., CreateTextureHostOGL
87 * 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 directory
104 * under gfx/layers/. To add a new backend, implement at least the following
105 * 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 Matrix;
117 class DrawTarget;
118 class DataSourceSurface;
119 } // namespace gfx
120
121 namespace layers {
122
123 struct Effect;
124 struct EffectChain;
125 class Image;
126 class ImageHostOverlay;
127 class Layer;
128 class TextureSource;
129 class DataTextureSource;
130 class CompositingRenderTarget;
131 class CompositorBridgeParent;
132 class LayerManagerComposite;
133 class CompositorOGL;
134 class CompositorD3D9;
135 class CompositorD3D11;
136 class BasicCompositor;
137 class TextureHost;
138 class TextureReadLock;
139
140 enum SurfaceInitMode
141 {
142 INIT_MODE_NONE,
143 INIT_MODE_CLEAR
144 };
145
146 /**
147 * Common interface for compositor backends.
148 *
149 * Compositor provides a cross-platform interface to a set of operations for
150 * compositing quads. Compositor knows nothing about the layer tree. It must be
151 * told everything about each composited quad - contents, location, transform,
152 * opacity, etc.
153 *
154 * In theory it should be possible for different widgets to use the same
155 * compositor. In practice, we use one compositor per window.
156 *
157 * # Usage
158 *
159 * For an example of a user of Compositor, see LayerManagerComposite.
160 *
161 * Initialization: create a Compositor object, call Initialize().
162 *
163 * Destruction: destroy any resources associated with the compositor, call
164 * Destroy(), delete the Compositor object.
165 *
166 * Composition:
167 * call BeginFrame,
168 * for each quad to be composited:
169 * call MakeCurrent if necessary (not necessary if no other context has been
170 * made current),
171 * take care of any texture upload required to composite the quad, this step
172 * is backend-dependent,
173 * construct an EffectChain for the quad,
174 * call DrawQuad,
175 * call EndFrame.
176 * If the compositor is usually used for compositing but compositing is
177 * temporarily done without the compositor, call EndFrameForExternalComposition
178 * after compositing each frame so the compositor can remain internally
179 * consistent.
180 *
181 * By default, the compositor will render to the screen, to render to a target,
182 * call SetTargetContext or SetRenderTarget, the latter with a target created
183 * by CreateRenderTarget or CreateRenderTargetFromSource.
184 *
185 * The target and viewport methods can be called before any DrawQuad call and
186 * affect any subsequent DrawQuad calls.
187 */
188 class Compositor
189 {
190 protected:
191 virtual ~Compositor();
192
193 public:
194 NS_INLINE_DECL_REFCOUNTING(Compositor)
195
196 explicit Compositor(widget::CompositorWidget* aWidget,
197 CompositorBridgeParent* aParent = nullptr);
198
199 virtual already_AddRefed<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) = 0;
200
201 virtual already_AddRefed<DataTextureSource>
CreateDataTextureSourceAround(gfx::DataSourceSurface * aSurface)202 CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) { return nullptr; }
203
204 virtual already_AddRefed<DataTextureSource>
CreateDataTextureSourceAroundYCbCr(TextureHost * aTexture)205 CreateDataTextureSourceAroundYCbCr(TextureHost* aTexture) { return nullptr; }
206
207 virtual bool Initialize(nsCString* const out_failureReason) = 0;
208 virtual void Destroy();
IsDestroyed()209 bool IsDestroyed() const { return mIsDestroyed; }
210
DetachWidget()211 virtual void DetachWidget() { mWidget = nullptr; }
212
213 /**
214 * Return true if the effect type is supported.
215 *
216 * By default Compositor implementations should support all effects but in
217 * some rare cases it is not possible to support an effect efficiently.
218 * This is the case for BasicCompositor with EffectYCbCr.
219 */
SupportsEffect(EffectTypes aEffect)220 virtual bool SupportsEffect(EffectTypes aEffect) { return true; }
221
222 /**
223 * Request a texture host identifier that may be used for creating textures
224 * across process or thread boundaries that are compatible with this
225 * compositor.
226 */
227 virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() = 0;
228
229 /**
230 * Properties of the compositor.
231 */
232 virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) = 0;
233 virtual int32_t GetMaxTextureSize() const = 0;
234
235 /**
236 * Set the target for rendering. Results will have been written to aTarget by
237 * the time that EndFrame returns.
238 *
239 * If this method is not used, or we pass in nullptr, we target the compositor's
240 * usual swap chain and render to the screen.
241 */
SetTargetContext(gfx::DrawTarget * aTarget,const gfx::IntRect & aRect)242 void SetTargetContext(gfx::DrawTarget* aTarget, const gfx::IntRect& aRect)
243 {
244 mTarget = aTarget;
245 mTargetBounds = aRect;
246 }
GetTargetContext()247 gfx::DrawTarget* GetTargetContext() const
248 {
249 return mTarget;
250 }
ClearTargetContext()251 void ClearTargetContext()
252 {
253 mTarget = nullptr;
254 }
255
256 typedef uint32_t MakeCurrentFlags;
257 static const MakeCurrentFlags ForceMakeCurrent = 0x1;
258 /**
259 * Make this compositor's rendering context the current context for the
260 * underlying graphics API. This may be a global operation, depending on the
261 * API. Our context will remain the current one until someone else changes it.
262 *
263 * Clients of the compositor should call this at the start of the compositing
264 * process, it might be required by texture uploads etc.
265 *
266 * If aFlags == ForceMakeCurrent then we will (re-)set our context on the
267 * underlying API even if it is already the current context.
268 */
269 virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) = 0;
270
271 /**
272 * Creates a Surface that can be used as a rendering target by this
273 * compositor.
274 */
275 virtual already_AddRefed<CompositingRenderTarget>
276 CreateRenderTarget(const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0;
277
278 /**
279 * Creates a Surface that can be used as a rendering target by this
280 * compositor, and initializes the surface by copying from aSource.
281 * If aSource is null, then the current screen buffer is used as source.
282 *
283 * aSourcePoint specifies the point in aSource to copy data from.
284 */
285 virtual already_AddRefed<CompositingRenderTarget>
286 CreateRenderTargetFromSource(const gfx::IntRect& aRect,
287 const CompositingRenderTarget* aSource,
288 const gfx::IntPoint& aSourcePoint) = 0;
289
290 /**
291 * Sets the given surface as the target for subsequent calls to DrawQuad.
292 * Passing null as aSurface sets the screen as the target.
293 */
294 virtual void SetRenderTarget(CompositingRenderTarget* aSurface) = 0;
295
296 /**
297 * Returns the current target for rendering. Will return null if we are
298 * rendering to the screen.
299 */
300 virtual CompositingRenderTarget* GetCurrentRenderTarget() const = 0;
301
302 /**
303 * Mostly the compositor will pull the size from a widget and this method will
304 * be ignored, but compositor implementations are free to use it if they like.
305 */
306 virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) = 0;
307
308 /**
309 * Declare an offset to use when rendering layers. This will be ignored when
310 * rendering to a target instead of the screen.
311 */
312 virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) = 0;
313
314 void DrawGeometry(const gfx::Rect& aRect,
315 const gfx::IntRect& aClipRect,
316 const EffectChain &aEffectChain,
317 gfx::Float aOpacity,
318 const gfx::Matrix4x4& aTransform,
319 const gfx::Rect& aVisibleRect,
320 const Maybe<gfx::Polygon3D>& aGeometry);
321
DrawGeometry(const gfx::Rect & aRect,const gfx::IntRect & aClipRect,const EffectChain & aEffectChain,gfx::Float aOpacity,const gfx::Matrix4x4 & aTransform,const Maybe<gfx::Polygon3D> & aGeometry)322 void DrawGeometry(const gfx::Rect& aRect,
323 const gfx::IntRect& aClipRect,
324 const EffectChain &aEffectChain,
325 gfx::Float aOpacity,
326 const gfx::Matrix4x4& aTransform,
327 const Maybe<gfx::Polygon3D>& aGeometry)
328 {
329 DrawGeometry(aRect, aClipRect, aEffectChain, aOpacity,
330 aTransform, aRect, aGeometry);
331 }
332
333 /**
334 * Tell the compositor to draw a quad. What to do draw and how it is
335 * drawn is specified by aEffectChain. aRect is the quad to draw, in user space.
336 * aTransform transforms from user space to screen space. If texture coords are
337 * required, these will be in the primary effect in the effect chain.
338 * aVisibleRect is used to determine which edges should be antialiased,
339 * without applying the effect to the inner edges of a tiled layer.
340 */
341 virtual void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect,
342 const EffectChain& aEffectChain,
343 gfx::Float aOpacity, const gfx::Matrix4x4& aTransform,
344 const gfx::Rect& aVisibleRect) = 0;
345
346 /**
347 * Overload of DrawQuad, with aVisibleRect defaulted to the value of aRect.
348 * Use this when you are drawing a single quad that is not part of a tiled
349 * layer.
350 */
DrawQuad(const gfx::Rect & aRect,const gfx::IntRect & aClipRect,const EffectChain & aEffectChain,gfx::Float aOpacity,const gfx::Matrix4x4 & aTransform)351 void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect,
352 const EffectChain& aEffectChain,
353 gfx::Float aOpacity, const gfx::Matrix4x4& aTransform) {
354 DrawQuad(aRect, aClipRect, aEffectChain, aOpacity, aTransform, aRect);
355 }
356
DrawTriangle(const gfx::TexturedTriangle & aTriangle,const gfx::IntRect & aClipRect,const EffectChain & aEffectChain,gfx::Float aOpacity,const gfx::Matrix4x4 & aTransform,const gfx::Rect & aVisibleRect)357 virtual void DrawTriangle(const gfx::TexturedTriangle& aTriangle,
358 const gfx::IntRect& aClipRect,
359 const EffectChain& aEffectChain,
360 gfx::Float aOpacity,
361 const gfx::Matrix4x4& aTransform,
362 const gfx::Rect& aVisibleRect)
363 {
364 MOZ_CRASH("Compositor::DrawTriangle is not implemented for the current platform!");
365 }
366
367 /**
368 * Draw an unfilled solid color rect. Typically used for debugging overlays.
369 */
370 void SlowDrawRect(const gfx::Rect& aRect, const gfx::Color& color,
371 const gfx::IntRect& aClipRect = gfx::IntRect(),
372 const gfx::Matrix4x4& aTransform = gfx::Matrix4x4(),
373 int aStrokeWidth = 1);
374
375 /**
376 * Draw a solid color filled rect. This is a simple DrawQuad helper.
377 */
378 void FillRect(const gfx::Rect& aRect, const gfx::Color& color,
379 const gfx::IntRect& aClipRect = gfx::IntRect(),
380 const gfx::Matrix4x4& aTransform = gfx::Matrix4x4());
381
SetClearColor(const gfx::Color & aColor)382 void SetClearColor(const gfx::Color& aColor) {
383 mClearColor = aColor;
384 }
385
SetDefaultClearColor(const gfx::Color & aColor)386 void SetDefaultClearColor(const gfx::Color& aColor) {
387 mDefaultClearColor = aColor;
388 }
389
SetClearColorToDefault()390 void SetClearColorToDefault() {
391 mClearColor = mDefaultClearColor;
392 }
393
394 /*
395 * Clear aRect on current render target.
396 */
397 virtual void ClearRect(const gfx::Rect& aRect) = 0;
398
399 /**
400 * Start a new frame.
401 *
402 * aInvalidRect is the invalid region of the screen; it can be ignored for
403 * compositors where the performance for compositing the entire window is
404 * sufficient.
405 *
406 * aClipRectIn is the clip rect for the window in window space (optional).
407 * aTransform is the transform from user space to window space.
408 * aRenderBounds bounding rect for rendering, in user space.
409 *
410 * If aClipRectIn is null, this method sets *aClipRectOut to the clip rect
411 * actually used for rendering (if aClipRectIn is non-null, we will use that
412 * for the clip rect).
413 *
414 * If aRenderBoundsOut is non-null, it will be set to the render bounds
415 * actually used by the compositor in window space. If aRenderBoundsOut
416 * is returned empty, composition should be aborted.
417 *
418 * If aOpaque is true, then all of aInvalidRegion will be drawn to with
419 * opaque content.
420 */
421 virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
422 const gfx::IntRect* aClipRectIn,
423 const gfx::IntRect& aRenderBounds,
424 const nsIntRegion& aOpaqueRegion,
425 gfx::IntRect* aClipRectOut = nullptr,
426 gfx::IntRect* aRenderBoundsOut = nullptr) = 0;
427
428 /**
429 * Flush the current frame to the screen and tidy up.
430 *
431 * Derived class overriding this should call Compositor::EndFrame.
432 */
433 virtual void EndFrame();
434
435 virtual void SetDispAcquireFence(Layer* aLayer);
436
437 /**
438 * Post-rendering stuff if the rendering is done outside of this Compositor
439 * e.g., by Composer2D.
440 * aTransform is the transform from user space to window space.
441 */
442 virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0;
443
444 /**
445 * Whether textures created by this compositor can receive partial updates.
446 */
447 virtual bool SupportsPartialTextureUpdate() = 0;
448
SetDiagnosticTypes(DiagnosticTypes aDiagnostics)449 void SetDiagnosticTypes(DiagnosticTypes aDiagnostics)
450 {
451 mDiagnosticTypes = aDiagnostics;
452 }
453
GetDiagnosticTypes()454 DiagnosticTypes GetDiagnosticTypes() const
455 {
456 return mDiagnosticTypes;
457 }
458
459 void DrawDiagnostics(DiagnosticFlags aFlags,
460 const gfx::Rect& visibleRect,
461 const gfx::IntRect& aClipRect,
462 const gfx::Matrix4x4& transform,
463 uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX);
464
465 void DrawDiagnostics(DiagnosticFlags aFlags,
466 const nsIntRegion& visibleRegion,
467 const gfx::IntRect& aClipRect,
468 const gfx::Matrix4x4& transform,
469 uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX);
470
471 #ifdef MOZ_DUMP_PAINTING
472 virtual const char* Name() const = 0;
473 #endif // MOZ_DUMP_PAINTING
474
475 virtual LayersBackend GetBackendType() const = 0;
476
AsCompositorOGL()477 virtual CompositorOGL* AsCompositorOGL() { return nullptr; }
AsCompositorD3D9()478 virtual CompositorD3D9* AsCompositorD3D9() { return nullptr; }
AsCompositorD3D11()479 virtual CompositorD3D11* AsCompositorD3D11() { return nullptr; }
AsBasicCompositor()480 virtual BasicCompositor* AsBasicCompositor() { return nullptr; }
481
482 /**
483 * Each Compositor has a unique ID.
484 * This ID is used to keep references to each Compositor in a map accessed
485 * from the compositor thread only, so that async compositables can find
486 * the right compositor parent and schedule compositing even if the compositor
487 * changed.
488 */
GetCompositorID()489 uint32_t GetCompositorID() const
490 {
491 return mCompositorID;
492 }
SetCompositorID(uint32_t aID)493 void SetCompositorID(uint32_t aID)
494 {
495 MOZ_ASSERT(mCompositorID == 0, "The compositor ID must be set only once.");
496 mCompositorID = aID;
497 }
498
499 /**
500 * Notify the compositor that composition is being paused. This allows the
501 * compositor to temporarily release any resources.
502 * Between calling Pause and Resume, compositing may fail.
503 */
Pause()504 virtual void Pause() {}
505 /**
506 * Notify the compositor that composition is being resumed. The compositor
507 * regain any resources it requires for compositing.
508 * Returns true if succeeded.
509 */
Resume()510 virtual bool Resume() { return true; }
511
512 /**
513 * Call before rendering begins to ensure the compositor is ready to
514 * composite. Returns false if rendering should be aborted.
515 */
Ready()516 virtual bool Ready() { return true; }
517
ForcePresent()518 virtual void ForcePresent() { }
519
IsPendingComposite()520 virtual bool IsPendingComposite() { return false; }
521
FinishPendingComposite()522 virtual void FinishPendingComposite() {}
523
GetWidget()524 widget::CompositorWidget* GetWidget() const { return mWidget; }
525
HasImageHostOverlays()526 virtual bool HasImageHostOverlays() { return false; }
527
AddImageHostOverlay(ImageHostOverlay * aOverlay)528 virtual void AddImageHostOverlay(ImageHostOverlay* aOverlay) {}
529
RemoveImageHostOverlay(ImageHostOverlay * aOverlay)530 virtual void RemoveImageHostOverlay(ImageHostOverlay* aOverlay) {}
531
532 /**
533 * Debug-build assertion that can be called to ensure code is running on the
534 * compositor thread.
535 */
536 static void AssertOnCompositorThread();
537
GetFillRatio()538 size_t GetFillRatio() {
539 float fillRatio = 0;
540 if (mPixelsFilled > 0 && mPixelsPerFrame > 0) {
541 fillRatio = 100.0f * float(mPixelsFilled) / float(mPixelsPerFrame);
542 if (fillRatio > 999.0f) {
543 fillRatio = 999.0f;
544 }
545 }
546 return fillRatio;
547 }
548
GetScreenRotation()549 ScreenRotation GetScreenRotation() const {
550 return mScreenRotation;
551 }
SetScreenRotation(ScreenRotation aRotation)552 void SetScreenRotation(ScreenRotation aRotation) {
553 mScreenRotation = aRotation;
554 }
555
GetCompositionTime()556 TimeStamp GetCompositionTime() const {
557 return mCompositionTime;
558 }
SetCompositionTime(TimeStamp aTimeStamp)559 void SetCompositionTime(TimeStamp aTimeStamp) {
560 mCompositionTime = aTimeStamp;
561 if (!mCompositionTime.IsNull() && !mCompositeUntilTime.IsNull() &&
562 mCompositionTime >= mCompositeUntilTime) {
563 mCompositeUntilTime = TimeStamp();
564 }
565 }
566
CompositeUntil(TimeStamp aTimeStamp)567 void CompositeUntil(TimeStamp aTimeStamp) {
568 if (mCompositeUntilTime.IsNull() ||
569 mCompositeUntilTime < aTimeStamp) {
570 mCompositeUntilTime = aTimeStamp;
571 }
572 }
GetCompositeUntilTime()573 TimeStamp GetCompositeUntilTime() const {
574 return mCompositeUntilTime;
575 }
576
577 // A stale Compositor has no CompositorBridgeParent; it will not process
578 // frames and should not be used.
579 void SetInvalid();
580 bool IsValid() const;
GetCompositorBridgeParent()581 CompositorBridgeParent* GetCompositorBridgeParent() const {
582 return mParent;
583 }
584
585 /// Most compositor backends operate asynchronously under the hood. This
586 /// means that when a layer stops using a texture it is often desirable to
587 /// wait for the end of the next composition before releasing the texture's
588 /// ReadLock.
589 /// This function provides a convenient way to do this delayed unlocking, if
590 /// the texture itself requires it.
591 void UnlockAfterComposition(TextureHost* aTexture);
592
593 /// Most compositor backends operate asynchronously under the hood. This
594 /// means that when a layer stops using a texture it is often desirable to
595 /// wait for the end of the next composition before NotifyNotUsed() call.
596 /// This function provides a convenient way to do this delayed NotifyNotUsed()
597 /// call, if the texture itself requires it.
598 /// See bug 1260611 and bug 1252835
599 void NotifyNotUsedAfterComposition(TextureHost* aTextureHost);
600
601 void FlushPendingNotifyNotUsed();
602
603 protected:
604 void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
605 const gfx::Rect& aVisibleRect,
606 const gfx::IntRect& aClipRect,
607 const gfx::Matrix4x4& transform,
608 uint32_t aFlashCounter);
609
610 bool ShouldDrawDiagnostics(DiagnosticFlags);
611
612 // Should be called at the end of each composition.
613 void ReadUnlockTextures();
614
615 /**
616 * Given a layer rect, clip, and transform, compute the area of the backdrop that
617 * needs to be copied for mix-blending. The output transform translates from 0..1
618 * space into the backdrop rect space.
619 *
620 * The transformed layer quad is also optionally returned - this is the same as
621 * the result rect, before rounding.
622 */
623 gfx::IntRect ComputeBackdropCopyRect(const gfx::Rect& aRect,
624 const gfx::IntRect& aClipRect,
625 const gfx::Matrix4x4& aTransform,
626 gfx::Matrix4x4* aOutTransform,
627 gfx::Rect* aOutLayerQuad = nullptr);
628
629 gfx::IntRect ComputeBackdropCopyRect(const gfx::Triangle& aTriangle,
630 const gfx::IntRect& aClipRect,
631 const gfx::Matrix4x4& aTransform,
632 gfx::Matrix4x4* aOutTransform,
633 gfx::Rect* aOutLayerQuad = nullptr);
634
635
636 /**
637 * An array of locks that will need to be unlocked after the next composition.
638 */
639 nsTArray<RefPtr<TextureHost>> mUnlockAfterComposition;
640
641 /**
642 * An array of TextureHosts that will need to call NotifyNotUsed() after the next composition.
643 */
644 nsTArray<RefPtr<TextureHost>> mNotifyNotUsedAfterComposition;
645
646 /**
647 * Last Composition end time.
648 */
649 TimeStamp mLastCompositionEndTime;
650
651 /**
652 * Render time for the current composition.
653 */
654 TimeStamp mCompositionTime;
655 /**
656 * When nonnull, during rendering, some compositable indicated that it will
657 * change its rendering at this time. In order not to miss it, we composite
658 * on every vsync until this time occurs (this is the latest such time).
659 */
660 TimeStamp mCompositeUntilTime;
661
662 uint32_t mCompositorID;
663 DiagnosticTypes mDiagnosticTypes;
664 CompositorBridgeParent* mParent;
665
666 /**
667 * We keep track of the total number of pixels filled as we composite the
668 * current frame. This value is an approximation and is not accurate,
669 * especially in the presence of transforms.
670 */
671 size_t mPixelsPerFrame;
672 size_t mPixelsFilled;
673
674 ScreenRotation mScreenRotation;
675
676 RefPtr<gfx::DrawTarget> mTarget;
677 gfx::IntRect mTargetBounds;
678
679 widget::CompositorWidget* mWidget;
680
681 bool mIsDestroyed;
682
683 gfx::Color mClearColor;
684 gfx::Color mDefaultClearColor;
685
686 private:
687 static LayersBackend sBackend;
688
689 };
690
691 // Returns the number of rects. (Up to 4)
692 typedef gfx::Rect decomposedRectArrayT[4];
693 size_t DecomposeIntoNoRepeatRects(const gfx::Rect& aRect,
694 const gfx::Rect& aTexCoordRect,
695 decomposedRectArrayT* aLayerRects,
696 decomposedRectArrayT* aTextureRects);
697
698 static inline bool
BlendOpIsMixBlendMode(gfx::CompositionOp aOp)699 BlendOpIsMixBlendMode(gfx::CompositionOp aOp)
700 {
701 switch (aOp) {
702 case gfx::CompositionOp::OP_MULTIPLY:
703 case gfx::CompositionOp::OP_SCREEN:
704 case gfx::CompositionOp::OP_OVERLAY:
705 case gfx::CompositionOp::OP_DARKEN:
706 case gfx::CompositionOp::OP_LIGHTEN:
707 case gfx::CompositionOp::OP_COLOR_DODGE:
708 case gfx::CompositionOp::OP_COLOR_BURN:
709 case gfx::CompositionOp::OP_HARD_LIGHT:
710 case gfx::CompositionOp::OP_SOFT_LIGHT:
711 case gfx::CompositionOp::OP_DIFFERENCE:
712 case gfx::CompositionOp::OP_EXCLUSION:
713 case gfx::CompositionOp::OP_HUE:
714 case gfx::CompositionOp::OP_SATURATION:
715 case gfx::CompositionOp::OP_COLOR:
716 case gfx::CompositionOp::OP_LUMINOSITY:
717 return true;
718 default:
719 return false;
720 }
721 }
722
723 } // namespace layers
724 } // namespace mozilla
725
726 #endif /* MOZILLA_GFX_COMPOSITOR_H */
727