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 #include "LayerManagerComposite.h"
8 #include <stddef.h>                   // for size_t
9 #include <stdint.h>                   // for uint16_t, uint32_t
10 #include "CanvasLayerComposite.h"     // for CanvasLayerComposite
11 #include "ColorLayerComposite.h"      // for ColorLayerComposite
12 #include "CompositableHost.h"         // for CompositableHost
13 #include "ContainerLayerComposite.h"  // for ContainerLayerComposite, etc
14 #include "Diagnostics.h"
15 #include "FPSCounter.h"           // for FPSState, FPSCounter
16 #include "FrameMetrics.h"         // for FrameMetrics
17 #include "ImageLayerComposite.h"  // for ImageLayerComposite
18 #include "Layers.h"               // for Layer, ContainerLayer, etc
19 #include "LayerScope.h"           // for LayerScope Tool
20 #include "LayerTreeInvalidation.h"
21 #include "protobuf/LayerScopePacket.pb.h"  // for protobuf (LayerScope)
22 #include "PaintedLayerComposite.h"         // for PaintedLayerComposite
23 #include "TiledContentHost.h"
24 #include "Units.h"                           // for ScreenIntRect
25 #include "UnitTransforms.h"                  // for ViewAs
26 #include "apz/src/AsyncPanZoomController.h"  // for AsyncPanZoomController
27 #include "gfxEnv.h"                          // for gfxEnv
28 
29 #ifdef XP_MACOSX
30 #  include "gfxPlatformMac.h"
31 #endif
32 #include "gfxRect.h"             // for gfxRect
33 #include "gfxUtils.h"            // for frame color util
34 #include "mozilla/Assertions.h"  // for MOZ_ASSERT, etc
35 #include "mozilla/ProfilerLabels.h"
36 #include "mozilla/RefPtr.h"  // for RefPtr, already_AddRefed
37 #include "mozilla/StaticPrefs_gfx.h"
38 #include "mozilla/StaticPrefs_layers.h"
39 #include "mozilla/gfx/2D.h"             // for DrawTarget
40 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
41 #include "mozilla/gfx/Point.h"          // for IntSize, Point
42 #include "mozilla/gfx/Rect.h"           // for Rect
43 #include "mozilla/gfx/Types.h"          // for Color, SurfaceFormat
44 #include "mozilla/layers/Compositor.h"  // for Compositor
45 #include "mozilla/layers/CompositorOGL.h"
46 #include "mozilla/layers/CompositorTypes.h"
47 #include "mozilla/layers/Effects.h"              // for Effect, EffectChain, etc
48 #include "mozilla/layers/LayerMetricsWrapper.h"  // for LayerMetricsWrapper
49 #include "mozilla/layers/LayersTypes.h"          // for etc
50 #include "mozilla/layers/NativeLayer.h"
51 #include "mozilla/layers/UiCompositorControllerParent.h"
52 #include "mozilla/widget/CompositorWidget.h"  // for WidgetRenderingContext
53 #include "ipc/CompositorBench.h"              // for CompositorBench
54 #include "ipc/SurfaceDescriptor.h"
55 #include "mozilla/mozalloc.h"  // for operator new, etc
56 #include "nsAppRunner.h"
57 #include "mozilla/RefPtr.h"   // for nsRefPtr
58 #include "nsCOMPtr.h"         // for already_AddRefed
59 #include "nsDebug.h"          // for NS_WARNING, etc
60 #include "nsISupportsImpl.h"  // for Layer::AddRef, etc
61 #include "nsPoint.h"          // for nsIntPoint
62 #include "nsRect.h"           // for mozilla::gfx::IntRect
63 #include "nsRegion.h"         // for nsIntRegion, etc
64 #if defined(MOZ_WIDGET_ANDROID)
65 #  include <android/log.h>
66 #  include <android/native_window.h>
67 #  include "mozilla/jni/Utils.h"
68 #  include "mozilla/widget/AndroidCompositorWidget.h"
69 #  include "GLConsts.h"
70 #  include "GLContextEGL.h"
71 #  include "GLContextProvider.h"
72 #  include "mozilla/Unused.h"
73 #  include "ScopedGLHelpers.h"
74 #endif
75 #include "TextRenderer.h"  // for TextRenderer
76 #include "mozilla/layers/CompositorBridgeParent.h"
77 #include "TreeTraversal.h"  // for ForEachNode
78 #include "CompositionRecorder.h"
79 
80 #ifdef USE_SKIA
81 #  include "PaintCounter.h"  // For PaintCounter
82 #endif
83 
84 class gfxContext;
85 
86 namespace mozilla {
87 namespace layers {
88 
89 class ImageLayer;
90 
91 using namespace mozilla::gfx;
92 using namespace mozilla::gl;
93 
ToLayerComposite(Layer * aLayer)94 static LayerComposite* ToLayerComposite(Layer* aLayer) {
95   return static_cast<LayerComposite*>(aLayer->ImplData());
96 }
97 
ClearSubtree(Layer * aLayer)98 static void ClearSubtree(Layer* aLayer) {
99   ForEachNode<ForwardIterator>(aLayer, [](Layer* layer) {
100     ToLayerComposite(layer)->CleanupResources();
101   });
102 }
103 
ClearCachedResources(Layer * aSubtree)104 void LayerManagerComposite::ClearCachedResources(Layer* aSubtree) {
105   MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this);
106   Layer* subtree = aSubtree ? aSubtree : mRoot.get();
107   if (!subtree) {
108     return;
109   }
110 
111   ClearSubtree(subtree);
112   // FIXME [bjacob]
113   // XXX the old LayerManagerOGL code had a mMaybeInvalidTree that it set to
114   // true here. Do we need that?
115 }
116 
HostLayerManager()117 HostLayerManager::HostLayerManager()
118     : mDebugOverlayWantsNextFrame(false),
119       mWarningLevel(0.0f),
120       mCompositorBridgeID(0),
121       mLastPaintTime(TimeDuration::Forever()),
122       mRenderStartTime(TimeStamp::Now()) {}
123 
124 HostLayerManager::~HostLayerManager() = default;
125 
RecordPaintTimes(const PaintTiming & aTiming)126 void HostLayerManager::RecordPaintTimes(const PaintTiming& aTiming) {
127   mDiagnostics->RecordPaintTimes(aTiming);
128 }
129 
RecordUpdateTime(float aValue)130 void HostLayerManager::RecordUpdateTime(float aValue) {
131   mDiagnostics->RecordUpdateTime(aValue);
132 }
133 
WriteCollectedFrames()134 void HostLayerManager::WriteCollectedFrames() {
135   if (mCompositionRecorder) {
136     mCompositionRecorder->WriteCollectedFrames();
137     mCompositionRecorder = nullptr;
138   }
139 }
140 
GetCollectedFrames()141 Maybe<CollectedFrames> HostLayerManager::GetCollectedFrames() {
142   Maybe<CollectedFrames> maybeFrames;
143 
144   if (mCompositionRecorder) {
145     maybeFrames.emplace(mCompositionRecorder->GetCollectedFrames());
146     mCompositionRecorder = nullptr;
147   }
148 
149   return maybeFrames;
150 }
151 
152 /**
153  * LayerManagerComposite
154  */
LayerManagerComposite(Compositor * aCompositor)155 LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
156     : mUnusedApzTransformWarning(false),
157       mDisabledApzWarning(false),
158       mCompositor(aCompositor),
159       mInTransaction(false),
160       mIsCompositorReady(false)
161 #if defined(MOZ_WIDGET_ANDROID)
162       ,
163       mScreenPixelsTarget(nullptr)
164 #endif  // defined(MOZ_WIDGET_ANDROID)
165 {
166   mTextRenderer = new TextRenderer();
167   mDiagnostics = MakeUnique<Diagnostics>();
168   MOZ_ASSERT(aCompositor);
169   mNativeLayerRoot = aCompositor->GetWidget()->GetNativeLayerRoot();
170   if (mNativeLayerRoot) {
171     mSurfacePoolHandle = aCompositor->GetSurfacePoolHandle();
172     MOZ_RELEASE_ASSERT(mSurfacePoolHandle);
173   }
174 
175 #ifdef USE_SKIA
176   mPaintCounter = nullptr;
177 #endif
178 }
179 
~LayerManagerComposite()180 LayerManagerComposite::~LayerManagerComposite() { Destroy(); }
181 
Destroy()182 void LayerManagerComposite::Destroy() {
183   if (!mDestroyed) {
184     mCompositor->GetWidget()->CleanupWindowEffects();
185     if (mRoot) {
186       RootLayer()->Destroy();
187     }
188     mCompositor->CancelFrame();
189     mRoot = nullptr;
190     mClonedLayerTreeProperties = nullptr;
191     mProfilerScreenshotGrabber.Destroy();
192 
193     if (mNativeLayerRoot) {
194       if (mGPUStatsLayer) {
195         mNativeLayerRoot->RemoveLayer(mGPUStatsLayer);
196         mGPUStatsLayer = nullptr;
197       }
198       if (mUnusedTransformWarningLayer) {
199         mNativeLayerRoot->RemoveLayer(mUnusedTransformWarningLayer);
200         mUnusedTransformWarningLayer = nullptr;
201       }
202       if (mDisabledApzWarningLayer) {
203         mNativeLayerRoot->RemoveLayer(mDisabledApzWarningLayer);
204         mDisabledApzWarningLayer = nullptr;
205       }
206       for (const auto& nativeLayer : mNativeLayers) {
207         mNativeLayerRoot->RemoveLayer(nativeLayer);
208       }
209       mNativeLayers.clear();
210       mNativeLayerRoot = nullptr;
211     }
212     mDestroyed = true;
213 
214 #ifdef USE_SKIA
215     mPaintCounter = nullptr;
216 #endif
217   }
218 }
219 
UpdateRenderBounds(const IntRect & aRect)220 void LayerManagerComposite::UpdateRenderBounds(const IntRect& aRect) {
221   mRenderBounds = aRect;
222 }
223 
AreComponentAlphaLayersEnabled()224 bool LayerManagerComposite::AreComponentAlphaLayersEnabled() {
225   return mCompositor->GetBackendType() != LayersBackend::LAYERS_BASIC &&
226          mCompositor->SupportsEffect(EffectTypes::COMPONENT_ALPHA) &&
227          LayerManager::AreComponentAlphaLayersEnabled();
228 }
229 
BeginTransaction(const nsCString & aURL)230 bool LayerManagerComposite::BeginTransaction(const nsCString& aURL) {
231   mInTransaction = true;
232 
233   if (!mCompositor->Ready()) {
234     return false;
235   }
236 
237   mIsCompositorReady = true;
238   return true;
239 }
240 
BeginTransactionWithDrawTarget(DrawTarget * aTarget,const IntRect & aRect)241 void LayerManagerComposite::BeginTransactionWithDrawTarget(
242     DrawTarget* aTarget, const IntRect& aRect) {
243   mInTransaction = true;
244 
245   if (!mCompositor->Ready()) {
246     return;
247   }
248 
249 #ifdef MOZ_LAYERS_HAVE_LOG
250   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
251   Log();
252 #endif
253 
254   if (mDestroyed) {
255     NS_WARNING("Call on destroyed layer manager");
256     return;
257   }
258 
259   mIsCompositorReady = true;
260   mTarget = aTarget;
261   mTargetBounds = aRect;
262 }
263 
264 template <typename Units>
TransformRect(const IntRectTyped<Units> & aRect,const Matrix & aTransform,bool aRoundIn=false)265 static IntRectTyped<Units> TransformRect(const IntRectTyped<Units>& aRect,
266                                          const Matrix& aTransform,
267                                          bool aRoundIn = false) {
268   if (aRect.IsEmpty()) {
269     return IntRectTyped<Units>();
270   }
271 
272   Rect rect(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
273   rect = aTransform.TransformBounds(rect);
274   if (aRoundIn) {
275     MOZ_ASSERT(aTransform.PreservesAxisAlignedRectangles());
276     rect.RoundIn();
277   } else {
278     rect.RoundOut();
279   }
280 
281   IntRect intRect;
282   if (!rect.ToIntRect(&intRect)) {
283     intRect = IntRect::MaxIntRect();
284   }
285 
286   return ViewAs<Units>(intRect);
287 }
288 
289 template <typename Units>
TransformRect(const IntRectTyped<Units> & aRect,const Matrix4x4 & aTransform,bool aRoundIn=false)290 static IntRectTyped<Units> TransformRect(const IntRectTyped<Units>& aRect,
291                                          const Matrix4x4& aTransform,
292                                          bool aRoundIn = false) {
293   if (aRect.IsEmpty()) {
294     return IntRectTyped<Units>();
295   }
296 
297   Rect rect(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
298   rect = aTransform.TransformAndClipBounds(rect, Rect::MaxIntRect());
299   if (aRoundIn) {
300     rect.RoundIn();
301   } else {
302     rect.RoundOut();
303   }
304 
305   IntRect intRect;
306   if (!rect.ToIntRect(&intRect)) {
307     intRect = IntRect::MaxIntRect();
308   }
309 
310   return ViewAs<Units>(intRect);
311 }
312 
313 template <typename Units, typename MatrixType>
TransformRectRoundIn(const IntRectTyped<Units> & aRect,const MatrixType & aTransform)314 static IntRectTyped<Units> TransformRectRoundIn(
315     const IntRectTyped<Units>& aRect, const MatrixType& aTransform) {
316   return TransformRect(aRect, aTransform, true);
317 }
318 
319 template <typename Units, typename MatrixType>
AddTransformedRegion(IntRegionTyped<Units> & aDest,const IntRegionTyped<Units> & aSource,const MatrixType & aTransform)320 static void AddTransformedRegion(IntRegionTyped<Units>& aDest,
321                                  const IntRegionTyped<Units>& aSource,
322                                  const MatrixType& aTransform) {
323   for (auto iter = aSource.RectIter(); !iter.Done(); iter.Next()) {
324     aDest.Or(aDest, TransformRect(iter.Get(), aTransform));
325   }
326   aDest.SimplifyOutward(20);
327 }
328 
329 template <typename Units, typename MatrixType>
AddTransformedRegionRoundIn(IntRegionTyped<Units> & aDest,const IntRegionTyped<Units> & aSource,const MatrixType & aTransform)330 static void AddTransformedRegionRoundIn(IntRegionTyped<Units>& aDest,
331                                         const IntRegionTyped<Units>& aSource,
332                                         const MatrixType& aTransform) {
333   for (auto iter = aSource.RectIter(); !iter.Done(); iter.Next()) {
334     aDest.Or(aDest, TransformRectRoundIn(iter.Get(), aTransform));
335   }
336 }
337 
PostProcessLayers(nsIntRegion & aOpaqueRegion)338 void LayerManagerComposite::PostProcessLayers(nsIntRegion& aOpaqueRegion) {
339   LayerIntRegion visible;
340   LayerComposite* rootComposite =
341       static_cast<LayerComposite*>(mRoot->AsHostLayer());
342   PostProcessLayers(
343       mRoot, aOpaqueRegion, visible,
344       ViewAs<RenderTargetPixel>(
345           rootComposite->GetShadowClipRect(),
346           PixelCastJustification::RenderTargetIsParentLayerForRoot),
347       Nothing(), true);
348 }
349 
350 // We want to skip directly through ContainerLayers that don't have an
351 // intermediate surface. We compute occlusions for leaves and intermediate
352 // surfaces against the layer that they actually composite into so that we can
353 // use the final (snapped) effective transform.
ShouldProcessLayer(Layer * aLayer)354 static bool ShouldProcessLayer(Layer* aLayer) {
355   if (!aLayer->AsContainerLayer()) {
356     return true;
357   }
358 
359   return aLayer->AsContainerLayer()->UseIntermediateSurface();
360 }
361 
PostProcessLayers(Layer * aLayer,nsIntRegion & aOpaqueRegion,LayerIntRegion & aVisibleRegion,const Maybe<RenderTargetIntRect> & aRenderTargetClip,const Maybe<ParentLayerIntRect> & aClipFromAncestors,bool aCanContributeOpaque)362 void LayerManagerComposite::PostProcessLayers(
363     Layer* aLayer, nsIntRegion& aOpaqueRegion, LayerIntRegion& aVisibleRegion,
364     const Maybe<RenderTargetIntRect>& aRenderTargetClip,
365     const Maybe<ParentLayerIntRect>& aClipFromAncestors,
366     bool aCanContributeOpaque) {
367   // Compute a clip that's the combination of our layer clip with the clip
368   // from our ancestors.
369   LayerComposite* composite =
370       static_cast<LayerComposite*>(aLayer->AsHostLayer());
371   Maybe<ParentLayerIntRect> layerClip = composite->GetShadowClipRect();
372   MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(),
373              "The layer with a clip should not participate "
374              "a 3D rendering context");
375   Maybe<ParentLayerIntRect> outsideClip =
376       IntersectMaybeRects(layerClip, aClipFromAncestors);
377 
378   Maybe<LayerIntRect> insideClip;
379   if (aLayer->Extend3DContext()) {
380     // If we're preserve-3d just pass the clip rect down directly, and we'll do
381     // the conversion at the preserve-3d leaf Layer.
382     if (outsideClip) {
383       insideClip = Some(ViewAs<LayerPixel>(
384           *outsideClip, PixelCastJustification::MovingDownToChildren));
385     }
386   } else if (outsideClip) {
387     // Convert the combined clip into our pre-transform coordinate space, so
388     // that it can later be intersected with our visible region.
389     // If our transform is a perspective, there's no meaningful insideClip rect
390     // we can compute (it would need to be a cone).
391     Matrix4x4 localTransform = aLayer->ComputeTransformToPreserve3DRoot();
392     if (!localTransform.HasPerspectiveComponent() && localTransform.Invert()) {
393       LayerRect insideClipFloat =
394           UntransformBy(ViewAs<ParentLayerToLayerMatrix4x4>(localTransform),
395                         ParentLayerRect(*outsideClip), LayerRect::MaxIntRect())
396               .valueOr(LayerRect());
397       insideClipFloat.RoundOut();
398       LayerIntRect insideClipInt;
399       if (insideClipFloat.ToIntRect(&insideClipInt)) {
400         insideClip = Some(insideClipInt);
401       }
402     }
403   }
404 
405   Maybe<ParentLayerIntRect> ancestorClipForChildren;
406   if (insideClip) {
407     ancestorClipForChildren = Some(ViewAs<ParentLayerPixel>(
408         *insideClip, PixelCastJustification::MovingDownToChildren));
409   }
410 
411   nsIntRegion dummy;
412   nsIntRegion& opaqueRegion = aOpaqueRegion;
413   if (aLayer->Extend3DContext() || aLayer->Combines3DTransformWithAncestors()) {
414     opaqueRegion = dummy;
415   }
416 
417   if (!ShouldProcessLayer(aLayer)) {
418     MOZ_ASSERT(aLayer->AsContainerLayer() &&
419                !aLayer->AsContainerLayer()->UseIntermediateSurface());
420     // For layers participating 3D rendering context, their visible
421     // region should be empty (invisible), so we pass through them
422     // without doing anything.
423     for (Layer* child = aLayer->GetLastChild(); child;
424          child = child->GetPrevSibling()) {
425       LayerComposite* childComposite =
426           static_cast<LayerComposite*>(child->AsHostLayer());
427       Maybe<RenderTargetIntRect> renderTargetClip = aRenderTargetClip;
428       if (childComposite->GetShadowClipRect()) {
429         RenderTargetIntRect clip = TransformBy(
430             ViewAs<ParentLayerToRenderTargetMatrix4x4>(
431                 aLayer->GetEffectiveTransform(),
432                 PixelCastJustification::RenderTargetIsParentLayerForRoot),
433             *childComposite->GetShadowClipRect());
434         renderTargetClip = IntersectMaybeRects(renderTargetClip, Some(clip));
435       }
436 
437       PostProcessLayers(
438           child, opaqueRegion, aVisibleRegion, renderTargetClip,
439           ancestorClipForChildren,
440           aCanContributeOpaque &
441               !(aLayer->GetContentFlags() & Layer::CONTENT_BACKFACE_HIDDEN));
442     }
443     return;
444   }
445 
446   nsIntRegion localOpaque;
447   // Treat layers on the path to the root of the 3D rendering context as
448   // a giant layer if it is a leaf.
449   Matrix4x4 transform = aLayer->GetEffectiveTransform();
450   Matrix transform2d;
451   bool canTransformOpaqueRegion = false;
452   // If aLayer has a simple transform (only an integer translation) then we
453   // can easily convert aOpaqueRegion into pre-transform coordinates and include
454   // that region.
455   if (aCanContributeOpaque &&
456       !(aLayer->GetContentFlags() & Layer::CONTENT_BACKFACE_HIDDEN) &&
457       transform.Is2D(&transform2d) &&
458       transform2d.PreservesAxisAlignedRectangles()) {
459     Matrix inverse = transform2d;
460     inverse.Invert();
461     AddTransformedRegionRoundIn(localOpaque, opaqueRegion, inverse);
462     canTransformOpaqueRegion = true;
463   }
464 
465   // Save the value of localOpaque, which currently stores the region obscured
466   // by siblings (and uncles and such), before our descendants contribute to it.
467   nsIntRegion obscured = localOpaque;
468 
469   // Recurse on our descendants, in front-to-back order. In this process:
470   //  - Occlusions are computed for them, and they contribute to localOpaque.
471   //  - They recalculate their visible regions, taking ancestorClipForChildren
472   //    into account, and accumulate them into descendantsVisibleRegion.
473   LayerIntRegion descendantsVisibleRegion;
474 
475   bool hasPreserve3DChild = false;
476   for (Layer* child = aLayer->GetLastChild(); child;
477        child = child->GetPrevSibling()) {
478     MOZ_ASSERT(aLayer->AsContainerLayer()->UseIntermediateSurface());
479     LayerComposite* childComposite =
480         static_cast<LayerComposite*>(child->AsHostLayer());
481     PostProcessLayers(
482         child, localOpaque, descendantsVisibleRegion,
483         ViewAs<RenderTargetPixel>(
484             childComposite->GetShadowClipRect(),
485             PixelCastJustification::RenderTargetIsParentLayerForRoot),
486         ancestorClipForChildren, true);
487     if (child->Extend3DContext()) {
488       hasPreserve3DChild = true;
489     }
490   }
491 
492   // Recalculate our visible region.
493   LayerIntRegion visible = composite->GetShadowVisibleRegion();
494 
495   // If we have descendants, throw away the visible region stored on this
496   // layer, and use the region accumulated by our descendants instead.
497   if (aLayer->GetFirstChild() && !hasPreserve3DChild) {
498     visible = descendantsVisibleRegion;
499   }
500 
501   // Subtract any areas that we know to be opaque.
502   if (!obscured.IsEmpty()) {
503     visible.SubOut(LayerIntRegion::FromUnknownRegion(obscured));
504   }
505 
506   // Clip the visible region using the combined clip.
507   if (insideClip) {
508     visible.AndWith(*insideClip);
509   }
510   composite->SetShadowVisibleRegion(visible);
511 
512   // Transform the newly calculated visible region into our parent's space,
513   // apply our clip to it (if any), and accumulate it into |aVisibleRegion|
514   // for the caller to use.
515   ParentLayerIntRegion visibleParentSpace =
516       TransformBy(ViewAs<LayerToParentLayerMatrix4x4>(transform), visible);
517   aVisibleRegion.OrWith(ViewAs<LayerPixel>(
518       visibleParentSpace, PixelCastJustification::MovingDownToChildren));
519 
520   // If we have a simple transform, then we can add our opaque area into
521   // aOpaqueRegion.
522   if (canTransformOpaqueRegion && !aLayer->HasMaskLayers() &&
523       aLayer->IsOpaqueForVisibility()) {
524     if (aLayer->IsOpaque()) {
525       localOpaque.OrWith(composite->GetFullyRenderedRegion());
526     }
527     nsIntRegion parentSpaceOpaque;
528     AddTransformedRegionRoundIn(parentSpaceOpaque, localOpaque, transform2d);
529     if (aRenderTargetClip) {
530       parentSpaceOpaque.AndWith(aRenderTargetClip->ToUnknownRect());
531     }
532     opaqueRegion.OrWith(parentSpaceOpaque);
533   }
534 }
535 
EndTransaction(const TimeStamp & aTimeStamp,EndTransactionFlags aFlags)536 void LayerManagerComposite::EndTransaction(const TimeStamp& aTimeStamp,
537                                            EndTransactionFlags aFlags) {
538   NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
539   NS_ASSERTION(!(aFlags & END_NO_COMPOSITE),
540                "Shouldn't get END_NO_COMPOSITE here");
541   mInTransaction = false;
542   mRenderStartTime = TimeStamp::Now();
543 
544   // Ensure we read unlock textures, even if we end up
545   // not compositing this frame.
546   TextureSourceProvider::AutoReadUnlockTextures unlock(mCompositor);
547 
548   if (!mIsCompositorReady) {
549     return;
550   }
551   mIsCompositorReady = false;
552 
553 #ifdef MOZ_LAYERS_HAVE_LOG
554   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
555   Log();
556 #endif
557 
558   if (mDestroyed) {
559     NS_WARNING("Call on destroyed layer manager");
560     return;
561   }
562 
563   // Set composition timestamp here because we need it in
564   // ComputeEffectiveTransforms (so the correct video frame size is picked) and
565   // also to compute invalid regions properly.
566   SetCompositionTime(aTimeStamp);
567 
568   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
569     MOZ_ASSERT(!aTimeStamp.IsNull());
570     UpdateAndRender();
571     mCompositor->FlushPendingNotifyNotUsed();
572   }
573 
574   mTarget = nullptr;
575 
576 #ifdef MOZ_LAYERS_HAVE_LOG
577   Log();
578   MOZ_LAYERS_LOG(("]----- EndTransaction"));
579 #endif
580 }
581 
SetRoot(Layer * aLayer)582 void LayerManagerComposite::SetRoot(Layer* aLayer) { mRoot = aLayer; }
583 
UpdateAndRender()584 void LayerManagerComposite::UpdateAndRender() {
585   mCompositionOpportunityId = mCompositionOpportunityId.Next();
586 
587   if (gfxEnv::SkipComposition()) {
588     mInvalidRegion.SetEmpty();
589     return;
590   }
591 
592   // The results of our drawing always go directly into a pixel buffer,
593   // so we don't need to pass any global transform here.
594   mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
595 
596   nsIntRegion opaque;
597   PostProcessLayers(opaque);
598 
599   if (mClonedLayerTreeProperties) {
600     // We need to compute layer tree differences even if we're not going to
601     // immediately use the resulting damage area, since ComputeDifferences
602     // is also responsible for invalidates intermediate surfaces in
603     // ContainerLayers.
604 
605     nsIntRegion changed;
606     const bool overflowed = !mClonedLayerTreeProperties->ComputeDifferences(
607         mRoot, changed, nullptr);
608 
609     if (overflowed) {
610       changed = mRenderBounds;
611     }
612 
613     mInvalidRegion.Or(mInvalidRegion, changed);
614   }
615 
616   nsIntRegion invalid;
617   if (mTarget) {
618     // Since we're composing to an external target, we're not going to use
619     // the damage region from layers changes - we want to composite
620     // everything in the target bounds. The layers damage region has been
621     // stored in mInvalidRegion and will be picked up by the next window
622     // composite.
623     invalid = mTargetBounds;
624   } else {
625     if (!mClonedLayerTreeProperties) {
626       // If we didn't have a previous layer tree, invalidate the entire render
627       // area.
628       mInvalidRegion = mRenderBounds;
629     }
630 
631     invalid = mInvalidRegion;
632   }
633 
634   if (invalid.IsEmpty()) {
635     // Composition requested, but nothing has changed. Don't do any work.
636     mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
637     mProfilerScreenshotGrabber.NotifyEmptyFrame();
638 
639     // Discard the current payloads. These payloads did not require a composite
640     // (they caused no changes to anything visible), so we don't want to measure
641     // their latency.
642     mPayload.Clear();
643 
644     return;
645   }
646 
647   // We don't want our debug overlay to cause more frames to happen
648   // so we will invalidate after we've decided if something changed.
649   // Only invalidate if we're not using native layers. When using native layers,
650   // UpdateDebugOverlayNativeLayers will repaint the appropriate layer areas.
651   if (!mNativeLayerRoot) {
652     InvalidateDebugOverlay(invalid, mRenderBounds);
653   }
654 
655   bool rendered = Render(invalid, opaque);
656 #if defined(MOZ_WIDGET_ANDROID)
657   RenderToPresentationSurface();
658 #endif
659 
660   if (!mTarget && rendered) {
661     mInvalidRegion.SetEmpty();
662   }
663 
664   // Update cached layer tree information.
665   mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
666 }
667 
CreateOptimalMaskDrawTarget(const IntSize & aSize)668 already_AddRefed<DrawTarget> LayerManagerComposite::CreateOptimalMaskDrawTarget(
669     const IntSize& aSize) {
670   MOZ_CRASH("Should only be called on the drawing side");
671   return nullptr;
672 }
673 
RootLayer() const674 LayerComposite* LayerManagerComposite::RootLayer() const {
675   if (mDestroyed) {
676     NS_WARNING("Call on destroyed layer manager");
677     return nullptr;
678   }
679 
680   return ToLayerComposite(mRoot);
681 }
682 
InvalidateDebugOverlay(nsIntRegion & aInvalidRegion,const IntRect & aBounds)683 void LayerManagerComposite::InvalidateDebugOverlay(nsIntRegion& aInvalidRegion,
684                                                    const IntRect& aBounds) {
685   bool drawFps = StaticPrefs::layers_acceleration_draw_fps();
686   bool drawFrameColorBars = StaticPrefs::gfx_draw_color_bars();
687 
688   if (drawFps) {
689     aInvalidRegion.Or(aInvalidRegion, nsIntRect(0, 0, 650, 400));
690   }
691   if (drawFrameColorBars) {
692     aInvalidRegion.Or(aInvalidRegion, nsIntRect(0, 0, 10, aBounds.Height()));
693   }
694 
695 #ifdef USE_SKIA
696   bool drawPaintTimes = StaticPrefs::gfx_content_always_paint();
697   if (drawPaintTimes) {
698     aInvalidRegion.Or(aInvalidRegion, nsIntRect(PaintCounter::GetPaintRect()));
699   }
700 #endif
701 }
702 
703 #ifdef USE_SKIA
DrawPaintTimes(Compositor * aCompositor)704 void LayerManagerComposite::DrawPaintTimes(Compositor* aCompositor) {
705   if (!mPaintCounter) {
706     mPaintCounter = new PaintCounter();
707   }
708 
709   TimeDuration compositeTime = TimeStamp::Now() - mRenderStartTime;
710   mPaintCounter->Draw(aCompositor, mLastPaintTime, compositeTime);
711 }
712 #endif
713 
RectWithEdges(int32_t aTop,int32_t aRight,int32_t aBottom,int32_t aLeft)714 static Rect RectWithEdges(int32_t aTop, int32_t aRight, int32_t aBottom,
715                           int32_t aLeft) {
716   return Rect(aLeft, aTop, aRight - aLeft, aBottom - aTop);
717 }
718 
DrawBorder(const IntRect & aOuter,int32_t aBorderWidth,const DeviceColor & aColor,const Matrix4x4 & aTransform)719 void LayerManagerComposite::DrawBorder(const IntRect& aOuter,
720                                        int32_t aBorderWidth,
721                                        const DeviceColor& aColor,
722                                        const Matrix4x4& aTransform) {
723   EffectChain effects;
724   effects.mPrimaryEffect = new EffectSolidColor(aColor);
725 
726   IntRect inner(aOuter);
727   inner.Deflate(aBorderWidth);
728   // Top and bottom border sides
729   mCompositor->DrawQuad(
730       RectWithEdges(aOuter.Y(), aOuter.XMost(), inner.Y(), aOuter.X()), aOuter,
731       effects, 1, aTransform);
732   mCompositor->DrawQuad(
733       RectWithEdges(inner.YMost(), aOuter.XMost(), aOuter.YMost(), aOuter.X()),
734       aOuter, effects, 1, aTransform);
735   // Left and right border sides
736   mCompositor->DrawQuad(
737       RectWithEdges(inner.Y(), inner.X(), inner.YMost(), aOuter.X()), aOuter,
738       effects, 1, aTransform);
739   mCompositor->DrawQuad(
740       RectWithEdges(inner.Y(), aOuter.XMost(), inner.YMost(), inner.XMost()),
741       aOuter, effects, 1, aTransform);
742 }
743 
DrawTranslationWarningOverlay(const IntRect & aBounds)744 void LayerManagerComposite::DrawTranslationWarningOverlay(
745     const IntRect& aBounds) {
746   // Black blorder
747   IntRect blackBorderBounds(aBounds);
748   blackBorderBounds.Deflate(4);
749   DrawBorder(blackBorderBounds, 6, DeviceColor(0, 0, 0, 1), Matrix4x4());
750 
751   // Warning border, yellow to red
752   IntRect warnBorder(aBounds);
753   warnBorder.Deflate(5);
754   DrawBorder(warnBorder, 4, DeviceColor(1, 1.f - mWarningLevel, 0, 1),
755              Matrix4x4());
756 }
757 
758 static uint16_t sFrameCount = 0;
RenderDebugOverlay(const IntRect & aBounds)759 void LayerManagerComposite::RenderDebugOverlay(const IntRect& aBounds) {
760   bool drawFps = StaticPrefs::layers_acceleration_draw_fps();
761   bool drawFrameColorBars = StaticPrefs::gfx_draw_color_bars();
762 
763   // Don't draw diagnostic overlays if we want to snapshot the output.
764   if (mTarget) {
765     return;
766   }
767 
768   if (drawFps) {
769 #ifdef ANDROID
770     // Draw a translation delay warning overlay
771     if (!mWarnTime.IsNull() && (TimeStamp::Now() - mWarnTime).ToMilliseconds() <
772                                    kVisualWarningDuration) {
773       DrawTranslationWarningOverlay(aBounds);
774       SetDebugOverlayWantsNextFrame(true);
775     }
776 #endif
777 
778     GPUStats stats;
779     stats.mScreenPixels = mRenderBounds.Width() * mRenderBounds.Height();
780     mCompositor->GetFrameStats(&stats);
781 
782     std::string text = mDiagnostics->GetFrameOverlayString(stats);
783     mTextRenderer->RenderText(mCompositor, text, IntPoint(2, 5), Matrix4x4(),
784                               24, 600, TextRenderer::FontType::FixedWidth);
785 
786     float alpha = 1;
787     if (mUnusedApzTransformWarning) {
788       // If we have an unused APZ transform on this composite, draw a 20x20 red
789       // box in the top-right corner
790       EffectChain effects;
791       effects.mPrimaryEffect =
792           new EffectSolidColor(gfx::DeviceColor(1, 0, 0, 1));
793       mCompositor->DrawQuad(gfx::Rect(aBounds.Width() - 20, 0, 20, 20), aBounds,
794                             effects, alpha, gfx::Matrix4x4());
795 
796       mUnusedApzTransformWarning = false;
797       SetDebugOverlayWantsNextFrame(true);
798     }
799     if (mDisabledApzWarning) {
800       // If we have a disabled APZ on this composite, draw a 20x20 yellow box
801       // in the top-right corner, to the left of the unused-apz-transform
802       // warning box
803       EffectChain effects;
804       effects.mPrimaryEffect =
805           new EffectSolidColor(gfx::DeviceColor(1, 1, 0, 1));
806       mCompositor->DrawQuad(gfx::Rect(aBounds.Width() - 40, 0, 20, 20), aBounds,
807                             effects, alpha, gfx::Matrix4x4());
808 
809       mDisabledApzWarning = false;
810       SetDebugOverlayWantsNextFrame(true);
811     }
812   }
813 
814   if (drawFrameColorBars) {
815     gfx::IntRect sideRect(0, 0, 10, aBounds.Height());
816 
817     EffectChain effects;
818     effects.mPrimaryEffect =
819         new EffectSolidColor(gfxUtils::GetColorForFrameNumber(sFrameCount));
820     mCompositor->DrawQuad(Rect(sideRect), sideRect, effects, 1.0,
821                           gfx::Matrix4x4());
822 
823     // We intentionally overflow at 2^16.
824     sFrameCount++;
825   }
826 
827 #ifdef USE_SKIA
828   bool drawPaintTimes = StaticPrefs::gfx_content_always_paint();
829   if (drawPaintTimes) {
830     DrawPaintTimes(mCompositor);
831   }
832 #endif
833 }
834 
UpdateDebugOverlayNativeLayers()835 void LayerManagerComposite::UpdateDebugOverlayNativeLayers() {
836   // Remove all debug layers first because PlaceNativeLayers might have changed
837   // the z-order. By removing and re-adding, we keep the debug overlay layers
838   // on top.
839   if (mGPUStatsLayer) {
840     mNativeLayerRoot->RemoveLayer(mGPUStatsLayer);
841   }
842   if (mUnusedTransformWarningLayer) {
843     mNativeLayerRoot->RemoveLayer(mUnusedTransformWarningLayer);
844   }
845   if (mDisabledApzWarningLayer) {
846     mNativeLayerRoot->RemoveLayer(mDisabledApzWarningLayer);
847   }
848 
849   bool drawFps = StaticPrefs::layers_acceleration_draw_fps();
850 
851   if (drawFps) {
852     GPUStats stats;
853     stats.mScreenPixels = mRenderBounds.Area();
854     mCompositor->GetFrameStats(&stats);
855 
856     std::string text = mDiagnostics->GetFrameOverlayString(stats);
857     IntSize size = mTextRenderer->ComputeSurfaceSize(
858         text, 600, TextRenderer::FontType::FixedWidth);
859 
860     if (!mGPUStatsLayer || mGPUStatsLayer->GetSize() != size) {
861       mGPUStatsLayer =
862           mNativeLayerRoot->CreateLayer(size, false, mSurfacePoolHandle);
863     }
864 
865     mGPUStatsLayer->SetPosition(IntPoint(2, 5));
866     IntRect bounds({}, size);
867     RefPtr<DrawTarget> dt = mGPUStatsLayer->NextSurfaceAsDrawTarget(
868         bounds, bounds, BackendType::SKIA);
869     mTextRenderer->RenderTextToDrawTarget(dt, text, 600,
870                                           TextRenderer::FontType::FixedWidth);
871     mGPUStatsLayer->NotifySurfaceReady();
872     mNativeLayerRoot->AppendLayer(mGPUStatsLayer);
873 
874     IntSize square(20, 20);
875     // The two warning layers are created on demand and their content is only
876     // drawn once. After that, they only get moved (if the window size changes)
877     // and conditionally shown.
878     // The drawing would be unnecessary if we had native "color layers".
879     if (mUnusedApzTransformWarning) {
880       // If we have an unused APZ transform on this composite, draw a 20x20 red
881       // box in the top-right corner.
882       if (!mUnusedTransformWarningLayer) {
883         mUnusedTransformWarningLayer =
884             mNativeLayerRoot->CreateLayer(square, true, mSurfacePoolHandle);
885         RefPtr<DrawTarget> dt =
886             mUnusedTransformWarningLayer->NextSurfaceAsDrawTarget(
887                 IntRect({}, square), IntRect({}, square), BackendType::SKIA);
888         dt->FillRect(Rect(0, 0, 20, 20), ColorPattern(DeviceColor(1, 0, 0, 1)));
889         mUnusedTransformWarningLayer->NotifySurfaceReady();
890       }
891       mUnusedTransformWarningLayer->SetPosition(
892           IntPoint(mRenderBounds.XMost() - 20, mRenderBounds.Y()));
893       mNativeLayerRoot->AppendLayer(mUnusedTransformWarningLayer);
894 
895       mUnusedApzTransformWarning = false;
896       SetDebugOverlayWantsNextFrame(true);
897     }
898 
899     if (mDisabledApzWarning) {
900       // If we have a disabled APZ on this composite, draw a 20x20 yellow box
901       // in the top-right corner, to the left of the unused-apz-transform
902       // warning box.
903       if (!mDisabledApzWarningLayer) {
904         mDisabledApzWarningLayer =
905             mNativeLayerRoot->CreateLayer(square, true, mSurfacePoolHandle);
906         RefPtr<DrawTarget> dt =
907             mDisabledApzWarningLayer->NextSurfaceAsDrawTarget(
908                 IntRect({}, square), IntRect({}, square), BackendType::SKIA);
909         dt->FillRect(Rect(0, 0, 20, 20), ColorPattern(DeviceColor(1, 1, 0, 1)));
910         mDisabledApzWarningLayer->NotifySurfaceReady();
911       }
912       mDisabledApzWarningLayer->SetPosition(
913           IntPoint(mRenderBounds.XMost() - 40, mRenderBounds.Y()));
914       mNativeLayerRoot->AppendLayer(mDisabledApzWarningLayer);
915 
916       mDisabledApzWarning = false;
917       SetDebugOverlayWantsNextFrame(true);
918     }
919   } else {
920     mGPUStatsLayer = nullptr;
921     mUnusedTransformWarningLayer = nullptr;
922     mDisabledApzWarningLayer = nullptr;
923   }
924 }
925 
926 RefPtr<CompositingRenderTarget>
PushGroupForLayerEffects()927 LayerManagerComposite::PushGroupForLayerEffects() {
928   // This is currently true, so just making sure that any new use of this
929   // method is flagged for investigation
930   MOZ_ASSERT(StaticPrefs::layers_effect_invert() ||
931              StaticPrefs::layers_effect_grayscale() ||
932              StaticPrefs::layers_effect_contrast() != 0.0);
933 
934   RefPtr<CompositingRenderTarget> previousTarget =
935       mCompositor->GetCurrentRenderTarget();
936   // make our render target the same size as the destination target
937   // so that we don't have to change size if the drawing area changes.
938   IntRect rect(previousTarget->GetOrigin(), previousTarget->GetSize());
939   // XXX: I'm not sure if this is true or not...
940   MOZ_ASSERT(rect.IsEqualXY(0, 0));
941   if (!mTwoPassTmpTarget ||
942       mTwoPassTmpTarget->GetSize() != previousTarget->GetSize() ||
943       mTwoPassTmpTarget->GetOrigin() != previousTarget->GetOrigin()) {
944     mTwoPassTmpTarget = mCompositor->CreateRenderTarget(rect, INIT_MODE_NONE);
945   }
946   MOZ_ASSERT(mTwoPassTmpTarget);
947   mCompositor->SetRenderTarget(mTwoPassTmpTarget);
948   return previousTarget;
949 }
950 
PopGroupForLayerEffects(RefPtr<CompositingRenderTarget> aPreviousTarget,IntRect aClipRect,bool aGrayscaleEffect,bool aInvertEffect,float aContrastEffect)951 void LayerManagerComposite::PopGroupForLayerEffects(
952     RefPtr<CompositingRenderTarget> aPreviousTarget, IntRect aClipRect,
953     bool aGrayscaleEffect, bool aInvertEffect, float aContrastEffect) {
954   MOZ_ASSERT(mTwoPassTmpTarget);
955 
956   // This is currently true, so just making sure that any new use of this
957   // method is flagged for investigation
958   MOZ_ASSERT(aInvertEffect || aGrayscaleEffect || aContrastEffect != 0.0);
959 
960   mCompositor->SetRenderTarget(aPreviousTarget);
961 
962   EffectChain effectChain(RootLayer());
963   Matrix5x4 effectMatrix;
964   if (aGrayscaleEffect) {
965     // R' = G' = B' = luminance
966     // R' = 0.2126*R + 0.7152*G + 0.0722*B
967     // G' = 0.2126*R + 0.7152*G + 0.0722*B
968     // B' = 0.2126*R + 0.7152*G + 0.0722*B
969     Matrix5x4 grayscaleMatrix(0.2126f, 0.2126f, 0.2126f, 0, 0.7152f, 0.7152f,
970                               0.7152f, 0, 0.0722f, 0.0722f, 0.0722f, 0, 0, 0, 0,
971                               1, 0, 0, 0, 0);
972     effectMatrix = grayscaleMatrix;
973   }
974 
975   if (aInvertEffect) {
976     // R' = 1 - R
977     // G' = 1 - G
978     // B' = 1 - B
979     Matrix5x4 colorInvertMatrix(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0,
980                                 1, 1, 1, 1, 0);
981     effectMatrix = effectMatrix * colorInvertMatrix;
982   }
983 
984   if (aContrastEffect != 0.0) {
985     // Multiplying with:
986     // R' = (1 + c) * (R - 0.5) + 0.5
987     // G' = (1 + c) * (G - 0.5) + 0.5
988     // B' = (1 + c) * (B - 0.5) + 0.5
989     float cP1 = aContrastEffect + 1;
990     float hc = 0.5 * aContrastEffect;
991     Matrix5x4 contrastMatrix(cP1, 0, 0, 0, 0, cP1, 0, 0, 0, 0, cP1, 0, 0, 0, 0,
992                              1, -hc, -hc, -hc, 0);
993     effectMatrix = effectMatrix * contrastMatrix;
994   }
995 
996   effectChain.mPrimaryEffect = new EffectRenderTarget(mTwoPassTmpTarget);
997   effectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX] =
998       new EffectColorMatrix(effectMatrix);
999 
1000   mCompositor->DrawQuad(Rect(Point(0, 0), Size(mTwoPassTmpTarget->GetSize())),
1001                         aClipRect, effectChain, 1., Matrix4x4());
1002 }
1003 
PlaceNativeLayers(const IntRegion & aRegion,bool aOpaque,std::deque<RefPtr<NativeLayer>> * aLayersToRecycle,IntRegion * aWindowInvalidRegion)1004 void LayerManagerComposite::PlaceNativeLayers(
1005     const IntRegion& aRegion, bool aOpaque,
1006     std::deque<RefPtr<NativeLayer>>* aLayersToRecycle,
1007     IntRegion* aWindowInvalidRegion) {
1008   IntSize tileSize(StaticPrefs::layers_compositing_tiles_width(),
1009                    StaticPrefs::layers_compositing_tiles_height());
1010   IntRect regionBounds = aRegion.GetBounds();
1011   for (int32_t y = 0; y < regionBounds.YMost(); y += tileSize.height) {
1012     for (int32_t x = 0; x < regionBounds.XMost(); x += tileSize.width) {
1013       IntRegion tileRegion;
1014       tileRegion.And(aRegion, IntRect(IntPoint(x, y), tileSize));
1015       for (auto iter = tileRegion.RectIter(); !iter.Done(); iter.Next()) {
1016         PlaceNativeLayer(iter.Get(), aOpaque, aLayersToRecycle,
1017                          aWindowInvalidRegion);
1018       }
1019     }
1020   }
1021 }
1022 
PlaceNativeLayer(const IntRect & aRect,bool aOpaque,std::deque<RefPtr<NativeLayer>> * aLayersToRecycle,IntRegion * aWindowInvalidRegion)1023 void LayerManagerComposite::PlaceNativeLayer(
1024     const IntRect& aRect, bool aOpaque,
1025     std::deque<RefPtr<NativeLayer>>* aLayersToRecycle,
1026     IntRegion* aWindowInvalidRegion) {
1027   RefPtr<NativeLayer> layer;
1028   if (aLayersToRecycle->empty() ||
1029       aLayersToRecycle->front()->GetSize() != aRect.Size() ||
1030       aLayersToRecycle->front()->IsOpaque() != aOpaque) {
1031     layer = mNativeLayerRoot->CreateLayer(aRect.Size(), aOpaque,
1032                                           mSurfacePoolHandle);
1033     mNativeLayerRoot->AppendLayer(layer);
1034     aWindowInvalidRegion->OrWith(aRect);
1035   } else {
1036     layer = aLayersToRecycle->front();
1037     aLayersToRecycle->pop_front();
1038     IntRect oldRect = layer->GetRect();
1039     if (!aRect.IsEqualInterior(oldRect)) {
1040       aWindowInvalidRegion->OrWith(oldRect);
1041       aWindowInvalidRegion->OrWith(aRect);
1042     }
1043   }
1044   layer->SetPosition(aRect.TopLeft());
1045   mNativeLayers.push_back(layer);
1046 }
1047 
1048 // Used to clear the 'mLayerComposited' flag at the beginning of each Render().
ClearLayerFlags(Layer * aLayer)1049 static void ClearLayerFlags(Layer* aLayer) {
1050   ForEachNode<ForwardIterator>(aLayer, [](Layer* layer) {
1051     if (layer->AsHostLayer()) {
1052       static_cast<LayerComposite*>(layer->AsHostLayer())
1053           ->SetLayerComposited(false);
1054     }
1055   });
1056 }
1057 
Render(const nsIntRegion & aInvalidRegion,const nsIntRegion & aOpaqueRegion)1058 bool LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion,
1059                                    const nsIntRegion& aOpaqueRegion) {
1060   AUTO_PROFILER_LABEL("LayerManagerComposite::Render", GRAPHICS);
1061 
1062   if (mDestroyed || !mCompositor || mCompositor->IsDestroyed()) {
1063     NS_WARNING("Call on destroyed layer manager");
1064     return false;
1065   }
1066 
1067   mCompositor->RequestAllowFrameRecording(!!mCompositionRecorder);
1068 
1069   ClearLayerFlags(mRoot);
1070 
1071   // At this time, it doesn't really matter if these preferences change
1072   // during the execution of the function; we should be safe in all
1073   // permutations. However, may as well just get the values onces and
1074   // then use them, just in case the consistency becomes important in
1075   // the future.
1076   bool invertVal = StaticPrefs::layers_effect_invert();
1077   bool grayscaleVal = StaticPrefs::layers_effect_grayscale();
1078   float contrastVal = StaticPrefs::layers_effect_contrast();
1079   bool haveLayerEffects = (invertVal || grayscaleVal || contrastVal != 0.0);
1080 
1081   // Set LayerScope begin/end frame
1082   LayerScopeAutoFrame frame(PR_Now());
1083 
1084   // If you're looking for the code to dump the layer tree, it was moved
1085   // to CompositorBridgeParent::CompositeToTarget().
1086 
1087   // Dump to LayerScope Viewer
1088   if (LayerScope::CheckSendable()) {
1089     // Create a LayersPacket, dump Layers into it and transfer the
1090     // packet('s ownership) to LayerScope.
1091     auto packet = MakeUnique<layerscope::Packet>();
1092     layerscope::LayersPacket* layersPacket = packet->mutable_layers();
1093     this->Dump(layersPacket);
1094     LayerScope::SendLayerDump(std::move(packet));
1095   }
1096 
1097   mozilla::widget::WidgetRenderingContext widgetContext;
1098 #if defined(XP_MACOSX)
1099   if (CompositorOGL* compositorOGL = mCompositor->AsCompositorOGL()) {
1100     widgetContext.mGL = compositorOGL->gl();
1101   }
1102 #endif
1103 
1104   {
1105     AUTO_PROFILER_LABEL("LayerManagerComposite::Render:Prerender", GRAPHICS);
1106 
1107     if (!mCompositor->GetWidget()->PreRender(&widgetContext)) {
1108       return false;
1109     }
1110   }
1111 
1112   CompositorBench(mCompositor, mRenderBounds);
1113 
1114   MOZ_ASSERT(mRoot->GetOpacity() == 1);
1115 #if defined(MOZ_WIDGET_ANDROID)
1116   LayerMetricsWrapper wrapper = GetRootContentLayer();
1117   if (wrapper) {
1118     mCompositor->SetClearColor(wrapper.Metadata().GetBackgroundColor());
1119   } else {
1120     mCompositor->SetClearColorToDefault();
1121   }
1122 #endif
1123 
1124   Maybe<IntRect> rootLayerClip = mRoot->GetClipRect().map(
1125       [](const ParentLayerIntRect& r) { return r.ToUnknownRect(); });
1126   Maybe<IntRect> maybeBounds;
1127   bool usingNativeLayers = false;
1128   if (mTarget) {
1129     maybeBounds = mCompositor->BeginFrameForTarget(
1130         aInvalidRegion, rootLayerClip, mRenderBounds, aOpaqueRegion, mTarget,
1131         mTargetBounds);
1132   } else if (mNativeLayerRoot) {
1133     mSurfacePoolHandle->OnBeginFrame();
1134     if (aInvalidRegion.Intersects(mRenderBounds)) {
1135       mCompositor->BeginFrameForNativeLayers();
1136       maybeBounds = Some(mRenderBounds);
1137       usingNativeLayers = true;
1138     }
1139   } else {
1140     maybeBounds = mCompositor->BeginFrameForWindow(
1141         aInvalidRegion, rootLayerClip, mRenderBounds, aOpaqueRegion);
1142   }
1143 
1144   if (!maybeBounds) {
1145     mProfilerScreenshotGrabber.NotifyEmptyFrame();
1146     mCompositor->GetWidget()->PostRender(&widgetContext);
1147 
1148     // Discard the current payloads. These payloads did not require a composite
1149     // (they caused no changes to anything visible), so we don't want to measure
1150     // their latency.
1151     mPayload.Clear();
1152 
1153     return true;
1154   }
1155 
1156   IntRect bounds = *maybeBounds;
1157   IntRect clipRect = rootLayerClip.valueOr(bounds);
1158 
1159   // Prepare our layers.
1160   {
1161     Diagnostics::Record record(mRenderStartTime);
1162     RootLayer()->Prepare(RenderTargetIntRect::FromUnknownRect(clipRect));
1163     if (record.Recording()) {
1164       mDiagnostics->RecordPrepareTime(record.Duration());
1165     }
1166   }
1167 
1168   auto RenderOnce = [&](const IntRect& aClipRect) {
1169     RefPtr<CompositingRenderTarget> previousTarget;
1170     if (haveLayerEffects) {
1171       previousTarget = PushGroupForLayerEffects();
1172     } else {
1173       mTwoPassTmpTarget = nullptr;
1174     }
1175 
1176     // Execute draw commands.
1177     RootLayer()->RenderLayer(aClipRect, Nothing());
1178 
1179     if (mTwoPassTmpTarget) {
1180       MOZ_ASSERT(haveLayerEffects);
1181       PopGroupForLayerEffects(previousTarget, aClipRect, grayscaleVal,
1182                               invertVal, contrastVal);
1183     }
1184     if (!mRegionToClear.IsEmpty()) {
1185       for (auto iter = mRegionToClear.RectIter(); !iter.Done(); iter.Next()) {
1186         mCompositor->ClearRect(Rect(iter.Get()));
1187       }
1188     }
1189     mCompositor->NormalDrawingDone();
1190   };
1191 
1192   {
1193     Diagnostics::Record record;
1194 
1195     if (usingNativeLayers) {
1196       // Update the placement of our native layers, so that transparent and
1197       // opaque parts of the window are covered by different layers and we can
1198       // update those parts separately.
1199       IntRegion opaqueRegion;
1200       opaqueRegion.And(aOpaqueRegion, mRenderBounds);
1201 
1202       // Limit the complexity of these regions. Usually, opaqueRegion should be
1203       // only one or two rects, so this SimplifyInward call will not change the
1204       // region if everything looks as expected.
1205       opaqueRegion.SimplifyInward(4);
1206 
1207       IntRegion transparentRegion;
1208       transparentRegion.Sub(mRenderBounds, opaqueRegion);
1209       std::deque<RefPtr<NativeLayer>> layersToRecycle =
1210           std::move(mNativeLayers);
1211       IntRegion invalidRegion = aInvalidRegion;
1212       PlaceNativeLayers(opaqueRegion, true, &layersToRecycle, &invalidRegion);
1213       PlaceNativeLayers(transparentRegion, false, &layersToRecycle,
1214                         &invalidRegion);
1215       for (const auto& unusedLayer : layersToRecycle) {
1216         mNativeLayerRoot->RemoveLayer(unusedLayer);
1217       }
1218 
1219       for (const auto& nativeLayer : mNativeLayers) {
1220         Maybe<IntRect> maybeLayerRect =
1221             mCompositor->BeginRenderingToNativeLayer(
1222                 invalidRegion, rootLayerClip, aOpaqueRegion, nativeLayer);
1223         if (!maybeLayerRect) {
1224           continue;
1225         }
1226 
1227         if (rootLayerClip) {
1228           RenderOnce(rootLayerClip->Intersect(*maybeLayerRect));
1229         } else {
1230           RenderOnce(*maybeLayerRect);
1231         }
1232         mCompositor->EndRenderingToNativeLayer();
1233       }
1234     } else {
1235       RenderOnce(clipRect);
1236     }
1237 
1238     if (record.Recording()) {
1239       mDiagnostics->RecordCompositeTime(record.Duration());
1240     }
1241   }
1242 
1243   RootLayer()->Cleanup();
1244 
1245   WindowLMC window(mCompositor);
1246   mProfilerScreenshotGrabber.MaybeGrabScreenshot(window, bounds.Size());
1247 
1248   if (mCompositionRecorder) {
1249     bool hasContentPaint = std::any_of(
1250         mPayload.begin(), mPayload.end(), [](CompositionPayload& payload) {
1251           return payload.mType == CompositionPayloadType::eContentPaint;
1252         });
1253 
1254     if (hasContentPaint) {
1255       if (RefPtr<RecordedFrame> frame =
1256               mCompositor->RecordFrame(TimeStamp::Now())) {
1257         mCompositionRecorder->RecordFrame(frame);
1258       }
1259     }
1260   }
1261 
1262   if (usingNativeLayers) {
1263     UpdateDebugOverlayNativeLayers();
1264   } else {
1265 #if defined(MOZ_WIDGET_ANDROID)
1266     HandlePixelsTarget();
1267 #endif  // defined(MOZ_WIDGET_ANDROID)
1268 
1269     // Debugging
1270     RenderDebugOverlay(bounds);
1271   }
1272 
1273   {
1274     AUTO_PROFILER_LABEL("LayerManagerComposite::Render:EndFrame", GRAPHICS);
1275 
1276     mCompositor->EndFrame();
1277 
1278     if (usingNativeLayers) {
1279       mNativeLayerRoot->CommitToScreen();
1280     }
1281   }
1282 
1283   mCompositor->GetWidget()->PostRender(&widgetContext);
1284 
1285   mProfilerScreenshotGrabber.MaybeProcessQueue();
1286 
1287   RecordFrame();
1288 
1289   PayloadPresented(TimeStamp::Now());
1290 
1291   // Our payload has now been presented.
1292   mPayload.Clear();
1293 
1294   if (usingNativeLayers) {
1295     mSurfacePoolHandle->OnEndFrame();
1296   }
1297 
1298   mCompositor->WaitForGPU();
1299 
1300   return true;
1301 }
1302 
1303 #if defined(MOZ_WIDGET_ANDROID)
1304 class ScopedCompostitorSurfaceSize {
1305  public:
ScopedCompostitorSurfaceSize(CompositorOGL * aCompositor,const gfx::IntSize & aSize)1306   ScopedCompostitorSurfaceSize(CompositorOGL* aCompositor,
1307                                const gfx::IntSize& aSize)
1308       : mCompositor(aCompositor),
1309         mOriginalSize(mCompositor->GetDestinationSurfaceSize()) {
1310     mCompositor->SetDestinationSurfaceSize(aSize);
1311   }
~ScopedCompostitorSurfaceSize()1312   ~ScopedCompostitorSurfaceSize() {
1313     mCompositor->SetDestinationSurfaceSize(mOriginalSize);
1314   }
1315 
1316  private:
1317   CompositorOGL* const mCompositor;
1318   const gfx::IntSize mOriginalSize;
1319 };
1320 
1321 class ScopedContextSurfaceOverride {
1322  public:
ScopedContextSurfaceOverride(GLContextEGL * aContext,void * aSurface)1323   ScopedContextSurfaceOverride(GLContextEGL* aContext, void* aSurface)
1324       : mContext(aContext) {
1325     MOZ_ASSERT(aSurface);
1326     mContext->SetEGLSurfaceOverride(aSurface);
1327     mContext->MakeCurrent(true);
1328   }
~ScopedContextSurfaceOverride()1329   ~ScopedContextSurfaceOverride() {
1330     mContext->SetEGLSurfaceOverride(EGL_NO_SURFACE);
1331     mContext->MakeCurrent(true);
1332   }
1333 
1334  private:
1335   GLContextEGL* const mContext;
1336 };
1337 
RenderToPresentationSurface()1338 void LayerManagerComposite::RenderToPresentationSurface() {
1339   if (!mCompositor) {
1340     return;
1341   }
1342 
1343   widget::CompositorWidget* const widget = mCompositor->GetWidget();
1344 
1345   if (!widget) {
1346     return;
1347   }
1348 
1349   ANativeWindow* window = widget->AsAndroid()->GetPresentationANativeWindow();
1350 
1351   if (!window) {
1352     return;
1353   }
1354 
1355   CompositorOGL* compositor = mCompositor->AsCompositorOGL();
1356   GLContext* gl = compositor->gl();
1357   GLContextEGL* egl = GLContextEGL::Cast(gl);
1358 
1359   if (!egl) {
1360     return;
1361   }
1362 
1363   EGLSurface surface = widget->AsAndroid()->GetPresentationEGLSurface();
1364 
1365   if (!surface) {
1366     // create surface;
1367     surface = egl->CreateCompatibleSurface(window);
1368     if (!surface) {
1369       return;
1370     }
1371 
1372     widget->AsAndroid()->SetPresentationEGLSurface(surface);
1373   }
1374 
1375   const IntSize windowSize(ANativeWindow_getWidth(window),
1376                            ANativeWindow_getHeight(window));
1377 
1378   if ((windowSize.width <= 0) || (windowSize.height <= 0)) {
1379     return;
1380   }
1381 
1382   ScreenRotation rotation = compositor->GetScreenRotation();
1383 
1384   const int actualWidth = windowSize.width;
1385   const int actualHeight = windowSize.height;
1386 
1387   const gfx::IntSize originalSize = compositor->GetDestinationSurfaceSize();
1388   const nsIntRect originalRect =
1389       nsIntRect(0, 0, originalSize.width, originalSize.height);
1390 
1391   int pageWidth = originalSize.width;
1392   int pageHeight = originalSize.height;
1393   if (rotation == ROTATION_90 || rotation == ROTATION_270) {
1394     pageWidth = originalSize.height;
1395     pageHeight = originalSize.width;
1396   }
1397 
1398   float scale = 1.0;
1399 
1400   if ((pageWidth > actualWidth) || (pageHeight > actualHeight)) {
1401     const float scaleWidth = (float)actualWidth / (float)pageWidth;
1402     const float scaleHeight = (float)actualHeight / (float)pageHeight;
1403     scale = scaleWidth <= scaleHeight ? scaleWidth : scaleHeight;
1404   }
1405 
1406   const gfx::IntSize actualSize(actualWidth, actualHeight);
1407   ScopedCompostitorSurfaceSize overrideSurfaceSize(compositor, actualSize);
1408 
1409   const ScreenPoint offset((actualWidth - (int)(scale * pageWidth)) / 2, 0);
1410   ScopedContextSurfaceOverride overrideSurface(egl, surface);
1411 
1412   Matrix viewMatrix = ComputeTransformForRotation(originalRect, rotation);
1413   viewMatrix.Invert();  // unrotate
1414   viewMatrix.PostScale(scale, scale);
1415   viewMatrix.PostTranslate(offset.x, offset.y);
1416   Matrix4x4 matrix = Matrix4x4::From2D(viewMatrix);
1417 
1418   mRoot->ComputeEffectiveTransforms(matrix);
1419   nsIntRegion opaque;
1420   PostProcessLayers(opaque);
1421 
1422   nsIntRegion invalid;
1423   IntRect bounds = IntRect::Truncate(0, 0, scale * pageWidth, actualHeight);
1424   MOZ_ASSERT(mRoot->GetOpacity() == 1);
1425   Unused << mCompositor->BeginFrameForWindow(invalid, Nothing(), bounds,
1426                                              nsIntRegion());
1427 
1428   // The Java side of Fennec sets a scissor rect that accounts for
1429   // chrome such as the URL bar. Override that so that the entire frame buffer
1430   // is cleared.
1431   ScopedScissorRect scissorRect(egl, 0, 0, actualWidth, actualHeight);
1432   egl->fClearColor(0.0, 0.0, 0.0, 0.0);
1433   egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
1434 
1435   const IntRect clipRect = IntRect::Truncate(0, 0, actualWidth, actualHeight);
1436 
1437   RootLayer()->Prepare(RenderTargetIntRect::FromUnknownRect(clipRect));
1438   RootLayer()->RenderLayer(clipRect, Nothing());
1439 
1440   mCompositor->EndFrame();
1441 }
1442 
1443 // Used by robocop tests to get a snapshot of the frame buffer.
HandlePixelsTarget()1444 void LayerManagerComposite::HandlePixelsTarget() {
1445   if (!mScreenPixelsTarget) {
1446     return;
1447   }
1448 
1449   int32_t bufferWidth = mRenderBounds.width;
1450   int32_t bufferHeight = mRenderBounds.height;
1451   ipc::Shmem mem;
1452   if (!mScreenPixelsTarget->AllocPixelBuffer(
1453           bufferWidth * bufferHeight * sizeof(uint32_t), &mem)) {
1454     // Failed to alloc shmem, Just bail out.
1455     return;
1456   }
1457   CompositorOGL* compositor = mCompositor->AsCompositorOGL();
1458   GLContext* gl = compositor->gl();
1459   MOZ_ASSERT(gl);
1460   gl->fReadPixels(0, 0, bufferWidth, bufferHeight, LOCAL_GL_RGBA,
1461                   LOCAL_GL_UNSIGNED_BYTE, mem.get<uint8_t>());
1462   Unused << mScreenPixelsTarget->SendScreenPixels(
1463       std::move(mem), ScreenIntSize(bufferWidth, bufferHeight), true);
1464   mScreenPixelsTarget = nullptr;
1465 }
1466 #endif
1467 
CreatePaintedLayer()1468 already_AddRefed<PaintedLayer> LayerManagerComposite::CreatePaintedLayer() {
1469   if (mDestroyed) {
1470     NS_WARNING("Call on destroyed layer manager");
1471     return nullptr;
1472   }
1473   return RefPtr<PaintedLayer>(new PaintedLayerComposite(this)).forget();
1474 }
1475 
CreateContainerLayer()1476 already_AddRefed<ContainerLayer> LayerManagerComposite::CreateContainerLayer() {
1477   if (mDestroyed) {
1478     NS_WARNING("Call on destroyed layer manager");
1479     return nullptr;
1480   }
1481   return RefPtr<ContainerLayer>(new ContainerLayerComposite(this)).forget();
1482 }
1483 
CreateImageLayer()1484 already_AddRefed<ImageLayer> LayerManagerComposite::CreateImageLayer() {
1485   if (mDestroyed) {
1486     NS_WARNING("Call on destroyed layer manager");
1487     return nullptr;
1488   }
1489   return RefPtr<ImageLayer>(new ImageLayerComposite(this)).forget();
1490 }
1491 
CreateColorLayer()1492 already_AddRefed<ColorLayer> LayerManagerComposite::CreateColorLayer() {
1493   if (LayerManagerComposite::mDestroyed) {
1494     NS_WARNING("Call on destroyed layer manager");
1495     return nullptr;
1496   }
1497   return RefPtr<ColorLayer>(new ColorLayerComposite(this)).forget();
1498 }
1499 
CreateCanvasLayer()1500 already_AddRefed<CanvasLayer> LayerManagerComposite::CreateCanvasLayer() {
1501   if (LayerManagerComposite::mDestroyed) {
1502     NS_WARNING("Call on destroyed layer manager");
1503     return nullptr;
1504   }
1505   return RefPtr<CanvasLayer>(new CanvasLayerComposite(this)).forget();
1506 }
1507 
CreateRefLayer()1508 already_AddRefed<RefLayer> LayerManagerComposite::CreateRefLayer() {
1509   if (LayerManagerComposite::mDestroyed) {
1510     NS_WARNING("Call on destroyed layer manager");
1511     return nullptr;
1512   }
1513   return RefPtr<RefLayer>(new RefLayerComposite(this)).forget();
1514 }
1515 
AutoAddMaskEffect(Layer * aMaskLayer,EffectChain & aEffects)1516 LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(
1517     Layer* aMaskLayer, EffectChain& aEffects)
1518     : mCompositable(nullptr), mFailed(false) {
1519   if (!aMaskLayer) {
1520     return;
1521   }
1522 
1523   mCompositable = ToLayerComposite(aMaskLayer)->GetCompositableHost();
1524   if (!mCompositable) {
1525     NS_WARNING("Mask layer with no compositable host");
1526     mFailed = true;
1527     return;
1528   }
1529 
1530   if (!mCompositable->AddMaskEffect(aEffects,
1531                                     aMaskLayer->GetEffectiveTransform())) {
1532     mCompositable = nullptr;
1533     mFailed = true;
1534   }
1535 }
1536 
~AutoAddMaskEffect()1537 LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect() {
1538   if (!mCompositable) {
1539     return;
1540   }
1541 
1542   mCompositable->RemoveMaskEffect();
1543 }
1544 
IsCompositingToScreen() const1545 bool LayerManagerComposite::IsCompositingToScreen() const { return !mTarget; }
1546 
LayerComposite(LayerManagerComposite * aManager)1547 LayerComposite::LayerComposite(LayerManagerComposite* aManager)
1548     : HostLayer(aManager),
1549       mCompositeManager(aManager),
1550       mCompositor(aManager->GetCompositor()),
1551       mDestroyed(false),
1552       mLayerComposited(false) {}
1553 
1554 LayerComposite::~LayerComposite() = default;
1555 
Destroy()1556 void LayerComposite::Destroy() {
1557   if (!mDestroyed) {
1558     mDestroyed = true;
1559     CleanupResources();
1560   }
1561 }
1562 
AddBlendModeEffect(EffectChain & aEffectChain)1563 void LayerComposite::AddBlendModeEffect(EffectChain& aEffectChain) {
1564   gfx::CompositionOp blendMode = GetLayer()->GetEffectiveMixBlendMode();
1565   if (blendMode == gfx::CompositionOp::OP_OVER) {
1566     return;
1567   }
1568 
1569   aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE] =
1570       new EffectBlendMode(blendMode);
1571 }
1572 
CanUseCanvasLayerForSize(const IntSize & aSize)1573 bool LayerManagerComposite::CanUseCanvasLayerForSize(const IntSize& aSize) {
1574   return mCompositor->CanUseCanvasLayerForSize(
1575       gfx::IntSize(aSize.width, aSize.height));
1576 }
1577 
NotifyShadowTreeTransaction()1578 void LayerManagerComposite::NotifyShadowTreeTransaction() {
1579   if (StaticPrefs::layers_acceleration_draw_fps()) {
1580     mDiagnostics->AddTxnFrame();
1581   }
1582 }
1583 
SetLayerManager(HostLayerManager * aManager)1584 void LayerComposite::SetLayerManager(HostLayerManager* aManager) {
1585   HostLayer::SetLayerManager(aManager);
1586   mCompositeManager = static_cast<LayerManagerComposite*>(aManager);
1587   mCompositor = mCompositeManager->GetCompositor();
1588 }
1589 
AsyncPanZoomEnabled() const1590 bool LayerManagerComposite::AsyncPanZoomEnabled() const {
1591   if (CompositorBridgeParent* bridge =
1592           mCompositor->GetCompositorBridgeParent()) {
1593     return bridge->GetOptions().UseAPZ();
1594   }
1595   return false;
1596 }
1597 
AlwaysScheduleComposite() const1598 bool LayerManagerComposite::AlwaysScheduleComposite() const {
1599   return !!(mCompositor->GetDiagnosticTypes() & DiagnosticTypes::FLASH_BORDERS);
1600 }
1601 
GetFullyRenderedRegion()1602 nsIntRegion LayerComposite::GetFullyRenderedRegion() {
1603   if (TiledContentHost* tiled =
1604           GetCompositableHost() ? GetCompositableHost()->AsTiledContentHost()
1605                                 : nullptr) {
1606     nsIntRegion shadowVisibleRegion =
1607         GetShadowVisibleRegion().ToUnknownRegion();
1608     // Discard the region which hasn't been drawn yet when doing
1609     // progressive drawing. Note that if the shadow visible region
1610     // shrunk the tiled valig region may not have discarded this yet.
1611     shadowVisibleRegion.And(shadowVisibleRegion, tiled->GetValidRegion());
1612     return shadowVisibleRegion;
1613   } else {
1614     return GetShadowVisibleRegion().ToUnknownRegion();
1615   }
1616 }
1617 
GetShadowTransform()1618 Matrix4x4 HostLayer::GetShadowTransform() {
1619   Matrix4x4 transform = mShadowTransform;
1620   Layer* layer = GetLayer();
1621 
1622   transform.PostScale(layer->GetPostXScale(), layer->GetPostYScale(), 1.0f);
1623   if (const ContainerLayer* c = layer->AsContainerLayer()) {
1624     transform.PreScale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
1625   }
1626 
1627   return transform;
1628 }
1629 
1630 // Async animations can move child layers without updating our visible region.
1631 // PostProcessLayers will recompute visible regions for layers with an
1632 // intermediate surface, but otherwise we need to do it now.
ComputeVisibleRegionForChildren(ContainerLayer * aContainer,LayerIntRegion & aResult)1633 static void ComputeVisibleRegionForChildren(ContainerLayer* aContainer,
1634                                             LayerIntRegion& aResult) {
1635   for (Layer* l = aContainer->GetFirstChild(); l; l = l->GetNextSibling()) {
1636     if (l->Extend3DContext()) {
1637       MOZ_ASSERT(l->AsContainerLayer());
1638       ComputeVisibleRegionForChildren(l->AsContainerLayer(), aResult);
1639     } else {
1640       AddTransformedRegion(aResult, l->GetLocalVisibleRegion(),
1641                            l->ComputeTransformToPreserve3DRoot());
1642     }
1643   }
1644 }
1645 
RecomputeShadowVisibleRegionFromChildren()1646 void HostLayer::RecomputeShadowVisibleRegionFromChildren() {
1647   mShadowVisibleRegion.SetEmpty();
1648   ContainerLayer* container = GetLayer()->AsContainerLayer();
1649   MOZ_ASSERT(container);
1650   // Layers that extend a 3d context have a local visible region
1651   // that can only be represented correctly in 3d space. Since
1652   // we can't do that, leave it empty instead to stop anyone
1653   // from trying to use it.
1654   NS_ASSERTION(
1655       !GetLayer()->Extend3DContext(),
1656       "Can't compute visible region for layers that extend a 3d context");
1657   if (container && !GetLayer()->Extend3DContext()) {
1658     ComputeVisibleRegionForChildren(container, mShadowVisibleRegion);
1659   }
1660 }
1661 
HasStaleCompositor() const1662 bool LayerComposite::HasStaleCompositor() const {
1663   return mCompositeManager->GetCompositor() != mCompositor;
1664 }
1665 
1666 #ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
1667 
1668 /*static*/
SupportsDirectTexturing()1669 bool LayerManagerComposite::SupportsDirectTexturing() { return false; }
1670 
1671 /*static*/
PlatformSyncBeforeReplyUpdate()1672 void LayerManagerComposite::PlatformSyncBeforeReplyUpdate() {}
1673 
1674 #endif  // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
1675 
1676 class RenderSourceLMC : public profiler_screenshots::RenderSource {
1677  public:
RenderSourceLMC(CompositingRenderTarget * aRT)1678   explicit RenderSourceLMC(CompositingRenderTarget* aRT)
1679       : RenderSource(aRT->GetSize()), mRT(aRT) {}
1680 
RenderTarget()1681   const auto& RenderTarget() { return mRT; }
1682 
1683  protected:
~RenderSourceLMC()1684   virtual ~RenderSourceLMC() {}
1685 
1686   RefPtr<CompositingRenderTarget> mRT;
1687 };
1688 
1689 class DownscaleTargetLMC : public profiler_screenshots::DownscaleTarget {
1690  public:
DownscaleTargetLMC(CompositingRenderTarget * aRT,Compositor * aCompositor)1691   explicit DownscaleTargetLMC(CompositingRenderTarget* aRT,
1692                               Compositor* aCompositor)
1693       : profiler_screenshots::DownscaleTarget(aRT->GetSize()),
1694         mRenderSource(new RenderSourceLMC(aRT)),
1695         mCompositor(aCompositor) {}
1696 
AsRenderSource()1697   already_AddRefed<profiler_screenshots::RenderSource> AsRenderSource()
1698       override {
1699     return do_AddRef(mRenderSource);
1700   }
1701 
DownscaleFrom(profiler_screenshots::RenderSource * aSource,const IntRect & aSourceRect,const IntRect & aDestRect)1702   bool DownscaleFrom(profiler_screenshots::RenderSource* aSource,
1703                      const IntRect& aSourceRect,
1704                      const IntRect& aDestRect) override {
1705     MOZ_RELEASE_ASSERT(aSourceRect.TopLeft() == IntPoint());
1706     MOZ_RELEASE_ASSERT(aDestRect.TopLeft() == IntPoint());
1707     RefPtr<CompositingRenderTarget> previousTarget =
1708         mCompositor->GetCurrentRenderTarget();
1709 
1710     mCompositor->SetRenderTarget(mRenderSource->RenderTarget());
1711     bool result = mCompositor->BlitRenderTarget(
1712         static_cast<RenderSourceLMC*>(aSource)->RenderTarget(),
1713         aSourceRect.Size(), aDestRect.Size());
1714 
1715     // Restore the old render target.
1716     mCompositor->SetRenderTarget(previousTarget);
1717 
1718     return result;
1719   }
1720 
1721  protected:
~DownscaleTargetLMC()1722   virtual ~DownscaleTargetLMC() {}
1723 
1724   RefPtr<RenderSourceLMC> mRenderSource;
1725   Compositor* mCompositor;
1726 };
1727 
1728 class AsyncReadbackBufferLMC
1729     : public profiler_screenshots::AsyncReadbackBuffer {
1730  public:
AsyncReadbackBufferLMC(mozilla::layers::AsyncReadbackBuffer * aARB,Compositor * aCompositor)1731   AsyncReadbackBufferLMC(mozilla::layers::AsyncReadbackBuffer* aARB,
1732                          Compositor* aCompositor)
1733       : profiler_screenshots::AsyncReadbackBuffer(aARB->GetSize()),
1734         mARB(aARB),
1735         mCompositor(aCompositor) {}
CopyFrom(profiler_screenshots::RenderSource * aSource)1736   void CopyFrom(profiler_screenshots::RenderSource* aSource) override {
1737     mCompositor->ReadbackRenderTarget(
1738         static_cast<RenderSourceLMC*>(aSource)->RenderTarget(), mARB);
1739   }
MapAndCopyInto(DataSourceSurface * aSurface,const IntSize & aReadSize)1740   bool MapAndCopyInto(DataSourceSurface* aSurface,
1741                       const IntSize& aReadSize) override {
1742     return mARB->MapAndCopyInto(aSurface, aReadSize);
1743   }
1744 
1745  protected:
~AsyncReadbackBufferLMC()1746   virtual ~AsyncReadbackBufferLMC() {}
1747 
1748   RefPtr<mozilla::layers::AsyncReadbackBuffer> mARB;
1749   Compositor* mCompositor;
1750 };
1751 
1752 already_AddRefed<profiler_screenshots::RenderSource>
GetWindowContents(const gfx::IntSize & aWindowSize)1753 WindowLMC::GetWindowContents(const gfx::IntSize& aWindowSize) {
1754   RefPtr<CompositingRenderTarget> rt = mCompositor->GetWindowRenderTarget();
1755   if (!rt) {
1756     return nullptr;
1757   }
1758   return MakeAndAddRef<RenderSourceLMC>(rt);
1759 }
1760 
1761 already_AddRefed<profiler_screenshots::DownscaleTarget>
CreateDownscaleTarget(const gfx::IntSize & aSize)1762 WindowLMC::CreateDownscaleTarget(const gfx::IntSize& aSize) {
1763   RefPtr<CompositingRenderTarget> rt =
1764       mCompositor->CreateRenderTarget(IntRect({}, aSize), INIT_MODE_NONE);
1765   return MakeAndAddRef<DownscaleTargetLMC>(rt, mCompositor);
1766 }
1767 
1768 already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
CreateAsyncReadbackBuffer(const gfx::IntSize & aSize)1769 WindowLMC::CreateAsyncReadbackBuffer(const gfx::IntSize& aSize) {
1770   RefPtr<AsyncReadbackBuffer> carb =
1771       mCompositor->CreateAsyncReadbackBuffer(aSize);
1772   if (!carb) {
1773     return nullptr;
1774   }
1775   return MakeAndAddRef<AsyncReadbackBufferLMC>(carb, mCompositor);
1776 }
1777 
1778 }  // namespace layers
1779 }  // namespace mozilla
1780