Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/composite/ContainerLayerComposite.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "ContainerLayerComposite.h"
8
#include <algorithm>                    // for min
9
#include "FrameMetrics.h"               // for FrameMetrics
10
#include "Units.h"                      // for LayerRect, LayerPixel, etc
11
#include "CompositableHost.h"           // for CompositableHost
12
#include "gfxEnv.h"                     // for gfxEnv
13
#include "gfxPrefs.h"                   // for gfxPrefs
14
#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
15
#include "mozilla/RefPtr.h"             // for RefPtr
16
#include "mozilla/UniquePtr.h"          // for UniquePtr
17
#include "mozilla/gfx/BaseRect.h"       // for BaseRect
18
#include "mozilla/gfx/Matrix.h"         // for Matrix4x4
19
#include "mozilla/gfx/Point.h"          // for Point, IntPoint
20
#include "mozilla/gfx/Rect.h"           // for IntRect, Rect
21
#include "mozilla/layers/APZSampler.h"  // for APZSampler
22
#include "mozilla/layers/Compositor.h"  // for Compositor, etc
23
#include "mozilla/layers/CompositorTypes.h"  // for DiagnosticFlags::CONTAINER
24
#include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
25
#include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget
26
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
27
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
28
#include "mozilla/mozalloc.h"           // for operator delete, etc
29
#include "mozilla/RefPtr.h"                   // for nsRefPtr
30
#include "nsDebug.h"                    // for NS_ASSERTION
31
#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
32
#include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
33
#include "nsRegion.h"                   // for nsIntRegion
34
#include "nsTArray.h"                   // for AutoTArray
35
#include <stack>
36
#include "TextRenderer.h"               // for TextRenderer
37
#include <vector>
38
#include "GeckoProfiler.h"              // for GeckoProfiler
39
40
#ifdef MOZ_GECKO_PROFILER
41
#include "ProfilerMarkerPayload.h"      // for LayerTranslationMarkerPayload
42
#endif
43
44
#define CULLING_LOG(...)
45
// #define CULLING_LOG(...) printf_stderr("CULLING: " __VA_ARGS__)
46
47
#define DUMP(...) do { if (gfxEnv::DumpDebug()) { printf_stderr(__VA_ARGS__); } } while(0)
48
#define XYWH(k)  (k).X(), (k).Y(), (k).Width(), (k).Height()
49
#define XY(k)    (k).X(), (k).Y()
50
#define WH(k)    (k).Width(), (k).Height()
51
52
namespace mozilla {
53
namespace layers {
54
55
using namespace gfx;
56
57
static void
58
DrawLayerInfo(const RenderTargetIntRect& aClipRect,
59
              LayerManagerComposite* aManager,
60
              Layer* aLayer)
61
0
{
62
0
  if (aLayer->GetType() == Layer::LayerType::TYPE_CONTAINER) {
63
0
    // XXX - should figure out a way to render this, but for now this
64
0
    // is hard to do, since it will often get superimposed over the first
65
0
    // child of the layer, which is bad.
66
0
    return;
67
0
  }
68
0
69
0
  std::stringstream ss;
70
0
  aLayer->PrintInfo(ss, "");
71
0
72
0
  LayerIntRegion visibleRegion = aLayer->GetVisibleRegion();
73
0
74
0
  uint32_t maxWidth = std::min<uint32_t>(visibleRegion.GetBounds().Width(), 500);
75
0
76
0
  IntPoint topLeft = visibleRegion.GetBounds().ToUnknownRect().TopLeft();
77
0
  aManager->GetTextRenderer()->RenderText(
78
0
    aManager->GetCompositor(),
79
0
    ss.str().c_str(),
80
0
    topLeft,
81
0
    aLayer->GetEffectiveTransform(), 16,
82
0
    maxWidth);
83
0
}
84
85
static void
86
PrintUniformityInfo(Layer* aLayer)
87
0
{
88
0
#if defined(MOZ_GECKO_PROFILER)
89
0
  if (!profiler_is_active()) {
90
0
    return;
91
0
  }
92
0
93
0
  // Don't want to print a log for smaller layers
94
0
  if (aLayer->GetLocalVisibleRegion().GetBounds().Width() < 300 ||
95
0
      aLayer->GetLocalVisibleRegion().GetBounds().Height() < 300) {
96
0
    return;
97
0
  }
98
0
99
0
  Matrix4x4 transform = aLayer->AsHostLayer()->GetShadowBaseTransform();
100
0
  if (!transform.Is2D()) {
101
0
    return;
102
0
  }
103
0
104
0
  Point translation = transform.As2D().GetTranslation();
105
0
  profiler_add_marker(
106
0
    "LayerTranslation",
107
0
    MakeUnique<LayerTranslationMarkerPayload>(aLayer, translation,
108
0
                                              TimeStamp::Now()));
109
0
#endif
110
0
}
111
112
static Maybe<gfx::Polygon>
113
SelectLayerGeometry(const Maybe<gfx::Polygon>& aParentGeometry,
114
                    const Maybe<gfx::Polygon>& aChildGeometry)
115
0
{
116
0
  // Both the parent and the child layer were split.
117
0
  if (aParentGeometry && aChildGeometry) {
118
0
    return Some(aParentGeometry->ClipPolygon(*aChildGeometry));
119
0
  }
120
0
121
0
  // The parent layer was split.
122
0
  if (aParentGeometry) {
123
0
    return aParentGeometry;
124
0
  }
125
0
126
0
  // The child layer was split.
127
0
  if(aChildGeometry) {
128
0
    return aChildGeometry;
129
0
  }
130
0
131
0
  // No split.
132
0
  return Nothing();
133
0
}
134
135
void
136
TransformLayerGeometry(Layer* aLayer, Maybe<gfx::Polygon>& aGeometry)
137
0
{
138
0
  Layer* parent = aLayer;
139
0
  gfx::Matrix4x4 transform;
140
0
141
0
  // Collect all parent transforms.
142
0
  while (parent != nullptr && !parent->Is3DContextLeaf()) {
143
0
    transform = transform * parent->GetLocalTransform();
144
0
    parent = parent->GetParent();
145
0
  }
146
0
147
0
  // Transform the geometry to the parent 3D context leaf coordinate space.
148
0
  transform = transform.ProjectTo2D();
149
0
150
0
  if (!transform.IsSingular()) {
151
0
    aGeometry->TransformToScreenSpace(transform.Inverse(), transform);
152
0
  } else {
153
0
    // Discard the geometry since the result might not be correct.
154
0
    aGeometry.reset();
155
0
  }
156
0
}
157
158
159
template<class ContainerT>
160
static gfx::IntRect ContainerVisibleRect(ContainerT* aContainer)
161
0
{
162
0
  gfx::IntRect surfaceRect = aContainer->GetLocalVisibleRegion().GetBounds().ToUnknownRect();
163
0
  return surfaceRect;
164
0
}
Unexecuted instantiation: Unified_cpp_gfx_layers6.cpp:mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> mozilla::layers::ContainerVisibleRect<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*)
Unexecuted instantiation: Unified_cpp_gfx_layers6.cpp:mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> mozilla::layers::ContainerVisibleRect<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*)
165
166
167
/* all of the per-layer prepared data we need to maintain */
168
struct PreparedLayer
169
{
170
  PreparedLayer(Layer *aLayer,
171
                RenderTargetIntRect aClipRect,
172
                Maybe<gfx::Polygon>&& aGeometry)
173
0
  : mLayer(aLayer), mClipRect(aClipRect), mGeometry(std::move(aGeometry)) {}
174
175
  RefPtr<Layer> mLayer;
176
  RenderTargetIntRect mClipRect;
177
  Maybe<Polygon> mGeometry;
178
};
179
180
/* all of the prepared data that we need in RenderLayer() */
181
struct PreparedData
182
{
183
  RefPtr<CompositingRenderTarget> mTmpTarget;
184
  AutoTArray<PreparedLayer, 12> mLayers;
185
  bool mNeedsSurfaceCopy;
186
};
187
188
// ContainerPrepare is shared between RefLayer and ContainerLayer
189
template<class ContainerT> void
190
ContainerPrepare(ContainerT* aContainer,
191
                 LayerManagerComposite* aManager,
192
                 const RenderTargetIntRect& aClipRect)
