Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/Layers.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 "Layers.h"
8
#include <algorithm>                    // for max, min
9
#include "apz/src/AsyncPanZoomController.h"
10
#include "CompositableHost.h"           // for CompositableHost
11
#include "ImageContainer.h"             // for ImageContainer, etc
12
#include "ImageLayers.h"                // for ImageLayer
13
#include "LayerSorter.h"                // for SortLayersBy3DZOrder
14
#include "LayersLogging.h"              // for AppendToString
15
#include "LayerUserData.h"
16
#include "ReadbackLayer.h"              // for ReadbackLayer
17
#include "UnitTransforms.h"             // for ViewAs
18
#include "gfxEnv.h"
19
#include "gfxPlatform.h"                // for gfxPlatform
20
#include "gfxPrefs.h"
21
#include "gfxUtils.h"                   // for gfxUtils, etc
22
#include "gfx2DGlue.h"
23
#include "mozilla/DebugOnly.h"          // for DebugOnly
24
#include "mozilla/IntegerPrintfMacros.h"
25
#include "mozilla/Telemetry.h"          // for Accumulate
26
#include "mozilla/ToString.h"
27
#include "mozilla/gfx/2D.h"             // for DrawTarget
28
#include "mozilla/gfx/BaseSize.h"       // for BaseSize
29
#include "mozilla/gfx/Matrix.h"         // for Matrix4x4
30
#include "mozilla/gfx/Polygon.h"        // for Polygon
31
#include "mozilla/layers/AsyncCanvasRenderer.h"
32
#include "mozilla/layers/BSPTree.h"     // for BSPTree
33
#include "mozilla/layers/CompositableClient.h"  // for CompositableClient
34
#include "mozilla/layers/Compositor.h"  // for Compositor
35
#include "mozilla/layers/CompositorTypes.h"
36
#include "mozilla/layers/LayerManagerComposite.h"  // for LayerComposite
37
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
38
#include "mozilla/layers/LayersMessages.h"  // for TransformFunction, etc
39
#include "mozilla/layers/LayersTypes.h"  // for TextureDumpMode
40
#include "mozilla/layers/PersistentBufferProvider.h"
41
#include "mozilla/layers/ShadowLayers.h"  // for ShadowableLayer
42
#include "nsAString.h"
43
#include "nsCSSValue.h"                 // for nsCSSValue::Array, etc
44
#include "nsDisplayList.h"              // for nsDisplayItem
45
#include "nsPrintfCString.h"            // for nsPrintfCString
46
#include "protobuf/LayerScopePacket.pb.h"
47
#include "mozilla/Compression.h"
48
#include "TreeTraversal.h"              // for ForEachNode
49
50
#include <list>
51
#include <set>
52
53
uint8_t gLayerManagerLayerBuilder;
54
55
namespace mozilla {
56
namespace layers {
57
58
FILE*
59
FILEOrDefault(FILE* aFile)
60
0
{
61
0
  return aFile ? aFile : stderr;
62
0
}
63
64
typedef FrameMetrics::ViewID ViewID;
65
66
using namespace mozilla::gfx;
67
using namespace mozilla::Compression;
68
69
//--------------------------------------------------
70
// LayerManager
71
72
/* static */ mozilla::LogModule*
73
LayerManager::GetLog()
74
0
{
75
0
  static LazyLogModule sLog("Layers");
76
0
  return sLog;
77
0
}
78
79
FrameMetrics::ViewID
80
LayerManager::GetRootScrollableLayerId()
81
0
{
82
0
  if (!mRoot) {
83
0
    return FrameMetrics::NULL_SCROLL_ID;
84
0
  }
85
0
86
0
  LayerMetricsWrapper layerMetricsRoot = LayerMetricsWrapper(mRoot);
87
0
88
0
  LayerMetricsWrapper rootScrollableLayerMetrics =
89
0
      BreadthFirstSearch<ForwardIterator>(
90
0
          layerMetricsRoot,
91
0
          [](LayerMetricsWrapper aLayerMetrics)
92
0
          {
93
0
            return aLayerMetrics.Metrics().IsScrollable();
94
0
          }
95
0
      );
96
0
97
0
  return rootScrollableLayerMetrics.IsValid() ?
98
0
      rootScrollableLayerMetrics.Metrics().GetScrollId() :
99
0
      FrameMetrics::NULL_SCROLL_ID;
100
0
}
101
102
LayerMetricsWrapper
103
LayerManager::GetRootContentLayer()
104
0
{
105
0
  if (!mRoot) {
106
0
    return LayerMetricsWrapper();
107
0
  }
108
0
109
0
  LayerMetricsWrapper root(mRoot);
110
0
111
0
  return BreadthFirstSearch<ForwardIterator>(root,
112
0
      [](LayerMetricsWrapper aLayerMetrics)
113
0
      {
114
0
        return aLayerMetrics.Metrics().IsRootContent();
115
0
      }
116
0
  );
117
0
}
118
119
already_AddRefed<DrawTarget>
120
LayerManager::CreateOptimalDrawTarget(const gfx::IntSize &aSize,
121
                                      SurfaceFormat aFormat)
122
0
{
123
0
  return gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(aSize,
124
0
                                                                      aFormat);
125
0
}
126
127
already_AddRefed<DrawTarget>
128
LayerManager::CreateOptimalMaskDrawTarget(const gfx::IntSize &aSize)
129
0
{
130
0
  return CreateOptimalDrawTarget(aSize, SurfaceFormat::A8);
131
0
}
132
133
already_AddRefed<DrawTarget>
134
LayerManager::CreateDrawTarget(const IntSize &aSize,
135
                               SurfaceFormat aFormat)
136
0
{
137
0
  return gfxPlatform::GetPlatform()->
138
0
    CreateOffscreenCanvasDrawTarget(aSize, aFormat);
139
0
}
140
141
already_AddRefed<PersistentBufferProvider>
142
LayerManager::CreatePersistentBufferProvider(const mozilla::gfx::IntSize &aSize,
143
                                             mozilla::gfx::SurfaceFormat aFormat)
144
0
{
145
0
  RefPtr<PersistentBufferProviderBasic> bufferProvider =
146
0
    PersistentBufferProviderBasic::Create(aSize, aFormat,
147
0
      gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
148
0
149
0
  if (!bufferProvider) {
150
0
    bufferProvider = PersistentBufferProviderBasic::Create(aSize, aFormat,
151
0
      gfxPlatform::GetPlatform()->GetFallbackCanvasBackend());
152
0
  }
153
0
154
0
  return bufferProvider.forget();
155
0
}
156
157
already_AddRefed<ImageContainer>
158
LayerManager::CreateImageContainer(ImageContainer::Mode flag)
159
0
{
160
0
  RefPtr<ImageContainer> container = new ImageContainer(flag);
161
0
  return container.forget();
162
0
}
163
164
bool
165
LayerManager::AreComponentAlphaLayersEnabled()
166
0
{
167
0
  return gfxPrefs::ComponentAlphaEnabled();
168
0
}
169
170
/*static*/ void
171
LayerManager::LayerUserDataDestroy(void* data)
172
0
{
173
0
  delete static_cast<LayerUserData*>(data);
174
0
}
175
176
UniquePtr<LayerUserData>
177
LayerManager::RemoveUserData(void* aKey)
178
0
{
179
0
  UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
180
0
  return d;
181
0
}
182
183
//--------------------------------------------------
184
// Layer
185
186
Layer::Layer(LayerManager* aManager, void* aImplData)
187
  : mManager(aManager)
188
  , mParent(nullptr)
189
  , mNextSibling(nullptr)
190
  , mPrevSibling(nullptr)
191
  , mImplData(aImplData)
192
  , mAnimationInfo(aManager)
193
  , mUseTileSourceRect(false)
194
#ifdef DEBUG
195
  , mDebugColorIndex(0)
196
#endif
197
0
{
198
0
}
199
200
Layer::~Layer()
201
0
{
202
0
}
203
204
void
205
Layer::SetCompositorAnimations(const CompositorAnimations& aCompositorAnimations)
206
0
{
207
0
  MOZ_LAYERS_LOG_IF_SHADOWABLE(
208
0
    this, ("Layer::Mutated(%p) SetCompositorAnimations with id=%" PRIu64, this, mAnimationInfo.GetCompositorAnimationsId()));
209
0
210
0
  mAnimationInfo.SetCompositorAnimations(aCompositorAnimations);
211
0
212
0
  Mutated();
213
0
}
214
215
void
216
Layer::ClearCompositorAnimations()
217
0
{
218
0
  MOZ_LAYERS_LOG_IF_SHADOWABLE(
219
0
    this, ("Layer::Mutated(%p) ClearCompositorAnimations with id=%" PRIu64, this, mAnimationInfo.GetCompositorAnimationsId()));
220
0
221
0
  mAnimationInfo.ClearAnimations();
222
0
223
0
  Mutated();
224
0
}
225
226
void
227
Layer::StartPendingAnimations(const TimeStamp& aReadyTime)
228
0
{
229
0
  ForEachNode<ForwardIterator>(
230
0
      this,
231
0
      [&aReadyTime](Layer *layer)
232
0
      {
233
0
        if (layer->mAnimationInfo.StartPendingAnimations(aReadyTime)) {
234
0
          layer->Mutated();
235
0
        }
236
0
      });
237
0
}
238
239
void
240
Layer::SetAsyncPanZoomController(uint32_t aIndex, AsyncPanZoomController *controller)
241
0
{
242
0
  MOZ_ASSERT(aIndex < GetScrollMetadataCount());
243
0
  // We should never be setting an APZC on a non-scrollable layer
244
0
  MOZ_ASSERT(!controller || GetFrameMetrics(aIndex).IsScrollable());
245
0
  mApzcs[aIndex] = controller;
246
0
}
247
248
AsyncPanZoomController*
249
Layer::GetAsyncPanZoomController(uint32_t aIndex) const
250
0
{
251
0
  MOZ_ASSERT(aIndex < GetScrollMetadataCount());
252
#ifdef DEBUG
253
  if (mApzcs[aIndex]) {
254
    MOZ_ASSERT(GetFrameMetrics(aIndex).IsScrollable());
255
  }
256
#endif
257
  return mApzcs[aIndex];
258
0
}
259
260
void
261
Layer::ScrollMetadataChanged()
262
0
{
263
0
  mApzcs.SetLength(GetScrollMetadataCount());
264
0
}
265
266
void
267
Layer::ApplyPendingUpdatesToSubtree()
268
0
{
269
0
  ForEachNode<ForwardIterator>(
270
0
      this,
271
0
      [] (Layer *layer)
272
0
      {
273
0
        layer->ApplyPendingUpdatesForThisTransaction();
274
0
      });
275
0
276
0
  // Once we're done recursing through the whole tree, clear the pending
277
0
  // updates from the manager.
278
0
  Manager()->ClearPendingScrollInfoUpdate();
279
0
}
280
281
bool
282
Layer::IsOpaqueForVisibility()
283
0
{
284
0
  return GetEffectiveOpacity() == 1.0f &&
285
0
         GetEffectiveMixBlendMode() == CompositionOp::OP_OVER;
286
0
}
287
288
bool
289
Layer::CanUseOpaqueSurface()
290
0
{
291
0
  // If the visible content in the layer is opaque, there is no need
292
0
  // for an alpha channel.
293
0
  if (GetContentFlags() & CONTENT_OPAQUE)
294
0
    return true;
295
0
  // Also, if this layer is the bottommost layer in a container which
296
0
  // doesn't need an alpha channel, we can use an opaque surface for this
297
0
  // layer too. Any transparent areas must be covered by something else
298
0
  // in the container.
299
0
  ContainerLayer* parent = GetParent();
300
0
  return parent && parent->GetFirstChild() == this &&
301
0
    parent->CanUseOpaqueSurface();
302
0
}
303
304
// NB: eventually these methods will be defined unconditionally, and
305
// can be moved into Layers.h
306
const Maybe<ParentLayerIntRect>&
307
Layer::GetLocalClipRect()
308
0
{
309
0
  if (HostLayer* shadow = AsHostLayer()) {
310
0
    return shadow->GetShadowClipRect();
311
0
  }
312
0
  return GetClipRect();
313
0
}
314
315
const LayerIntRegion&
316
Layer::GetLocalVisibleRegion()
317
0
{
318
0
  if (HostLayer* shadow = AsHostLayer()) {
319
0
    return shadow->GetShadowVisibleRegion();
320
0
  }
321
0
  return GetVisibleRegion();
322
0
}
323
324
Matrix4x4
325
Layer::SnapTransformTranslation(const Matrix4x4& aTransform,
326
                                Matrix* aResidualTransform)
327
0
{
328
0
  if (aResidualTransform) {
329
0
    *aResidualTransform = Matrix();
330
0
  }
331
0
332
0
  if (!mManager->IsSnappingEffectiveTransforms()) {
333
0
    return aTransform;
334
0
  }
335
0
336
0
  Matrix matrix2D;
337
0
  if (aTransform.CanDraw2D(&matrix2D) &&
338
0
      !matrix2D.HasNonTranslation() &&
339
0
      matrix2D.HasNonIntegerTranslation()) {
340
0
    auto snappedTranslation = IntPoint::Round(matrix2D.GetTranslation());
341
0
    Matrix snappedMatrix = Matrix::Translation(snappedTranslation.x,
342
0
                                               snappedTranslation.y);
343
0
    Matrix4x4 result = Matrix4x4::From2D(snappedMatrix);
344
0
    if (aResidualTransform) {
345
0
      // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
346
0
      // (I.e., appying snappedMatrix after aResidualTransform gives the
347
0
      // ideal transform.)
348
0
      *aResidualTransform =
349
0
        Matrix::Translation(matrix2D._31 - snappedTranslation.x,
350
0
                            matrix2D._32 - snappedTranslation.y);
351
0
    }
352
0
    return result;
353
0
  }
354
0
355
0
  return SnapTransformTranslation3D(aTransform, aResidualTransform);
356
0
}
357
358
Matrix4x4
359
Layer::SnapTransformTranslation3D(const Matrix4x4& aTransform,
360
                                  Matrix* aResidualTransform)
361
0
{
362
0
  if(aTransform.IsSingular() ||
363
0
     aTransform.HasPerspectiveComponent() ||
364
0
     aTransform.HasNonTranslation() ||
365
0
     !aTransform.HasNonIntegerTranslation()) {
366
0
    // For a singular transform, there is no reversed matrix, so we
367
0
    // don't snap it.
368
0
    // For a perspective transform, the content is transformed in
369
0
    // non-linear, so we don't snap it too.
370
0
    return aTransform;
371
0
  }
372
0
373
0
  // Snap for 3D Transforms
374
0
375
0
  Point3D transformedOrigin = aTransform.TransformPoint(Point3D());
376
0
377
0
  // Compute the transformed snap by rounding the values of
378
0
  // transformed origin.
379
0
  auto transformedSnapXY = IntPoint::Round(transformedOrigin.x, transformedOrigin.y);
380
0
  Matrix4x4 inverse = aTransform;
381
0
  inverse.Invert();
382
0
  // see Matrix4x4::ProjectPoint()
383
0
  Float transformedSnapZ =
384
0
    inverse._33 == 0 ? 0 : (-(transformedSnapXY.x * inverse._13 +
385
0
                              transformedSnapXY.y * inverse._23 +
386
0
                              inverse._43) / inverse._33);
387
0
  Point3D transformedSnap =
388
0
    Point3D(transformedSnapXY.x, transformedSnapXY.y, transformedSnapZ);
389
0
  if (transformedOrigin == transformedSnap) {
390
0
    return aTransform;
391
0
  }
392
0
393
0
  // Compute the snap from the transformed snap.
394
0
  Point3D snap = inverse.TransformPoint(transformedSnap);
395
0
  if (snap.z > 0.001 || snap.z < -0.001) {
396
0
    // Allow some level of accumulated computation error.
397
0
    MOZ_ASSERT(inverse._33 == 0.0);
398
0
    return aTransform;
399
0
  }
400
0
401
0
  // The difference between the origin and snap is the residual transform.
402
0
  if (aResidualTransform) {
403
0
    // The residual transform is to translate the snap to the origin
404
0
    // of the content buffer.
405
0
    *aResidualTransform = Matrix::Translation(-snap.x, -snap.y);
406
0
  }
407
0
408
0
  // Translate transformed origin to transformed snap since the
409
0
  // residual transform would trnslate the snap to the origin.
410
0
  Point3D transformedShift = transformedSnap - transformedOrigin;
411
0
  Matrix4x4 result = aTransform;
412
0
  result.PostTranslate(transformedShift.x,
413
0
                       transformedShift.y,
414
0
                       transformedShift.z);
415
0
416
0
  // For non-2d transform, residual translation could be more than
417
0
  // 0.5 pixels for every axis.
418
0
419
0
  return result;
420
0
}
421
422
Matrix4x4
423
Layer::SnapTransform(const Matrix4x4& aTransform,
424
                     const gfxRect& aSnapRect,
425
                     Matrix* aResidualTransform)
426
0
{
427
0
  if (aResidualTransform) {
428
0
    *aResidualTransform = Matrix();
429
0
  }
430
0
431
0
  Matrix matrix2D;
432
0
  Matrix4x4 result;
433
0
  if (mManager->IsSnappingEffectiveTransforms() &&
434
0
      aTransform.Is2D(&matrix2D) &&
435
0
      gfxSize(1.0, 1.0) <= aSnapRect.Size() &&
436
0
      matrix2D.PreservesAxisAlignedRectangles()) {
437
0
    auto transformedTopLeft = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.TopLeft())));
438
0
    auto transformedTopRight = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.TopRight())));
