Line data Source code
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 GFX_LayerManagerComposite_H
7 : #define GFX_LayerManagerComposite_H
8 :
9 : #include <stdint.h> // for int32_t, uint32_t
10 : #include "CompositableHost.h" // for CompositableHost, ImageCompositeNotificationInfo
11 : #include "GLDefs.h" // for GLenum
12 : #include "Layers.h"
13 : #include "Units.h" // for ParentLayerIntRect
14 : #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
15 : #include "mozilla/Attributes.h" // for override
16 : #include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed
17 : #include "mozilla/gfx/2D.h"
18 : #include "mozilla/gfx/Point.h" // for IntSize
19 : #include "mozilla/gfx/Rect.h" // for Rect
20 : #include "mozilla/gfx/Types.h" // for SurfaceFormat
21 : #include "mozilla/layers/CompositorTypes.h"
22 : #include "mozilla/layers/Effects.h" // for EffectChain
23 : #include "mozilla/layers/LayersMessages.h"
24 : #include "mozilla/layers/LayersTypes.h" // for LayersBackend, etc
25 : #include "mozilla/Maybe.h" // for Maybe
26 : #include "mozilla/RefPtr.h"
27 : #include "mozilla/UniquePtr.h"
28 : #include "nsAString.h"
29 : #include "mozilla/RefPtr.h" // for nsRefPtr
30 : #include "nsCOMPtr.h" // for already_AddRefed
31 : #include "nsDebug.h" // for NS_ASSERTION
32 : #include "nsISupportsImpl.h" // for Layer::AddRef, etc
33 : #include "nsRect.h" // for mozilla::gfx::IntRect
34 : #include "nsRegion.h" // for nsIntRegion
35 : #include "nscore.h" // for nsAString, etc
36 : #include "LayerTreeInvalidation.h"
37 :
38 : class gfxContext;
39 :
40 : #ifdef XP_WIN
41 : #include <windows.h>
42 : #endif
43 :
44 : namespace mozilla {
45 : namespace gfx {
46 : class DrawTarget;
47 : } // namespace gfx
48 :
49 : namespace layers {
50 :
51 : class CanvasLayerComposite;
52 : class ColorLayerComposite;
53 : class Compositor;
54 : class ContainerLayerComposite;
55 : class Diagnostics;
56 : struct EffectChain;
57 : class ImageLayer;
58 : class ImageLayerComposite;
59 : class LayerComposite;
60 : class RefLayerComposite;
61 : class PaintedLayerComposite;
62 : class TextRenderer;
63 : class CompositingRenderTarget;
64 : struct FPSState;
65 : class PaintCounter;
66 : class LayerMLGPU;
67 : class LayerManagerMLGPU;
68 : class UiCompositorControllerParent;
69 :
70 : static const int kVisualWarningDuration = 150; // ms
71 :
72 : // An implementation of LayerManager that acts as a pair with ClientLayerManager
73 : // and is mirrored across IPDL. This gets managed/updated by LayerTransactionParent.
74 : class HostLayerManager : public LayerManager
75 : {
76 : public:
77 : HostLayerManager();
78 : ~HostLayerManager();
79 :
80 0 : virtual bool BeginTransactionWithTarget(gfxContext* aTarget) override
81 : {
82 0 : MOZ_CRASH("GFX: Use BeginTransactionWithDrawTarget");
83 : }
84 :
85 0 : virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) override
86 : {
87 0 : MOZ_CRASH("GFX: Use EndTransaction(aTimeStamp)");
88 : return false;
89 : }
90 :
91 0 : virtual void EndTransaction(DrawPaintedLayerCallback aCallback,
92 : void* aCallbackData,
93 : EndTransactionFlags aFlags = END_DEFAULT) override
94 : {
95 0 : MOZ_CRASH("GFX: Use EndTransaction(aTimeStamp)");
96 : }
97 :
98 0 : virtual int32_t GetMaxTextureSize() const override
99 : {
100 0 : MOZ_CRASH("GFX: Call on compositor, not LayerManagerComposite");
101 : }
102 :
103 0 : virtual void GetBackendName(nsAString& name) override
104 : {
105 0 : MOZ_CRASH("GFX: Shouldn't be called for composited layer manager");
106 : }
107 :
108 : virtual void ForcePresent() = 0;
109 : virtual void AddInvalidRegion(const nsIntRegion& aRegion) = 0;
110 : virtual void ClearApproximatelyVisibleRegions(uint64_t aLayersId,
111 : const Maybe<uint32_t>& aPresShellId) = 0;
112 : virtual void UpdateApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid,
113 : const CSSIntRegion& aRegion) = 0;
114 :
115 0 : virtual void NotifyShadowTreeTransaction() {}
116 : virtual void BeginTransactionWithDrawTarget(gfx::DrawTarget* aTarget,
117 : const gfx::IntRect& aRect) = 0;
118 : virtual Compositor* GetCompositor() const = 0;
119 : virtual TextureSourceProvider* GetTextureSourceProvider() const = 0;
120 : virtual void EndTransaction(const TimeStamp& aTimeStamp,
121 : EndTransactionFlags aFlags = END_DEFAULT) = 0;
122 0 : virtual void UpdateRenderBounds(const gfx::IntRect& aRect) {}
123 0 : virtual void SetDiagnosticTypes(DiagnosticTypes aDiagnostics) {}
124 :
125 0 : virtual HostLayerManager* AsHostLayerManager() override {
126 0 : return this;
127 : }
128 0 : virtual LayerManagerMLGPU* AsLayerManagerMLGPU() {
129 0 : return nullptr;
130 : }
131 :
132 29 : void ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications)
133 : {
134 29 : aNotifications->AppendElements(Move(mImageCompositeNotifications));
135 29 : }
136 :
137 0 : void AppendImageCompositeNotification(const ImageCompositeNotificationInfo& aNotification)
138 : {
139 : // Only send composite notifications when we're drawing to the screen,
140 : // because that's what they mean.
141 : // Also when we're not drawing to the screen, DidComposite will not be
142 : // called to extract and send these notifications, so they might linger
143 : // and contain stale ImageContainerParent pointers.
144 0 : if (IsCompositingToScreen()) {
145 0 : mImageCompositeNotifications.AppendElement(aNotification);
146 : }
147 0 : }
148 :
149 : /**
150 : * LayerManagerComposite provides sophisticated debug overlays
151 : * that can request a next frame.
152 : */
153 29 : bool DebugOverlayWantsNextFrame() { return mDebugOverlayWantsNextFrame; }
154 29 : void SetDebugOverlayWantsNextFrame(bool aVal)
155 29 : { mDebugOverlayWantsNextFrame = aVal; }
156 :
157 : /**
158 : * Add an on frame warning.
159 : * @param severity ranges from 0 to 1. It's used to compute the warning color.
160 : */
161 0 : void VisualFrameWarning(float severity) {
162 0 : mozilla::TimeStamp now = TimeStamp::Now();
163 0 : if (mWarnTime.IsNull() ||
164 0 : severity > mWarningLevel ||
165 0 : mWarnTime + TimeDuration::FromMilliseconds(kVisualWarningDuration) < now) {
166 0 : mWarnTime = now;
167 0 : mWarningLevel = severity;
168 : }
169 0 : }
170 :
171 : // Indicate that we need to composite even if nothing in our layers has
172 : // changed, so that the widget can draw something different in its window
173 : // overlay.
174 0 : void SetWindowOverlayChanged() { mWindowOverlayChanged = true; }
175 :
176 0 : void SetPaintTime(const TimeDuration& aPaintTime) { mLastPaintTime = aPaintTime; }
177 :
178 0 : virtual bool AlwaysScheduleComposite() const {
179 0 : return false;
180 : }
181 0 : virtual bool IsCompositingToScreen() const {
182 0 : return false;
183 : }
184 :
185 : void RecordPaintTimes(const PaintTiming& aTiming);
186 : void RecordUpdateTime(float aValue);
187 :
188 0 : TimeStamp GetCompositionTime() const {
189 0 : return mCompositionTime;
190 : }
191 86 : void SetCompositionTime(TimeStamp aTimeStamp) {
192 86 : mCompositionTime = aTimeStamp;
193 86 : if (!mCompositionTime.IsNull() && !mCompositeUntilTime.IsNull() &&
194 0 : mCompositionTime >= mCompositeUntilTime) {
195 0 : mCompositeUntilTime = TimeStamp();
196 : }
197 86 : }
198 0 : void CompositeUntil(TimeStamp aTimeStamp) {
199 0 : if (mCompositeUntilTime.IsNull() ||
200 0 : mCompositeUntilTime < aTimeStamp) {
201 0 : mCompositeUntilTime = aTimeStamp;
202 : }
203 0 : }
204 29 : TimeStamp GetCompositeUntilTime() const {
205 29 : return mCompositeUntilTime;
206 : }
207 :
208 : // We maintaining a global mapping from ID to CompositorBridgeParent for
209 : // async compositables.
210 22 : uint32_t GetCompositorBridgeID() const {
211 22 : return mCompositorBridgeID;
212 : }
213 1 : void SetCompositorBridgeID(uint32_t aID) {
214 1 : MOZ_ASSERT(mCompositorBridgeID == 0, "The compositor ID must be set only once.");
215 1 : mCompositorBridgeID = aID;
216 1 : }
217 :
218 : protected:
219 : bool mDebugOverlayWantsNextFrame;
220 : nsTArray<ImageCompositeNotificationInfo> mImageCompositeNotifications;
221 : // Testing property. If hardware composer is supported, this will return
222 : // true if the last frame was deemed 'too complicated' to be rendered.
223 : float mWarningLevel;
224 : mozilla::TimeStamp mWarnTime;
225 : UniquePtr<Diagnostics> mDiagnostics;
226 : uint32_t mCompositorBridgeID;
227 :
228 : bool mWindowOverlayChanged;
229 : TimeDuration mLastPaintTime;
230 : TimeStamp mRenderStartTime;
231 :
232 : // Render time for the current composition.
233 : TimeStamp mCompositionTime;
234 :
235 : // When nonnull, during rendering, some compositable indicated that it will
236 : // change its rendering at this time. In order not to miss it, we composite
237 : // on every vsync until this time occurs (this is the latest such time).
238 : TimeStamp mCompositeUntilTime;
239 : #if defined(MOZ_WIDGET_ANDROID)
240 : public:
241 : // Used by UiCompositorControllerParent to set itself as the target for the
242 : // contents of the frame buffer after a composite.
243 : // Implemented in LayerManagerComposite
244 : virtual void RequestScreenPixels(UiCompositorControllerParent* aController) {}
245 : #endif // defined(MOZ_WIDGET_ANDROID)
246 : };
247 :
248 : // A layer manager implementation that uses the Compositor API
249 : // to render layers.
250 : class LayerManagerComposite final : public HostLayerManager
251 : {
252 : typedef mozilla::gfx::DrawTarget DrawTarget;
253 : typedef mozilla::gfx::IntSize IntSize;
254 : typedef mozilla::gfx::SurfaceFormat SurfaceFormat;
255 :
256 : public:
257 : explicit LayerManagerComposite(Compositor* aCompositor);
258 : ~LayerManagerComposite();
259 :
260 : virtual void Destroy() override;
261 :
262 : /**
263 : * Sets the clipping region for this layer manager. This is important on
264 : * windows because using OGL we no longer have GDI's native clipping. Therefor
265 : * widget must tell us what part of the screen is being invalidated,
266 : * and we should clip to this.
267 : *
268 : * \param aClippingRegion Region to clip to. Setting an empty region
269 : * will disable clipping.
270 : */
271 : void SetClippingRegion(const nsIntRegion& aClippingRegion)
272 : {
273 : mClippingRegion = aClippingRegion;
274 : }
275 :
276 : /**
277 : * LayerManager implementation.
278 : */
279 0 : virtual LayerManagerComposite* AsLayerManagerComposite() override
280 : {
281 0 : return this;
282 : }
283 :
284 : void UpdateRenderBounds(const gfx::IntRect& aRect) override;
285 :
286 : virtual bool BeginTransaction() override;
287 : void BeginTransactionWithDrawTarget(gfx::DrawTarget* aTarget,
288 : const gfx::IntRect& aRect) override;
289 : void EndTransaction(const TimeStamp& aTimeStamp,
290 : EndTransactionFlags aFlags = END_DEFAULT) override;
291 0 : virtual void EndTransaction(DrawPaintedLayerCallback aCallback,
292 : void* aCallbackData,
293 : EndTransactionFlags aFlags = END_DEFAULT) override
294 : {
295 0 : MOZ_CRASH("GFX: Use EndTransaction(aTimeStamp)");
296 : }
297 :
298 24 : virtual void SetRoot(Layer* aLayer) override { mRoot = aLayer; }
299 :
300 : // XXX[nrc]: never called, we should move this logic to ClientLayerManager
301 : // (bug 946926).
302 : virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override;
303 :
304 : virtual void ClearCachedResources(Layer* aSubtree = nullptr) override;
305 :
306 : virtual already_AddRefed<PaintedLayer> CreatePaintedLayer() override;
307 : virtual already_AddRefed<ContainerLayer> CreateContainerLayer() override;
308 : virtual already_AddRefed<ImageLayer> CreateImageLayer() override;
309 : virtual already_AddRefed<ColorLayer> CreateColorLayer() override;
310 : virtual already_AddRefed<TextLayer> CreateTextLayer() override;
311 : virtual already_AddRefed<BorderLayer> CreateBorderLayer() override;
312 : virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() override;
313 : virtual already_AddRefed<RefLayer> CreateRefLayer() override;
314 :
315 : virtual bool AreComponentAlphaLayersEnabled() override;
316 :
317 : virtual already_AddRefed<DrawTarget>
318 : CreateOptimalMaskDrawTarget(const IntSize &aSize) override;
319 :
320 0 : virtual const char* Name() const override { return ""; }
321 : virtual bool IsCompositingToScreen() const override;
322 :
323 : bool AlwaysScheduleComposite() const override;
324 :
325 : /**
326 : * Post-processes layers before composition. This performs the following:
327 : *
328 : * - Applies occlusion culling. This restricts the shadow visible region
329 : * of layers that are covered with opaque content.
330 : * |aOpaqueRegion| is the region already known to be covered with opaque
331 : * content, in the post-transform coordinate space of aLayer.
332 : *
333 : * - Recomputes visible regions to account for async transforms.
334 : * Each layer accumulates into |aVisibleRegion| its post-transform
335 : * (including async transforms) visible region.
336 : *
337 : * - aRenderTargetClip is the exact clip required for aLayer, in the coordinates
338 : * of the nearest render target (the same as GetEffectiveTransform).
339 : *
340 : * - aClipFromAncestors is the approximate combined clip from all ancestors, in
341 : * the coordinate space of our parent, but maybe be an overestimate in the
342 : * presence of complex transforms.
343 : */
344 : void PostProcessLayers(nsIntRegion& aOpaqueRegion);
345 : void PostProcessLayers(Layer* aLayer,
346 : nsIntRegion& aOpaqueRegion,
347 : LayerIntRegion& aVisibleRegion,
348 : const Maybe<RenderTargetIntRect>& aRenderTargetClip,
349 : const Maybe<ParentLayerIntRect>& aClipFromAncestors);
350 :
351 : /**
352 : * RAII helper class to add a mask effect with the compositable from aMaskLayer
353 : * to the EffectChain aEffect and notify the compositable when we are done.
354 : */
355 : class AutoAddMaskEffect
356 : {
357 : public:
358 : AutoAddMaskEffect(Layer* aMaskLayer,
359 : EffectChain& aEffect);
360 : ~AutoAddMaskEffect();
361 :
362 0 : bool Failed() const { return mFailed; }
363 : private:
364 : CompositableHost* mCompositable;
365 : bool mFailed;
366 : };
367 :
368 : /**
369 : * returns true if PlatformAllocBuffer will return a buffer that supports
370 : * direct texturing
371 : */
372 : static bool SupportsDirectTexturing();
373 :
374 : static void PlatformSyncBeforeReplyUpdate();
375 :
376 1 : void AddInvalidRegion(const nsIntRegion& aRegion) override
377 : {
378 1 : mInvalidRegion.Or(mInvalidRegion, aRegion);
379 1 : }
380 :
381 0 : void ClearApproximatelyVisibleRegions(uint64_t aLayersId,
382 : const Maybe<uint32_t>& aPresShellId) override
383 : {
384 0 : for (auto iter = mVisibleRegions.Iter(); !iter.Done(); iter.Next()) {
385 0 : if (iter.Key().mLayersId == aLayersId &&
386 0 : (!aPresShellId || iter.Key().mPresShellId == *aPresShellId)) {
387 0 : iter.Remove();
388 : }
389 : }
390 0 : }
391 :
392 0 : void UpdateApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid,
393 : const CSSIntRegion& aRegion) override
394 : {
395 0 : CSSIntRegion* regionForScrollFrame = mVisibleRegions.LookupOrAdd(aGuid);
396 0 : MOZ_ASSERT(regionForScrollFrame);
397 :
398 0 : *regionForScrollFrame = aRegion;
399 0 : }
400 :
401 0 : CSSIntRegion* GetApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid)
402 : {
403 0 : return mVisibleRegions.Get(aGuid);
404 : }
405 :
406 458 : Compositor* GetCompositor() const override {
407 458 : return mCompositor;
408 : }
409 22 : TextureSourceProvider* GetTextureSourceProvider() const override {
410 22 : return mCompositor;
411 : }
412 :
413 : void NotifyShadowTreeTransaction() override;
414 :
415 0 : TextRenderer* GetTextRenderer() { return mTextRenderer; }
416 :
417 0 : void UnusedApzTransformWarning() {
418 0 : mUnusedApzTransformWarning = true;
419 0 : }
420 0 : void DisabledApzWarning() {
421 0 : mDisabledApzWarning = true;
422 0 : }
423 :
424 : bool AsyncPanZoomEnabled() const override;
425 :
426 : public:
427 1 : virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override {
428 1 : return mCompositor->GetTextureFactoryIdentifier();
429 : }
430 0 : virtual LayersBackend GetBackendType() override {
431 0 : return mCompositor ? mCompositor->GetBackendType() : LayersBackend::LAYERS_NONE;
432 : }
433 0 : virtual void SetDiagnosticTypes(DiagnosticTypes aDiagnostics) override {
434 0 : mCompositor->SetDiagnosticTypes(aDiagnostics);
435 0 : }
436 :
437 0 : void ForcePresent() override { mCompositor->ForcePresent(); }
438 :
439 : private:
440 : /** Region we're clipping our current drawing to. */
441 : nsIntRegion mClippingRegion;
442 : gfx::IntRect mRenderBounds;
443 :
444 : /** Current root layer. */
445 : LayerComposite* RootLayer() const;
446 :
447 : /**
448 : * Update the invalid region and render it.
449 : */
450 : void UpdateAndRender();
451 :
452 : /**
453 : * Render the current layer tree to the active target.
454 : */
455 : void Render(const nsIntRegion& aInvalidRegion, const nsIntRegion& aOpaqueRegion);
456 : #if defined(MOZ_WIDGET_ANDROID)
457 : void RenderToPresentationSurface();
458 : // Shifts the content down so the toolbar does not cover it.
459 : // Returns the Y shift of the content in screen pixels
460 : ScreenCoord GetContentShiftForToolbar();
461 : // Renders the static snapshot after the content has been rendered.
462 : void RenderToolbar();
463 : // Used by robocop tests to get a snapshot of the frame buffer.
464 : void HandlePixelsTarget();
465 : #endif
466 :
467 : /**
468 : * We need to know our invalid region before we're ready to render.
469 : */
470 : void InvalidateDebugOverlay(nsIntRegion& aInvalidRegion, const gfx::IntRect& aBounds);
471 :
472 : /**
473 : * Render debug overlays such as the FPS/FrameCounter above the frame.
474 : */
475 : void RenderDebugOverlay(const gfx::IntRect& aBounds);
476 :
477 :
478 : RefPtr<CompositingRenderTarget> PushGroupForLayerEffects();
479 : void PopGroupForLayerEffects(RefPtr<CompositingRenderTarget> aPreviousTarget,
480 : gfx::IntRect aClipRect,
481 : bool aGrayscaleEffect,
482 : bool aInvertEffect,
483 : float aContrastEffect);
484 :
485 : bool mUnusedApzTransformWarning;
486 : bool mDisabledApzWarning;
487 : RefPtr<Compositor> mCompositor;
488 : UniquePtr<LayerProperties> mClonedLayerTreeProperties;
489 :
490 : /**
491 : * Context target, nullptr when drawing directly to our swap chain.
492 : */
493 : RefPtr<gfx::DrawTarget> mTarget;
494 : gfx::IntRect mTargetBounds;
495 :
496 : nsIntRegion mInvalidRegion;
497 :
498 : typedef nsClassHashtable<nsGenericHashKey<ScrollableLayerGuid>,
499 : CSSIntRegion> VisibleRegions;
500 : VisibleRegions mVisibleRegions;
501 :
502 : bool mInTransaction;
503 : bool mIsCompositorReady;
504 :
505 : RefPtr<CompositingRenderTarget> mTwoPassTmpTarget;
506 : RefPtr<TextRenderer> mTextRenderer;
507 :
508 : #ifdef USE_SKIA
509 : /**
510 : * Render paint and composite times above the frame.
511 : */
512 : void DrawPaintTimes(Compositor* aCompositor);
513 : RefPtr<PaintCounter> mPaintCounter;
514 : #endif
515 : #if defined(MOZ_WIDGET_ANDROID)
516 : public:
517 : virtual void RequestScreenPixels(UiCompositorControllerParent* aController) override
518 : {
519 : mScreenPixelsTarget = aController;
520 : }
521 : private:
522 : UiCompositorControllerParent* mScreenPixelsTarget;
523 : #endif // defined(MOZ_WIDGET_ANDROID)
524 : };
525 :
526 : /**
527 : * Compositor layers are for use with OMTC on the compositor thread only. There
528 : * must be corresponding Client layers on the content thread. For composite
529 : * layers, the layer manager only maintains the layer tree.
530 : */
531 : class HostLayer
532 : {
533 : public:
534 31 : explicit HostLayer(HostLayerManager* aManager)
535 31 : : mCompositorManager(aManager)
536 : , mShadowOpacity(1.0)
537 : , mShadowTransformSetByAnimation(false)
538 31 : , mShadowOpacitySetByAnimation(false)
539 : {
540 31 : }
541 :
542 0 : virtual void SetLayerManager(HostLayerManager* aManager)
543 : {
544 0 : mCompositorManager = aManager;
545 0 : }
546 0 : HostLayerManager* GetLayerManager() const { return mCompositorManager; }
547 :
548 :
549 23 : virtual ~HostLayer() {}
550 :
551 0 : virtual LayerComposite* GetFirstChildComposite()
552 : {
553 0 : return nullptr;
554 : }
555 :
556 : virtual Layer* GetLayer() = 0;
557 :
558 0 : virtual LayerMLGPU* AsLayerMLGPU() { return nullptr; }
559 :
560 0 : virtual bool SetCompositableHost(CompositableHost*)
561 : {
562 : // We must handle this gracefully, see bug 967824
563 0 : NS_WARNING("called SetCompositableHost for a layer type not accepting a compositable");
564 0 : return false;
565 : }
566 : virtual CompositableHost* GetCompositableHost() = 0;
567 :
568 : /**
569 : * The following methods are
570 : *
571 : * CONSTRUCTION PHASE ONLY
572 : *
573 : * They are analogous to the Layer interface.
574 : */
575 492 : void SetShadowVisibleRegion(const LayerIntRegion& aRegion)
576 : {
577 492 : mShadowVisibleRegion = aRegion;
578 492 : }
579 0 : void SetShadowVisibleRegion(LayerIntRegion&& aRegion)
580 : {
581 0 : mShadowVisibleRegion = Move(aRegion);
582 0 : }
583 :
584 371 : void SetShadowOpacity(float aOpacity)
585 : {
586 371 : mShadowOpacity = aOpacity;
587 371 : }
588 371 : void SetShadowOpacitySetByAnimation(bool aSetByAnimation)
589 : {
590 371 : mShadowOpacitySetByAnimation = aSetByAnimation;
591 371 : }
592 :
593 411 : void SetShadowClipRect(const Maybe<ParentLayerIntRect>& aRect)
594 : {
595 411 : mShadowClipRect = aRect;
596 411 : }
597 :
598 440 : void SetShadowBaseTransform(const gfx::Matrix4x4& aMatrix)
599 : {
600 440 : mShadowTransform = aMatrix;
601 440 : }
602 371 : void SetShadowTransformSetByAnimation(bool aSetByAnimation)
603 : {
604 371 : mShadowTransformSetByAnimation = aSetByAnimation;
605 371 : }
606 :
607 : // These getters can be used anytime.
608 1122 : float GetShadowOpacity() { return mShadowOpacity; }
609 1615 : const Maybe<ParentLayerIntRect>& GetShadowClipRect() { return mShadowClipRect; }
610 0 : const LayerIntRegion& GetShadowVisibleRegion() const { return mShadowVisibleRegion; }
611 29 : const gfx::Matrix4x4& GetShadowBaseTransform() { return mShadowTransform; }
612 : gfx::Matrix4x4 GetShadowTransform();
613 0 : bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; }
614 : bool GetShadowOpacitySetByAnimation() { return mShadowOpacitySetByAnimation; }
615 967 : LayerIntRegion&& GetShadowVisibleRegion() { return Move(mShadowVisibleRegion); }
616 :
617 : protected:
618 : HostLayerManager* mCompositorManager;
619 :
620 : gfx::Matrix4x4 mShadowTransform;
621 : LayerIntRegion mShadowVisibleRegion;
622 : Maybe<ParentLayerIntRect> mShadowClipRect;
623 : float mShadowOpacity;
624 : bool mShadowTransformSetByAnimation;
625 : bool mShadowOpacitySetByAnimation;
626 : };
627 :
628 : /**
629 : * Composite layers are for use with OMTC on the compositor thread only. There
630 : * must be corresponding Client layers on the content thread. For composite
631 : * layers, the layer manager only maintains the layer tree, all rendering is
632 : * done by a Compositor (see Compositor.h). As such, composite layers are
633 : * platform-independent and can be used on any platform for which there is a
634 : * Compositor implementation.
635 : *
636 : * The composite layer tree reflects exactly the basic layer tree. To
637 : * composite to screen, the layer manager walks the layer tree calling render
638 : * methods which in turn call into their CompositableHosts' Composite methods.
639 : * These call Compositor::DrawQuad to do the rendering.
640 : *
641 : * Mostly, layers are updated during the layers transaction. This is done from
642 : * CompositableClient to CompositableHost without interacting with the layer.
643 : *
644 : * A reference to the Compositor is stored in LayerManagerComposite.
645 : */
646 : class LayerComposite : public HostLayer
647 : {
648 : public:
649 : explicit LayerComposite(LayerManagerComposite* aManager);
650 :
651 : virtual ~LayerComposite();
652 :
653 : virtual void SetLayerManager(HostLayerManager* aManager);
654 :
655 0 : virtual LayerComposite* GetFirstChildComposite()
656 : {
657 0 : return nullptr;
658 : }
659 :
660 : /* Do NOT call this from the generic LayerComposite destructor. Only from the
661 : * concrete class destructor
662 : */
663 : virtual void Destroy();
664 114 : virtual void Cleanup() {}
665 :
666 : /**
667 : * Perform a first pass over the layer tree to render all of the intermediate
668 : * surfaces that we can. This allows us to avoid framebuffer switches in the
669 : * middle of our render which is inefficient especially on mobile GPUs. This
670 : * must be called before RenderLayer.
671 : */
672 80 : virtual void Prepare(const RenderTargetIntRect& aClipRect) {}
673 :
674 : // TODO: This should also take RenderTargetIntRect like Prepare.
675 : virtual void RenderLayer(const gfx::IntRect& aClipRect,
676 : const Maybe<gfx::Polygon>& aGeometry) = 0;
677 :
678 0 : virtual bool SetCompositableHost(CompositableHost*)
679 : {
680 : // We must handle this gracefully, see bug 967824
681 0 : NS_WARNING("called SetCompositableHost for a layer type not accepting a compositable");
682 0 : return false;
683 : }
684 :
685 : virtual void CleanupResources() = 0;
686 :
687 0 : virtual void DestroyFrontBuffer() { }
688 :
689 : void AddBlendModeEffect(EffectChain& aEffectChain);
690 :
691 0 : virtual void GenEffectChain(EffectChain& aEffect) { }
692 :
693 202 : void SetLayerComposited(bool value)
694 : {
695 202 : mLayerComposited = value;
696 202 : }
697 :
698 0 : void SetClearRect(const gfx::IntRect& aRect)
699 : {
700 0 : mClearRect = aRect;
701 0 : }
702 :
703 141 : bool HasLayerBeenComposited() { return mLayerComposited; }
704 0 : gfx::IntRect GetClearRect() { return mClearRect; }
705 :
706 : // Returns false if the layer is attached to an older compositor.
707 : bool HasStaleCompositor() const;
708 :
709 : /**
710 : * Return the part of the visible region that has been fully rendered.
711 : * While progressive drawing is in progress this region will be
712 : * a subset of the shadow visible region.
713 : */
714 : virtual nsIntRegion GetFullyRenderedRegion();
715 :
716 : protected:
717 : LayerManagerComposite* mCompositeManager;
718 :
719 : RefPtr<Compositor> mCompositor;
720 : bool mDestroyed;
721 : bool mLayerComposited;
722 : gfx::IntRect mClearRect;
723 : };
724 :
725 : // Render aLayer using aCompositor and apply all mask layers of aLayer: The
726 : // layer's own mask layer (aLayer->GetMaskLayer()), and any ancestor mask
727 : // layers.
728 : // If more than one mask layer needs to be applied, we use intermediate surfaces
729 : // (CompositingRenderTargets) for rendering, applying one mask layer at a time.
730 : // Callers need to provide a callback function aRenderCallback that does the
731 : // actual rendering of the source. It needs to have the following form:
732 : // void (EffectChain& effectChain, const Rect& clipRect)
733 : // aRenderCallback is called exactly once, inside this function, unless aLayer's
734 : // visible region is completely clipped out (in that case, aRenderCallback won't
735 : // be called at all).
736 : // This function calls aLayer->AsHostLayer()->AddBlendModeEffect for the
737 : // final rendering pass.
738 : //
739 : // (This function should really live in LayerManagerComposite.cpp, but we
740 : // need to use templates for passing lambdas until bug 1164522 is resolved.)
741 : template<typename RenderCallbackType>
742 : void
743 80 : RenderWithAllMasks(Layer* aLayer, Compositor* aCompositor,
744 : const gfx::IntRect& aClipRect,
745 : RenderCallbackType aRenderCallback)
746 : {
747 80 : Layer* firstMask = nullptr;
748 80 : size_t maskLayerCount = 0;
749 80 : size_t nextAncestorMaskLayer = 0;
750 :
751 80 : size_t ancestorMaskLayerCount = aLayer->GetAncestorMaskLayerCount();
752 80 : if (Layer* ownMask = aLayer->GetMaskLayer()) {
753 0 : firstMask = ownMask;
754 0 : maskLayerCount = ancestorMaskLayerCount + 1;
755 0 : nextAncestorMaskLayer = 0;
756 80 : } else if (ancestorMaskLayerCount > 0) {
757 0 : firstMask = aLayer->GetAncestorMaskLayerAt(0);
758 0 : maskLayerCount = ancestorMaskLayerCount;
759 0 : nextAncestorMaskLayer = 1;
760 : } else {
761 : // no mask layers at all
762 : }
763 :
764 80 : if (maskLayerCount <= 1) {
765 : // This is the common case. Render in one pass and return.
766 160 : EffectChain effectChain(aLayer);
767 : LayerManagerComposite::AutoAddMaskEffect
768 160 : autoMaskEffect(firstMask, effectChain);
769 80 : static_cast<LayerComposite*>(aLayer->AsHostLayer())->AddBlendModeEffect(effectChain);
770 80 : aRenderCallback(effectChain, aClipRect);
771 80 : return;
772 : }
773 :
774 : // We have multiple mask layers.
775 : // We split our list of mask layers into three parts:
776 : // (1) The first mask
777 : // (2) The list of intermediate masks (every mask except first and last)
778 : // (3) The final mask.
779 : // Part (2) can be empty.
780 : // For parts (1) and (2) we need to allocate intermediate surfaces to render
781 : // into. The final mask gets rendered into the original render target.
782 :
783 : // Calculate the size of the intermediate surfaces.
784 0 : gfx::Rect visibleRect(aLayer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds());
785 0 : gfx::Matrix4x4 transform = aLayer->GetEffectiveTransform();
786 : // TODO: Use RenderTargetIntRect and TransformBy here
787 : gfx::IntRect surfaceRect =
788 0 : RoundedOut(transform.TransformAndClipBounds(visibleRect, gfx::Rect(aClipRect)));
789 0 : if (surfaceRect.IsEmpty()) {
790 0 : return;
791 : }
792 :
793 : RefPtr<CompositingRenderTarget> originalTarget =
794 0 : aCompositor->GetCurrentRenderTarget();
795 :
796 : RefPtr<CompositingRenderTarget> firstTarget =
797 0 : aCompositor->CreateRenderTarget(surfaceRect, INIT_MODE_CLEAR);
798 0 : if (!firstTarget) {
799 0 : return;
800 : }
801 :
802 : // Render the source while applying the first mask.
803 0 : aCompositor->SetRenderTarget(firstTarget);
804 : {
805 0 : EffectChain firstEffectChain(aLayer);
806 : LayerManagerComposite::AutoAddMaskEffect
807 0 : firstMaskEffect(firstMask, firstEffectChain);
808 0 : aRenderCallback(firstEffectChain, aClipRect - surfaceRect.TopLeft());
809 : // firstTarget now contains the transformed source with the first mask and
810 : // opacity already applied.
811 : }
812 :
813 : // Apply the intermediate masks.
814 0 : gfx::IntRect intermediateClip(surfaceRect - surfaceRect.TopLeft());
815 0 : RefPtr<CompositingRenderTarget> previousTarget = firstTarget;
816 0 : for (size_t i = nextAncestorMaskLayer; i < ancestorMaskLayerCount - 1; i++) {
817 0 : Layer* intermediateMask = aLayer->GetAncestorMaskLayerAt(i);
818 : RefPtr<CompositingRenderTarget> intermediateTarget =
819 0 : aCompositor->CreateRenderTarget(surfaceRect, INIT_MODE_CLEAR);
820 0 : if (!intermediateTarget) {
821 0 : break;
822 : }
823 0 : aCompositor->SetRenderTarget(intermediateTarget);
824 0 : EffectChain intermediateEffectChain(aLayer);
825 : LayerManagerComposite::AutoAddMaskEffect
826 0 : intermediateMaskEffect(intermediateMask, intermediateEffectChain);
827 0 : if (intermediateMaskEffect.Failed()) {
828 0 : continue;
829 : }
830 0 : intermediateEffectChain.mPrimaryEffect = new EffectRenderTarget(previousTarget);
831 0 : aCompositor->DrawQuad(gfx::Rect(surfaceRect), intermediateClip,
832 : intermediateEffectChain, 1.0, gfx::Matrix4x4());
833 0 : previousTarget = intermediateTarget;
834 : }
835 :
836 0 : aCompositor->SetRenderTarget(originalTarget);
837 :
838 : // Apply the final mask, rendering into originalTarget.
839 0 : EffectChain finalEffectChain(aLayer);
840 0 : finalEffectChain.mPrimaryEffect = new EffectRenderTarget(previousTarget);
841 0 : Layer* finalMask = aLayer->GetAncestorMaskLayerAt(ancestorMaskLayerCount - 1);
842 :
843 : // The blend mode needs to be applied in this final step, because this is
844 : // where we're blending with the actual background (which is in originalTarget).
845 0 : static_cast<LayerComposite*>(aLayer->AsHostLayer())->AddBlendModeEffect(finalEffectChain);
846 0 : LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(finalMask, finalEffectChain);
847 0 : if (!autoMaskEffect.Failed()) {
848 0 : aCompositor->DrawQuad(gfx::Rect(surfaceRect), aClipRect,
849 : finalEffectChain, 1.0, gfx::Matrix4x4());
850 : }
851 : }
852 :
853 : } // namespace layers
854 : } // namespace mozilla
855 :
856 : #endif /* GFX_LayerManagerComposite_H */
|