193
0
{
194
0
  // We can end up calling prepare multiple times if we duplicated
195
0
  // layers due to preserve-3d plane splitting. The results
196
0
  // should be identical, so we only need to do it once.
197
0
  if (aContainer->mPrepared) {
198
0
    return;
199
0
  }
200
0
  aContainer->mPrepared = MakeUnique<PreparedData>();
201
0
  aContainer->mPrepared->mNeedsSurfaceCopy = false;
202
0
203
0
  const ContainerLayerComposite::SortMode sortMode =
204
0
    aManager->GetCompositor()->SupportsLayerGeometry()
205
0
    ? ContainerLayerComposite::SortMode::WITH_GEOMETRY
206
0
    : ContainerLayerComposite::SortMode::WITHOUT_GEOMETRY;
207
0
208
0
  nsTArray<LayerPolygon> polygons =
209
0
    aContainer->SortChildrenBy3DZOrder(sortMode);
210
0
211
0
  for (LayerPolygon& layer : polygons) {
212
0
    LayerComposite* layerToRender =
213
0
      static_cast<LayerComposite*>(layer.layer->ImplData());
214
0
215
0
    RenderTargetIntRect clipRect =
216
0
      layerToRender->GetLayer()->CalculateScissorRect(aClipRect);
217
0
218
0
    if (layerToRender->GetLayer()->IsBackfaceHidden()) {
219
0
      continue;
220
0
    }
221
0
222
0
    // We don't want to skip container layers because otherwise their mPrepared
223
0
    // may be null which is not allowed.
224
0
    if (!layerToRender->GetLayer()->AsContainerLayer()) {
225
0
      if (!layerToRender->GetLayer()->IsVisible()) {
226
0
        CULLING_LOG("Sublayer %p has no effective visible region\n", layerToRender->GetLayer());
227
0
        continue;
228
0
      }
229
0
230
0
      if (clipRect.IsEmpty()) {
231
0
        CULLING_LOG("Sublayer %p has an empty world clip rect\n", layerToRender->GetLayer());
232
0
        continue;
233
0
      }
234
0
    }
235
0
236
0
    CULLING_LOG("Preparing sublayer %p\n", layerToRender->GetLayer());
237
0
238
0
    layerToRender->Prepare(clipRect);
239
0
    aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender->GetLayer(),
240
0
                                                               clipRect,
241
0
                                                               std::move(layer.geometry)));