439
0
    auto transformedBottomRight = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.BottomRight())));
440
0
441
0
    Matrix snappedMatrix = gfxUtils::TransformRectToRect(aSnapRect,
442
0
      transformedTopLeft, transformedTopRight, transformedBottomRight);
443
0
444
0
    result = Matrix4x4::From2D(snappedMatrix);
445
0
    if (aResidualTransform && !snappedMatrix.IsSingular()) {
446
0
      // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
447
0
      // (i.e., appying snappedMatrix after aResidualTransform gives the
448
0
      // ideal transform.
449
0
      Matrix snappedMatrixInverse = snappedMatrix;
450
0
      snappedMatrixInverse.Invert();
451
0
      *aResidualTransform = matrix2D * snappedMatrixInverse;
452
0
    }
453
0
  } else {
454
0
    result = aTransform;
455
0
  }
456
0
  return result;
457
0
}
458
459
static bool
460
AncestorLayerMayChangeTransform(Layer* aLayer)
461
0
{
462
0
  for (Layer* l = aLayer; l; l = l->GetParent()) {
463
0
    if (l->GetContentFlags() & Layer::CONTENT_MAY_CHANGE_TRANSFORM) {
464
0
      return true;
465
0
    }
466
0
467
0
    if (l->GetParent() && l->GetParent()->AsRefLayer()) {
468
0
      return false;
469
0
    }
470
0
  }
471
0
  return false;
472
0
}
473
474
bool
475
Layer::MayResample()
476
0
{
477
0
  Matrix transform2d;
478
0
  return !GetEffectiveTransform().Is2D(&transform2d) ||
479
0
         ThebesMatrix(transform2d).HasNonIntegerTranslation() ||
480
0
         AncestorLayerMayChangeTransform(this);
481
0
}
482
483
RenderTargetIntRect
484
Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect)
485
0
{
486
0
  ContainerLayer* container = GetParent();
487
0
  ContainerLayer* containerChild = nullptr;
488
0
  NS_ASSERTION(GetParent(), "This can't be called on the root!");
489
0
490
0
  // Find the layer creating the 3D context.
491
0
  while (container->Extend3DContext() &&
492
0
         !container->UseIntermediateSurface()) {
493
0
    containerChild = container;
494
0
    container = container->GetParent();
495
0
    MOZ_ASSERT(container);
496
0
  }
497
0
498
0
  // Find the nearest layer with a clip, or this layer.
499
0
  // ContainerState::SetupScrollingMetadata() may install a clip on
500
0
  // the layer.
501
0
  Layer *clipLayer =
502
0
    containerChild && containerChild->GetLocalClipRect() ?
503
0
    containerChild : this;
504
0
505
0
  // Establish initial clip rect: it's either the one passed in, or
506
0
  // if the parent has an intermediate surface, it's the extents of that surface.
507
0
  RenderTargetIntRect currentClip;
508
0
  if (container->UseIntermediateSurface()) {
509
0
    currentClip.SizeTo(container->GetIntermediateSurfaceRect().Size());
510
0
  } else {
511
0
    currentClip = aCurrentScissorRect;
512
0
  }
513
0
514
0
  if (!clipLayer->GetLocalClipRect()) {
515
0
    return currentClip;
516
0
  }
517
0
518
0
  if (GetLocalVisibleRegion().IsEmpty()) {
519
0
    // When our visible region is empty, our parent may not have created the
520
0
    // intermediate surface that we would require for correct clipping; however,
521
0
    // this does not matter since we are invisible.
522
0
    // Make sure we still compute a clip rect if we want to draw checkboarding
523
0
    // for this layer, since we want to do this even if the layer is invisible.
524
0
    return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
525
0
  }
526
0
527
0
  const RenderTargetIntRect clipRect =
528
0
    ViewAs<RenderTargetPixel>(*clipLayer->GetLocalClipRect(),
529
0
                              PixelCastJustification::RenderTargetIsParentLayerForRoot);
530
0
  if (clipRect.IsEmpty()) {
531
0
    // We might have a non-translation transform in the container so we can't
532
0
    // use the code path below.
533
0
    return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
534
0
  }
535
0
536
0
  RenderTargetIntRect scissor = clipRect;
537
0
  if (!container->UseIntermediateSurface()) {
538
0
    gfx::Matrix matrix;
539
0
    DebugOnly<bool> is2D = container->GetEffectiveTransform().Is2D(&matrix);
540
0
    // See DefaultComputeEffectiveTransforms below
541
0
    NS_ASSERTION(is2D && matrix.PreservesAxisAlignedRectangles(),
542
0
                 "Non preserves axis aligned transform with clipped child should have forced intermediate surface");
543
0
    gfx::Rect r(scissor.X(), scissor.Y(), scissor.Width(), scissor.Height());
544
0
    gfxRect trScissor = gfx::ThebesRect(matrix.TransformBounds(r));
545
0
    trScissor.Round();
546
0
    IntRect tmp;
547
0
    if (!gfxUtils::GfxRectToIntRect(trScissor, &tmp)) {
548
0
      return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
549
0
    }
550
0
    scissor = ViewAs<RenderTargetPixel>(tmp);
551
0
552
0
    // Find the nearest ancestor with an intermediate surface
553
0
    do {
554
0
      container = container->GetParent();
555
0
    } while (container && !container->UseIntermediateSurface());
556
0
  }
557
0
558
0
  if (container) {
559
0
    scissor.MoveBy(-container->GetIntermediateSurfaceRect().TopLeft());
560
0
  }
561
0
  return currentClip.Intersect(scissor);
562
0
}
563
564
Maybe<ParentLayerIntRect>
565
Layer::GetScrolledClipRect() const
566
0
{
567
0
  const Maybe<LayerClip> clip = mSimpleAttrs.GetScrolledClip();
568
0
  return clip ? Some(clip->GetClipRect()) : Nothing();
569
0
}
570
571
const ScrollMetadata&
572
Layer::GetScrollMetadata(uint32_t aIndex) const
573
0
{
574
0
  MOZ_ASSERT(aIndex < GetScrollMetadataCount());
575
0
  return mScrollMetadata[aIndex];
576
0
}
577
578
const FrameMetrics&
579
Layer::GetFrameMetrics(uint32_t aIndex) const
580
0
{
581
0
  return GetScrollMetadata(aIndex).GetMetrics();
582
0
}
583
584
bool
585
Layer::HasScrollableFrameMetrics() const
586
0
{
587
0
  for (uint32_t i = 0; i < GetScrollMetadataCount(); i++) {
588
0
    if (GetFrameMetrics(i).IsScrollable()) {
589
0
      return true;
590
0
    }
591
0
  }
592
0
  return false;
593
0
}
594
595
bool
596
Layer::HasRootScrollableFrameMetrics() const
597
0
{
598
0
  for (uint32_t i = 0; i < GetScrollMetadataCount(); i++) {
599
0
    if (GetFrameMetrics(i).IsScrollable() && GetFrameMetrics(i).IsRootContent()) {
600
0
      return true;
601
0
    }
602
0
  }
603
0
  return false;
604
0
}
605
606
bool
607
Layer::IsScrollableWithoutContent() const
608
0
{
609
0
  // A scrollable container layer with no children
610
0
  return AsContainerLayer()
611
0
      && HasScrollableFrameMetrics()
612
0
      && !GetFirstChild();
613
0
}
614
615
Matrix4x4
616
Layer::GetTransform() const
617
0
{
618
0
  Matrix4x4 transform = mSimpleAttrs.GetTransform();
619
0
  transform.PostScale(GetPostXScale(), GetPostYScale(), 1.0f);
620
0
  if (const ContainerLayer* c = AsContainerLayer()) {
621
0
    transform.PreScale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
622
0
  }
623
0
  return transform;
624
0
}
625
626
const CSSTransformMatrix
627
Layer::GetTransformTyped() const
628
0
{
629
0
  return ViewAs<CSSTransformMatrix>(GetTransform());
630
0
}
631
632
Matrix4x4
633
Layer::GetLocalTransform()
634
0
{
635
0
  if (HostLayer* shadow = AsHostLayer()) {
636
0
    return shadow->GetShadowTransform();
637
0
  }
638
0
  return GetTransform();
639
0
}
640
641
const LayerToParentLayerMatrix4x4
642
Layer::GetLocalTransformTyped()
643
0
{
644
0
  return ViewAs<LayerToParentLayerMatrix4x4>(GetLocalTransform());
645
0
}
646
647
bool
648
Layer::IsScrollbarContainer() const
649
0
{
650
0
  const ScrollbarData& data = GetScrollbarData();
651
0
  return (data.mScrollbarLayerType == ScrollbarLayerType::Container)
652
0
      ? data.mDirection.isSome()
653
0
      : false;
654
0
}
655
656
bool
657
Layer::HasTransformAnimation() const
658
0
{
659
0
  return mAnimationInfo.HasTransformAnimation();
660
0
}
661
662
void
663
Layer::ApplyPendingUpdatesForThisTransaction()
664
0
{
665
0
  if (mPendingTransform && *mPendingTransform != mSimpleAttrs.GetTransform()) {
666
0
    MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
667
0
    mSimpleAttrs.SetTransform(*mPendingTransform);
668
0
    MutatedSimple();
669
0
  }
670
0
  mPendingTransform = nullptr;
671
0
672
0
  if (mAnimationInfo.ApplyPendingUpdatesForThisTransaction()) {
673
0
    MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
674
0
    Mutated();
675
0
  }
676
0
677
0
  for (size_t i = 0; i < mScrollMetadata.Length(); i++) {
678
0
    FrameMetrics& fm = mScrollMetadata[i].GetMetrics();
679
0
    Maybe<ScrollUpdateInfo> update = Manager()->GetPendingScrollInfoUpdate(fm.GetScrollId());
680
0
    if (update) {
681
0
      fm.UpdatePendingScrollInfo(update.value());
682
0
      Mutated();
683
0
    }
684
0
  }
685
0
}
686
687
float
688
Layer::GetLocalOpacity()
689
0
{
690
0
  float opacity = mSimpleAttrs.GetOpacity();
691
0
  if (HostLayer* shadow = AsHostLayer())
692
0
    opacity = shadow->GetShadowOpacity();
693
0
  return std::min(std::max(opacity, 0.0f), 1.0f);
694
0
}
695
696
float
697
Layer::GetEffectiveOpacity()
698
0
{
699
0
  float opacity = GetLocalOpacity();
700
0
  for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
701
0
       c = c->GetParent()) {
702
0
    opacity *= c->GetLocalOpacity();
703
0
  }
