Coverage Report

Created: 2018-09-25 14:53

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