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 "GeckoProfiler.h"                 // for profiler_*
18 #include "ImageLayerComposite.h"           // for ImageLayerComposite
19 #include "Layers.h"                        // for Layer, ContainerLayer, etc
20 #include "LayerScope.h"                    // for LayerScope Tool
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 "gfxPrefs.h"                        // for gfxPrefs
28 #ifdef XP_MACOSX
29 #include "gfxPlatformMac.h"
30 #endif
31 #include "gfxRect.h"                    // for gfxRect
32 #include "gfxUtils.h"                   // for frame color util
33 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
34 #include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
35 #include "mozilla/gfx/2D.h"             // for DrawTarget
36 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
37 #include "mozilla/gfx/Point.h"          // for IntSize, Point
38 #include "mozilla/gfx/Rect.h"           // for Rect
39 #include "mozilla/gfx/Types.h"          // for Color, SurfaceFormat
40 #include "mozilla/layers/Compositor.h"  // for Compositor
41 #include "mozilla/layers/CompositorTypes.h"
42 #include "mozilla/layers/Effects.h"              // for Effect, EffectChain, etc
43 #include "mozilla/layers/LayerMetricsWrapper.h"  // for LayerMetricsWrapper
44 #include "mozilla/layers/LayersTypes.h"          // for etc
45 #include "mozilla/widget/CompositorWidget.h"     // for WidgetRenderingContext
46 #include "ipc/CompositorBench.h"                 // for CompositorBench
47 #include "ipc/ShadowLayerUtils.h"
48 #include "mozilla/mozalloc.h"  // for operator new, etc
49 #include "nsAppRunner.h"
50 #include "mozilla/RefPtr.h"   // for nsRefPtr
51 #include "nsCOMPtr.h"         // for already_AddRefed
52 #include "nsDebug.h"          // for NS_WARNING, etc
53 #include "nsISupportsImpl.h"  // for Layer::AddRef, etc
54 #include "nsPoint.h"          // for nsIntPoint
55 #include "nsRect.h"           // for mozilla::gfx::IntRect
56 #include "nsRegion.h"         // for nsIntRegion, etc
57 #if defined(MOZ_WIDGET_ANDROID)
58 #include <android/log.h>
59 #include <android/native_window.h>
60 #include "mozilla/widget/AndroidCompositorWidget.h"
61 #include "opengl/CompositorOGL.h"
62 #include "GLConsts.h"
63 #include "GLContextEGL.h"
64 #include "GLContextProvider.h"
65 #include "mozilla/Unused.h"
66 #include "mozilla/widget/AndroidCompositorWidget.h"
67 #include "ScopedGLHelpers.h"
68 #endif
69 #include "GeckoProfiler.h"
70 #include "TextRenderer.h"  // for TextRenderer
71 #include "mozilla/layers/CompositorBridgeParent.h"
72 #include "TreeTraversal.h"  // for ForEachNode
73 
74 #ifdef USE_SKIA
75 #include "PaintCounter.h"  // For PaintCounter
76 #endif
77 
78 class gfxContext;
79 
80 namespace mozilla {
81 namespace layers {
82 
83 class ImageLayer;
84 
85 using namespace mozilla::gfx;
86 using namespace mozilla::gl;
87 
ToLayerComposite(Layer * aLayer)88 static LayerComposite* ToLayerComposite(Layer* aLayer) {
89   return static_cast<LayerComposite*>(aLayer->ImplData());
90 }
91 
ClearSubtree(Layer * aLayer)92 static void ClearSubtree(Layer* aLayer) {
93   ForEachNode<ForwardIterator>(aLayer, [](Layer* layer) {
94     ToLayerComposite(layer)->CleanupResources();
95   });
96 }
97 
ClearCachedResources(Layer * aSubtree)98 void LayerManagerComposite::ClearCachedResources(Layer* aSubtree) {
99   MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this);
100   Layer* subtree = aSubtree ? aSubtree : mRoot.get();
101   if (!subtree) {
102     return;
103   }
104 
105   ClearSubtree(subtree);
106   // FIXME [bjacob]
107   // XXX the old LayerManagerOGL code had a mMaybeInvalidTree that it set to
108   // true here. Do we need that?
109 }
110 
HostLayerManager()111 HostLayerManager::HostLayerManager()
112     : mDebugOverlayWantsNextFrame(false),
113       mWarningLevel(0.0f),
114       mCompositorBridgeID(0),
115       mWindowOverlayChanged(false),
116       mLastPaintTime(TimeDuration::Forever()),
117       mRenderStartTime(TimeStamp::Now()) {}
118 
~HostLayerManager()119 HostLayerManager::~HostLayerManager() {}
120 
RecordPaintTimes(const PaintTiming & aTiming)121 void HostLayerManager::RecordPaintTimes(const PaintTiming& aTiming) {
122   mDiagnostics->RecordPaintTimes(aTiming);
123 }
124 
RecordUpdateTime(float aValue)125 void HostLayerManager::RecordUpdateTime(float aValue) {
126   mDiagnostics->RecordUpdateTime(aValue);
127 }
128 
129 /**
130  * LayerManagerComposite
131  */
LayerManagerComposite(Compositor * aCompositor)132 LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
133     : mUnusedApzTransformWarning(false),
134       mDisabledApzWarning(false),
135       mCompositor(aCompositor),
136       mInTransaction(false),
137       mIsCompositorReady(false)
138 #if defined(MOZ_WIDGET_ANDROID)
139       ,
140       mScreenPixelsTarget(nullptr)
141 #endif  // defined(MOZ_WIDGET_ANDROID)
142 {
143   mTextRenderer = new TextRenderer();
144   mDiagnostics = MakeUnique<Diagnostics>();
145   MOZ_ASSERT(aCompositor);
146 
147 #ifdef USE_SKIA
148   mPaintCounter = nullptr;
149 #endif
150 }
151 
~LayerManagerComposite()152 LayerManagerComposite::~LayerManagerComposite() { Destroy(); }
153 
Destroy()154 void LayerManagerComposite::Destroy() {
155   if (!mDestroyed) {
156     mCompositor->GetWidget()->CleanupWindowEffects();
157     if (mRoot) {
158       RootLayer()->Destroy();
159     }
160     mCompositor->CancelFrame();
161     mRoot = nullptr;
162     mClonedLayerTreeProperties = nullptr;
163     mDestroyed = true;
164 
165 #ifdef USE_SKIA
166     mPaintCounter = nullptr;
167 #endif
168   }
169 }
170 
UpdateRenderBounds(const IntRect & aRect)171 void LayerManagerComposite::UpdateRenderBounds(const IntRect& aRect) {
172   mRenderBounds = aRect;
173 }
174 
AreComponentAlphaLayersEnabled()175 bool LayerManagerComposite::AreComponentAlphaLayersEnabled() {
176   return mCompositor->GetBackendType() != LayersBackend::LAYERS_BASIC &&
177          mCompositor->SupportsEffect(EffectTypes::COMPONENT_ALPHA) &&
178          LayerManager::AreComponentAlphaLayersEnabled();
179 }
180 
BeginTransaction()181 bool LayerManagerComposite::BeginTransaction() {
182   mInTransaction = true;
183 
184   if (!mCompositor->Ready()) {
185     return false;
186   }
187 
188   mIsCompositorReady = true;
189   return true;
190 }
191 
BeginTransactionWithDrawTarget(DrawTarget * aTarget,const IntRect & aRect)192 void LayerManagerComposite::BeginTransactionWithDrawTarget(
193     DrawTarget* aTarget, const IntRect& aRect) {
194   mInTransaction = true;
195 
196   if (!mCompositor->Ready()) {
197     return;
198   }
199 
200 #ifdef MOZ_LAYERS_HAVE_LOG
201   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
202   Log();
203 #endif
204 
205   if (mDestroyed) {
206     NS_WARNING("Call on destroyed layer manager");
207     return;
208   }
209 
210   mIsCompositorReady = true;
211   mCompositor->SetTargetContext(aTarget, aRect);
212   mTarget = aTarget;
213   mTargetBounds = aRect;
214 }
215 
PostProcessLayers(nsIntRegion & aOpaqueRegion)216 void LayerManagerComposite::PostProcessLayers(nsIntRegion& aOpaqueRegion) {
217   LayerIntRegion visible;
218   LayerComposite* rootComposite =
219       static_cast<LayerComposite*>(mRoot->AsHostLayer());
220   PostProcessLayers(
221       mRoot, aOpaqueRegion, visible,
222       ViewAs<RenderTargetPixel>(
223           rootComposite->GetShadowClipRect(),
224           PixelCastJustification::RenderTargetIsParentLayerForRoot),
225       Nothing());
226 }
227 
228 // We want to skip directly through ContainerLayers that don't have an
229 // intermediate surface. We compute occlusions for leaves and intermediate
230 // surfaces against the layer that they actually composite into so that we can
231 // use the final (snapped) effective transform.
ShouldProcessLayer(Layer * aLayer)232 bool ShouldProcessLayer(Layer* aLayer) {
233   if (!aLayer->AsContainerLayer()) {
234     return true;
235   }
236 
237   return aLayer->AsContainerLayer()->UseIntermediateSurface();
238 }
239 
PostProcessLayers(Layer * aLayer,nsIntRegion & aOpaqueRegion,LayerIntRegion & aVisibleRegion,const Maybe<RenderTargetIntRect> & aRenderTargetClip,const Maybe<ParentLayerIntRect> & aClipFromAncestors)240 void LayerManagerComposite::PostProcessLayers(
241     Layer* aLayer, nsIntRegion& aOpaqueRegion, LayerIntRegion& aVisibleRegion,
242     const Maybe<RenderTargetIntRect>& aRenderTargetClip,
243     const Maybe<ParentLayerIntRect>& aClipFromAncestors) {
244   // Compute a clip that's the combination of our layer clip with the clip
245   // from our ancestors.
246   LayerComposite* composite =
247       static_cast<LayerComposite*>(aLayer->AsHostLayer());
248   Maybe<ParentLayerIntRect> layerClip = composite->GetShadowClipRect();
249   MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(),
250              "The layer with a clip should not participate "
251              "a 3D rendering context");
252   Maybe<ParentLayerIntRect> outsideClip =
253       IntersectMaybeRects(layerClip, aClipFromAncestors);
254 
255   Maybe<LayerIntRect> insideClip;
256   if (aLayer->Extend3DContext()) {
257     // If we're preserve-3d just pass the clip rect down directly, and we'll do
258     // the conversion at the preserve-3d leaf Layer.
259     if (outsideClip) {
260       insideClip = Some(ViewAs<LayerPixel>(
261           *outsideClip, PixelCastJustification::MovingDownToChildren));
262     }
263   } else if (outsideClip) {
264     // Convert the combined clip into our pre-transform coordinate space, so
265     // that it can later be intersected with our visible region.
266     // If our transform is a perspective, there's no meaningful insideClip rect
267     // we can compute (it would need to be a cone).
268     Matrix4x4 localTransform = aLayer->ComputeTransformToPreserve3DRoot();
269     if (!localTransform.HasPerspectiveComponent() && localTransform.Invert()) {
270       LayerRect insideClipFloat =
271           UntransformBy(ViewAs<ParentLayerToLayerMatrix4x4>(localTransform),
272                         ParentLayerRect(*outsideClip), LayerRect::MaxIntRect())
273               .valueOr(LayerRect());
274       insideClipFloat.RoundOut();
275       LayerIntRect insideClipInt;
276       if (insideClipFloat.ToIntRect(&insideClipInt)) {
277         insideClip = Some(insideClipInt);
278       }
279     }
280   }
281 
282   Maybe<ParentLayerIntRect> ancestorClipForChildren;
283   if (insideClip) {
284     ancestorClipForChildren = Some(ViewAs<ParentLayerPixel>(
285         *insideClip, PixelCastJustification::MovingDownToChildren));
286   }
287 
288   nsIntRegion dummy;
289   nsIntRegion& opaqueRegion = aOpaqueRegion;
290   if (aLayer->Extend3DContext() || aLayer->Combines3DTransformWithAncestors()) {
291     opaqueRegion = dummy;
292   }
293 
294   if (!ShouldProcessLayer(aLayer)) {
295     MOZ_ASSERT(aLayer->AsContainerLayer() &&
296                !aLayer->AsContainerLayer()->UseIntermediateSurface());
297     // For layers participating 3D rendering context, their visible
298     // region should be empty (invisible), so we pass through them
299     // without doing anything.
300     for (Layer* child = aLayer->GetLastChild(); child;
301          child = child->GetPrevSibling()) {
302       LayerComposite* childComposite =
303           static_cast<LayerComposite*>(child->AsHostLayer());
304       Maybe<RenderTargetIntRect> renderTargetClip = aRenderTargetClip;
305       if (childComposite->GetShadowClipRect()) {
306         RenderTargetIntRect clip = TransformBy(
307             ViewAs<ParentLayerToRenderTargetMatrix4x4>(
308                 aLayer->GetEffectiveTransform(),
309                 PixelCastJustification::RenderTargetIsParentLayerForRoot),
310             *childComposite->GetShadowClipRect());
311         renderTargetClip = IntersectMaybeRects(renderTargetClip, Some(clip));
312       }
313 
314       PostProcessLayers(child, opaqueRegion, aVisibleRegion, renderTargetClip,
315                         ancestorClipForChildren);
316     }
317     return;
318   }
319 
320   nsIntRegion localOpaque;
321   // Treat layers on the path to the root of the 3D rendering context as
322   // a giant layer if it is a leaf.
323   Matrix4x4 transform = aLayer->GetEffectiveTransform();
324   Matrix transform2d;
325   Maybe<IntPoint> integerTranslation;
326   // If aLayer has a simple transform (only an integer translation) then we
327   // can easily convert aOpaqueRegion into pre-transform coordinates and include
328   // that region.
329   if (transform.Is2D(&transform2d)) {
330     if (transform2d.IsIntegerTranslation()) {
331       integerTranslation =
332           Some(IntPoint::Truncate(transform2d.GetTranslation()));
333       localOpaque = opaqueRegion;
334       localOpaque.MoveBy(-*integerTranslation);
335     }
336   }
337 
338   // Save the value of localOpaque, which currently stores the region obscured
339   // by siblings (and uncles and such), before our descendants contribute to it.
340   nsIntRegion obscured = localOpaque;
341 
342   // Recurse on our descendants, in front-to-back order. In this process:
343   //  - Occlusions are computed for them, and they contribute to localOpaque.
344   //  - They recalculate their visible regions, taking ancestorClipForChildren
345   //    into account, and accumulate them into descendantsVisibleRegion.
346   LayerIntRegion descendantsVisibleRegion;
347 
348   bool hasPreserve3DChild = false;
349   for (Layer* child = aLayer->GetLastChild(); child;
350        child = child->GetPrevSibling()) {
351     MOZ_ASSERT(aLayer->AsContainerLayer()->UseIntermediateSurface());
352     LayerComposite* childComposite =
353         static_cast<LayerComposite*>(child->AsHostLayer());
354     PostProcessLayers(
355         child, localOpaque, descendantsVisibleRegion,
356         ViewAs<RenderTargetPixel>(
357             childComposite->GetShadowClipRect(),
358             PixelCastJustification::RenderTargetIsParentLayerForRoot),
359         ancestorClipForChildren);
360     if (child->Extend3DContext()) {
361       hasPreserve3DChild = true;
362     }
363   }
364 
365   // Recalculate our visible region.
366   LayerIntRegion visible = composite->GetShadowVisibleRegion();
367 
368   // If we have descendants, throw away the visible region stored on this
369   // layer, and use the region accumulated by our descendants instead.
370   if (aLayer->GetFirstChild() && !hasPreserve3DChild) {
371     visible = descendantsVisibleRegion;
372   }
373 
374   // Subtract any areas that we know to be opaque.
375   if (!obscured.IsEmpty()) {
376     visible.SubOut(LayerIntRegion::FromUnknownRegion(obscured));
377   }
378 
379   // Clip the visible region using the combined clip.
380   if (insideClip) {
381     visible.AndWith(*insideClip);
382   }
383   composite->SetShadowVisibleRegion(visible);
384 
385   // Transform the newly calculated visible region into our parent's space,
386   // apply our clip to it (if any), and accumulate it into |aVisibleRegion|
387   // for the caller to use.
388   ParentLayerIntRegion visibleParentSpace =
389       TransformBy(ViewAs<LayerToParentLayerMatrix4x4>(transform), visible);
390   aVisibleRegion.OrWith(ViewAs<LayerPixel>(
391       visibleParentSpace, PixelCastJustification::MovingDownToChildren));
392 
393   // If we have a simple transform, then we can add our opaque area into
394   // aOpaqueRegion.
395   if (integerTranslation && !aLayer->HasMaskLayers() &&
396       aLayer->IsOpaqueForVisibility()) {
397     if (aLayer->IsOpaque()) {
398       localOpaque.OrWith(composite->GetFullyRenderedRegion());
399     }
400     localOpaque.MoveBy(*integerTranslation);
401     if (aRenderTargetClip) {
402       localOpaque.AndWith(aRenderTargetClip->ToUnknownRect());
403     }
404     opaqueRegion.OrWith(localOpaque);
405   }
406 }
407 
EndTransaction(const TimeStamp & aTimeStamp,EndTransactionFlags aFlags)408 void LayerManagerComposite::EndTransaction(const TimeStamp& aTimeStamp,
409                                            EndTransactionFlags aFlags) {
410   NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
411   NS_ASSERTION(!(aFlags & END_NO_COMPOSITE),
412                "Shouldn't get END_NO_COMPOSITE here");
413   mInTransaction = false;
414   mRenderStartTime = TimeStamp::Now();
415 
416   if (!mIsCompositorReady) {
417     return;
418   }
419   mIsCompositorReady = false;
420 
421 #ifdef MOZ_LAYERS_HAVE_LOG
422   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
423   Log();
424 #endif
425 
426   if (mDestroyed) {
427     NS_WARNING("Call on destroyed layer manager");
428     return;
429   }
430 
431   // Set composition timestamp here because we need it in
432   // ComputeEffectiveTransforms (so the correct video frame size is picked) and
433   // also to compute invalid regions properly.
434   SetCompositionTime(aTimeStamp);
435 
436   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
437     MOZ_ASSERT(!aTimeStamp.IsNull());
438     UpdateAndRender();
439     mCompositor->FlushPendingNotifyNotUsed();
440   }
441 
442   mCompositor->ClearTargetContext();
443   mTarget = nullptr;
444 
445 #ifdef MOZ_LAYERS_HAVE_LOG
446   Log();
447   MOZ_LAYERS_LOG(("]----- EndTransaction"));
448 #endif
449 }
450 
UpdateAndRender()451 void LayerManagerComposite::UpdateAndRender() {
452   nsIntRegion invalid;
453   // The results of our drawing always go directly into a pixel buffer,
454   // so we don't need to pass any global transform here.
455   mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
456 
457   nsIntRegion opaque;
458   PostProcessLayers(opaque);
459 
460   if (mClonedLayerTreeProperties) {
461     // We need to compute layer tree differences even if we're not going to
462     // immediately use the resulting damage area, since ComputeDifferences
463     // is also responsible for invalidates intermediate surfaces in
464     // ContainerLayers.
465     nsIntRegion changed;
466     if (!mClonedLayerTreeProperties->ComputeDifferences(mRoot, changed,
467                                                         nullptr)) {
468       changed = mTargetBounds;
469     }
470 
471     if (mTarget) {
472       // Since we're composing to an external target, we're not going to use
473       // the damage region from layers changes - we want to composite
474       // everything in the target bounds. Instead we accumulate the layers
475       // damage region for the next window composite.
476       mInvalidRegion.Or(mInvalidRegion, changed);
477     } else {
478       invalid = Move(changed);
479     }
480   }
481 
482   if (mTarget) {
483     invalid.Or(invalid, mTargetBounds);
484   } else {
485     // If we didn't have a previous layer tree, invalidate the entire render
486     // area.
487     if (!mClonedLayerTreeProperties) {
488       invalid.Or(invalid, mRenderBounds);
489     }
490 
491     // Add any additional invalid rects from the window manager or previous
492     // damage computed during ComposeToTarget().
493     invalid.Or(invalid, mInvalidRegion);
494     mInvalidRegion.SetEmpty();
495   }
496 
497   if (invalid.IsEmpty() && !mWindowOverlayChanged) {
498     // Composition requested, but nothing has changed. Don't do any work.
499     mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
500     return;
501   }
502 
503   // We don't want our debug overlay to cause more frames to happen
504   // so we will invalidate after we've decided if something changed.
505   InvalidateDebugOverlay(invalid, mRenderBounds);
506 
507   Render(invalid, opaque);
508 #if defined(MOZ_WIDGET_ANDROID)
509   RenderToPresentationSurface();
510 #endif
511   mWindowOverlayChanged = false;
512 
513   // Update cached layer tree information.
514   mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
515 }
516 
CreateOptimalMaskDrawTarget(const IntSize & aSize)517 already_AddRefed<DrawTarget> LayerManagerComposite::CreateOptimalMaskDrawTarget(
518     const IntSize& aSize) {
519   MOZ_CRASH("Should only be called on the drawing side");
520   return nullptr;
521 }
522 
RootLayer() const523 LayerComposite* LayerManagerComposite::RootLayer() const {
524   if (mDestroyed) {
525     NS_WARNING("Call on destroyed layer manager");
526     return nullptr;
527   }
528 
529   return ToLayerComposite(mRoot);
530 }
531 
InvalidateDebugOverlay(nsIntRegion & aInvalidRegion,const IntRect & aBounds)532 void LayerManagerComposite::InvalidateDebugOverlay(nsIntRegion& aInvalidRegion,
533                                                    const IntRect& aBounds) {
534   bool drawFps = gfxPrefs::LayersDrawFPS();
535   bool drawFrameColorBars = gfxPrefs::CompositorDrawColorBars();
536 
537   if (drawFps) {
538     aInvalidRegion.Or(aInvalidRegion, nsIntRect(0, 0, 650, 400));
539   }
540   if (drawFrameColorBars) {
541     aInvalidRegion.Or(aInvalidRegion, nsIntRect(0, 0, 10, aBounds.Height()));
542   }
543 
544 #ifdef USE_SKIA
545   bool drawPaintTimes = gfxPrefs::AlwaysPaint();
546   if (drawPaintTimes) {
547     aInvalidRegion.Or(aInvalidRegion, nsIntRect(PaintCounter::GetPaintRect()));
548   }
549 #endif
550 }
551 
552 #ifdef USE_SKIA
DrawPaintTimes(Compositor * aCompositor)553 void LayerManagerComposite::DrawPaintTimes(Compositor* aCompositor) {
554   if (!mPaintCounter) {
555     mPaintCounter = new PaintCounter();
556   }
557 
558   TimeDuration compositeTime = TimeStamp::Now() - mRenderStartTime;
559   mPaintCounter->Draw(aCompositor, mLastPaintTime, compositeTime);
560 }
561 #endif
562 
563 static uint16_t sFrameCount = 0;
RenderDebugOverlay(const IntRect & aBounds)564 void LayerManagerComposite::RenderDebugOverlay(const IntRect& aBounds) {
565   bool drawFps = gfxPrefs::LayersDrawFPS();
566   bool drawFrameColorBars = gfxPrefs::CompositorDrawColorBars();
567 
568   // Don't draw diagnostic overlays if we want to snapshot the output.
569   if (mTarget) {
570     return;
571   }
572 
573   if (drawFps) {
574     float alpha = 1;
575 #ifdef ANDROID
576     // Draw a translation delay warning overlay
577     int width;
578     int border;
579 
580     TimeStamp now = TimeStamp::Now();
581     if (!mWarnTime.IsNull() &&
582         (now - mWarnTime).ToMilliseconds() < kVisualWarningDuration) {
583       EffectChain effects;
584 
585       // Black blorder
586       border = 4;
587       width = 6;
588       effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(0, 0, 0, 1));
589       mCompositor->DrawQuad(
590           gfx::Rect(border, border, aBounds.Width() - 2 * border, width),
591           aBounds, effects, alpha, gfx::Matrix4x4());
592       mCompositor->DrawQuad(gfx::Rect(border, aBounds.Height() - border - width,
593                                       aBounds.Width() - 2 * border, width),
594                             aBounds, effects, alpha, gfx::Matrix4x4());
595       mCompositor->DrawQuad(
596           gfx::Rect(border, border + width, width,
597                     aBounds.Height() - 2 * border - width * 2),
598           aBounds, effects, alpha, gfx::Matrix4x4());
599       mCompositor->DrawQuad(
600           gfx::Rect(aBounds.Width() - border - width, border + width, width,
601                     aBounds.Height() - 2 * border - 2 * width),
602           aBounds, effects, alpha, gfx::Matrix4x4());
603 
604       // Content
605       border = 5;
606       width = 4;
607       effects.mPrimaryEffect =
608           new EffectSolidColor(gfx::Color(1, 1.f - mWarningLevel, 0, 1));
609       mCompositor->DrawQuad(
610           gfx::Rect(border, border, aBounds.Width() - 2 * border, width),
611           aBounds, effects, alpha, gfx::Matrix4x4());
612       mCompositor->DrawQuad(gfx::Rect(border, aBounds.height - border - width,
613                                       aBounds.Width() - 2 * border, width),
614                             aBounds, effects, alpha, gfx::Matrix4x4());
615       mCompositor->DrawQuad(
616           gfx::Rect(border, border + width, width,
617                     aBounds.Height() - 2 * border - width * 2),
618           aBounds, effects, alpha, gfx::Matrix4x4());
619       mCompositor->DrawQuad(
620           gfx::Rect(aBounds.Width() - border - width, border + width, width,
621                     aBounds.Height() - 2 * border - 2 * width),
622           aBounds, effects, alpha, gfx::Matrix4x4());
623       SetDebugOverlayWantsNextFrame(true);
624     }
625 #endif
626 
627     GPUStats stats;
628     stats.mScreenPixels = mRenderBounds.Width() * mRenderBounds.Height();
629     mCompositor->GetFrameStats(&stats);
630 
631     std::string text = mDiagnostics->GetFrameOverlayString(stats);
632     mTextRenderer->RenderText(mCompositor, text, IntPoint(2, 5), Matrix4x4(),
633                               24, 600, TextRenderer::FontType::FixedWidth);
634 
635     if (mUnusedApzTransformWarning) {
636       // If we have an unused APZ transform on this composite, draw a 20x20 red
637       // box in the top-right corner
638       EffectChain effects;
639       effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(1, 0, 0, 1));
640       mCompositor->DrawQuad(gfx::Rect(aBounds.Width() - 20, 0, 20, 20), aBounds,
641                             effects, alpha, gfx::Matrix4x4());
642 
643       mUnusedApzTransformWarning = false;
644       SetDebugOverlayWantsNextFrame(true);
645     }
646     if (mDisabledApzWarning) {
647       // If we have a disabled APZ on this composite, draw a 20x20 yellow box
648       // in the top-right corner, to the left of the unused-apz-transform
649       // warning box
650       EffectChain effects;
651       effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(1, 1, 0, 1));
652       mCompositor->DrawQuad(gfx::Rect(aBounds.Width() - 40, 0, 20, 20), aBounds,
653                             effects, alpha, gfx::Matrix4x4());
654 
655       mDisabledApzWarning = false;
656       SetDebugOverlayWantsNextFrame(true);
657     }
658   }
659 
660   if (drawFrameColorBars) {
661     gfx::IntRect sideRect(0, 0, 10, aBounds.Height());
662 
663     EffectChain effects;
664     effects.mPrimaryEffect =
665         new EffectSolidColor(gfxUtils::GetColorForFrameNumber(sFrameCount));
666     mCompositor->DrawQuad(Rect(sideRect), sideRect, effects, 1.0,
667                           gfx::Matrix4x4());
668   }
669 
670   if (drawFrameColorBars) {
671     // We intentionally overflow at 2^16.
672     sFrameCount++;
673   }
674 
675 #ifdef USE_SKIA
676   bool drawPaintTimes = gfxPrefs::AlwaysPaint();
677   if (drawPaintTimes) {
678     DrawPaintTimes(mCompositor);
679   }
680 #endif
681 }
682 
683 RefPtr<CompositingRenderTarget>
PushGroupForLayerEffects()684 LayerManagerComposite::PushGroupForLayerEffects() {
685   // This is currently true, so just making sure that any new use of this
686   // method is flagged for investigation
687   MOZ_ASSERT(gfxPrefs::LayersEffectInvert() ||
688              gfxPrefs::LayersEffectGrayscale() ||
689              gfxPrefs::LayersEffectContrast() != 0.0);
690 
691   RefPtr<CompositingRenderTarget> previousTarget =
692       mCompositor->GetCurrentRenderTarget();
693   // make our render target the same size as the destination target
694   // so that we don't have to change size if the drawing area changes.
695   IntRect rect(previousTarget->GetOrigin(), previousTarget->GetSize());
696   // XXX: I'm not sure if this is true or not...
697   MOZ_ASSERT(rect.IsEqualXY(0, 0));
698   if (!mTwoPassTmpTarget ||
699       mTwoPassTmpTarget->GetSize() != previousTarget->GetSize() ||
700       mTwoPassTmpTarget->GetOrigin() != previousTarget->GetOrigin()) {
701     mTwoPassTmpTarget = mCompositor->CreateRenderTarget(rect, INIT_MODE_NONE);
702   }
703   MOZ_ASSERT(mTwoPassTmpTarget);
704   mCompositor->SetRenderTarget(mTwoPassTmpTarget);
705   return previousTarget;
706 }
PopGroupForLayerEffects(RefPtr<CompositingRenderTarget> aPreviousTarget,IntRect aClipRect,bool aGrayscaleEffect,bool aInvertEffect,float aContrastEffect)707 void LayerManagerComposite::PopGroupForLayerEffects(
708     RefPtr<CompositingRenderTarget> aPreviousTarget, IntRect aClipRect,
709     bool aGrayscaleEffect, bool aInvertEffect, float aContrastEffect) {
710   MOZ_ASSERT(mTwoPassTmpTarget);
711 
712   // This is currently true, so just making sure that any new use of this
713   // method is flagged for investigation
714   MOZ_ASSERT(aInvertEffect || aGrayscaleEffect || aContrastEffect != 0.0);
715 
716   mCompositor->SetRenderTarget(aPreviousTarget);
717 
718   EffectChain effectChain(RootLayer());
719   Matrix5x4 effectMatrix;
720   if (aGrayscaleEffect) {
721     // R' = G' = B' = luminance
722     // R' = 0.2126*R + 0.7152*G + 0.0722*B
723     // G' = 0.2126*R + 0.7152*G + 0.0722*B
724     // B' = 0.2126*R + 0.7152*G + 0.0722*B
725     Matrix5x4 grayscaleMatrix(0.2126f, 0.2126f, 0.2126f, 0, 0.7152f, 0.7152f,
726                               0.7152f, 0, 0.0722f, 0.0722f, 0.0722f, 0, 0, 0, 0,
727                               1, 0, 0, 0, 0);
728     effectMatrix = grayscaleMatrix;
729   }
730 
731   if (aInvertEffect) {
732     // R' = 1 - R
733     // G' = 1 - G
734     // B' = 1 - B
735     Matrix5x4 colorInvertMatrix(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0,
736                                 1, 1, 1, 1, 0);
737     effectMatrix = effectMatrix * colorInvertMatrix;
738   }
739 
740   if (aContrastEffect != 0.0) {
741     // Multiplying with:
742     // R' = (1 + c) * (R - 0.5) + 0.5
743     // G' = (1 + c) * (G - 0.5) + 0.5
744     // B' = (1 + c) * (B - 0.5) + 0.5
745     float cP1 = aContrastEffect + 1;
746     float hc = 0.5 * aContrastEffect;
747     Matrix5x4 contrastMatrix(cP1, 0, 0, 0, 0, cP1, 0, 0, 0, 0, cP1, 0, 0, 0, 0,
748                              1, -hc, -hc, -hc, 0);
749     effectMatrix = effectMatrix * contrastMatrix;
750   }
751 
752   effectChain.mPrimaryEffect = new EffectRenderTarget(mTwoPassTmpTarget);
753   effectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX] =
754       new EffectColorMatrix(effectMatrix);
755 
756   mCompositor->DrawQuad(Rect(Point(0, 0), Size(mTwoPassTmpTarget->GetSize())),
757                         aClipRect, effectChain, 1., Matrix4x4());
758 }
759 
760 // Used to clear the 'mLayerComposited' flag at the beginning of each Render().
ClearLayerFlags(Layer * aLayer)761 static void ClearLayerFlags(Layer* aLayer) {
762   ForEachNode<ForwardIterator>(aLayer, [](Layer* layer) {
763     if (layer->AsHostLayer()) {
764       static_cast<LayerComposite*>(layer->AsHostLayer())
765           ->SetLayerComposited(false);
766     }
767   });
768 }
769 
770 #if defined(MOZ_WIDGET_ANDROID)
771 class ScopedCompositorRenderOffset {
772  public:
ScopedCompositorRenderOffset(CompositorOGL * aCompositor,const ScreenPoint & aOffset)773   ScopedCompositorRenderOffset(CompositorOGL* aCompositor,
774                                const ScreenPoint& aOffset)
775       : mCompositor(aCompositor),
776         mOriginalOffset(mCompositor->GetScreenRenderOffset()),
777         mOriginalProjection(mCompositor->GetProjMatrix()) {
778     ScreenPoint offset(mOriginalOffset.x + aOffset.x,
779                        mOriginalOffset.y + aOffset.y);
780     mCompositor->SetScreenRenderOffset(offset);
781     // Calling CompositorOGL::SetScreenRenderOffset does not affect the
782     // projection matrix so adjust that as well.
783     gfx::Matrix4x4 mat = mOriginalProjection;
784     mat.PreTranslate(aOffset.x, aOffset.y, 0.0f);
785     mCompositor->SetProjMatrix(mat);
786   }
~ScopedCompositorRenderOffset()787   ~ScopedCompositorRenderOffset() {
788     mCompositor->SetScreenRenderOffset(mOriginalOffset);
789     mCompositor->SetProjMatrix(mOriginalProjection);
790   }
791 
792  private:
793   CompositorOGL* const mCompositor;
794   const ScreenPoint mOriginalOffset;
795   const gfx::Matrix4x4 mOriginalProjection;
796 };
797 #endif  // defined(MOZ_WIDGET_ANDROID)
798 
Render(const nsIntRegion & aInvalidRegion,const nsIntRegion & aOpaqueRegion)799 void LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion,
800                                    const nsIntRegion& aOpaqueRegion) {
801   AUTO_PROFILER_LABEL("LayerManagerComposite::Render", GRAPHICS);
802 
803   if (mDestroyed || !mCompositor || mCompositor->IsDestroyed()) {
804     NS_WARNING("Call on destroyed layer manager");
805     return;
806   }
807 
808   ClearLayerFlags(mRoot);
809 
810   // At this time, it doesn't really matter if these preferences change
811   // during the execution of the function; we should be safe in all
812   // permutations. However, may as well just get the values onces and
813   // then use them, just in case the consistency becomes important in
814   // the future.
815   bool invertVal = gfxPrefs::LayersEffectInvert();
816   bool grayscaleVal = gfxPrefs::LayersEffectGrayscale();
817   float contrastVal = gfxPrefs::LayersEffectContrast();
818   bool haveLayerEffects = (invertVal || grayscaleVal || contrastVal != 0.0);
819 
820   // Set LayerScope begin/end frame
821   LayerScopeAutoFrame frame(PR_Now());
822 
823   // Dump to console
824   if (gfxPrefs::LayersDump()) {
825     this->Dump(/* aSorted= */ true);
826   }
827 
828   // Dump to LayerScope Viewer
829   if (LayerScope::CheckSendable()) {
830     // Create a LayersPacket, dump Layers into it and transfer the
831     // packet('s ownership) to LayerScope.
832     auto packet = MakeUnique<layerscope::Packet>();
833     layerscope::LayersPacket* layersPacket = packet->mutable_layers();
834     this->Dump(layersPacket);
835     LayerScope::SendLayerDump(Move(packet));
836   }
837 
838   mozilla::widget::WidgetRenderingContext widgetContext;
839 #if defined(XP_MACOSX)
840   widgetContext.mLayerManager = this;
841 #elif defined(MOZ_WIDGET_ANDROID)
842   widgetContext.mCompositor = GetCompositor();
843 #endif
844 
845   {
846     AUTO_PROFILER_LABEL("LayerManagerComposite::Render:Prerender", GRAPHICS);
847 
848     if (!mCompositor->GetWidget()->PreRender(&widgetContext)) {
849       return;
850     }
851   }
852 
853   ParentLayerIntRect clipRect;
854   IntRect bounds(mRenderBounds.X(), mRenderBounds.Y(), mRenderBounds.Width(),
855                  mRenderBounds.Height());
856   IntRect actualBounds;
857 
858   CompositorBench(mCompositor, bounds);
859 
860   MOZ_ASSERT(mRoot->GetOpacity() == 1);
861 #if defined(MOZ_WIDGET_ANDROID)
862   LayerMetricsWrapper wrapper = GetRootContentLayer();
863   if (wrapper) {
864     mCompositor->SetClearColor(wrapper.Metadata().GetBackgroundColor());
865   } else {
866     mCompositor->SetClearColorToDefault();
867   }
868 #endif
869   if (mRoot->GetClipRect()) {
870     clipRect = *mRoot->GetClipRect();
871     IntRect rect(clipRect.X(), clipRect.Y(), clipRect.Width(),
872                  clipRect.Height());
873     mCompositor->BeginFrame(aInvalidRegion, &rect, bounds, aOpaqueRegion,
874                             nullptr, &actualBounds);
875   } else {
876     gfx::IntRect rect;
877     mCompositor->BeginFrame(aInvalidRegion, nullptr, bounds, aOpaqueRegion,
878                             &rect, &actualBounds);
879     clipRect =
880         ParentLayerIntRect(rect.X(), rect.Y(), rect.Width(), rect.Height());
881   }
882 #if defined(MOZ_WIDGET_ANDROID)
883   ScreenCoord offset = GetContentShiftForToolbar();
884   ScopedCompositorRenderOffset scopedOffset(mCompositor->AsCompositorOGL(),
885                                             ScreenPoint(0.0f, offset));
886 #endif
887 
888   if (actualBounds.IsEmpty()) {
889     mCompositor->GetWidget()->PostRender(&widgetContext);
890     return;
891   }
892 
893   // Allow widget to render a custom background.
894   mCompositor->GetWidget()->DrawWindowUnderlay(
895       &widgetContext, LayoutDeviceIntRect::FromUnknownRect(actualBounds));
896 
897   RefPtr<CompositingRenderTarget> previousTarget;
898   if (haveLayerEffects) {
899     previousTarget = PushGroupForLayerEffects();
900   } else {
901     mTwoPassTmpTarget = nullptr;
902   }
903 
904   // Render our layers.
905   {
906     Diagnostics::Record record(mRenderStartTime);
907     RootLayer()->Prepare(ViewAs<RenderTargetPixel>(
908         clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot));
909     if (record.Recording()) {
910       mDiagnostics->RecordPrepareTime(record.Duration());
911     }
912   }
913   // Execute draw commands.
914   {
915     Diagnostics::Record record;
916     RootLayer()->RenderLayer(clipRect.ToUnknownRect(), Nothing());
917     if (record.Recording()) {
918       mDiagnostics->RecordCompositeTime(record.Duration());
919     }
920   }
921   RootLayer()->Cleanup();
922 
923   if (!mRegionToClear.IsEmpty()) {
924     for (auto iter = mRegionToClear.RectIter(); !iter.Done(); iter.Next()) {
925       const IntRect& r = iter.Get();
926       mCompositor->ClearRect(Rect(r.X(), r.Y(), r.Width(), r.Height()));
927     }
928   }
929 
930   if (mTwoPassTmpTarget) {
931     MOZ_ASSERT(haveLayerEffects);
932     PopGroupForLayerEffects(previousTarget, clipRect.ToUnknownRect(),
933                             grayscaleVal, invertVal, contrastVal);
934   }
935 
936   // Allow widget to render a custom foreground.
937   mCompositor->GetWidget()->DrawWindowOverlay(
938       &widgetContext, LayoutDeviceIntRect::FromUnknownRect(actualBounds));
939 
940   mCompositor->NormalDrawingDone();
941 
942 #if defined(MOZ_WIDGET_ANDROID)
943   // Depending on the content shift the toolbar may be rendered on top of
944   // some of the content so it must be rendered after the content.
945   RenderToolbar();
946   HandlePixelsTarget();
947 #endif  // defined(MOZ_WIDGET_ANDROID)
948 
949   // Debugging
950   RenderDebugOverlay(actualBounds);
951 
952   {
953     AUTO_PROFILER_LABEL("LayerManagerComposite::Render:EndFrame", GRAPHICS);
954 
955     mCompositor->EndFrame();
956 
957     // Call after EndFrame()
958     mCompositor->SetDispAcquireFence(mRoot);
959   }
960 
961   mCompositor->GetWidget()->PostRender(&widgetContext);
962 
963   RecordFrame();
964 }
965 
966 #if defined(MOZ_WIDGET_ANDROID)
967 class ScopedCompositorProjMatrix {
968  public:
ScopedCompositorProjMatrix(CompositorOGL * aCompositor,const Matrix4x4 & aProjMatrix)969   ScopedCompositorProjMatrix(CompositorOGL* aCompositor,
970                              const Matrix4x4& aProjMatrix)
971       : mCompositor(aCompositor),
972         mOriginalProjMatrix(mCompositor->GetProjMatrix()) {
973     mCompositor->SetProjMatrix(aProjMatrix);
974   }
975 
~ScopedCompositorProjMatrix()976   ~ScopedCompositorProjMatrix() {
977     mCompositor->SetProjMatrix(mOriginalProjMatrix);
978   }
979 
980  private:
981   CompositorOGL* const mCompositor;
982   const Matrix4x4 mOriginalProjMatrix;
983 };
984 
985 class ScopedCompostitorSurfaceSize {
986  public:
ScopedCompostitorSurfaceSize(CompositorOGL * aCompositor,const gfx::IntSize & aSize)987   ScopedCompostitorSurfaceSize(CompositorOGL* aCompositor,
988                                const gfx::IntSize& aSize)
989       : mCompositor(aCompositor),
990         mOriginalSize(mCompositor->GetDestinationSurfaceSize()) {
991     mCompositor->SetDestinationSurfaceSize(aSize);
992   }
~ScopedCompostitorSurfaceSize()993   ~ScopedCompostitorSurfaceSize() {
994     mCompositor->SetDestinationSurfaceSize(mOriginalSize);
995   }
996 
997  private:
998   CompositorOGL* const mCompositor;
999   const gfx::IntSize mOriginalSize;
1000 };
1001 
1002 class ScopedContextSurfaceOverride {
1003  public:
ScopedContextSurfaceOverride(GLContextEGL * aContext,void * aSurface)1004   ScopedContextSurfaceOverride(GLContextEGL* aContext, void* aSurface)
1005       : mContext(aContext) {
1006     MOZ_ASSERT(aSurface);
1007     mContext->SetEGLSurfaceOverride(aSurface);
1008     mContext->MakeCurrent(true);
1009   }
~ScopedContextSurfaceOverride()1010   ~ScopedContextSurfaceOverride() {
1011     mContext->SetEGLSurfaceOverride(EGL_NO_SURFACE);
1012     mContext->MakeCurrent(true);
1013   }
1014 
1015  private:
1016   GLContextEGL* const mContext;
1017 };
1018 
RenderToPresentationSurface()1019 void LayerManagerComposite::RenderToPresentationSurface() {
1020   if (!mCompositor) {
1021     return;
1022   }
1023 
1024   widget::CompositorWidget* const widget = mCompositor->GetWidget();
1025 
1026   if (!widget) {
1027     return;
1028   }
1029 
1030   ANativeWindow* window = widget->AsAndroid()->GetPresentationANativeWindow();
1031 
1032   if (!window) {
1033     return;
1034   }
1035 
1036   CompositorOGL* compositor = mCompositor->AsCompositorOGL();
1037   GLContext* gl = compositor->gl();
1038   GLContextEGL* egl = GLContextEGL::Cast(gl);
1039 
1040   if (!egl) {
1041     return;
1042   }
1043 
1044   EGLSurface surface = widget->AsAndroid()->GetPresentationEGLSurface();
1045 
1046   if (!surface) {
1047     // create surface;
1048     surface = egl->CreateCompatibleSurface(window);
1049     if (!surface) {
1050       return;
1051     }
1052 
1053     widget->AsAndroid()->SetPresentationEGLSurface(surface);
1054   }
1055 
1056   const IntSize windowSize(ANativeWindow_getWidth(window),
1057                            ANativeWindow_getHeight(window));
1058 
1059   if ((windowSize.width <= 0) || (windowSize.height <= 0)) {
1060     return;
1061   }
1062 
1063   ScreenRotation rotation = compositor->GetScreenRotation();
1064 
1065   const int actualWidth = windowSize.width;
1066   const int actualHeight = windowSize.height;
1067 
1068   const gfx::IntSize originalSize = compositor->GetDestinationSurfaceSize();
1069   const nsIntRect originalRect =
1070       nsIntRect(0, 0, originalSize.width, originalSize.height);
1071 
1072   int pageWidth = originalSize.width;
1073   int pageHeight = originalSize.height;
1074   if (rotation == ROTATION_90 || rotation == ROTATION_270) {
1075     pageWidth = originalSize.height;
1076     pageHeight = originalSize.width;
1077   }
1078 
1079   float scale = 1.0;
1080 
1081   if ((pageWidth > actualWidth) || (pageHeight > actualHeight)) {
1082     const float scaleWidth = (float)actualWidth / (float)pageWidth;
1083     const float scaleHeight = (float)actualHeight / (float)pageHeight;
1084     scale = scaleWidth <= scaleHeight ? scaleWidth : scaleHeight;
1085   }
1086 
1087   const gfx::IntSize actualSize(actualWidth, actualHeight);
1088   ScopedCompostitorSurfaceSize overrideSurfaceSize(compositor, actualSize);
1089 
1090   const ScreenPoint offset((actualWidth - (int)(scale * pageWidth)) / 2, 0);
1091   ScopedContextSurfaceOverride overrideSurface(egl, surface);
1092 
1093   Matrix viewMatrix = ComputeTransformForRotation(originalRect, rotation);
1094   viewMatrix.Invert();  // unrotate
1095   viewMatrix.PostScale(scale, scale);
1096   viewMatrix.PostTranslate(offset.x, offset.y);
1097   Matrix4x4 matrix = Matrix4x4::From2D(viewMatrix);
1098 
1099   mRoot->ComputeEffectiveTransforms(matrix);
1100   nsIntRegion opaque;
1101   PostProcessLayers(opaque);
1102 
1103   nsIntRegion invalid;
1104   IntRect bounds = IntRect::Truncate(0, 0, scale * pageWidth, actualHeight);
1105   IntRect rect, actualBounds;
1106   MOZ_ASSERT(mRoot->GetOpacity() == 1);
1107   mCompositor->BeginFrame(invalid, nullptr, bounds, nsIntRegion(), &rect,
1108                           &actualBounds);
1109 
1110   // The Java side of Fennec sets a scissor rect that accounts for
1111   // chrome such as the URL bar. Override that so that the entire frame buffer
1112   // is cleared.
1113   ScopedScissorRect scissorRect(egl, 0, 0, actualWidth, actualHeight);
1114   egl->fClearColor(0.0, 0.0, 0.0, 0.0);
1115   egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
1116 
1117   const IntRect clipRect = IntRect::Truncate(0, 0, actualWidth, actualHeight);
1118 
1119   RootLayer()->Prepare(RenderTargetIntRect::FromUnknownRect(clipRect));
1120   RootLayer()->RenderLayer(clipRect, Nothing());
1121 
1122   mCompositor->EndFrame();
1123 }
1124 
GetContentShiftForToolbar()1125 ScreenCoord LayerManagerComposite::GetContentShiftForToolbar() {
1126   ScreenCoord result(0.0f);
1127   // If GetTargetContext return is not null we are not drawing to the screen so
1128   // there will not be any content offset.
1129   if (mCompositor->GetTargetContext() != nullptr) {
1130     return result;
1131   }
1132 
1133   if (CompositorBridgeParent* bridge =
1134           mCompositor->GetCompositorBridgeParent()) {
1135     AndroidDynamicToolbarAnimator* animator =
1136         bridge->GetAndroidDynamicToolbarAnimator();
1137     MOZ_RELEASE_ASSERT(animator);
1138     result.value = (float)animator->GetCurrentContentOffset().value;
1139   }
1140   return result;
1141 }
1142 
RenderToolbar()1143 void LayerManagerComposite::RenderToolbar() {
1144   // If GetTargetContext return is not null we are not drawing to the screen so
1145   // don't draw the toolbar.
1146   if (mCompositor->GetTargetContext() != nullptr) {
1147     return;
1148   }
1149 
1150   if (CompositorBridgeParent* bridge =
1151           mCompositor->GetCompositorBridgeParent()) {
1152     AndroidDynamicToolbarAnimator* animator =
1153         bridge->GetAndroidDynamicToolbarAnimator();
1154     MOZ_RELEASE_ASSERT(animator);
1155 
1156     animator->UpdateToolbarSnapshotTexture(mCompositor->AsCompositorOGL());
1157 
1158     int32_t toolbarHeight = animator->GetCurrentToolbarHeight();
1159     if (toolbarHeight == 0) {
1160       return;
1161     }
1162 
1163     EffectChain effects;
1164     effects.mPrimaryEffect = animator->GetToolbarEffect();
1165 
1166     // If GetToolbarEffect returns null, nothing is rendered for the static
1167     // snapshot of the toolbar. If the real toolbar chrome is not covering this
1168     // portion of the surface, the clear color of the surface will be visible.
1169     // On Android the clear color is the background color of the page.
1170     if (effects.mPrimaryEffect) {
1171       ScopedCompositorRenderOffset toolbarOffset(
1172           mCompositor->AsCompositorOGL(),
1173           ScreenPoint(0.0f, -animator->GetCurrentContentOffset()));
1174       mCompositor->DrawQuad(gfx::Rect(0, 0, mRenderBounds.width, toolbarHeight),
1175                             IntRect(0, 0, mRenderBounds.width, toolbarHeight),
1176                             effects, 1.0, gfx::Matrix4x4());
1177     }
1178   }
1179 }
1180 
1181 // Used by robocop tests to get a snapshot of the frame buffer.
HandlePixelsTarget()1182 void LayerManagerComposite::HandlePixelsTarget() {
1183   if (!mScreenPixelsTarget) {
1184     return;
1185   }
1186 
1187   int32_t bufferWidth = mRenderBounds.width;
1188   int32_t bufferHeight = mRenderBounds.height;
1189   ipc::Shmem mem;
1190   if (!mScreenPixelsTarget->AllocPixelBuffer(
1191           bufferWidth * bufferHeight * sizeof(uint32_t), &mem)) {
1192     // Failed to alloc shmem, Just bail out.
1193     return;
1194   }
1195   CompositorOGL* compositor = mCompositor->AsCompositorOGL();
1196   GLContext* gl = compositor->gl();
1197   MOZ_ASSERT(gl);
1198   gl->fReadPixels(0, 0, bufferWidth, bufferHeight, LOCAL_GL_RGBA,
1199                   LOCAL_GL_UNSIGNED_BYTE, mem.get<uint8_t>());
1200   Unused << mScreenPixelsTarget->SendScreenPixels(
1201       mem, ScreenIntSize(bufferWidth, bufferHeight));
1202   mScreenPixelsTarget = nullptr;
1203 }
1204 #endif
1205 
1206 class BorderLayerComposite : public BorderLayer, public LayerComposite {
1207  public:
BorderLayerComposite(LayerManagerComposite * aManager)1208   explicit BorderLayerComposite(LayerManagerComposite* aManager)
1209       : BorderLayer(aManager, nullptr), LayerComposite(aManager) {
1210     MOZ_COUNT_CTOR(BorderLayerComposite);
1211     mImplData = static_cast<LayerComposite*>(this);
1212   }
1213 
1214  protected:
~BorderLayerComposite()1215   ~BorderLayerComposite() {
1216     MOZ_COUNT_DTOR(BorderLayerComposite);
1217     Destroy();
1218   }
1219 
1220  public:
1221   // LayerComposite Implementation
GetLayer()1222   virtual Layer* GetLayer() override { return this; }
1223 
SetLayerManager(HostLayerManager * aManager)1224   virtual void SetLayerManager(HostLayerManager* aManager) override {
1225     LayerComposite::SetLayerManager(aManager);
1226     mManager = aManager;
1227   }
1228 
Destroy()1229   virtual void Destroy() override { mDestroyed = true; }
1230 
RenderLayer(const gfx::IntRect & aClipRect,const Maybe<gfx::Polygon> & aGeometry)1231   virtual void RenderLayer(const gfx::IntRect& aClipRect,
1232                            const Maybe<gfx::Polygon>& aGeometry) override {}
CleanupResources()1233   virtual void CleanupResources() override{};
1234 
GenEffectChain(EffectChain & aEffect)1235   virtual void GenEffectChain(EffectChain& aEffect) override {}
1236 
GetCompositableHost()1237   CompositableHost* GetCompositableHost() override { return nullptr; }
1238 
AsHostLayer()1239   virtual HostLayer* AsHostLayer() override { return this; }
1240 
Name() const1241   virtual const char* Name() const override { return "BorderLayerComposite"; }
1242 };
1243 
CreatePaintedLayer()1244 already_AddRefed<PaintedLayer> LayerManagerComposite::CreatePaintedLayer() {
1245   if (mDestroyed) {
1246     NS_WARNING("Call on destroyed layer manager");
1247     return nullptr;
1248   }
1249   return RefPtr<PaintedLayer>(new PaintedLayerComposite(this)).forget();
1250 }
1251 
CreateContainerLayer()1252 already_AddRefed<ContainerLayer> LayerManagerComposite::CreateContainerLayer() {
1253   if (mDestroyed) {
1254     NS_WARNING("Call on destroyed layer manager");
1255     return nullptr;
1256   }
1257   return RefPtr<ContainerLayer>(new ContainerLayerComposite(this)).forget();
1258 }
1259 
CreateImageLayer()1260 already_AddRefed<ImageLayer> LayerManagerComposite::CreateImageLayer() {
1261   if (mDestroyed) {
1262     NS_WARNING("Call on destroyed layer manager");
1263     return nullptr;
1264   }
1265   return RefPtr<ImageLayer>(new ImageLayerComposite(this)).forget();
1266 }
1267 
CreateColorLayer()1268 already_AddRefed<ColorLayer> LayerManagerComposite::CreateColorLayer() {
1269   if (LayerManagerComposite::mDestroyed) {
1270     NS_WARNING("Call on destroyed layer manager");
1271     return nullptr;
1272   }
1273   return RefPtr<ColorLayer>(new ColorLayerComposite(this)).forget();
1274 }
1275 
CreateCanvasLayer()1276 already_AddRefed<CanvasLayer> LayerManagerComposite::CreateCanvasLayer() {
1277   if (LayerManagerComposite::mDestroyed) {
1278     NS_WARNING("Call on destroyed layer manager");
1279     return nullptr;
1280   }
1281   return RefPtr<CanvasLayer>(new CanvasLayerComposite(this)).forget();
1282 }
1283 
CreateRefLayer()1284 already_AddRefed<RefLayer> LayerManagerComposite::CreateRefLayer() {
1285   if (LayerManagerComposite::mDestroyed) {
1286     NS_WARNING("Call on destroyed layer manager");
1287     return nullptr;
1288   }
1289   return RefPtr<RefLayer>(new RefLayerComposite(this)).forget();
1290 }
1291 
CreateBorderLayer()1292 already_AddRefed<BorderLayer> LayerManagerComposite::CreateBorderLayer() {
1293   if (LayerManagerComposite::mDestroyed) {
1294     NS_WARNING("Call on destroyed layer manager");
1295     return nullptr;
1296   }
1297   return RefPtr<BorderLayer>(new BorderLayerComposite(this)).forget();
1298 }
1299 
AutoAddMaskEffect(Layer * aMaskLayer,EffectChain & aEffects)1300 LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(
1301     Layer* aMaskLayer, EffectChain& aEffects)
1302     : mCompositable(nullptr), mFailed(false) {
1303   if (!aMaskLayer) {
1304     return;
1305   }
1306 
1307   mCompositable = ToLayerComposite(aMaskLayer)->GetCompositableHost();
1308   if (!mCompositable) {
1309     NS_WARNING("Mask layer with no compositable host");
1310     mFailed = true;
1311     return;
1312   }
1313 
1314   if (!mCompositable->AddMaskEffect(aEffects,
1315                                     aMaskLayer->GetEffectiveTransform())) {
1316     mCompositable = nullptr;
1317     mFailed = true;
1318   }
1319 }
1320 
~AutoAddMaskEffect()1321 LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect() {
1322   if (!mCompositable) {
1323     return;
1324   }
1325 
1326   mCompositable->RemoveMaskEffect();
1327 }
1328 
IsCompositingToScreen() const1329 bool LayerManagerComposite::IsCompositingToScreen() const {
1330   if (!mCompositor) {
1331     return true;
1332   }
1333   return !mCompositor->GetTargetContext();
1334 }
1335 
LayerComposite(LayerManagerComposite * aManager)1336 LayerComposite::LayerComposite(LayerManagerComposite* aManager)
1337     : HostLayer(aManager),
1338       mCompositeManager(aManager),
1339       mCompositor(aManager->GetCompositor()),
1340       mDestroyed(false),
1341       mLayerComposited(false) {}
1342 
~LayerComposite()1343 LayerComposite::~LayerComposite() {}
1344 
Destroy()1345 void LayerComposite::Destroy() {
1346   if (!mDestroyed) {
1347     mDestroyed = true;
1348     CleanupResources();
1349   }
1350 }
1351 
AddBlendModeEffect(EffectChain & aEffectChain)1352 void LayerComposite::AddBlendModeEffect(EffectChain& aEffectChain) {
1353   gfx::CompositionOp blendMode = GetLayer()->GetEffectiveMixBlendMode();
1354   if (blendMode == gfx::CompositionOp::OP_OVER) {
1355     return;
1356   }
1357 
1358   aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE] =
1359       new EffectBlendMode(blendMode);
1360 }
1361 
CanUseCanvasLayerForSize(const IntSize & aSize)1362 bool LayerManagerComposite::CanUseCanvasLayerForSize(const IntSize& aSize) {
1363   return mCompositor->CanUseCanvasLayerForSize(
1364       gfx::IntSize(aSize.width, aSize.height));
1365 }
1366 
NotifyShadowTreeTransaction()1367 void LayerManagerComposite::NotifyShadowTreeTransaction() {
1368   if (gfxPrefs::LayersDrawFPS()) {
1369     mDiagnostics->AddTxnFrame();
1370   }
1371 }
1372 
SetLayerManager(HostLayerManager * aManager)1373 void LayerComposite::SetLayerManager(HostLayerManager* aManager) {
1374   HostLayer::SetLayerManager(aManager);
1375   mCompositeManager = static_cast<LayerManagerComposite*>(aManager);
1376   mCompositor = mCompositeManager->GetCompositor();
1377 }
1378 
AsyncPanZoomEnabled() const1379 bool LayerManagerComposite::AsyncPanZoomEnabled() const {
1380   if (CompositorBridgeParent* bridge =
1381           mCompositor->GetCompositorBridgeParent()) {
1382     return bridge->GetOptions().UseAPZ();
1383   }
1384   return false;
1385 }
1386 
AlwaysScheduleComposite() const1387 bool LayerManagerComposite::AlwaysScheduleComposite() const {
1388   return !!(mCompositor->GetDiagnosticTypes() & DiagnosticTypes::FLASH_BORDERS);
1389 }
1390 
GetFullyRenderedRegion()1391 nsIntRegion LayerComposite::GetFullyRenderedRegion() {
1392   if (TiledContentHost* tiled =
1393           GetCompositableHost() ? GetCompositableHost()->AsTiledContentHost()
1394                                 : nullptr) {
1395     nsIntRegion shadowVisibleRegion =
1396         GetShadowVisibleRegion().ToUnknownRegion();
1397     // Discard the region which hasn't been drawn yet when doing
1398     // progressive drawing. Note that if the shadow visible region
1399     // shrunk the tiled valig region may not have discarded this yet.
1400     shadowVisibleRegion.And(shadowVisibleRegion, tiled->GetValidRegion());
1401     return shadowVisibleRegion;
1402   } else {
1403     return GetShadowVisibleRegion().ToUnknownRegion();
1404   }
1405 }
1406 
GetShadowTransform()1407 Matrix4x4 HostLayer::GetShadowTransform() {
1408   Matrix4x4 transform = mShadowTransform;
1409   Layer* layer = GetLayer();
1410 
1411   transform.PostScale(layer->GetPostXScale(), layer->GetPostYScale(), 1.0f);
1412   if (const ContainerLayer* c = layer->AsContainerLayer()) {
1413     transform.PreScale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
1414   }
1415 
1416   return transform;
1417 }
1418 
TransformRect(const LayerIntRect & aRect,const Matrix4x4 & aTransform)1419 static LayerIntRect TransformRect(const LayerIntRect& aRect,
1420                                   const Matrix4x4& aTransform) {
1421   if (aRect.IsEmpty()) {
1422     return LayerIntRect();
1423   }
1424 
1425   Rect rect(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
1426   rect = aTransform.TransformAndClipBounds(rect, Rect::MaxIntRect());
1427   rect.RoundOut();
1428 
1429   IntRect intRect;
1430   if (!gfxUtils::GfxRectToIntRect(ThebesRect(rect), &intRect)) {
1431     return LayerIntRect();
1432   }
1433 
1434   return ViewAs<LayerPixel>(intRect);
1435 }
1436 
AddTransformedRegion(LayerIntRegion & aDest,const LayerIntRegion & aSource,const Matrix4x4 & aTransform)1437 static void AddTransformedRegion(LayerIntRegion& aDest,
1438                                  const LayerIntRegion& aSource,
1439                                  const Matrix4x4& aTransform) {
1440   for (auto iter = aSource.RectIter(); !iter.Done(); iter.Next()) {
1441     aDest.Or(aDest, TransformRect(iter.Get(), aTransform));
1442   }
1443   aDest.SimplifyOutward(20);
1444 }
1445 
1446 // Async animations can move child layers without updating our visible region.
1447 // PostProcessLayers will recompute visible regions for layers with an
1448 // intermediate surface, but otherwise we need to do it now.
ComputeVisibleRegionForChildren(ContainerLayer * aContainer,LayerIntRegion & aResult)1449 void ComputeVisibleRegionForChildren(ContainerLayer* aContainer,
1450                                      LayerIntRegion& aResult) {
1451   for (Layer* l = aContainer->GetFirstChild(); l; l = l->GetNextSibling()) {
1452     if (l->Extend3DContext()) {
1453       MOZ_ASSERT(l->AsContainerLayer());
1454       ComputeVisibleRegionForChildren(l->AsContainerLayer(), aResult);
1455     } else {
1456       AddTransformedRegion(aResult, l->GetLocalVisibleRegion(),
1457                            l->ComputeTransformToPreserve3DRoot());
1458     }
1459   }
1460 }
1461 
RecomputeShadowVisibleRegionFromChildren()1462 void HostLayer::RecomputeShadowVisibleRegionFromChildren() {
1463   mShadowVisibleRegion.SetEmpty();
1464   ContainerLayer* container = GetLayer()->AsContainerLayer();
1465   MOZ_ASSERT(container);
1466   if (container) {
1467     ComputeVisibleRegionForChildren(container, mShadowVisibleRegion);
1468   }
1469 }
1470 
HasStaleCompositor() const1471 bool LayerComposite::HasStaleCompositor() const {
1472   return mCompositeManager->GetCompositor() != mCompositor;
1473 }
1474 
1475 #ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
1476 
SupportsDirectTexturing()1477 /*static*/ bool LayerManagerComposite::SupportsDirectTexturing() {
1478   return false;
1479 }
1480 
PlatformSyncBeforeReplyUpdate()1481 /*static*/ void LayerManagerComposite::PlatformSyncBeforeReplyUpdate() {}
1482 
1483 #endif  // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
1484 
1485 }  // namespace layers
1486 }  // namespace mozilla
1487