704
0
  return opacity;
705
0
}
706
707
CompositionOp
708
Layer::GetEffectiveMixBlendMode()
709
0
{
710
0
  if (mSimpleAttrs.GetMixBlendMode() != CompositionOp::OP_OVER)
711
0
    return mSimpleAttrs.GetMixBlendMode();
712
0
  for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
713
0
    c = c->GetParent()) {
714
0
    if(c->mSimpleAttrs.GetMixBlendMode() != CompositionOp::OP_OVER)
715
0
      return c->mSimpleAttrs.GetMixBlendMode();
716
0
  }
717
0
718
0
  return mSimpleAttrs.GetMixBlendMode();
719
0
}
720
721
Matrix4x4
722
Layer::ComputeTransformToPreserve3DRoot()
723
0
{
724
0
  Matrix4x4 transform = GetLocalTransform();
725
0
  for (Layer* layer = GetParent();
726
0
       layer && layer->Extend3DContext();
727
0
       layer = layer->GetParent()) {
728
0
    transform = transform * layer->GetLocalTransform();
729
0
  }
730
0
  return transform;
731
0
}
732
733
void
734
Layer::ComputeEffectiveTransformForMaskLayers(const gfx::Matrix4x4& aTransformToSurface)
735
0
{
736
0
  if (GetMaskLayer()) {
737
0
    ComputeEffectiveTransformForMaskLayer(GetMaskLayer(), aTransformToSurface);
738
0
  }
739
0
  for (size_t i = 0; i < GetAncestorMaskLayerCount(); i++) {
740
0
    Layer* maskLayer = GetAncestorMaskLayerAt(i);
741
0
    ComputeEffectiveTransformForMaskLayer(maskLayer, aTransformToSurface);
742
0
  }
743
0
}
744
745
/* static */ void
746
Layer::ComputeEffectiveTransformForMaskLayer(Layer* aMaskLayer, const gfx::Matrix4x4& aTransformToSurface)
747
0
{
748
0
  aMaskLayer->mEffectiveTransform = aTransformToSurface;
749
0
750
#ifdef DEBUG
751
  bool maskIs2D = aMaskLayer->GetTransform().CanDraw2D();
752
  NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
753
#endif
754
  // The mask layer can have an async transform applied to it in some
755
0
  // situations, so be sure to use its GetLocalTransform() rather than
756
0
  // its GetTransform().
757
0
  aMaskLayer->mEffectiveTransform = aMaskLayer->GetLocalTransform() *
758
0
    aMaskLayer->mEffectiveTransform;
759
0
}
760
761
RenderTargetRect
762
Layer::TransformRectToRenderTarget(const LayerIntRect& aRect)
763
0
{
764
0
  LayerRect rect(aRect);
765
0
  RenderTargetRect quad = RenderTargetRect::FromUnknownRect(
766
0
    GetEffectiveTransform().TransformBounds(rect.ToUnknownRect()));
767
0
  return quad;
768
0
}
769
770
bool
771
Layer::GetVisibleRegionRelativeToRootLayer(nsIntRegion& aResult,
772
                                           IntPoint* aLayerOffset)
773
0
{
774
0
  MOZ_ASSERT(aLayerOffset, "invalid offset pointer");
775
0
776
0
  if (!GetParent()) {
777
0
    return false;
778
0
  }
779
0
780
0
  IntPoint offset;
781
0
  aResult = GetLocalVisibleRegion().ToUnknownRegion();
782
0
  for (Layer* layer = this; layer; layer = layer->GetParent()) {
783
0
    gfx::Matrix matrix;
784
0
    if (!layer->GetLocalTransform().Is2D(&matrix) ||
785
0
        !matrix.IsTranslation()) {
786
0
      return false;
787
0
    }
788
0
789
0
    // The offset of |layer| to its parent.
790
0
    auto currentLayerOffset = IntPoint::Round(matrix.GetTranslation());
791
0
792
0
    // Translate the accumulated visible region of |this| by the offset of
793
0
    // |layer|.
794
0
    aResult.MoveBy(currentLayerOffset.x, currentLayerOffset.y);
795
0
796
0
    // If the parent layer clips its lower layers, clip the visible region
797
0
    // we're accumulating.
798
0
    if (layer->GetLocalClipRect()) {
799
0
      aResult.AndWith(layer->GetLocalClipRect()->ToUnknownRect());
800
0
    }
801
0
802
0
    // Now we need to walk across the list of siblings for this parent layer,
803
0
    // checking to see if any of these layer trees obscure |this|. If so,
804
0
    // remove these areas from the visible region as well. This will pick up
805
0
    // chrome overlays like a tab modal prompt.
806
0
    Layer* sibling;
807
0
    for (sibling = layer->GetNextSibling(); sibling;
808
0
         sibling = sibling->GetNextSibling()) {
809
0
      gfx::Matrix siblingMatrix;
810
0
      if (!sibling->GetLocalTransform().Is2D(&siblingMatrix) ||
811
0
          !siblingMatrix.IsTranslation()) {
812
0
        continue;
813
0
      }
814
0
815
0
      // Retreive the translation from sibling to |layer|. The accumulated
816
0
      // visible region is currently oriented with |layer|.
817
0
      auto siblingOffset = IntPoint::Round(siblingMatrix.GetTranslation());
818
0
      nsIntRegion siblingVisibleRegion(sibling->GetLocalVisibleRegion().ToUnknownRegion());
819
0
      // Translate the siblings region to |layer|'s origin.
820
0
      siblingVisibleRegion.MoveBy(-siblingOffset.x, -siblingOffset.y);
821
0
      // Apply the sibling's clip.
822
0
      // Layer clip rects are not affected by the layer's transform.
823
0
      Maybe<ParentLayerIntRect> clipRect = sibling->GetLocalClipRect();
824
0
      if (clipRect) {
825
0
        siblingVisibleRegion.AndWith(clipRect->ToUnknownRect());
826
0
      }
827
0
      // Subtract the sibling visible region from the visible region of |this|.
828
0
      aResult.SubOut(siblingVisibleRegion);
829
0
    }
830
0
831
0
    // Keep track of the total offset for aLayerOffset.  We use this in plugin
832
0
    // positioning code.
833
0
    offset += currentLayerOffset;
834
0
  }
835
0
836
0
  *aLayerOffset = IntPoint(offset.x, offset.y);
837
0
  return true;
838
0
}
839
840
InfallibleTArray<AnimData>&
841
Layer::GetAnimationData()
842
0
{
843
0
  return mAnimationInfo.GetAnimationData();
844
0
}
845
846
Maybe<ParentLayerIntRect>
847
Layer::GetCombinedClipRect() const
848
0
{
849
0
  Maybe<ParentLayerIntRect> clip = GetClipRect();
850
0
851
0
  clip = IntersectMaybeRects(clip, GetScrolledClipRect());
852
0
853
0
  for (size_t i = 0; i < mScrollMetadata.Length(); i++) {
854
0
    clip = IntersectMaybeRects(clip, mScrollMetadata[i].GetClipRect());
855
0
  }
856
0
857
0
  return clip;
858
0
}
859
860
ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData)
861
  : Layer(aManager, aImplData),
862
    mFirstChild(nullptr),
863
    mLastChild(nullptr),
864
    mPreXScale(1.0f),
865
    mPreYScale(1.0f),
866
    mInheritedXScale(1.0f),
867
    mInheritedYScale(1.0f),
868
    mPresShellResolution(1.0f),
869
    mScaleToResolution(false),
870
    mUseIntermediateSurface(false),
871
    mSupportsComponentAlphaChildren(false),
872
    mMayHaveReadbackChild(false),
873
    mChildrenChanged(false)
874
0
{
875
0
}
876
877
ContainerLayer::~ContainerLayer()
878
{
879
}
880
881
bool
882
ContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
883
0
{
884
0
  if(aChild->Manager() != Manager()) {
885
0
    NS_ERROR("Child has wrong manager");
886
0
    return false;
887
0
  }
888
0
  if(aChild->GetParent()) {
889
0
    NS_ERROR("aChild already in the tree");
890
0
    return false;
891
0
  }
892
0
  if (aChild->GetNextSibling() || aChild->GetPrevSibling()) {
893
0
    NS_ERROR("aChild already has siblings?");
894
0
    return false;
895
0
  }
896
0
  if (aAfter && (aAfter->Manager() != Manager() ||
897
0
                 aAfter->GetParent() != this))
898
0
  {
899
0
    NS_ERROR("aAfter is not our child");
900
0
    return false;
901
0
  }
902
0
903
0
  aChild->SetParent(this);
904
0
  if (aAfter == mLastChild) {
905
0
    mLastChild = aChild;
906
0
  }
907
0
  if (!aAfter) {
908
0
    aChild->SetNextSibling(mFirstChild);
909
0
    if (mFirstChild) {
910
0
      mFirstChild->SetPrevSibling(aChild);
911
0
    }
912
0
    mFirstChild = aChild;
913
0
    NS_ADDREF(aChild);
914
0
    DidInsertChild(aChild);
915
0
    return true;
916
0
  }
917
0
918
0
  Layer* next = aAfter->GetNextSibling();
919
0
  aChild->SetNextSibling(next);
920
0
  aChild->SetPrevSibling(aAfter);
921
0
  if (next) {
922
0
    next->SetPrevSibling(aChild);
923
0
  }
924
0
  aAfter->SetNextSibling(aChild);
925
0
  NS_ADDREF(aChild);
926
0
  DidInsertChild(aChild);
927
0
  return true;
928
0
}
929
930
void
931
ContainerLayer::RemoveAllChildren()
932
0
{
933
0
  // Optimizes "while (mFirstChild) ContainerLayer::RemoveChild(mFirstChild);"
934
0
  Layer* current = mFirstChild;
935
0
936
0
  // This is inlining DidRemoveChild() on each layer; we can skip the calls
937
0
  // to NotifyPaintedLayerRemoved as it gets taken care of when as we call
938
0
  // NotifyRemoved prior to removing any layers.
939
0
  while (current) {
940
0
    Layer* next = current->GetNextSibling();
941
0
    if (current->GetType() == TYPE_READBACK) {
942
0
      static_cast<ReadbackLayer*>(current)->NotifyRemoved();
943
0
    }
944
0
    current = next;
945
0
  }
946
0
947
0
  current = mFirstChild;
948
0
  mFirstChild = nullptr;
949
0
  while (current) {
950
0
    MOZ_ASSERT(!current->GetPrevSibling());
951
0
952
0
    Layer* next = current->GetNextSibling();
953
0
    current->SetParent(nullptr);
954
0
    current->SetNextSibling(nullptr);
955
0
    if (next) {
956
0
      next->SetPrevSibling(nullptr);
957
0
    }
958
0
    NS_RELEASE(current);
959
0
    current = next;
960
0
  }
961
0
}
962
963
// Note that ContainerLayer::RemoveAllChildren is an optimized
964
// version of this code; if you make changes to ContainerLayer::RemoveChild
965
// consider whether the matching changes need to be made to
966
// ContainerLayer::RemoveAllChildren
967
bool
968
ContainerLayer::RemoveChild(Layer *aChild)
969
0
{
970
0
  if (aChild->Manager() != Manager()) {
971
0
    NS_ERROR("Child has wrong manager");
972
0
    return false;
973
0
  }
974
0
  if (aChild->GetParent() != this) {
975
0
    NS_ERROR("aChild not our child");
976
0
    return false;
977
0
  }
978
0
979
0
  Layer* prev = aChild->GetPrevSibling();
980
0
  Layer* next = aChild->GetNextSibling();
981
0
  if (prev) {
982
0
    prev->SetNextSibling(next);
983
0
  } else {
984
0
    this->mFirstChild = next;
985
0
  }
986
0
  if (next) {
987
0
    next->SetPrevSibling(prev);
988
0
  } else {
989
0
    this->mLastChild = prev;
990
0
  }
991
0
992
0
  aChild->SetNextSibling(nullptr);
993
0
  aChild->SetPrevSibling(nullptr);
994
0
  aChild->SetParent(nullptr);
995
0
996
0
  this->DidRemoveChild(aChild);
997
0
  NS_RELEASE(aChild);
998
0
  return true;
999
0
}
1000
1001
1002
bool
1003
ContainerLayer::RepositionChild(Layer* aChild, Layer* aAfter)
1004
0
{
1005
0
  if (aChild->Manager() != Manager()) {
1006
0
    NS_ERROR("Child has wrong manager");
1007
0
    return false;
1008
0
  }
1009
0
  if (aChild->GetParent() != this) {
1010
0
    NS_ERROR("aChild not our child");
1011
0
    return false;
1012
0
  }
1013
0
  if (aAfter && (aAfter->Manager() != Manager() ||
1014
0
                 aAfter->GetParent() != this))
1015
0
  {
1016
0
    NS_ERROR("aAfter is not our child");
1017
0
    return false;
1018
0
  }
1019
0
  if (aChild == aAfter) {
1020
0
    NS_ERROR("aChild cannot be the same as aAfter");
1021
0
    return false;
1022
0
  }
1023
0
1024
0
  Layer* prev = aChild->GetPrevSibling();
1025
0
  Layer* next = aChild->GetNextSibling();
1026
0
  if (prev == aAfter) {
1027
0
    // aChild is already in the correct position, nothing to do.
1028
0
    return true;
1029
0
  }
1030
0
  if (prev) {
1031
0
    prev->SetNextSibling(next);
1032
0
  } else {
1033
0
    mFirstChild = next;
1034
0
  }
1035
0
  if (next) {
1036
0
    next->SetPrevSibling(prev);
1037
0
  } else {
1038
0
    mLastChild = prev;
1039
0
  }
1040
0
  if (!aAfter) {
1041
0
    aChild->SetPrevSibling(nullptr);
1042
0
    aChild->SetNextSibling(mFirstChild);
1043
0
    if (mFirstChild) {
1044
0
      mFirstChild->SetPrevSibling(aChild);
1045
0
    }
1046
0
    mFirstChild = aChild;
1047
0
    return true;
1048
0
  }
1049
0
1050
0
  Layer* afterNext = aAfter->GetNextSibling();
1051
0
  if (afterNext) {
1052
0
    afterNext->SetPrevSibling(aChild);
1053
0
  } else {
1054
0
    mLastChild = aChild;
1055
0
  }
1056
0
  aAfter->SetNextSibling(aChild);
1057
0
  aChild->SetPrevSibling(aAfter);
1058
0
  aChild->SetNextSibling(afterNext);
1059
0
  return true;
1060
0
}
1061
1062
void
1063
ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
1064
0
{
1065
0
  aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale,
1066
0
                                    mInheritedXScale, mInheritedYScale,
1067
0
                                    mPresShellResolution, mScaleToResolution);