242
0
  }
243
0
244
0
  CULLING_LOG("Preparing container layer %p\n", aContainer->GetLayer());
245
0
246
0
  /**
247
0
   * Setup our temporary surface for rendering the contents of this container.
248
0
   */
249
0
250
0
  gfx::IntRect surfaceRect = ContainerVisibleRect(aContainer);
251
0
  if (surfaceRect.IsEmpty()) {
252
0
    return;
253
0
  }
254
0
255
0
  bool surfaceCopyNeeded;
256
0
  // DefaultComputeSupportsComponentAlphaChildren can mutate aContainer so call it unconditionally
257
0
  aContainer->DefaultComputeSupportsComponentAlphaChildren(&surfaceCopyNeeded);
258
0
  if (aContainer->UseIntermediateSurface()) {
259
0
    if (!surfaceCopyNeeded) {
260
0
      RefPtr<CompositingRenderTarget> surface = nullptr;
261
0
262
0
      RefPtr<CompositingRenderTarget>& lastSurf = aContainer->mLastIntermediateSurface;
263
0
      if (lastSurf && !aContainer->mChildrenChanged && lastSurf->GetRect().IsEqualEdges(surfaceRect)) {
264
0
        surface = lastSurf;
265
0
      }
266
0
267
0
      if (!surface) {
268
0
        // If we don't need a copy we can render to the intermediate now to avoid
269
0
        // unecessary render target switching. This brings a big perf boost on mobile gpus.
270
0
        surface = CreateOrRecycleTarget(aContainer, aManager);
271
0
272
0
        MOZ_PERFORMANCE_WARNING("gfx", "[%p] Container layer requires intermediate surface rendering\n", aContainer);
273
0
        RenderIntermediate(aContainer, aManager, aClipRect.ToUnknownRect(), surface);
274
0
        aContainer->SetChildrenChanged(false);
275
0
      }
276
0
277
0
      aContainer->mPrepared->mTmpTarget = surface;
278
0
    } else {
279
0
      MOZ_PERFORMANCE_WARNING("gfx", "[%p] Container layer requires intermediate surface copy\n", aContainer);
280
0
      aContainer->mPrepared->mNeedsSurfaceCopy = true;
281
0
      aContainer->mLastIntermediateSurface = nullptr;
282
0
    }
283
0
  } else {
284
0
    aContainer->mLastIntermediateSurface = nullptr;
285
0
  }
286
0
}
Unexecuted instantiation: void mozilla::layers::ContainerPrepare<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::RenderTargetPixel> const&)
Unexecuted instantiation: void mozilla::layers::ContainerPrepare<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::RenderTargetPixel> const&)
287
288
template<class ContainerT> void
289
RenderMinimap(ContainerT* aContainer,
290
              const RefPtr<APZSampler>& aSampler,
291
              LayerManagerComposite* aManager,
292
              const RenderTargetIntRect& aClipRect, Layer* aLayer)
