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