1068
0
}
1069
1070
bool
1071
ContainerLayer::Creates3DContextWithExtendingChildren()
1072
0
{
1073
0
  if (Extend3DContext()) {
1074
0
    return false;
1075
0
  }
1076
0
  for (Layer* child = GetFirstChild();
1077
0
       child;
1078
0
       child = child->GetNextSibling()) {
1079
0
      if (child->Extend3DContext()) {
1080
0
        return true;
1081
0
      }
1082
0
  }
1083
0
  return false;
1084
0
}
1085
1086
RenderTargetIntRect
1087
ContainerLayer::GetIntermediateSurfaceRect()
1088
0
{
1089
0
  NS_ASSERTION(mUseIntermediateSurface, "Must have intermediate surface");
1090
0
  LayerIntRect bounds = GetLocalVisibleRegion().GetBounds();
1091
0
  return RenderTargetIntRect::FromUnknownRect(bounds.ToUnknownRect());
1092
0
}
1093
1094
bool
1095
ContainerLayer::HasMultipleChildren()
1096
0
{
1097
0
  uint32_t count = 0;
1098
0
  for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
1099
0
    const Maybe<ParentLayerIntRect>& clipRect = child->GetLocalClipRect();
1100
0
    if (clipRect && clipRect->IsEmpty())
1101
0
      continue;
1102
0
    if (child->GetLocalVisibleRegion().IsEmpty())
1103
0
      continue;
1104
0
    ++count;
1105
0
    if (count > 1)
1106
0
      return true;
1107
0
  }
1108
0
1109
0
  return false;
1110
0
}
1111
1112
/**
1113
 * Collect all leaf descendants of the current 3D context.
1114
 */
1115
void
1116
ContainerLayer::Collect3DContextLeaves(nsTArray<Layer*>& aToSort)
1117
0
{
1118
0
  ForEachNode<ForwardIterator>(
1119
0
      (Layer*) this,
1120
0
      [this, &aToSort](Layer* layer)
1121
0
      {
1122
0
        ContainerLayer* container = layer->AsContainerLayer();
1123
0
        if (layer == this || (container && container->Extend3DContext() &&
1124
0
            !container->UseIntermediateSurface())) {
1125
0
          return TraversalFlag::Continue;
1126
0
        }
1127
0
        aToSort.AppendElement(layer);
1128
0
        return TraversalFlag::Skip;
1129
0
      }
1130
0
  );
1131
0
}
1132
1133
static nsTArray<LayerPolygon>
1134
SortLayersWithBSPTree(nsTArray<Layer*>& aArray)
1135
0
{
1136
0
  std::list<LayerPolygon> inputLayers;
1137
0
1138
0
  // Build a list of polygons to be sorted.
1139
0
  for (Layer* layer : aArray) {
1140
0
    // Ignore invisible layers.
1141
0
    if (!layer->IsVisible()) {
1142
0
      continue;
1143
0
    }
1144
0
1145
0
    const gfx::IntRect& bounds =
1146
0
      layer->GetLocalVisibleRegion().GetBounds().ToUnknownRect();
1147
0
1148
0
    const gfx::Matrix4x4& transform = layer->GetEffectiveTransform();
1149
0
1150
0
    if (transform.IsSingular()) {
1151
0
      // Transform cannot be inverted.
1152
0
      continue;
1153
0
    }
1154
0
1155
0
    gfx::Polygon polygon = gfx::Polygon::FromRect(gfx::Rect(bounds));
1156
0
1157
0
    // Transform the polygon to screen space.
1158
0
    polygon.TransformToScreenSpace(transform);
1159
0
1160
0
    if (polygon.GetPoints().Length() >= 3) {
1161
0
      inputLayers.push_back(LayerPolygon(layer, std::move(polygon)));
1162
0
    }
1163
0
  }
1164
0
1165
0
  if (inputLayers.empty()) {
1166
0
    return nsTArray<LayerPolygon>();
1167
0
  }
1168
0
1169
0
  // Build a BSP tree from the list of polygons.
1170
0
  BSPTree tree(inputLayers);
1171
0
1172
0
  nsTArray<LayerPolygon> orderedLayers(tree.GetDrawOrder());
1173
0
1174
0
  // Transform the polygons back to layer space.
1175
0
  for (LayerPolygon& layerPolygon : orderedLayers) {
1176
0
    gfx::Matrix4x4 inverse =
1177
0
      layerPolygon.layer->GetEffectiveTransform().Inverse();
1178
0
1179
0
    MOZ_ASSERT(layerPolygon.geometry);
1180
0
    layerPolygon.geometry->TransformToLayerSpace(inverse);
1181
0
  }
1182
0
1183
0
  return orderedLayers;
1184
0
}
1185
1186
static nsTArray<LayerPolygon>
1187
StripLayerGeometry(const nsTArray<LayerPolygon>& aLayers)
1188
0
{
1189
0
  nsTArray<LayerPolygon> layers;
1190
0
  std::set<Layer*> uniqueLayers;
1191
0
1192
0
  for (const LayerPolygon& layerPolygon : aLayers) {
1193
0
    auto result = uniqueLayers.insert(layerPolygon.layer);
1194
0
1195
0
    if (result.second) {
1196
0
      // Layer was added to the set.
1197
0
      layers.AppendElement(LayerPolygon(layerPolygon.layer));
1198
0
    }
1199
0
  }
1200
0
1201
0
  return layers;
1202
0
}
1203
1204
nsTArray<LayerPolygon>
1205
ContainerLayer::SortChildrenBy3DZOrder(SortMode aSortMode)
1206
0
{
1207
0
  AutoTArray<Layer*, 10> toSort;
1208
0
  nsTArray<LayerPolygon> drawOrder;
1209
0
1210
0
  for (Layer* layer = GetFirstChild(); layer; layer = layer->GetNextSibling()) {
1211
0
    ContainerLayer* container = layer->AsContainerLayer();
1212
0
1213
0
    if (container && container->Extend3DContext() &&
1214
0
        !container->UseIntermediateSurface()) {
1215
0
1216
0
      // Collect 3D layers in toSort array.
1217
0
      container->Collect3DContextLeaves(toSort);
1218
0
1219
0
      // Sort the 3D layers.
1220
0
      if (toSort.Length() > 0) {
1221
0
        nsTArray<LayerPolygon> sorted = SortLayersWithBSPTree(toSort);
1222
0
        drawOrder.AppendElements(std::move(sorted));
1223
0
1224
0
        toSort.ClearAndRetainStorage();
1225
0
      }
1226
0
1227
0
      continue;
1228
0
    }
1229
0
1230
0
    drawOrder.AppendElement(LayerPolygon(layer));
1231
0
  }
1232
0
1233
0
  if (aSortMode == SortMode::WITHOUT_GEOMETRY) {
1234
0
    // Compositor does not support arbitrary layers, strip the layer geometry
1235
0
    // and duplicate layers.
1236
0
    return StripLayerGeometry(drawOrder);
1237
0
  }
1238
0
1239
0
  return drawOrder;
1240
0
}
1241
1242
bool
1243
ContainerLayer::AnyAncestorOrThisIs3DContextLeaf()
1244
0
{
1245
0
  Layer* parent = this;
1246
0
  while (parent != nullptr) {
1247
0
    if (parent->Is3DContextLeaf()) {
1248
0
      return true;
1249
0
    }
1250
0
1251
0
    parent = parent->GetParent();
1252
0
  }
1253
0
1254
0
  return false;
1255
0
}
1256
1257
void
1258
ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface)
1259
0
{
1260
0
  Matrix residual;
1261
0
  Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
1262
0
1263
0
  // Keep 3D transforms for leaves to keep z-order sorting correct.
1264
0
  if (!Extend3DContext() && !Is3DContextLeaf()) {
1265
0
    idealTransform.ProjectTo2D();
1266
0
  }
1267
0
1268
0
  bool useIntermediateSurface;
1269
0
  if (HasMaskLayers() ||
1270
0
      GetForceIsolatedGroup()) {
1271
0
    useIntermediateSurface = true;
1272
#ifdef MOZ_DUMP_PAINTING
1273
  } else if (gfxEnv::DumpPaintIntermediate() && !Extend3DContext()) {
1274
    useIntermediateSurface = true;
1275
#endif
1276
0
  } else {
1277
0
    /* Don't use an intermediate surface for opacity when it's within a 3d
1278
0
     * context, since we'd rather keep the 3d effects. This matches the
1279
0
     * WebKit/blink behaviour, but is changing in the latest spec.
1280
0
     */
1281
0
    float opacity = GetEffectiveOpacity();
1282
0
    CompositionOp blendMode = GetEffectiveMixBlendMode();
1283
0
    if ((HasMultipleChildren() || Creates3DContextWithExtendingChildren()) &&
1284
0
        ((opacity != 1.0f && !Extend3DContext()) ||
1285
0
         (blendMode != CompositionOp::OP_OVER))) {
1286
0
      useIntermediateSurface = true;
1287
0
    } else if ((!idealTransform.Is2D() || AnyAncestorOrThisIs3DContextLeaf()) &&
1288
0
               Creates3DContextWithExtendingChildren()) {
1289
0
      useIntermediateSurface = true;
1290
0
    } else if (blendMode != CompositionOp::OP_OVER &&
1291
0
               Manager()->BlendingRequiresIntermediateSurface()) {
1292
0
      useIntermediateSurface = true;
1293
0
    } else {
1294
0
      useIntermediateSurface = false;
1295
0
      gfx::Matrix contTransform;
1296
0
      bool checkClipRect = false;
1297
0
      bool checkMaskLayers = false;
1298
0
1299
0
      if (!idealTransform.Is2D(&contTransform)) {
1300
0
        // In 3D case, always check if we should use IntermediateSurface.
1301
0
        checkClipRect = true;
1302
0
        checkMaskLayers = true;
1303
0
      } else {
1304
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
1305
        if (!contTransform.PreservesAxisAlignedRectangles()) {
1306
#else
1307
0
        if (gfx::ThebesMatrix(contTransform).HasNonIntegerTranslation()) {
1308
0
#endif
1309
0
          checkClipRect = true;
1310
0
        }
1311
0
        /* In 2D case, only translation and/or positive scaling can be done w/o using IntermediateSurface.
1312
0
         * Otherwise, when rotation or flip happen, we should check whether to use IntermediateSurface.
1313
0
         */
1314
0
        if (contTransform.HasNonAxisAlignedTransform() || contTransform.HasNegativeScaling()) {
1315
0
          checkMaskLayers = true;
1316
0
        }
1317
0
      }
1318
0
1319
0
      if (checkClipRect || checkMaskLayers) {
1320
0
        for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
1321
0
          const Maybe<ParentLayerIntRect>& clipRect = child->GetLocalClipRect();
1322
0
          /* We can't (easily) forward our transform to children with a non-empty clip
1323
0
           * rect since it would need to be adjusted for the transform. See
1324
0
           * the calculations performed by CalculateScissorRect above.
1325
0
           * Nor for a child with a mask layer.
1326
0
           */
1327
0
          if (checkClipRect && (clipRect && !clipRect->IsEmpty() && !child->GetLocalVisibleRegion().IsEmpty())) {
1328
0
            useIntermediateSurface = true;
1329
0
            break;
1330
0
          }
1331
0
          if (checkMaskLayers && child->HasMaskLayers()) {
1332
0
            useIntermediateSurface = true;
1333
0
            break;
1334
0
          }
1335
0
        }
1336
0
      }
1337
0
    }
1338
0
  }
1339
0
1340
0
  NS_ASSERTION(!Extend3DContext() || !useIntermediateSurface, "Can't have an intermediate surface with preserve-3d!");
1341
0
1342
0
  if (useIntermediateSurface) {
1343
0
    mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual);
1344
0
  } else {
1345
0
    mEffectiveTransform = idealTransform;
1346
0
  }