293
0
{
294
0
  Compositor* compositor = aManager->GetCompositor();
295
0
  MOZ_ASSERT(aSampler);
296
0
297
0
  if (aLayer->GetScrollMetadataCount() < 1) {
298
0
    return;
299
0
  }
300
0
301
0
  LayerMetricsWrapper wrapper(aLayer, 0);
302
0
  if (!wrapper.GetApzc()) {
303
0
    return;
304
0
  }
305
0
  const FrameMetrics& fm = wrapper.Metrics();
306
0
  MOZ_ASSERT(fm.IsScrollable());
307
0
308
0
  ParentLayerPoint scrollOffset = aSampler->GetCurrentAsyncScrollOffset(wrapper);
309
0
310
0
  // Options
311
0
  const int verticalPadding = 10;
312
0
  const int horizontalPadding = 5;
313
0
  gfx::Color backgroundColor(0.3f, 0.3f, 0.3f, 0.3f);
314
0
  gfx::Color tileActiveColor(1, 1, 1, 0.4f);
315
0
  gfx::Color tileBorderColor(0, 0, 0, 0.1f);
316
0
  gfx::Color pageBorderColor(0, 0, 0);
317
0
  gfx::Color criticalDisplayPortColor(1.f, 1.f, 0);
318
0
  gfx::Color displayPortColor(0, 1.f, 0);
319
0
  gfx::Color layoutPortColor(1.f, 0, 0);
320
0
  gfx::Color visualPortColor(0, 0, 1.f, 0.3f);
321
0
322
0
  // Rects
323
0
  ParentLayerRect compositionBounds = fm.GetCompositionBounds();
324
0
  LayerRect scrollRect = fm.GetScrollableRect() * fm.LayersPixelsPerCSSPixel();
325
0
  LayerRect visualRect = ParentLayerRect(scrollOffset, compositionBounds.Size()) / LayerToParentLayerScale(1);
326
0
  LayerRect dp = (fm.GetDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel();
327
0
  Maybe<LayerRect> layoutRect;
328
0
  Maybe<LayerRect> cdp;
329
0
  if (fm.IsRootContent()) {
330
0
    CSSRect viewport = aSampler->GetCurrentAsyncLayoutViewport(wrapper);
331
0
    layoutRect = Some(viewport * fm.LayersPixelsPerCSSPixel());
332
0
  }
333
0
  if (!fm.GetCriticalDisplayPort().IsEmpty()) {
334
0
    cdp = Some((fm.GetCriticalDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel());
335
0
  }
336
0
337
0
  // Don't render trivial minimap. They can show up from textboxes and other tiny frames.
338
0
  if (visualRect.Width() < 64 && visualRect.Height() < 64) {
339
0
    return;
340
0
  }
341
0
342
0
  // Compute a scale with an appropriate aspect ratio
343
0
  // We allocate up to 100px of width and the height of this layer.
344
0
  float scaleFactor;
345
0
  float scaleFactorX;
346
0
  float scaleFactorY;
347
0
  Rect dest = Rect(aClipRect.ToUnknownRect());
348
0
  if (aLayer->GetLocalClipRect()) {
349
0
    dest = Rect(aLayer->GetLocalClipRect().value().ToUnknownRect());
350
0
  } else {
351
0
    dest = aContainer->GetEffectiveTransform().Inverse().TransformBounds(dest);
352
0
  }
353
0
  dest = dest.Intersect(compositionBounds.ToUnknownRect());
354
0
  scaleFactorX = std::min(100.f, dest.Width() - (2 * horizontalPadding)) / scrollRect.Width();
355
0
  scaleFactorY = (dest.Height() - (2 * verticalPadding)) / scrollRect.Height();
356
0
  scaleFactor = std::min(scaleFactorX, scaleFactorY);
357
0
  if (scaleFactor <= 0) {
358
0
    return;
359
0
  }
360
0
361
0
  Matrix4x4 transform = Matrix4x4::Scaling(scaleFactor, scaleFactor, 1);
362
0
  transform.PostTranslate(horizontalPadding + dest.X(), verticalPadding + dest.Y(), 0);
363
0
364
0
  Rect transformedScrollRect = transform.TransformBounds(scrollRect.ToUnknownRect());
365
0
366
0
  IntRect clipRect = RoundedOut(aContainer->GetEffectiveTransform().TransformBounds(transformedScrollRect));
367
0
368
0
  // Render the scrollable area.
369
0
  compositor->FillRect(transformedScrollRect, backgroundColor, clipRect, aContainer->GetEffectiveTransform());
370
0
  compositor->SlowDrawRect(transformedScrollRect, pageBorderColor, clipRect, aContainer->GetEffectiveTransform());
371
0
372
0
  // Render the displayport.
373
0
  Rect r = transform.TransformBounds(dp.ToUnknownRect());
374
0
  compositor->FillRect(r, tileActiveColor, clipRect, aContainer->GetEffectiveTransform());
375
0
  compositor->SlowDrawRect(r, displayPortColor, clipRect, aContainer->GetEffectiveTransform());
376
0
377
0
  // Render the critical displayport if there is one
378
0
  if (cdp) {
379
0
    r = transform.TransformBounds(cdp->ToUnknownRect());
380
0
    compositor->SlowDrawRect(r, criticalDisplayPortColor, clipRect, aContainer->GetEffectiveTransform());
381
0
  }
382
0
383
0
  // Render the layout viewport if it exists (which is only in the root
384
0
  // content APZC).
385
0
  if (layoutRect) {
386
0
    r = transform.TransformBounds(layoutRect->ToUnknownRect());
387
0
    compositor->SlowDrawRect(r, layoutPortColor, clipRect, aContainer->GetEffectiveTransform());
388
0
  }
389
0
390
0
  // Render the visual viewport.
391
0
  r = transform.TransformBounds(visualRect.ToUnknownRect());
392
0
  compositor->SlowDrawRect(r, visualPortColor, clipRect, aContainer->GetEffectiveTransform(), 2);
393
0
}
Unexecuted instantiation: void mozilla::layers::RenderMinimap<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, RefPtr<mozilla::layers::APZSampler> const&, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::RenderTargetPixel> const&, mozilla::layers::Layer*)
Unexecuted instantiation: void mozilla::layers::RenderMinimap<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, RefPtr<mozilla::layers::APZSampler> const&, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::RenderTargetPixel> const&, mozilla::layers::Layer*)
394
395
template<class ContainerT> void
396
RenderLayers(ContainerT* aContainer, LayerManagerComposite* aManager,
397
             const RenderTargetIntRect& aClipRect,
398
             const Maybe<gfx::Polygon>& aGeometry)
