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