1347
0
1348
0
  // For layers extending 3d context, its ideal transform should be
1349
0
  // applied on children.
1350
0
  if (!Extend3DContext()) {
1351
0
    // Without this projection, non-container children would get a 3D
1352
0
    // transform while 2D is expected.
1353
0
    idealTransform.ProjectTo2D();
1354
0
  }
1355
0
  mUseIntermediateSurface = useIntermediateSurface;
1356
0
  if (useIntermediateSurface) {
1357
0
    ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual));
1358
0
  } else {
1359
0
    ComputeEffectiveTransformsForChildren(idealTransform);
1360
0
  }
1361
0
1362
0
  ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
1363
0
}
1364
1365
void
1366
ContainerLayer::DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurfaceCopy)
1367
0
{
1368
0
  if (!(GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA_DESCENDANT) ||
1369
0
      !Manager()->AreComponentAlphaLayersEnabled()) {
1370
0
    mSupportsComponentAlphaChildren = false;
1371
0
    if (aNeedsSurfaceCopy) {
1372
0
      *aNeedsSurfaceCopy = false;
1373
0
    }
1374
0
    return;
1375
0
  }
1376
0
1377
0
  mSupportsComponentAlphaChildren = false;
1378
0
  bool needsSurfaceCopy = false;
1379
0
  CompositionOp blendMode = GetEffectiveMixBlendMode();
1380
0
  if (UseIntermediateSurface()) {
1381
0
    if (GetLocalVisibleRegion().GetNumRects() == 1 &&
1382
0
        (GetContentFlags() & Layer::CONTENT_OPAQUE))
1383
0
    {
1384
0
      mSupportsComponentAlphaChildren = true;
1385
0
    } else {
1386
0
      gfx::Matrix transform;
1387
0
      if (HasOpaqueAncestorLayer(this) &&
1388
0
          GetEffectiveTransform().Is2D(&transform) &&
1389
0
          !gfx::ThebesMatrix(transform).HasNonIntegerTranslation() &&
1390
0
          blendMode == gfx::CompositionOp::OP_OVER)
1391
0
      {
1392
0
        mSupportsComponentAlphaChildren = true;
1393
0
        needsSurfaceCopy = true;
1394
0
      }
1395
0
    }
1396
0
  } else if (blendMode == gfx::CompositionOp::OP_OVER) {
1397
0
    mSupportsComponentAlphaChildren =
1398
0
      (GetContentFlags() & Layer::CONTENT_OPAQUE) ||
1399
0
      (GetParent() && GetParent()->SupportsComponentAlphaChildren());
1400
0
  }
1401
0
1402
0
  if (aNeedsSurfaceCopy) {
1403
0
    *aNeedsSurfaceCopy = mSupportsComponentAlphaChildren && needsSurfaceCopy;
1404
0
  }
1405
0
}
1406
1407
void
1408
ContainerLayer::ComputeEffectiveTransformsForChildren(const Matrix4x4& aTransformToSurface)
1409
0
{
1410
0
  for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
1411
0
    l->ComputeEffectiveTransforms(aTransformToSurface);
1412
0
  }
1413
0
}
1414
1415
/* static */ bool
1416
ContainerLayer::HasOpaqueAncestorLayer(Layer* aLayer)
1417
0
{
1418
0
  for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
1419
0
    if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
1420
0
      return true;
1421
0
  }
1422
0
  return false;
1423
0
}
1424
1425
// Note that ContainerLayer::RemoveAllChildren contains an optimized
1426
// version of this code; if you make changes to ContainerLayer::DidRemoveChild
1427
// consider whether the matching changes need to be made to
1428
// ContainerLayer::RemoveAllChildren
1429
void
1430
ContainerLayer::DidRemoveChild(Layer* aLayer)
1431
0
{
1432
0
  PaintedLayer* tl = aLayer->AsPaintedLayer();
1433
0
  if (tl && tl->UsedForReadback()) {
1434
0
    for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
1435
0
      if (l->GetType() == TYPE_READBACK) {
1436
0
        static_cast<ReadbackLayer*>(l)->NotifyPaintedLayerRemoved(tl);
1437
0
      }
1438
0
    }
1439
0
  }
1440
0
  if (aLayer->GetType() == TYPE_READBACK) {
1441
0
    static_cast<ReadbackLayer*>(aLayer)->NotifyRemoved();
1442
0
  }
1443
0
}
1444
1445
void
1446
ContainerLayer::DidInsertChild(Layer* aLayer)
1447
0
{
1448
0
  if (aLayer->GetType() == TYPE_READBACK) {
1449
0
    mMayHaveReadbackChild = true;
1450
0
  }
1451
0
}
1452
1453
void
1454
RefLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
1455
0
{
1456
0
  aAttrs = RefLayerAttributes(GetReferentId(), mEventRegionsOverride);
1457
0
}
1458
1459
/**
1460
 * StartFrameTimeRecording, together with StopFrameTimeRecording
1461
 * enable recording of frame intervals.
1462
 *
1463
 * To allow concurrent consumers, a cyclic array is used which serves all
1464
 * consumers, practically stateless with regard to consumers.
1465
 *
1466
 * To save resources, the buffer is allocated on first call to StartFrameTimeRecording
1467
 * and recording is paused if no consumer which called StartFrameTimeRecording is able
1468
 * to get valid results (because the cyclic buffer was overwritten since that call).
1469
 *
1470
 * To determine availability of the data upon StopFrameTimeRecording:
1471
 * - mRecording.mNextIndex increases on each RecordFrame, and never resets.
1472
 * - Cyclic buffer position is realized as mNextIndex % bufferSize.
1473
 * - StartFrameTimeRecording returns mNextIndex. When StopFrameTimeRecording is called,
1474
 *   the required start index is passed as an arg, and we're able to calculate the required
1475
 *   length. If this length is bigger than bufferSize, it means data was overwritten.
1476
 *   otherwise, we can return the entire sequence.
1477
 * - To determine if we need to pause, mLatestStartIndex is updated to mNextIndex
1478
 *   on each call to StartFrameTimeRecording. If this index gets overwritten,
1479
 *   it means that all earlier start indices obtained via StartFrameTimeRecording
1480
 *   were also overwritten, hence, no point in recording, so pause.
1481
 * - mCurrentRunStartIndex indicates the oldest index of the recording after which
1482
 *   the recording was not paused. If StopFrameTimeRecording is invoked with a start index
1483
 *   older than this, it means that some frames were not recorded, so data is invalid.
1484
 */
1485
uint32_t
1486
FrameRecorder::StartFrameTimeRecording(int32_t aBufferSize)
1487
0
{
1488
0
  if (mRecording.mIsPaused) {
1489
0
    mRecording.mIsPaused = false;
1490
0
1491
0
    if (!mRecording.mIntervals.Length()) { // Initialize recording buffers
1492
0
      mRecording.mIntervals.SetLength(aBufferSize);
1493
0
    }
1494
0
1495
0
    // After being paused, recent values got invalid. Update them to now.
1496
0
    mRecording.mLastFrameTime = TimeStamp::Now();
1497
0
1498
0
    // Any recording which started before this is invalid, since we were paused.
1499
0
    mRecording.mCurrentRunStartIndex = mRecording.mNextIndex;
1500
0
  }
1501
0
1502
0
  // If we'll overwrite this index, there are no more consumers with aStartIndex
1503
0
  // for which we're able to provide the full recording, so no point in keep recording.
1504
0
  mRecording.mLatestStartIndex = mRecording.mNextIndex;
1505
0
  return mRecording.mNextIndex;
1506
0
}
1507
1508
void
1509
FrameRecorder::RecordFrame()
1510
0
{
1511
0
  if (!mRecording.mIsPaused) {
1512
0
    TimeStamp now = TimeStamp::Now();
1513
0
    uint32_t i = mRecording.mNextIndex % mRecording.mIntervals.Length();
1514
0
    mRecording.mIntervals[i] = static_cast<float>((now - mRecording.mLastFrameTime)
1515
0
                                                  .ToMilliseconds());
1516
0
    mRecording.mNextIndex++;
1517
0
    mRecording.mLastFrameTime = now;
1518
0
1519
0
    if (mRecording.mNextIndex > (mRecording.mLatestStartIndex + mRecording.mIntervals.Length())) {
1520
0
      // We've just overwritten the most recent recording start -> pause.
1521
0
      mRecording.mIsPaused = true;
1522
0
    }
1523
0
  }
1524
0
}
1525
1526
void
1527
FrameRecorder::StopFrameTimeRecording(uint32_t         aStartIndex,
1528
                                      nsTArray<float>& aFrameIntervals)
1529
0
{
1530
0
  uint32_t bufferSize = mRecording.mIntervals.Length();
1531
0
  uint32_t length = mRecording.mNextIndex - aStartIndex;
1532
0
  if (mRecording.mIsPaused || length > bufferSize || aStartIndex < mRecording.mCurrentRunStartIndex) {
1533
0
    // aStartIndex is too old. Also if aStartIndex was issued before mRecordingNextIndex overflowed (uint32_t)
1534
0
    //   and stopped after the overflow (would happen once every 828 days of constant 60fps).
1535
0
    length = 0;
1536
0
  }
1537
0
1538
0
  if (!length) {
1539
0
    aFrameIntervals.Clear();
1540
0
    return; // empty recording, return empty arrays.
1541
0
  }
1542
0
  // Set length in advance to avoid possibly repeated reallocations
1543
0
  aFrameIntervals.SetLength(length);
1544
0
1545
0
  uint32_t cyclicPos = aStartIndex % bufferSize;
1546
0
  for (uint32_t i = 0; i < length; i++, cyclicPos++) {
1547
0
    if (cyclicPos == bufferSize) {
1548
0
      cyclicPos = 0;
1549
0
    }
1550
0
    aFrameIntervals[i] = mRecording.mIntervals[cyclicPos];
1551
0
  }
1552
0
}
1553
1554
static void PrintInfo(std::stringstream& aStream, HostLayer* aLayerComposite);
1555
1556
#ifdef MOZ_DUMP_PAINTING
1557
template <typename T>
1558
void WriteSnapshotToDumpFile_internal(T* aObj, DataSourceSurface* aSurf)
1559
{
1560
  nsCString string(aObj->Name());
1561
  string.Append('-');
1562
  string.AppendInt((uint64_t)aObj);
1563
  if (gfxUtils::sDumpPaintFile != stderr) {
1564
    fprintf_stderr(gfxUtils::sDumpPaintFile, R"(array["%s"]=")", string.BeginReading());
1565
  }
1566
  gfxUtils::DumpAsDataURI(aSurf, gfxUtils::sDumpPaintFile);
1567
  if (gfxUtils::sDumpPaintFile != stderr) {
1568
    fprintf_stderr(gfxUtils::sDumpPaintFile, R"(";)");
1569
  }
1570
}
1571
1572
void WriteSnapshotToDumpFile(Layer* aLayer, DataSourceSurface* aSurf)
1573
{
1574
  WriteSnapshotToDumpFile_internal(aLayer, aSurf);
1575
}
1576
1577
void WriteSnapshotToDumpFile(LayerManager* aManager, DataSourceSurface* aSurf)
1578
{
1579
  WriteSnapshotToDumpFile_internal(aManager, aSurf);
1580
}
1581
1582
void WriteSnapshotToDumpFile(Compositor* aCompositor, DrawTarget* aTarget)
1583
{
1584
  RefPtr<SourceSurface> surf = aTarget->Snapshot();
1585
  RefPtr<DataSourceSurface> dSurf = surf->GetDataSurface();
1586
  WriteSnapshotToDumpFile_internal(aCompositor, dSurf);
1587
}
1588
#endif
1589
1590
void
1591
Layer::Dump(std::stringstream& aStream, const char* aPrefix,
1592
            bool aDumpHtml, bool aSorted, const Maybe<gfx::Polygon>& aGeometry)