399
0
{
400
0
  Compositor* compositor = aManager->GetCompositor();
401
0
402
0
  RefPtr<APZSampler> sampler;
403
0
  if (CompositorBridgeParent* cbp = compositor->GetCompositorBridgeParent()) {
404
0
    sampler = cbp->GetAPZSampler();
405
0
  }
406
0
407
0
  for (size_t i = 0u; i < aContainer->mPrepared->mLayers.Length(); i++) {
408
0
    PreparedLayer& preparedData = aContainer->mPrepared->mLayers[i];
409
0
410
0
    const gfx::IntRect clipRect = preparedData.mClipRect.ToUnknownRect();
411
0
    LayerComposite* layerToRender = static_cast<LayerComposite*>(preparedData.mLayer->ImplData());
412
0
    const Maybe<gfx::Polygon>& childGeometry = preparedData.mGeometry;
413
0
414
0
    Layer* layer = layerToRender->GetLayer();
415
0
416
0
    if (layerToRender->HasStaleCompositor()) {
417
0
      continue;
418
0
    }
419
0
420
0
    if (gfxPrefs::LayersDrawFPS()) {
421
0
      for (const auto& metadata : layer->GetAllScrollMetadata()) {
422
0
        if (metadata.IsApzForceDisabled()) {
423
0
          aManager->DisabledApzWarning();
424
0
          break;
425
0
        }
426
0
      }
427
0
    }
428
0
429
0
    if (layerToRender->HasLayerBeenComposited()) {
430
0
      // Composer2D will compose this layer so skip GPU composition
431
0
      // this time. The flag will be reset for the next composition phase
432
0
      // at the beginning of LayerManagerComposite::Rener().
433
0
      gfx::IntRect clearRect = layerToRender->GetClearRect();
434
0
      if (!clearRect.IsEmpty()) {
435
0
        // Clear layer's visible rect on FrameBuffer with transparent pixels
436
0
        gfx::Rect fbRect(clearRect.X(), clearRect.Y(), clearRect.Width(), clearRect.Height());
437
0
        compositor->ClearRect(fbRect);
438
0
        layerToRender->SetClearRect(gfx::IntRect(0, 0, 0, 0));
439
0
      }
440
0
    } else {
441
0
      // Since we force an intermediate surface for nested 3D contexts,
442
0
      // aGeometry and childGeometry are both in the same coordinate space.
443
0
      Maybe<gfx::Polygon> geometry =
444
0
        SelectLayerGeometry(aGeometry, childGeometry);
445
0
446
0
      // If we are dealing with a nested 3D context, we might need to transform
447
0
      // the geometry back to the coordinate space of the current layer before
448
0
      // rendering the layer.
449
0
      ContainerLayer* container = layer->AsContainerLayer();
450
0
      const bool isLeafLayer = !container || container->UseIntermediateSurface();
451
0
452
0
      if (geometry && isLeafLayer) {
453
0
        TransformLayerGeometry(layer, geometry);
454
0
      }
455
0
456
0
      layerToRender->RenderLayer(clipRect, geometry);
457
0
    }
458
0
459
0
    if (gfxPrefs::UniformityInfo()) {
460
0
      PrintUniformityInfo(layer);
461
0
    }
462
0
463
0
    if (gfxPrefs::DrawLayerInfo()) {
464
0
      DrawLayerInfo(preparedData.mClipRect, aManager, layer);
465
0
    }
466
0
467
0
    // Draw a border around scrollable layers.
468
0
    // A layer can be scrolled by multiple scroll frames. Draw a border
469
0
    // for each.
470
0
    // Within the list of scroll frames for a layer, the layer border for a
471
0
    // scroll frame lower down is affected by the async transforms on scroll
472
0
    // frames higher up, so loop from the top down, and accumulate an async
473
0
    // transform as we go along.
474
0
    Matrix4x4 asyncTransform;
475
0
    if (sampler) {
476
0
      for (uint32_t i = layer->GetScrollMetadataCount(); i > 0; --i) {
477
0
        LayerMetricsWrapper wrapper(layer, i - 1);
478
0
        if (wrapper.GetApzc()) {
479
0
          MOZ_ASSERT(wrapper.Metrics().IsScrollable());
480
0
          // Since the composition bounds are in the parent layer's coordinates,
481
0
          // use the parent's effective transform rather than the layer's own.
482
0
          ParentLayerRect compositionBounds = wrapper.Metrics().GetCompositionBounds();
483
0
          aManager->GetCompositor()->DrawDiagnostics(DiagnosticFlags::CONTAINER,
484
0
                                                     compositionBounds.ToUnknownRect(),
485
0
                                                     aClipRect.ToUnknownRect(),
486
0
                                                     asyncTransform * aContainer->GetEffectiveTransform());
487
0
          asyncTransform =
488
0
              sampler->GetCurrentAsyncTransformWithOverscroll(wrapper).ToUnknownMatrix()
489
0
              * asyncTransform;
490
0
        }
491
0
      }
492
0
493
0
      if (gfxPrefs::APZMinimap()) {
494
0
        RenderMinimap(aContainer, sampler, aManager, aClipRect, layer);
495
0
      }
496
0
    }
497
0
498
0
    // invariant: our GL context should be current here, I don't think we can
499
0
    // assert it though
500
0
  }
501
0
}
Unexecuted instantiation: void mozilla::layers::RenderLayers<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::RenderTargetPixel> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)
Unexecuted instantiation: void mozilla::layers::RenderLayers<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::RenderTargetPixel> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)
502
503
template<class ContainerT> RefPtr<CompositingRenderTarget>
504
CreateOrRecycleTarget(ContainerT* aContainer,
505
                      LayerManagerComposite* aManager)