1593
0
{
1594
#ifdef MOZ_DUMP_PAINTING
1595
  bool dumpCompositorTexture = gfxEnv::DumpCompositorTextures() && AsHostLayer() &&
1596
                               AsHostLayer()->GetCompositableHost();
1597
  bool dumpClientTexture = gfxEnv::DumpPaint() && AsShadowableLayer() &&
1598
                           AsShadowableLayer()->GetCompositableClient();
1599
  nsCString layerId(Name());
1600
  layerId.Append('-');
1601
  layerId.AppendInt((uint64_t)this);
1602
#endif
1603
0
  if (aDumpHtml) {
1604
0
    aStream << nsPrintfCString(R"(<li><a id="%p" )", this).get();
1605
#ifdef MOZ_DUMP_PAINTING
1606
    if (dumpCompositorTexture || dumpClientTexture) {
1607
      aStream << nsPrintfCString(R"lit(href="javascript:ViewImage('%s')")lit", layerId.BeginReading()).get();
1608
    }
1609
#endif
1610
    aStream << ">";
1611
0
  }
1612
0
  DumpSelf(aStream, aPrefix, aGeometry);
1613
0
1614
#ifdef MOZ_DUMP_PAINTING
1615
  if (dumpCompositorTexture) {
1616
    AsHostLayer()->GetCompositableHost()->Dump(aStream, aPrefix, aDumpHtml);
1617
  } else if (dumpClientTexture) {
1618
    if (aDumpHtml) {
1619
      aStream << nsPrintfCString(R"(<script>array["%s"]=")", layerId.BeginReading()).get();
1620
    }
1621
    AsShadowableLayer()->GetCompositableClient()->Dump(aStream, aPrefix,
1622
        aDumpHtml, TextureDumpMode::DoNotCompress);
1623
    if (aDumpHtml) {
1624
      aStream << R"(";</script>)";
1625
    }
1626
  }
1627
#endif
1628
1629
0
  if (aDumpHtml) {
1630
0
    aStream << "</a>";
1631
#ifdef MOZ_DUMP_PAINTING
1632
    if (dumpClientTexture) {
1633
      aStream << nsPrintfCString("<br><img id=\"%s\">\n", layerId.BeginReading()).get();
1634
    }
1635
#endif
1636
  }
1637
0
1638
0
  if (Layer* mask = GetMaskLayer()) {
1639
0
    aStream << nsPrintfCString("%s  Mask layer:\n", aPrefix).get();
1640
0
    nsAutoCString pfx(aPrefix);
1641
0
    pfx += "    ";
1642
0
    mask->Dump(aStream, pfx.get(), aDumpHtml);
1643
0
  }
1644
0
1645
0
  for (size_t i = 0; i < GetAncestorMaskLayerCount(); i++) {
1646
0
    aStream << nsPrintfCString("%s  Ancestor mask layer %d:\n", aPrefix, uint32_t(i)).get();
1647
0
    nsAutoCString pfx(aPrefix);
1648
0
    pfx += "    ";
1649
0
    GetAncestorMaskLayerAt(i)->Dump(aStream, pfx.get(), aDumpHtml);
1650
0
  }
1651
0
1652
#ifdef MOZ_DUMP_PAINTING
1653
  for (size_t i = 0; i < mExtraDumpInfo.Length(); i++) {
1654
    const nsCString& str = mExtraDumpInfo[i];
1655
    aStream << aPrefix << "  Info:\n" << str.get();
1656
  }
1657
#endif
1658
1659
0
  if (ContainerLayer* container = AsContainerLayer()) {
1660
0
    nsTArray<LayerPolygon> children;
1661
0
    if (aSorted) {
1662
0
      children =
1663
0
        container->SortChildrenBy3DZOrder(ContainerLayer::SortMode::WITH_GEOMETRY);
1664
0
    } else {
1665
0
      for (Layer* l = container->GetFirstChild(); l; l = l->GetNextSibling()) {
1666
0
        children.AppendElement(LayerPolygon(l));
1667
0
      }
1668
0
    }
1669
0
    nsAutoCString pfx(aPrefix);
1670
0
    pfx += "  ";
1671
0
    if (aDumpHtml) {
1672
0
      aStream << "<ul>";
1673
0
    }
1674
0
1675
0
    for (LayerPolygon& child : children) {
1676
0
      child.layer->Dump(aStream, pfx.get(), aDumpHtml, aSorted, child.geometry);
1677
0
    }
1678
0
1679
0
    if (aDumpHtml) {
1680
0
      aStream << "</ul>";
1681
0
    }
1682
0
  }
1683
0
1684
0
  if (aDumpHtml) {
1685
0
    aStream << "</li>";
1686
0
  }
1687
0
}
1688
1689
static void
1690
DumpGeometry(std::stringstream& aStream, const Maybe<gfx::Polygon>& aGeometry)
1691
0
{
1692
0
  aStream << " [geometry=[";
1693
0
1694
0
  const nsTArray<gfx::Point4D>& points = aGeometry->GetPoints();
1695
0
  for (size_t i = 0; i < points.Length(); ++i) {
1696
0
    const gfx::IntPoint point = TruncatedToInt(points[i].As2DPoint());
1697
0
    const char* sfx = (i != points.Length() - 1) ? "," : "";
1698
0
    AppendToString(aStream, point, "", sfx);
1699
0
  }
1700
0
1701
0
  aStream << "]]";
1702
0
}
1703
1704
void
1705
Layer::DumpSelf(std::stringstream& aStream, const char* aPrefix,
1706
                const Maybe<gfx::Polygon>& aGeometry)
1707
0
{
1708
0
  PrintInfo(aStream, aPrefix);
1709
0
1710
0
  if (aGeometry) {
1711
0
    DumpGeometry(aStream, aGeometry);
1712
0
  }
1713
0
1714
0
  aStream << "\n";
1715
0
}
1716
1717
void
1718
Layer::Dump(layerscope::LayersPacket* aPacket, const void* aParent)
1719
0
{
1720
0
  DumpPacket(aPacket, aParent);
1721
0
1722
0
  if (Layer* kid = GetFirstChild()) {
1723
0
    kid->Dump(aPacket, this);
1724
0
  }
1725
0
1726
0
  if (Layer* next = GetNextSibling()) {
1727
0
    next->Dump(aPacket, aParent);
1728
0
  }
1729
0
}
1730
1731
void
1732
Layer::SetDisplayListLog(const char* log)
1733
0
{
1734
0
  if (gfxUtils::DumpDisplayList()) {
1735
0
    mDisplayListLog = log;
1736
0
  }
1737
0
}
1738
1739
void
1740
Layer::GetDisplayListLog(nsCString& log)
1741
0
{
1742
0
  log.SetLength(0);
1743
0
1744
0
  if (gfxUtils::DumpDisplayList()) {
1745
0
    // This function returns a plain text string which consists of two things
1746
0
    //   1. DisplayList log.
1747
0
    //   2. Memory address of this layer.
1748
0
    // We know the target layer of each display item by information in #1.
1749
0
    // Here is an example of a Text display item line log in #1
1750
0
    //   Text p=0xa9850c00 f=0x0xaa405b00(.....
1751
0
    // f keeps the address of the target client layer of a display item.
1752
0
    // For LayerScope, display-item-to-client-layer mapping is not enough since
1753
0
    // LayerScope, which lives in the chrome process, knows only composite layers.
1754
0
    // As so, we need display-item-to-client-layer-to-layer-composite
1755
0
    // mapping. That's the reason we insert #2 into the log
1756
0
    log.AppendPrintf("0x%p\n%s",(void*) this, mDisplayListLog.get());
1757
0
  }
1758
0
}
1759
1760
void
1761
Layer::Log(const char* aPrefix)
1762
0
{
1763
0
  if (!IsLogEnabled())
1764
0
    return;
1765
0
1766
0
  LogSelf(aPrefix);
1767
0
1768
0
  if (Layer* kid = GetFirstChild()) {
1769
0
    nsAutoCString pfx(aPrefix);
1770
0
    pfx += "  ";
1771
0
    kid->Log(pfx.get());
1772
0
  }
1773
0
1774
0
  if (Layer* next = GetNextSibling())
1775
0
    next->Log(aPrefix);
1776
0
}
1777
1778
void
1779
Layer::LogSelf(const char* aPrefix)
1780
0
{
1781
0
  if (!IsLogEnabled())
1782
0
    return;
1783
0
1784
0
  std::stringstream ss;
1785
0
  PrintInfo(ss, aPrefix);
1786
0
  MOZ_LAYERS_LOG(("%s", ss.str().c_str()));
1787
0
1788
0
  if (mMaskLayer) {
1789
0
    nsAutoCString pfx(aPrefix);
1790
0
    pfx += R"(   \ MaskLayer )";
1791
0
    mMaskLayer->LogSelf(pfx.get());
1792
0
  }
1793
0
}
1794
1795
void
1796
Layer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
1797
0
{
1798
0
  aStream << aPrefix;
1799
0
  aStream << nsPrintfCString("%s%s (0x%p)", mManager->Name(), Name(), this).get();
1800
0
1801
0
  layers::PrintInfo(aStream, AsHostLayer());
1802
0
1803
0
  if (mClipRect) {
1804
0
    AppendToString(aStream, *mClipRect, " [clip=", "]");
1805
0
  }
1806
0
  if (mSimpleAttrs.GetScrolledClip()) {
1807
0
    AppendToString(aStream, mSimpleAttrs.GetScrolledClip()->GetClipRect(), " [scrolled-clip=", "]");
1808
0
    if (const Maybe<size_t>& ix = mSimpleAttrs.GetScrolledClip()->GetMaskLayerIndex()) {
1809
0
      AppendToString(aStream, ix.value(), " [scrolled-mask=", "]");
1810
0
    }
1811
0
  }
1812
0
  if (1.0 != mSimpleAttrs.GetPostXScale() || 1.0 != mSimpleAttrs.GetPostYScale()) {
1813
0
    aStream << nsPrintfCString(" [postScale=%g, %g]", mSimpleAttrs.GetPostXScale(), mSimpleAttrs.GetPostYScale()).get();
1814
0
  }
1815
0
  if (!GetBaseTransform().IsIdentity()) {
1816
0
    AppendToString(aStream, GetBaseTransform(), " [transform=", "]");
1817
0
  }
1818
0
  if (!GetEffectiveTransform().IsIdentity()) {
1819
0
    AppendToString(aStream, GetEffectiveTransform(), " [effective-transform=", "]");
1820
0
  }
1821
0
  if (GetTransformIsPerspective()) {
1822
0
    aStream << " [perspective]";
1823
0
  }
1824
0
  if (!mVisibleRegion.IsEmpty()) {
1825
0
    AppendToString(aStream, mVisibleRegion.ToUnknownRegion(), " [visible=", "]");
1826
0
  } else {
1827
0
    aStream << " [not visible]";
1828
0
  }
1829
0
  if (!mEventRegions.IsEmpty()) {
1830
0
    AppendToString(aStream, mEventRegions, " ", "");
1831
0
  }
1832
0
  if (1.0 != GetOpacity()) {
1833
0
    aStream << nsPrintfCString(" [opacity=%g]", GetOpacity()).get();
1834
0
  }
1835
0
  if (IsOpaque()) {
1836
0
    aStream << " [opaqueContent]";
1837
0
  }
1838
0
  if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) {
1839
0
    aStream << " [componentAlpha]";
1840
0
  }
1841
0
  if (GetContentFlags() & CONTENT_BACKFACE_HIDDEN) {
1842
0
    aStream << " [backfaceHidden]";
1843
0
  }
1844
0
  if (Extend3DContext()) {
1845
0
    aStream << " [extend3DContext]";
1846
0
  }
1847
0
  if (Combines3DTransformWithAncestors()) {
1848
0
    aStream << " [combines3DTransformWithAncestors]";
1849
0
  }
1850
0
  if (Is3DContextLeaf()) {
1851
0
    aStream << " [is3DContextLeaf]";
1852
0
  }
1853
0
  if (IsScrollbarContainer()) {
1854
0
    aStream << " [scrollbar]";
1855
0
  }
1856
0
  if (GetScrollbarData().IsThumb()) {
1857
0
    if (Maybe<ScrollDirection> thumbDirection = GetScrollbarData().mDirection) {
1858
0
      if (*thumbDirection == ScrollDirection::eVertical) {
1859
0
        aStream << nsPrintfCString(" [vscrollbar=%" PRIu64 "]", GetScrollbarData().mTargetViewId).get();
1860
0
      }
1861
0
      if (*thumbDirection == ScrollDirection::eHorizontal) {
1862
0
        aStream << nsPrintfCString(" [hscrollbar=%" PRIu64 "]", GetScrollbarData().mTargetViewId).get();
1863
0
      }
1864
0
    }
1865
0
  }
1866
0
  if (GetIsFixedPosition()) {
1867
0
    LayerPoint anchor = GetFixedPositionAnchor();
1868
0
    aStream << nsPrintfCString(" [isFixedPosition scrollId=%" PRIu64 " sides=0x%x anchor=%s]",
1869
0
                     GetFixedPositionScrollContainerId(),
1870
0
                     GetFixedPositionSides(),
1871
0
                     ToString(anchor).c_str()).get();
1872
0
  }
1873
0
  if (GetIsStickyPosition()) {
1874
0
    aStream << nsPrintfCString(" [isStickyPosition scrollId=%" PRIu64 " outer=(%.3f,%.3f)-(%.3f,%.3f) "
1875
0
                     "inner=(%.3f,%.3f)-(%.3f,%.3f)]",
1876
0
                     GetStickyScrollContainerId(),
1877
0
                     GetStickyScrollRangeOuter().X(),
1878
0
                     GetStickyScrollRangeOuter().Y(),
1879
0
                     GetStickyScrollRangeOuter().XMost(),
1880
0
                     GetStickyScrollRangeOuter().YMost(),
1881
0
                     GetStickyScrollRangeInner().X(),
1882
0
                     GetStickyScrollRangeInner().Y(),
1883
0
                     GetStickyScrollRangeInner().XMost(),
1884
0
                     GetStickyScrollRangeInner().YMost()).get();
1885
0
  }
1886
0
  if (mMaskLayer) {
1887
0
    aStream << nsPrintfCString(" [mMaskLayer=%p]", mMaskLayer.get()).get();
1888
0
  }
1889
0
  for (uint32_t i = 0; i < mScrollMetadata.Length(); i++) {
1890
0
    if (!mScrollMetadata[i].IsDefault()) {
1891
0
      aStream << nsPrintfCString(" [metrics%d=", i).get();
1892
0
      AppendToString(aStream, mScrollMetadata[i], "", "]");
1893
0
    }
1894
0
  }
1895
0
  if (!mAnimationInfo.GetAnimations().IsEmpty()) {
1896
0
    aStream << nsPrintfCString(" [%d animations with id=%" PRIu64 " ]",
1897
0
                               (int) mAnimationInfo.GetAnimations().Length(),
1898
0
                               mAnimationInfo.GetCompositorAnimationsId()).get();
1899
0
  }
1900
0
}
1901
1902
// The static helper function sets the transform matrix into the packet
1903
static void
1904
DumpTransform(layerscope::LayersPacket::Layer::Matrix* aLayerMatrix, const Matrix4x4& aMatrix)
1905
0
{
1906
0
  aLayerMatrix->set_is2d(aMatrix.Is2D());
1907
0
  if (aMatrix.Is2D()) {
1908
0
    Matrix m = aMatrix.As2D();
1909
0
    aLayerMatrix->set_isid(m.IsIdentity());
1910
0
    if (!m.IsIdentity()) {
1911
0
      aLayerMatrix->add_m(m._11); aLayerMatrix->add_m(m._12);
1912
0
      aLayerMatrix->add_m(m._21); aLayerMatrix->add_m(m._22);
1913
0
      aLayerMatrix->add_m(m._31); aLayerMatrix->add_m(m._32);
1914
0
    }
1915
0
  } else {
1916
0
    aLayerMatrix->add_m(aMatrix._11); aLayerMatrix->add_m(aMatrix._12);
1917
0
    aLayerMatrix->add_m(aMatrix._13); aLayerMatrix->add_m(aMatrix._14);
1918
0
    aLayerMatrix->add_m(aMatrix._21); aLayerMatrix->add_m(aMatrix._22);
1919
0
    aLayerMatrix->add_m(aMatrix._23); aLayerMatrix->add_m(aMatrix._24);
1920
0
    aLayerMatrix->add_m(aMatrix._31); aLayerMatrix->add_m(aMatrix._32);
1921
0
    aLayerMatrix->add_m(aMatrix._33); aLayerMatrix->add_m(aMatrix._34);
1922
0
    aLayerMatrix->add_m(aMatrix._41); aLayerMatrix->add_m(aMatrix._42);
1923
0
    aLayerMatrix->add_m(aMatrix._43); aLayerMatrix->add_m(aMatrix._44);
1924
0
  }
1925
0
}
1926
1927
// The static helper function sets the IntRect into the packet
1928
template <typename T, typename Sub, typename Point, typename SizeT, typename MarginT>
1929
static void
1930
DumpRect(layerscope::LayersPacket::Layer::Rect* aLayerRect,
1931
         const BaseRect<T, Sub, Point, SizeT, MarginT>& aRect)
1932
0
{
1933
0
  aLayerRect->set_x(aRect.X());
1934
0
  aLayerRect->set_y(aRect.Y());
1935
0
  aLayerRect->set_w(aRect.Width());
1936
0
  aLayerRect->set_h(aRect.Height());
1937
0
}
Unexecuted instantiation: Unified_cpp_gfx_layers1.cpp:void mozilla::layers::DumpRect<int, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits>, mozilla::gfx::IntPointTyped<mozilla::gfx::UnknownUnits>, mozilla::gfx::IntSizeTyped<mozilla::gfx::UnknownUnits>, mozilla::gfx::IntMarginTyped<mozilla::gfx::UnknownUnits> >(mozilla::layers::layerscope::LayersPacket_Layer_Rect*, mozilla::gfx::BaseRect<int, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits>, mozilla::gfx::IntPointTyped<mozilla::gfx::UnknownUnits>, mozilla::gfx::IntSizeTyped<mozilla::gfx::UnknownUnits>, mozilla::gfx::IntMarginTyped<mozilla::gfx::UnknownUnits> > const&)
Unexecuted instantiation: Unified_cpp_gfx_layers1.cpp:void mozilla::layers::DumpRect<int, mozilla::gfx::IntRectTyped<mozilla::ParentLayerPixel>, mozilla::gfx::IntPointTyped<mozilla::ParentLayerPixel>, mozilla::gfx::IntSizeTyped<mozilla::ParentLayerPixel>, mozilla::gfx::IntMarginTyped<mozilla::ParentLayerPixel> >(mozilla::layers::layerscope::LayersPacket_Layer_Rect*, mozilla::gfx::BaseRect<int, mozilla::gfx::IntRectTyped<mozilla::ParentLayerPixel>, mozilla::gfx::IntPointTyped<mozilla::ParentLayerPixel>, mozilla::gfx::IntSizeTyped<mozilla::ParentLayerPixel>, mozilla::gfx::IntMarginTyped<mozilla::ParentLayerPixel> > const&)
1938
1939
// The static helper function sets the nsIntRegion into the packet
1940
static void
1941
DumpRegion(layerscope::LayersPacket::Layer::Region* aLayerRegion, const nsIntRegion& aRegion)
1942
0
{
1943
0
  for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
1944
0
    DumpRect(aLayerRegion->add_r(), iter.Get());
1945
0
  }
1946
0
}
1947
1948
void
1949
Layer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
1950
0
{
1951
0
  // Add a new layer (UnknownLayer)
1952
0
  using namespace layerscope;
1953
0
  LayersPacket::Layer* layer = aPacket->add_layer();
1954
0
  // Basic information
1955
0
  layer->set_type(LayersPacket::Layer::UnknownLayer);
1956
0
  layer->set_ptr(reinterpret_cast<uint64_t>(this));
1957
0
  layer->set_parentptr(reinterpret_cast<uint64_t>(aParent));
1958
0
  // Shadow
1959
0
  if (HostLayer* lc = AsHostLayer()) {
1960
0
    LayersPacket::Layer::Shadow* s = layer->mutable_shadow();
1961
0
    if (const Maybe<ParentLayerIntRect>& clipRect = lc->GetShadowClipRect()) {
1962
0
      DumpRect(s->mutable_clip(), *clipRect);
1963
0
    }
1964
0
    if (!lc->GetShadowBaseTransform().IsIdentity()) {
1965
0
      DumpTransform(s->mutable_transform(), lc->GetShadowBaseTransform());
1966
0
    }
1967
0
    if (!lc->GetShadowVisibleRegion().IsEmpty()) {
1968
0
      DumpRegion(s->mutable_vregion(), lc->GetShadowVisibleRegion().ToUnknownRegion());
1969
0
    }
1970
0
  }
1971
0
  // Clip
1972
0
  if (mClipRect) {
1973
0
    DumpRect(layer->mutable_clip(), *mClipRect);
1974
0
  }
1975
0
  // Transform
1976
0
  if (!GetBaseTransform().IsIdentity()) {
1977
0
    DumpTransform(layer->mutable_transform(), GetBaseTransform());
1978
0
  }
1979
0
  // Visible region
1980
0
  if (!mVisibleRegion.ToUnknownRegion().IsEmpty()) {
1981
0
    DumpRegion(layer->mutable_vregion(), mVisibleRegion.ToUnknownRegion());
1982
0
  }
1983
0
  // EventRegions
1984
0
  if (!mEventRegions.IsEmpty()) {
1985
0
    const EventRegions &e = mEventRegions;
1986
0
    if (!e.mHitRegion.IsEmpty()) {
1987
0
      DumpRegion(layer->mutable_hitregion(), e.mHitRegion);
1988
0
    }
1989
0
    if (!e.mDispatchToContentHitRegion.IsEmpty()) {
1990
0
      DumpRegion(layer->mutable_dispatchregion(), e.mDispatchToContentHitRegion);
1991
0
    }
1992
0
    if (!e.mNoActionRegion.IsEmpty()) {
1993
0
      DumpRegion(layer->mutable_noactionregion(), e.mNoActionRegion);
1994
0
    }
1995
0
    if (!e.mHorizontalPanRegion.IsEmpty()) {
1996
0
      DumpRegion(layer->mutable_hpanregion(), e.mHorizontalPanRegion);
1997
0
    }
1998
0
    if (!e.mVerticalPanRegion.IsEmpty()) {
1999
0
      DumpRegion(layer->mutable_vpanregion(), e.mVerticalPanRegion);
2000
0
    }
2001
0
  }
2002
0
  // Opacity
2003
0
  layer->set_opacity(GetOpacity());
2004
0
  // Content opaque
2005
0
  layer->set_copaque(static_cast<bool>(GetContentFlags() & CONTENT_OPAQUE));
2006
0
  // Component alpha
2007
0
  layer->set_calpha(static_cast<bool>(GetContentFlags() & CONTENT_COMPONENT_ALPHA));
2008
0
  // Vertical or horizontal bar
2009
0
  if (GetScrollbarData().mScrollbarLayerType == layers::ScrollbarLayerType::Thumb) {
2010
0
    layer->set_direct(*GetScrollbarData().mDirection == ScrollDirection::eVertical ?
2011
0
                      LayersPacket::Layer::VERTICAL :
2012
0
                      LayersPacket::Layer::HORIZONTAL);
2013
0
    layer->set_barid(GetScrollbarData().mTargetViewId);
2014
0
  }
2015
0
2016
0
  // Mask layer
2017
0
  if (mMaskLayer) {
2018
0
    layer->set_mask(reinterpret_cast<uint64_t>(mMaskLayer.get()));
2019
0
  }
2020
0
2021
0
  // DisplayList log.
2022
0
  if (mDisplayListLog.Length() > 0) {
2023
0
    layer->set_displaylistloglength(mDisplayListLog.Length());
2024
0
    auto compressedData =
2025
0
      MakeUnique<char[]>(LZ4::maxCompressedSize(mDisplayListLog.Length()));
2026
0
    int compressedSize = LZ4::compress((char*)mDisplayListLog.get(),
2027
0
                                       mDisplayListLog.Length(),
2028
0
                                       compressedData.get());
2029
0
    layer->set_displaylistlog(compressedData.get(), compressedSize);
2030
0
  }
2031
0
}
2032
2033
bool
2034
Layer::IsBackfaceHidden()
2035
0
{
2036
0
  if (GetContentFlags() & CONTENT_BACKFACE_HIDDEN) {
2037
0
    Layer* container = AsContainerLayer() ? this : GetParent();
2038
0
    if (container) {
2039
0
      // The effective transform can include non-preserve-3d parent
2040
0
      // transforms, since we don't always require an intermediate.
2041
0
      if (container->Extend3DContext() || container->Is3DContextLeaf()) {
2042
0
        return container->GetEffectiveTransform().IsBackfaceVisible();
2043
0
      }
2044
0
      return container->GetBaseTransform().IsBackfaceVisible();
2045
0
    }
2046
0
  }
2047
0
  return false;
2048
0
}
2049
2050
UniquePtr<LayerUserData>
2051
Layer::RemoveUserData(void* aKey)
2052
0
{
2053
0
  UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
2054
0
  return d;
2055
0
}
2056
2057
void
2058
Layer::SetManager(LayerManager* aManager, HostLayer* aSelf)
2059
0
{
2060
0
  // No one should be calling this for weird reasons.
2061
0
  MOZ_ASSERT(aSelf);
2062
0
  MOZ_ASSERT(aSelf->GetLayer() == this);
2063
0
  mManager = aManager;
2064
0
}
2065
2066
void
2067
PaintedLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
2068
0
{
2069
0
  Layer::PrintInfo(aStream, aPrefix);
2070
0
  nsIntRegion validRegion = GetValidRegion();
2071
0
  if (!validRegion.IsEmpty()) {
2072
0
    AppendToString(aStream, validRegion, " [valid=", "]");
2073
0
  }
2074
0
}
2075
2076
void
2077
PaintedLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
2078
0
{
2079
0
  Layer::DumpPacket(aPacket, aParent);
2080
0
  // get this layer data
2081
0
  using namespace layerscope;
2082
0
  LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
2083
0
  layer->set_type(LayersPacket::Layer::PaintedLayer);
2084
0
  nsIntRegion validRegion = GetValidRegion();
2085
0
  if (!validRegion.IsEmpty()) {
2086
0
    DumpRegion(layer->mutable_valid(), validRegion);
2087
0
  }
2088
0
}
2089
2090
void
2091
ContainerLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
2092
0
{
2093
0
  Layer::PrintInfo(aStream, aPrefix);
2094
0
  if (UseIntermediateSurface()) {
2095
0
    aStream << " [usesTmpSurf]";
2096
0
  }
2097
0
  if (1.0 != mPreXScale || 1.0 != mPreYScale) {
2098
0
    aStream << nsPrintfCString(" [preScale=%g, %g]", mPreXScale, mPreYScale).get();
2099
0
  }
2100
0
  if (mScaleToResolution) {
2101
0
    aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get();
2102
0
  }
2103
0
}
2104
2105
void
2106
ContainerLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
2107
0
{
2108
0
  Layer::DumpPacket(aPacket, aParent);
2109
0
  // Get this layer data
2110
0
  using namespace layerscope;
2111
0
  LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
2112
0
  layer->set_type(LayersPacket::Layer::ContainerLayer);
2113
0
}
2114
2115
void
2116
ColorLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
2117
0
{
2118
0
  Layer::PrintInfo(aStream, aPrefix);
2119
0
  AppendToString(aStream, mColor, " [color=", "]");
2120
0
  AppendToString(aStream, mBounds, " [bounds=", "]");
2121
0
}
2122
2123
void
2124
ColorLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
2125
0
{
2126
0
  Layer::DumpPacket(aPacket, aParent);
2127
0
  // Get this layer data
2128
0
  using namespace layerscope;
2129
0
  LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
2130
0
  layer->set_type(LayersPacket::Layer::ColorLayer);
2131
0
  layer->set_color(mColor.ToABGR());
2132
0
}
2133
2134
CanvasLayer::CanvasLayer(LayerManager* aManager, void* aImplData)
2135
  : Layer(aManager, aImplData)