506
0
{
507
0
  Compositor* compositor = aManager->GetCompositor();
508
0
  SurfaceInitMode mode = INIT_MODE_CLEAR;
509
0
  gfx::IntRect surfaceRect = ContainerVisibleRect(aContainer);
510
0
  if (aContainer->GetLocalVisibleRegion().GetNumRects() == 1 &&
511
0
      (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE))
512
0
  {
513
0
    mode = INIT_MODE_NONE;
514
0
  }
515
0
516
0
  RefPtr<CompositingRenderTarget>& lastSurf = aContainer->mLastIntermediateSurface;
517
0
  if (lastSurf && lastSurf->GetRect().IsEqualEdges(surfaceRect)) {
518
0
    if (mode == INIT_MODE_CLEAR) {
519
0
      lastSurf->ClearOnBind();
520
0
    }
521
0
522
0
    return lastSurf;
523
0
  } else {
524
0
    lastSurf = compositor->CreateRenderTarget(surfaceRect, mode);
525
0
526
0
    return lastSurf;
527
0
  }
528
0
}
Unexecuted instantiation: RefPtr<mozilla::layers::CompositingRenderTarget> mozilla::layers::CreateOrRecycleTarget<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*)
Unexecuted instantiation: RefPtr<mozilla::layers::CompositingRenderTarget> mozilla::layers::CreateOrRecycleTarget<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*)
529
530
template<class ContainerT> RefPtr<CompositingRenderTarget>
531
CreateTemporaryTargetAndCopyFromBackground(ContainerT* aContainer,
532
                                           LayerManagerComposite* aManager)
533
0
{
534
0
  Compositor* compositor = aManager->GetCompositor();
535
0
  gfx::IntRect visibleRect = aContainer->GetLocalVisibleRegion().GetBounds().ToUnknownRect();
536
0
  RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
537
0
  gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.X(), visibleRect.Y(),
538
0
                                          visibleRect.Width(), visibleRect.Height());
539
0
540
0
  gfx::IntPoint sourcePoint = gfx::IntPoint(visibleRect.X(), visibleRect.Y());
541
0
542
0
  gfx::Matrix4x4 transform = aContainer->GetEffectiveTransform();
543
0
  DebugOnly<gfx::Matrix> transform2d;
544
0
  MOZ_ASSERT(transform.Is2D(&transform2d) && !gfx::ThebesMatrix(transform2d).HasNonIntegerTranslation());
545
0
  sourcePoint += gfx::IntPoint::Truncate(transform._41, transform._42);
546
0
547
0
  sourcePoint -= compositor->GetCurrentRenderTarget()->GetOrigin();
548
0
549
0
  return compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget, sourcePoint);
550
0
}
Unexecuted instantiation: RefPtr<mozilla::layers::CompositingRenderTarget> mozilla::layers::CreateTemporaryTargetAndCopyFromBackground<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*)
Unexecuted instantiation: RefPtr<mozilla::layers::CompositingRenderTarget> mozilla::layers::CreateTemporaryTargetAndCopyFromBackground<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*)
551
552
template<class ContainerT> void
553
RenderIntermediate(ContainerT* aContainer,
554
                   LayerManagerComposite* aManager,
555
                   const gfx::IntRect& aClipRect,
556
                   RefPtr<CompositingRenderTarget> surface)