2136
  , mSamplingFilter(SamplingFilter::GOOD)
2137
0
{
2138
0
}
2139
2140
0
CanvasLayer::~CanvasLayer() = default;
2141
2142
void
2143
CanvasLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
2144
0
{
2145
0
  Layer::PrintInfo(aStream, aPrefix);
2146
0
  if (mSamplingFilter != SamplingFilter::GOOD) {
2147
0
    AppendToString(aStream, mSamplingFilter, " [filter=", "]");
2148
0
  }
2149
0
}
2150
2151
// This help function is used to assign the correct enum value
2152
// to the packet
2153
static void
2154
DumpFilter(layerscope::LayersPacket::Layer* aLayer,
2155
           const SamplingFilter& aSamplingFilter)
2156
{
2157
  using namespace layerscope;
2158
  switch (aSamplingFilter) {
2159
    case SamplingFilter::GOOD:
2160
      aLayer->set_filter(LayersPacket::Layer::FILTER_GOOD);
2161
      break;
2162
    case SamplingFilter::LINEAR:
2163
      aLayer->set_filter(LayersPacket::Layer::FILTER_LINEAR);
2164
      break;
2165
    case SamplingFilter::POINT:
2166
      aLayer->set_filter(LayersPacket::Layer::FILTER_POINT);
2167
      break;
2168
    default:
2169
      // ignore it
2170
      break;
2171
  }
2172
}
2173
2174
void
2175
CanvasLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
2176
0
{
2177
0
  Layer::DumpPacket(aPacket, aParent);
2178
0
  // Get this layer data
2179
0
  using namespace layerscope;
2180
0
  LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
2181
0
  layer->set_type(LayersPacket::Layer::CanvasLayer);
2182
0
  DumpFilter(layer, mSamplingFilter);
2183
0
}
2184
2185
CanvasRenderer*
2186
CanvasLayer::CreateOrGetCanvasRenderer()
2187
0
{
2188
0
  if (!mCanvasRenderer) {
2189
0
    mCanvasRenderer.reset(CreateCanvasRendererInternal());
2190
0
  }
2191
0
2192
0
  return mCanvasRenderer.get();
2193
0
}
2194
2195
void
2196
ImageLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
2197
0
{
2198
0
  Layer::PrintInfo(aStream, aPrefix);
2199
0
  if (mSamplingFilter != SamplingFilter::GOOD) {
2200
0
    AppendToString(aStream, mSamplingFilter, " [filter=", "]");
2201
0
  }
2202
0
}
2203
2204
void
2205
ImageLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
2206
0
{
2207
0
  Layer::DumpPacket(aPacket, aParent);
2208
0
  // Get this layer data
2209
0
  using namespace layerscope;
2210
0
  LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
2211
0
  layer->set_type(LayersPacket::Layer::ImageLayer);
2212
0
  DumpFilter(layer, mSamplingFilter);
2213
0
}
2214
2215
void
2216
RefLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
2217
0
{
2218
0
  ContainerLayer::PrintInfo(aStream, aPrefix);
2219
0
  if (mId.IsValid()) {
2220
0
    AppendToString(aStream, uint64_t(mId), " [id=", "]");
2221
0
  }
2222
0
  if (mEventRegionsOverride & EventRegionsOverride::ForceDispatchToContent) {
2223
0
    aStream << " [force-dtc]";
2224
0
  }
2225
0
  if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
2226
0
    aStream << " [force-ehr]";
2227
0
  }
2228
0
}
2229
2230
void
2231
RefLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
2232
0
{
2233
0
  Layer::DumpPacket(aPacket, aParent);
2234
0
  // Get this layer data
2235
0
  using namespace layerscope;
2236
0
  LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
2237
0
  layer->set_type(LayersPacket::Layer::RefLayer);
2238
0
  layer->set_refid(uint64_t(mId));
2239
0
}
2240
2241
void
2242
ReadbackLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
2243
0
{
2244
0
  Layer::PrintInfo(aStream, aPrefix);
2245
0
  AppendToString(aStream, mSize, " [size=", "]");
2246
0
  if (mBackgroundLayer) {
2247
0
    AppendToString(aStream, mBackgroundLayer, " [backgroundLayer=", "]");
2248
0
    AppendToString(aStream, mBackgroundLayerOffset, " [backgroundOffset=", "]");
2249
0
  } else if (mBackgroundColor.a == 1.f) {
2250
0
    AppendToString(aStream, mBackgroundColor, " [backgroundColor=", "]");
2251
0
  } else {
2252
0
    aStream << " [nobackground]";
2253
0
  }
2254
0
}
2255
2256
void
2257
ReadbackLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
2258
0
{
2259
0
  Layer::DumpPacket(aPacket, aParent);
2260
0
  // Get this layer data
2261
0
  using namespace layerscope;
2262
0
  LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
2263
0
  layer->set_type(LayersPacket::Layer::ReadbackLayer);
2264
0
  LayersPacket::Layer::Size* size = layer->mutable_size();
2265
0
  size->set_w(mSize.width);
2266
0
  size->set_h(mSize.height);
2267
0
}
2268
2269
//--------------------------------------------------
2270
// LayerManager
2271
2272
void
2273
LayerManager::Dump(std::stringstream& aStream, const char* aPrefix,
2274
                   bool aDumpHtml, bool aSorted)
2275
0
{
2276
#ifdef MOZ_DUMP_PAINTING
2277
  if (aDumpHtml) {
2278
    aStream << "<ul><li>";
2279
  }
2280
#endif
2281
  DumpSelf(aStream, aPrefix, aSorted);
2282
0
2283
0
  nsAutoCString pfx(aPrefix);
2284
0
  pfx += "  ";
2285
0
  if (!GetRoot()) {
2286
0
    aStream << nsPrintfCString("%s(null)\n", pfx.get()).get();
2287
0
    if (aDumpHtml) {
2288
0
      aStream << "</li></ul>";
2289
0
    }
2290
0
    return;
2291
0
  }
2292
0
2293
0
  if (aDumpHtml) {
2294
0
    aStream << "<ul>";
2295
0
  }
2296
0
  GetRoot()->Dump(aStream, pfx.get(), aDumpHtml, aSorted);
2297
0
  if (aDumpHtml) {
2298
0
    aStream << "</ul></li></ul>";
2299
0
  }
2300
0
  aStream << "\n";
2301
0
}
2302
2303
void
2304
LayerManager::DumpSelf(std::stringstream& aStream, const char* aPrefix, bool aSorted)
2305
0
{
2306
0
  PrintInfo(aStream, aPrefix);
2307
0
  aStream << " --- in " << (aSorted ? "3D-sorted rendering order" : "content order");
2308
0
  aStream << "\n";
2309
0
}
2310
2311
void
2312
LayerManager::Dump(bool aSorted)
2313
0
{
2314
0
  std::stringstream ss;
2315
0
  Dump(ss, "", false, aSorted);
2316
0
  print_stderr(ss);
2317
0
}
2318
2319
void
2320
LayerManager::Dump(layerscope::LayersPacket* aPacket)
2321
0
{
2322
0
  DumpPacket(aPacket);
2323
0
2324
0
  if (GetRoot()) {
2325
0
    GetRoot()->Dump(aPacket, this);
2326
0
  }
2327
0
}
2328
2329
void
2330
LayerManager::Log(const char* aPrefix)
2331
0
{
2332
0
  if (!IsLogEnabled())
2333
0
    return;
2334
0
2335
0
  LogSelf(aPrefix);
2336
0
2337
0
  nsAutoCString pfx(aPrefix);
2338
0
  pfx += "  ";
2339
0
  if (!GetRoot()) {
2340
0
    MOZ_LAYERS_LOG(("%s(null)", pfx.get()));
2341
0
    return;
2342
0
  }
2343
0
2344
0
  GetRoot()->Log(pfx.get());
2345
0
}
2346
2347
void
2348
LayerManager::LogSelf(const char* aPrefix)
2349
0
{
2350
0
  nsAutoCString str;
2351
0
  std::stringstream ss;
2352
0
  PrintInfo(ss, aPrefix);
2353
0
  MOZ_LAYERS_LOG(("%s", ss.str().c_str()));
2354
0
}
2355
2356
void
2357
LayerManager::PrintInfo(std::stringstream& aStream, const char* aPrefix)
2358
0
{
2359
0
  aStream << aPrefix << nsPrintfCString("%sLayerManager (0x%p)", Name(), this).get();
2360
0
}
2361
2362
void
2363
LayerManager::DumpPacket(layerscope::LayersPacket* aPacket)
2364
0
{
2365
0
  using namespace layerscope;
2366
0
  // Add a new layer data (LayerManager)
2367
0
  LayersPacket::Layer* layer = aPacket->add_layer();
2368
0
  layer->set_type(LayersPacket::Layer::LayerManager);
2369
0
  layer->set_ptr(reinterpret_cast<uint64_t>(this));
2370
0
  // Layer Tree Root
2371
0
  layer->set_parentptr(0);
2372
0
}
2373
2374
/*static*/ bool
2375
LayerManager::IsLogEnabled()
2376
0
{
2377
0
  return MOZ_LOG_TEST(GetLog(), LogLevel::Debug);
2378
0
}
2379
2380
bool
2381
LayerManager::SetPendingScrollUpdateForNextTransaction(FrameMetrics::ViewID aScrollId,
2382
                                                       const ScrollUpdateInfo& aUpdateInfo)
2383
0
{
2384
0
  Layer* withPendingTransform = DepthFirstSearch<ForwardIterator>(GetRoot(),
2385
0
      [](Layer* aLayer) {
2386
0
        return aLayer->HasPendingTransform();
2387
0
      });
2388
0
  if (withPendingTransform) {
2389
0
    return false;
2390
0
  }
2391
0
2392
0
  mPendingScrollUpdates[aScrollId] = aUpdateInfo;
2393
0
  return true;
2394
0
}
2395
2396
Maybe<ScrollUpdateInfo>
2397
LayerManager::GetPendingScrollInfoUpdate(FrameMetrics::ViewID aScrollId)
2398
0
{
2399
0
  auto it = mPendingScrollUpdates.find(aScrollId);
2400
0
  if (it != mPendingScrollUpdates.end()) {
2401
0
    return Some(it->second);
2402
0
  }
2403
0
  return Nothing();
2404
0
}
2405
2406
void
2407
LayerManager::ClearPendingScrollInfoUpdate()
2408
0
{
2409
0
  mPendingScrollUpdates.clear();
2410
0
}
2411
2412
void
2413
PrintInfo(std::stringstream& aStream, HostLayer* aLayerComposite)
2414
0
{
2415
0
  if (!aLayerComposite) {
2416
0
    return;
2417
0
  }
2418
0
  if (const Maybe<ParentLayerIntRect>& clipRect = aLayerComposite->GetShadowClipRect()) {
2419
0
    AppendToString(aStream, *clipRect, " [shadow-clip=", "]");
2420
0
  }
2421
0
  if (!aLayerComposite->GetShadowBaseTransform().IsIdentity()) {
2422
0
    AppendToString(aStream, aLayerComposite->GetShadowBaseTransform(), " [shadow-transform=", "]");
2423
0
  }
2424
0
  if (!aLayerComposite->GetShadowVisibleRegion().IsEmpty()) {
2425
0
    AppendToString(aStream, aLayerComposite->GetShadowVisibleRegion().ToUnknownRegion(), " [shadow-visible=", "]");
2426
0
  }
2427
0
}
2428
2429
void
2430
SetAntialiasingFlags(Layer* aLayer, DrawTarget* aTarget)
2431
0
{
2432
0
  bool permitSubpixelAA = !(aLayer->GetContentFlags() & Layer::CONTENT_DISABLE_SUBPIXEL_AA);
2433
0
  if (aTarget->IsCurrentGroupOpaque()) {
2434
0
    aTarget->SetPermitSubpixelAA(permitSubpixelAA);
2435
0
    return;
2436
0
  }
2437
0
2438
0
  const IntRect& bounds = aLayer->GetVisibleRegion().GetBounds().ToUnknownRect();
2439
0
  gfx::Rect transformedBounds = aTarget->GetTransform().TransformBounds(gfx::Rect(Float(bounds.X()), Float(bounds.Y()),
2440
0
                                                                                  Float(bounds.Width()), Float(bounds.Height())));
2441
0
  transformedBounds.RoundOut();
2442
0
  IntRect intTransformedBounds;
2443
0
  transformedBounds.ToIntRect(&intTransformedBounds);
2444
0
  permitSubpixelAA &= !(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
2445
0
                      aTarget->GetOpaqueRect().Contains(intTransformedBounds);
2446
0
  aTarget->SetPermitSubpixelAA(permitSubpixelAA);
2447
0
}
2448
2449
IntRect
2450
ToOutsideIntRect(const gfxRect &aRect)
2451
0
{
2452
0
  return IntRect::RoundOut(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
2453
0
}
2454
2455
} // namespace layers
2456
} // namespace mozilla