557
0
{
558
0
  Compositor* compositor = aManager->GetCompositor();
559
0
  RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
560
0
561
0
  if (!surface) {
562
0
    return;
563
0
  }
564
0
565
0
  compositor->SetRenderTarget(surface);
566
0
  // pre-render all of the layers into our temporary
567
0
  RenderLayers(aContainer, aManager,
568
0
               RenderTargetIntRect::FromUnknownRect(aClipRect),
569
0
               Nothing());
570
0
571
0
  // Unbind the current surface and rebind the previous one.
572
0
  compositor->SetRenderTarget(previousTarget);
573
0
}
Unexecuted instantiation: void mozilla::layers::RenderIntermediate<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, RefPtr<mozilla::layers::CompositingRenderTarget>)
Unexecuted instantiation: void mozilla::layers::RenderIntermediate<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, RefPtr<mozilla::layers::CompositingRenderTarget>)
574
575
template<class ContainerT> void
576
ContainerRender(ContainerT* aContainer,
577
                 LayerManagerComposite* aManager,
578
                 const gfx::IntRect& aClipRect,
579
                 const Maybe<gfx::Polygon>& aGeometry)
580
0
{
581
0
  MOZ_ASSERT(aContainer->mPrepared);
582
0
583
0
  if (aContainer->UseIntermediateSurface()) {
584
0
    RefPtr<CompositingRenderTarget> surface;
585
0
586
0
    if (aContainer->mPrepared->mNeedsSurfaceCopy) {
587
0
      // we needed to copy the background so we waited until now to render the intermediate
588
0
      surface = CreateTemporaryTargetAndCopyFromBackground(aContainer, aManager);
589
0
      RenderIntermediate(aContainer, aManager,
590
0
                         aClipRect, surface);
591
0
    } else {
592
0
      surface = aContainer->mPrepared->mTmpTarget;
593
0
    }
594
0
595
0
    if (!surface) {
596
0
      return;
597
0
    }
598
0
599
0
    gfx::Rect visibleRect(aContainer->GetLocalVisibleRegion().GetBounds().ToUnknownRect());
600
0
601
0
    RefPtr<Compositor> compositor = aManager->GetCompositor();
602
#ifdef MOZ_DUMP_PAINTING
603
    if (gfxEnv::DumpCompositorTextures()) {
604
      RefPtr<gfx::DataSourceSurface> surf = surface->Dump(compositor);
605
      if (surf) {
606
        WriteSnapshotToDumpFile(aContainer, surf);
607
      }
608
    }
609
#endif
610
611
0
    RefPtr<ContainerT> container = aContainer;
612
0
    RenderWithAllMasks(aContainer, compositor, aClipRect,
613
0
                       [&, surface, compositor, container](EffectChain& effectChain, const IntRect& clipRect) {
614
0
      effectChain.mPrimaryEffect = new EffectRenderTarget(surface);
615
0
616
0
      compositor->DrawGeometry(visibleRect, clipRect, effectChain,
617
0
                               container->GetEffectiveOpacity(),
618
0
                               container->GetEffectiveTransform(), aGeometry);
619
0
    });
Unexecuted instantiation: void mozilla::layers::ContainerRender<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::{lambda(mozilla::layers::EffectChain&, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&)#1}::operator()(mozilla::layers::EffectChain&, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&) const
Unexecuted instantiation: void mozilla::layers::ContainerRender<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::{lambda(mozilla::layers::EffectChain&, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&)#1}::operator()(mozilla::layers::EffectChain&, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&) const
620
0
621
0
  } else {
622
0
    RenderLayers(aContainer, aManager,
623
0
                 RenderTargetIntRect::FromUnknownRect(aClipRect),
624
0
                 aGeometry);
625
0
  }
626
0
627
0
  // If it is a scrollable container layer with no child layers, and one of the APZCs
628
0
  // attached to it has a nonempty async transform, then that transform is not applied
629
0
  // to any visible content. Display a warning box (conditioned on the FPS display being
630
0
  // enabled).
631
0
  if (gfxPrefs::LayersDrawFPS() && aContainer->IsScrollableWithoutContent()) {
632
0
    RefPtr<APZSampler> sampler = aManager->GetCompositor()->GetCompositorBridgeParent()->GetAPZSampler();
633
0
    // Since aContainer doesn't have any children we can just iterate from the top metrics
634
0
    // on it down to the bottom using GetFirstChild and not worry about walking onto another
635
0
    // underlying layer.
636
0
    for (LayerMetricsWrapper i(aContainer); i; i = i.GetFirstChild()) {
637
0
      if (sampler->HasUnusedAsyncTransform(i)) {
638
0
        aManager->UnusedApzTransformWarning();
639
0
        break;
640
0
      }
641
0
    }
642
0
  }
643
0
}
Unexecuted instantiation: void mozilla::layers::ContainerRender<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)
Unexecuted instantiation: void mozilla::layers::ContainerRender<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)
644
645
ContainerLayerComposite::ContainerLayerComposite(LayerManagerComposite *aManager)
646
  : ContainerLayer(aManager, nullptr)
647
  , LayerComposite(aManager)
648
0
{
649
0
  MOZ_COUNT_CTOR(ContainerLayerComposite);
650
0
  mImplData = static_cast<LayerComposite*>(this);
651
0
}
652
653
ContainerLayerComposite::~ContainerLayerComposite()
654
0
{
655
0
  MOZ_COUNT_DTOR(ContainerLayerComposite);
656
0
657
0
  // We don't Destroy() on destruction here because this destructor
658
0
  // can be called after remote content has crashed, and it may not be
659
0
  // safe to free the IPC resources of our children.  Those resources
660
0
  // are automatically cleaned up by IPDL-generated code.
661
0
  //
662
0
  // In the common case of normal shutdown, either
663
0
  // LayerManagerComposite::Destroy(), a parent
664
0
  // *ContainerLayerComposite::Destroy(), or Disconnect() will trigger
665
0
  // cleanup of our resources.
666
0
  RemoveAllChildren();
667
0
}
668
669
void
670
ContainerLayerComposite::Destroy()
671
0
{
672
0
  if (!mDestroyed) {
673
0
    while (mFirstChild) {
674
0
      GetFirstChildComposite()->Destroy();
675
0
      RemoveChild(mFirstChild);
676
0
    }
677
0
    mDestroyed = true;
678
0
  }
679
0
}
680
681
LayerComposite*
682
ContainerLayerComposite::GetFirstChildComposite()
683
0
{
684
0
  if (!mFirstChild) {
685
0
    return nullptr;
686
0
   }
687
0
  return static_cast<LayerComposite*>(mFirstChild->AsHostLayer());
688
0
}
689
690
void
691
ContainerLayerComposite::Cleanup()
692
0
{
693
0
  mPrepared = nullptr;
694
0
695
0
  for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
696
0
    static_cast<LayerComposite*>(l->AsHostLayer())->Cleanup();
697
0
  }
698
0
}
699
700
void
701
ContainerLayerComposite::RenderLayer(const gfx::IntRect& aClipRect,
702
                                     const Maybe<gfx::Polygon>& aGeometry)
703
0
{
704
0
  ContainerRender(this, mCompositeManager, aClipRect, aGeometry);
705
0
}
706
707
void
708
ContainerLayerComposite::Prepare(const RenderTargetIntRect& aClipRect)
709
0
{
710
0
  ContainerPrepare(this, mCompositeManager, aClipRect);
711
0
}
712
713
void
714
ContainerLayerComposite::CleanupResources()
715
0
{
716
0
  mLastIntermediateSurface = nullptr;
717
0
  mPrepared = nullptr;
718
0
719
0
  for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
720
0
    static_cast<LayerComposite*>(l->AsHostLayer())->CleanupResources();
721
0
  }
722
0
}
723
724
const LayerIntRegion&
725
ContainerLayerComposite::GetShadowVisibleRegion()
726
0
{
727
0
  if (!UseIntermediateSurface()) {
728
0
    RecomputeShadowVisibleRegionFromChildren();
729
0
  }
730
0
731
0
  return mShadowVisibleRegion;
732
0
}
733
734
const LayerIntRegion&
735
RefLayerComposite::GetShadowVisibleRegion()
736
0
{
737
0
  if (!UseIntermediateSurface()) {
738
0
    RecomputeShadowVisibleRegionFromChildren();
739
0
  }
740
0
741
0
  return mShadowVisibleRegion;
742
0
}
743
744
RefLayerComposite::RefLayerComposite(LayerManagerComposite* aManager)
745
  : RefLayer(aManager, nullptr)
746
  , LayerComposite(aManager)
747
0
{
748
0
  mImplData = static_cast<LayerComposite*>(this);
749
0
}
750
751
RefLayerComposite::~RefLayerComposite()
752
0
{
753
0
  Destroy();
754
0
}
755
756
void
757
RefLayerComposite::Destroy()
758
0
{
759
0
  MOZ_ASSERT(!mFirstChild);
760
0
  mDestroyed = true;
761
0
}
762
763
LayerComposite*
764
RefLayerComposite::GetFirstChildComposite()
765
0
{
766
0
  if (!mFirstChild) {
767
0
    return nullptr;
768
0
   }
769
0
  return static_cast<LayerComposite*>(mFirstChild->AsHostLayer());
770
0
}
771
772
void
773
RefLayerComposite::RenderLayer(const gfx::IntRect& aClipRect,
774
                               const Maybe<gfx::Polygon>& aGeometry)
775
0
{
776
0
  ContainerRender(this, mCompositeManager, aClipRect, aGeometry);
777
0
}
778
779
void
780
RefLayerComposite::Prepare(const RenderTargetIntRect& aClipRect)
781
0
{
782
0
  ContainerPrepare(this, mCompositeManager, aClipRect);
783
0
}
784
785
void
786
RefLayerComposite::Cleanup()
787
0
{
788
0
  mPrepared = nullptr;
789
0
790
0
  for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
791
0
    static_cast<LayerComposite*>(l->AsHostLayer())->Cleanup();
792
0
  }
793
0
}
794
795
void
796
RefLayerComposite::CleanupResources()
797
0
{
798
0
  mLastIntermediateSurface = nullptr;
799
0
  mPrepared = nullptr;
800
0
}
801
802
} // namespace layers
803
} // namespace mozilla