Source code

Revision control

Other Tools

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 "FrameLayerBuilder.h"
8
9
#include <algorithm>
10
#include <deque>
11
#include <functional>
12
#include <utility>
13
14
#include "ActiveLayerTracker.h"
15
#include "BasicLayers.h"
16
#include "GeckoProfiler.h"
17
#include "ImageContainer.h"
18
#include "ImageLayers.h"
19
#include "LayerTreeInvalidation.h"
20
#include "LayerUserData.h"
21
#include "Layers.h"
22
#include "LayersLogging.h"
23
#include "MaskLayerImageCache.h"
24
#include "MatrixStack.h"
25
#include "UnitTransforms.h"
26
#include "Units.h"
27
#include "gfx2DGlue.h"
28
#include "gfxContext.h"
29
#include "gfxEnv.h"
30
#include "gfxUtils.h"
31
#include "mozilla/DebugOnly.h"
32
#include "mozilla/EffectCompositor.h"
33
#include "mozilla/LayerAnimationInfo.h"
34
#include "mozilla/LayerTimelineMarker.h"
35
#include "mozilla/LookAndFeel.h"
36
#include "mozilla/Maybe.h"
37
#include "mozilla/PerfStats.h"
38
#include "mozilla/PresShell.h"
39
#include "mozilla/ReverseIterator.h"
40
#include "mozilla/StaticPrefs_gfx.h"
41
#include "mozilla/StaticPrefs_layers.h"
42
#include "mozilla/StaticPrefs_layout.h"
43
#include "mozilla/Unused.h"
44
#include "mozilla/dom/EffectsInfo.h"
45
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
46
#include "mozilla/dom/RemoteBrowser.h"
47
#include "mozilla/gfx/2D.h"
48
#include "mozilla/gfx/Matrix.h"
49
#include "mozilla/gfx/Tools.h"
50
#include "mozilla/layers/ShadowLayers.h"
51
#include "mozilla/layers/TextureClient.h"
52
#include "mozilla/layers/TextureWrapperImage.h"
53
#include "mozilla/layers/WebRenderUserData.h"
54
#include "nsDisplayList.h"
55
#include "nsDocShell.h"
56
#include "nsIScrollableFrame.h"
57
#include "nsImageFrame.h"
58
#include "nsLayoutUtils.h"
59
#include "nsPresContext.h"
60
#include "nsPrintfCString.h"
61
#include "nsSVGIntegrationUtils.h"
62
#include "nsSubDocumentFrame.h"
63
#include "nsTransitionManager.h"
64
65
using namespace mozilla::layers;
66
using namespace mozilla::gfx;
67
using mozilla::UniquePtr;
68
using mozilla::WrapUnique;
69
70
// PaintedLayerData::mAssignedDisplayItems is a std::vector, which is
71
// non-memmovable
72
DECLARE_USE_COPY_CONSTRUCTORS(mozilla::PaintedLayerData);
73
74
namespace mozilla {
75
76
class PaintedDisplayItemLayerUserData;
77
78
static nsTHashtable<nsPtrHashKey<DisplayItemData>>* sAliveDisplayItemDatas;
79
80
/**
81
* The address of gPaintedDisplayItemLayerUserData is used as the user
82
* data key for PaintedLayers created by FrameLayerBuilder.
83
* It identifies PaintedLayers used to draw non-layer content, which are
84
* therefore eligible for recycling. We want display items to be able to
85
* create their own dedicated PaintedLayers in BuildLayer, if necessary,
86
* and we wouldn't want to accidentally recycle those.
87
* The user data is a PaintedDisplayItemLayerUserData.
88
*/
89
uint8_t gPaintedDisplayItemLayerUserData;
90
/**
91
* The address of gColorLayerUserData is used as the user
92
* data key for ColorLayers created by FrameLayerBuilder.
93
* The user data is null.
94
*/
95
uint8_t gColorLayerUserData;
96
/**
97
* The address of gImageLayerUserData is used as the user
98
* data key for ImageLayers created by FrameLayerBuilder.
99
* The user data is null.
100
*/
101
uint8_t gImageLayerUserData;
102
/**
103
* The address of gLayerManagerUserData is used as the user
104
* data key for retained LayerManagers managed by FrameLayerBuilder.
105
* The user data is a LayerManagerData.
106
*/
107
uint8_t gLayerManagerUserData;
108
/**
109
* The address of gMaskLayerUserData is used as the user
110
* data key for mask layers managed by FrameLayerBuilder.
111
* The user data is a MaskLayerUserData.
112
*/
113
uint8_t gMaskLayerUserData;
114
/**
115
* The address of gCSSMaskLayerUserData is used as the user
116
* data key for mask layers of css masking managed by FrameLayerBuilder.
117
* The user data is a CSSMaskLayerUserData.
118
*/
119
uint8_t gCSSMaskLayerUserData;
120
121
// a global cache of image containers used for mask layers
122
static MaskLayerImageCache* gMaskLayerImageCache = nullptr;
123
124
static inline MaskLayerImageCache* GetMaskLayerImageCache() {
125
if (!gMaskLayerImageCache) {
126
gMaskLayerImageCache = new MaskLayerImageCache();
127
}
128
129
return gMaskLayerImageCache;
130
}
131
132
struct DisplayItemEntry {
133
DisplayItemEntry(nsDisplayItem* aItem, DisplayItemEntryType aType)
134
: mItem(aItem), mType(aType) {}
135
136
nsDisplayItem* mItem;
137
DisplayItemEntryType mType;
138
};
139
140
/**
141
* Returns true if the given |aType| is an effect start marker.
142
*/
143
static bool IsEffectStartMarker(DisplayItemEntryType aType) {
144
return aType == DisplayItemEntryType::PushOpacity ||
145
aType == DisplayItemEntryType::PushOpacityWithBg ||
146
aType == DisplayItemEntryType::PushTransform;
147
}
148
149
/**
150
* Returns true if the given |aType| is an effect end marker.
151
*/
152
static bool IsEffectEndMarker(DisplayItemEntryType aType) {
153
return aType == DisplayItemEntryType::PopOpacity ||
154
aType == DisplayItemEntryType::PopTransform;
155
}
156
157
enum class MarkerType { StartMarker, EndMarker };
158
159
/**
160
* Returns true if the given nsDisplayOpacity |aItem| has had opacity applied
161
* to its children and can be flattened away.
162
*/
163
static bool IsOpacityAppliedToChildren(nsDisplayItem* aItem) {
164
MOZ_ASSERT(aItem->GetType() == DisplayItemType::TYPE_OPACITY);
165
return static_cast<nsDisplayOpacity*>(aItem)->OpacityAppliedToChildren();
166
}
167
168
/**
169
* Returns true if the given display item type supports flattening with markers.
170
*/
171
static bool SupportsFlatteningWithMarkers(const DisplayItemType& aType) {
172
return aType == DisplayItemType::TYPE_OPACITY ||
173
aType == DisplayItemType::TYPE_TRANSFORM;
174
}
175
176
/**
177
* Adds the effect marker to |aMarkers| based on the type of |aItem| and whether
178
* |markerType| is a start or end marker.
179
*/
180
template <MarkerType markerType>
181
static bool AddMarkerIfNeeded(nsDisplayItem* aItem,
182
std::deque<DisplayItemEntry>& aMarkers) {
183
const DisplayItemType type = aItem->GetType();
184
if (!SupportsFlatteningWithMarkers(type)) {
185
return false;
186
}
187
188
DisplayItemEntryType marker;
189
190
// Just a fancy way to avoid writing two separate functions to select between
191
// PUSH and POP markers. This is done during compile time based on |markerType|.
192
#define GET_MARKER(start_marker, end_marker) \
193
std::conditional< \
194
markerType == MarkerType::StartMarker, \
195
std::integral_constant<DisplayItemEntryType, start_marker>, \
196
std::integral_constant<DisplayItemEntryType, end_marker>>::type::value;
197
198
switch (type) {
199
case DisplayItemType::TYPE_OPACITY:
200
if (IsOpacityAppliedToChildren(aItem)) {
201
// TODO(miko): I am not a fan of this. The more correct solution would
202
// be to return an enum from nsDisplayItem::ShouldFlattenAway(), so that
203
// we could distinguish between different flattening methods and avoid
204
// entering this function when markers are not needed.
205
return false;
206
}
207
208
marker = GET_MARKER(DisplayItemEntryType::PushOpacity,
209
DisplayItemEntryType::PopOpacity);
210
break;
211
case DisplayItemType::TYPE_TRANSFORM:
212
marker = GET_MARKER(DisplayItemEntryType::PushTransform,
213
DisplayItemEntryType::PopTransform);
214
break;
215
default:
216
MOZ_ASSERT_UNREACHABLE("Invalid display item type!");
217
break;
218
}
219
220
aMarkers.emplace_back(aItem, marker);
221
return true;
222
}
223
224
DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey,
225
Layer* aLayer, nsIFrame* aFrame)
226
227
: mRefCnt(0),
228
mParent(aParent),
229
mLayer(aLayer),
230
mDisplayItemKey(aKey),
231
mItem(nullptr),
232
mUsed(true),
233
mIsInvalid(false),
234
mReusedItem(false) {
235
MOZ_COUNT_CTOR(DisplayItemData);
236
237
if (!sAliveDisplayItemDatas) {
238
sAliveDisplayItemDatas = new nsTHashtable<nsPtrHashKey<DisplayItemData>>();
239
}
240
MOZ_RELEASE_ASSERT(!sAliveDisplayItemDatas->Contains(this));
241
sAliveDisplayItemDatas->PutEntry(this);
242
243
MOZ_RELEASE_ASSERT(mLayer);
244
if (aFrame) {
245
AddFrame(aFrame);
246
}
247
}
248
249
void DisplayItemData::AddFrame(nsIFrame* aFrame) {
250
MOZ_RELEASE_ASSERT(mLayer);
251
MOZ_RELEASE_ASSERT(!mFrameList.Contains(aFrame));
252
mFrameList.AppendElement(aFrame);
253
254
SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
255
array.AppendElement(this);
256
}
257
258
void DisplayItemData::RemoveFrame(nsIFrame* aFrame) {
259
MOZ_RELEASE_ASSERT(mLayer);
260
bool result = mFrameList.RemoveElement(aFrame);
261
MOZ_RELEASE_ASSERT(result, "Can't remove a frame that wasn't added!");
262
263
SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
264
array.RemoveElement(this);
265
}
266
267
void DisplayItemData::EndUpdate() {
268
MOZ_RELEASE_ASSERT(mLayer);
269
mIsInvalid = false;
270
mUsed = false;
271
mReusedItem = false;
272
mOldTransform = nullptr;
273
}
274
275
void DisplayItemData::EndUpdate(UniquePtr<nsDisplayItemGeometry>&& aGeometry) {
276
MOZ_RELEASE_ASSERT(mLayer);
277
MOZ_ASSERT(mItem);
278
MOZ_ASSERT(mGeometry || aGeometry);
279
280
if (aGeometry) {
281
mGeometry = std::move(aGeometry);
282
}
283
mClip = mItem->GetClip();
284
mChangedFrameInvalidations.SetEmpty();
285
286
EndUpdate();
287
}
288
289
void DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState,
290
bool aFirstUpdate,
291
nsPaintedDisplayItem* aItem /* = nullptr */) {
292
bool isReused = false;
293
bool isMerged = false;
294
295
if (aItem) {
296
isReused = !aFirstUpdate ? aItem->IsReused() : false;
297
298
const nsDisplayWrapList* wraplist = aItem->AsDisplayWrapList();
299
isMerged = wraplist && wraplist->HasMergedFrames();
300
}
301
302
BeginUpdate(aLayer, aState, aItem, isReused, isMerged);
303
}
304
305
void DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState,
306
nsPaintedDisplayItem* aItem, bool aIsReused,
307
bool aIsMerged) {
308
MOZ_RELEASE_ASSERT(mLayer);
309
MOZ_RELEASE_ASSERT(aLayer);
310
mLayer = aLayer;
311
mOptLayer = nullptr;
312
mInactiveManager = nullptr;
313
mLayerState = aState;
314
mUsed = true;
315
316
if (aLayer->AsPaintedLayer()) {
317
if (aItem != mItem) {
318
aItem->SetDisplayItemData(this, aLayer->Manager());
319
} else {
320
MOZ_ASSERT(aItem->GetDisplayItemData() == this);
321
}
322
mReusedItem = aIsReused;
323
}
324
325
if (!aItem) {
326
return;
327
}
328
329
if (!aIsMerged && mFrameList.Length() == 1) {
330
MOZ_ASSERT(mFrameList[0] == aItem->Frame());
331
return;
332
}
333
334
// We avoid adding or removing element unnecessarily
335
// since we have to modify userdata each time
336
AutoTArray<nsIFrame*, 4> copy(mFrameList);
337
if (!copy.RemoveElement(aItem->Frame())) {
338
AddFrame(aItem->Frame());
339
mChangedFrameInvalidations.Or(mChangedFrameInvalidations,
340
aItem->Frame()->GetVisualOverflowRect());
341
}
342
343
if (aIsMerged) {
344
MOZ_ASSERT(aItem->AsDisplayWrapList());
345
346
for (nsIFrame* frame : aItem->AsDisplayWrapList()->GetMergedFrames()) {
347
if (!copy.RemoveElement(frame)) {
348
AddFrame(frame);
349
mChangedFrameInvalidations.Or(mChangedFrameInvalidations,
350
frame->GetVisualOverflowRect());
351
}
352
}
353
}
354
355
for (nsIFrame* frame : copy) {
356
RemoveFrame(frame);
357
mChangedFrameInvalidations.Or(mChangedFrameInvalidations,
358
frame->GetVisualOverflowRect());
359
}
360
}
361
362
static const nsIFrame* sDestroyedFrame = nullptr;
363
DisplayItemData::~DisplayItemData() {
364
MOZ_COUNT_DTOR(DisplayItemData);
365
366
if (mItem) {
367
MOZ_ASSERT(mItem->GetDisplayItemData() == this);
368
mItem->SetDisplayItemData(nullptr, nullptr);
369
}
370
371
for (uint32_t i = 0; i < mFrameList.Length(); i++) {
372
nsIFrame* frame = mFrameList[i];
373
if (frame == sDestroyedFrame) {
374
continue;
375
}
376
377
SmallPointerArray<DisplayItemData>& array = frame->DisplayItemData();
378
array.RemoveElement(this);
379
}
380
381
MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas);
382
nsPtrHashKey<mozilla::DisplayItemData>* entry =
383
sAliveDisplayItemDatas->GetEntry(this);
384
MOZ_RELEASE_ASSERT(entry);
385
386
sAliveDisplayItemDatas->RemoveEntry(entry);
387
388
if (sAliveDisplayItemDatas->Count() == 0) {
389
delete sAliveDisplayItemDatas;
390
sAliveDisplayItemDatas = nullptr;
391
}
392
}
393
394
void DisplayItemData::NotifyRemoved() {
395
if (mDisplayItemKey > static_cast<uint8_t>(DisplayItemType::TYPE_MAX)) {
396
// This is sort of a hack. The display item key has higher bits set, which
397
// means that it is not the only display item for the frame.
398
// This branch skips separator transforms.
399
return;
400
}
401
402
const DisplayItemType type = GetDisplayItemTypeFromKey(mDisplayItemKey);
403
404
if (type == DisplayItemType::TYPE_REMOTE) {
405
// TYPE_REMOTE doesn't support merging, so access it directly
406
MOZ_ASSERT(mFrameList.Length() == 1);
407
if (mFrameList.Length() != 1) {
408
return;
409
}
410
411
// This is a remote browser that is going away, notify it that it is now
412
// hidden
413
nsIFrame* frame = mFrameList[0];
414
nsSubDocumentFrame* subdoc = static_cast<nsSubDocumentFrame*>(frame);
415
nsFrameLoader* frameLoader = subdoc->FrameLoader();
416
if (frameLoader && frameLoader->GetRemoteBrowser()) {
417
frameLoader->GetRemoteBrowser()->UpdateEffects(
418
mozilla::dom::EffectsInfo::FullyHidden());
419
}
420
}
421
422
if (type != DisplayItemType::TYPE_TRANSFORM &&
423
type != DisplayItemType::TYPE_OPACITY &&
424
type != DisplayItemType::TYPE_BACKGROUND_COLOR) {
425
return;
426
}
427
428
for (nsIFrame* frame : mFrameList) {
429
EffectCompositor::ClearIsRunningOnCompositor(frame, type);
430
}
431
}
432
433
const nsRegion& DisplayItemData::GetChangedFrameInvalidations() {
434
return mChangedFrameInvalidations;
435
}
436
437
DisplayItemData* DisplayItemData::AssertDisplayItemData(
438
DisplayItemData* aData) {
439
MOZ_RELEASE_ASSERT(aData);
440
MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas &&
441
sAliveDisplayItemDatas->Contains(aData));
442
MOZ_RELEASE_ASSERT(aData->mLayer);
443
return aData;
444
}
445
446
/**
447
* This is the userdata we associate with a layer manager.
448
*/
449
class LayerManagerData : public LayerUserData {
450
public:
451
explicit LayerManagerData(LayerManager* aManager)
452
: mLayerManager(aManager),
453
#ifdef DEBUG_DISPLAY_ITEM_DATA
454
mParent(nullptr),
455
#endif
456
mInvalidateAllLayers(false) {
457
MOZ_COUNT_CTOR(LayerManagerData);
458
}
459
~LayerManagerData() override { MOZ_COUNT_DTOR(LayerManagerData); }
460
461
#ifdef DEBUG_DISPLAY_ITEM_DATA
462
void Dump(const char* aPrefix = "") {
463
printf_stderr("%sLayerManagerData %p\n", aPrefix, this);
464
465
for (auto& data : mDisplayItems) {
466
nsAutoCString prefix;
467
prefix += aPrefix;
468
prefix += " ";
469
470
const char* layerState;
471
switch (data->mLayerState) {
472
case LayerState::LAYER_NONE:
473
layerState = "LAYER_NONE";
474
break;
475
case LayerState::LAYER_INACTIVE:
476
layerState = "LAYER_INACTIVE";
477
break;
478
case LayerState::LAYER_ACTIVE:
479
layerState = "LAYER_ACTIVE";
480
break;
481
case LayerState::LAYER_ACTIVE_FORCE:
482
layerState = "LAYER_ACTIVE_FORCE";
483
break;
484
case LayerState::LAYER_ACTIVE_EMPTY:
485
layerState = "LAYER_ACTIVE_EMPTY";
486
break;
487
case LayerState::LAYER_SVG_EFFECTS:
488
layerState = "LAYER_SVG_EFFECTS";
489
break;
490
}
491
uint32_t mask = (1 << TYPE_BITS) - 1;
492
493
nsAutoCString str;
494
str += prefix;
495
str += nsPrintfCString("Frame %p ", data->mFrameList[0]);
496
str += nsDisplayItem::DisplayItemTypeName(
497
static_cast<nsDisplayItem::Type>(data->mDisplayItemKey & mask));
498
if ((data->mDisplayItemKey >> TYPE_BITS)) {
499
str += nsPrintfCString("(%i)", data->mDisplayItemKey >> TYPE_BITS);
500
}
501
str += nsPrintfCString(", %s, Layer %p", layerState, data->mLayer.get());
502
if (data->mOptLayer) {
503
str += nsPrintfCString(", OptLayer %p", data->mOptLayer.get());
504
}
505
if (data->mInactiveManager) {
506
str += nsPrintfCString(", InactiveLayerManager %p",
507
data->mInactiveManager.get());
508
}
509
str += "\n";
510
511
printf_stderr("%s", str.get());
512
513
if (data->mInactiveManager) {
514
prefix += " ";
515
printf_stderr("%sDumping inactive layer info:\n", prefix.get());
516
LayerManagerData* lmd = static_cast<LayerManagerData*>(
517
data->mInactiveManager->GetUserData(&gLayerManagerUserData));
518
lmd->Dump(prefix.get());
519
}
520
}
521
}
522
#endif
523
524
/**
525
* Tracks which frames have layers associated with them.
526
*/
527
LayerManager* mLayerManager;
528
#ifdef DEBUG_DISPLAY_ITEM_DATA
529
LayerManagerData* mParent;
530
#endif
531
std::vector<RefPtr<DisplayItemData>> mDisplayItems;
532
bool mInvalidateAllLayers;
533
};
534
535
/* static */
536
void FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame) {
537
RemoveFrameFromLayerManager(aFrame, aFrame->DisplayItemData());
538
aFrame->DisplayItemData().Clear();
539
540
// Destroying a WebRenderUserDataTable can cause destruction of other objects
541
// which can remove frame properties in their destructor. If we delete a frame
542
// property it runs the destructor of the stored object in the middle of
543
// updating the frame property table, so if the destruction of that object
544
// causes another update to the frame property table it would leave the frame
545
// property table in an inconsistent state. So we remove it from the table and
546
// then destroy it. (bug 1530657)
547
WebRenderUserDataTable* userDataTable =
548
aFrame->TakeProperty(WebRenderUserDataProperty::Key());
549
if (userDataTable) {
550
for (auto iter = userDataTable->Iter(); !iter.Done(); iter.Next()) {
551
iter.UserData()->RemoveFromTable();
552
}
553
delete userDataTable;
554
}
555
}
556
557
/**
558
* We keep a stack of these to represent the PaintedLayers that are
559
* currently available to have display items added to.
560
* We use a stack here because as much as possible we want to
561
* assign display items to existing PaintedLayers, and to the lowest
562
* PaintedLayer in z-order. This reduces the number of layers and
563
* makes it more likely a display item will be rendered to an opaque
564
* layer, giving us the best chance of getting subpixel AA.
565
*/
566
class PaintedLayerData {
567
public:
568
PaintedLayerData()
569
: mAnimatedGeometryRoot(nullptr),
570
mASR(nullptr),
571
mClipChain(nullptr),
572
mReferenceFrame(nullptr),
573
mLayer(nullptr),
574
mSolidColor(NS_RGBA(0, 0, 0, 0)),
575
mIsSolidColorInVisibleRegion(false),
576
mNeedComponentAlpha(false),
577
mForceTransparentSurface(false),
578
mHideAllLayersBelow(false),
579
mOpaqueForAnimatedGeometryRootParent(false),
580
mBackfaceHidden(false),
581
mDTCRequiresTargetConfirmation(false),
582
mImage(nullptr),
583
mItemClip(nullptr),
584
mNewChildLayersIndex(-1)
585
#ifdef DEBUG
586
,
587
mTransformLevel(0)
588
#endif
589
{
590
}
591
592
PaintedLayerData(PaintedLayerData&& aRhs) = default;
593
594
~PaintedLayerData() { MOZ_ASSERT(mTransformLevel == 0); }
595
596
#ifdef MOZ_DUMP_PAINTING
597
/**
598
* Keep track of important decisions for debugging.
599
*/
600
nsCString mLog;
601
602
# define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \
603
if (StaticPrefs::layers_dump_decision()) { \
604
pld->mLog.AppendPrintf("\t\t\t\t"); \
605
pld->mLog.AppendPrintf(__VA_ARGS__); \
606
}
607
#else
608
# define FLB_LOG_PAINTED_LAYER_DECISION(...)
609
#endif
610
611
/**
612
* Disables component alpha for |aItem| if the component alpha bounds are not
613
* contained in |mOpaqueRegion|. Alternatively if possible, sets
614
* |mNeedComponentAlpha| to true for this PaintedLayerData.
615
*/
616
bool SetupComponentAlpha(ContainerState* aState, nsPaintedDisplayItem* aItem,
617
const nsIntRect& aVisibleRect,
618
const TransformClipNode* aTransform);
619
620
/**
621
* Record that an item has been added to the PaintedLayer, so we
622
* need to update our regions.
623
* @param aVisibleRect the area of the item that's visible
624
* @param aSolidColor if non-null, the visible area of the item is
625
* a constant color given by *aSolidColor
626
*/
627
void Accumulate(ContainerState* aState, nsPaintedDisplayItem* aItem,
628
const nsIntRect& aVisibleRect, const nsRect& aContentRect,
629
const DisplayItemClip& aClip, LayerState aLayerState,
630
nsDisplayList* aList, DisplayItemEntryType aType,
631
nsTArray<size_t>& aOpacityIndices,
632
const RefPtr<TransformClipNode>& aTransform);
633
634
UniquePtr<InactiveLayerData> CreateInactiveLayerData(
635
ContainerState* aState, nsPaintedDisplayItem* aItem,
636
DisplayItemData* aData);
637
638
/**
639
* Updates the status of |mTransform| and |aOpacityIndices|, based on |aType|.
640
*/
641
void UpdateEffectStatus(DisplayItemEntryType aType,
642
nsTArray<size_t>& aOpacityIndices);
643
644
AnimatedGeometryRoot* GetAnimatedGeometryRoot() {
645
return mAnimatedGeometryRoot;
646
}
647
648
/**
649
* A region including the horizontal pan, vertical pan, and no action regions.
650
*/
651
nsRegion CombinedTouchActionRegion();
652
653
/**
654
* Add the given hit test info to the hit regions for this PaintedLayer.
655
*/
656
void AccumulateHitTestItem(ContainerState* aState, nsDisplayItem* aItem,
657
const DisplayItemClip& aClip,
658
TransformClipNode* aTransform);
659
660
void HitRegionsUpdated();
661
662
/**
663
* If this represents only a nsDisplayImage, and the image type supports being
664
* optimized to an ImageLayer, returns true.
665
*/
666
bool CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
667
668
/**
669
* If this represents only a nsDisplayImage, and the image type supports being
670
* optimized to an ImageLayer, returns an ImageContainer for the underlying
671
* image if one is available.
672
*/
673
already_AddRefed<ImageContainer> GetContainerForImageLayer(
674
nsDisplayListBuilder* aBuilder);
675
676
bool VisibleAboveRegionIntersects(const nsIntRegion& aRegion) const {
677
return !mVisibleAboveRegion.Intersect(aRegion).IsEmpty();
678
}
679
bool VisibleRegionIntersects(const nsIntRegion& aRegion) const {
680
return !mVisibleRegion.Intersect(aRegion).IsEmpty();
681
}
682
683
/**
684
* The owning ContainerState that created this PaintedLayerData.
685
*/
686
ContainerState* mState;
687
688
/**
689
* The region of visible content in the layer, relative to the
690
* container layer (which is at the snapped top-left of the display
691
* list reference frame).
692
*/
693
nsIntRegion mVisibleRegion;
694
/**
695
* The region of visible content in the layer that is opaque.
696
* Same coordinate system as mVisibleRegion.
697
*/
698
nsIntRegion mOpaqueRegion;
699
/**
700
* The definitely-hit region for this PaintedLayer.
701
*/
702
nsRegion mHitRegion;
703
/**
704
* The maybe-hit region for this PaintedLayer.
705
*/
706
nsRegion mMaybeHitRegion;
707
/**
708
* The dispatch-to-content hit region for this PaintedLayer.
709
*/
710
nsRegion mDispatchToContentHitRegion;
711
/**
712
* The region for this PaintedLayer that is sensitive to events
713
* but disallows panning and zooming. This is an approximation
714
* and any deviation from the true region will be part of the
715
* mDispatchToContentHitRegion.
716
*/
717
nsRegion mNoActionRegion;
718
/**
719
* The region for this PaintedLayer that is sensitive to events and
720
* allows horizontal panning but not zooming. This is an approximation
721
* and any deviation from the true region will be part of the
722
* mDispatchToContentHitRegion.
723
*/
724
nsRegion mHorizontalPanRegion;
725
/**
726
* The region for this PaintedLayer that is sensitive to events and
727
* allows vertical panning but not zooming. This is an approximation
728
* and any deviation from the true region will be part of the
729
* mDispatchToContentHitRegion.
730
*/
731
nsRegion mVerticalPanRegion;
732
733
bool mCollapsedTouchActions = false;
734
/**
735
* Scaled versions of the bounds of mHitRegion and mMaybeHitRegion.
736
* We store these because FindPaintedLayerFor() needs to consume them
737
* in this form, and it's a hot code path so we don't want to scale
738
* them inside that function.
739
*/
740
nsIntRect mScaledHitRegionBounds;
741
nsIntRect mScaledMaybeHitRegionBounds;
742
/**
743
* The "active scrolled root" for all content in the layer. Must
744
* be non-null; all content in a PaintedLayer must have the same
745
* active scrolled root.
746
*/
747
AnimatedGeometryRoot* mAnimatedGeometryRoot;
748
const ActiveScrolledRoot* mASR;
749
/**
750
* The chain of clips that should apply to this layer.
751
*/
752
const DisplayItemClipChain* mClipChain;
753
/**
754
* The offset between mAnimatedGeometryRoot and the reference frame.
755
*/
756
nsPoint mAnimatedGeometryRootOffset;
757
/**
758
* If non-null, the frame from which we'll extract "fixed positioning"
759
* metadata for this layer. This can be a position:fixed frame or a viewport
760
* frame; the latter case is used for background-attachment:fixed content.
761
*/
762
const nsIFrame* mReferenceFrame;
763
PaintedLayer* mLayer;
764
/**
765
* If mIsSolidColorInVisibleRegion is true, this is the color of the visible
766
* region.
767
*/
768
nscolor mSolidColor;
769
/**
770
* True if every pixel in mVisibleRegion will have color mSolidColor.
771
*/
772
bool mIsSolidColorInVisibleRegion;
773
/**
774
* True if there is any text visible in the layer that's over
775
* transparent pixels in the layer.
776
*/
777
bool mNeedComponentAlpha;
778
/**
779
* Set if the layer should be treated as transparent, even if its entire
780
* area is covered by opaque display items. For example, this needs to
781
* be set if something is going to "punch holes" in the layer by clearing
782
* part of its surface.
783
*/
784
bool mForceTransparentSurface;
785
/**
786
* Set if all layers below this PaintedLayer should be hidden.
787
*/
788
bool mHideAllLayersBelow;
789
/**
790
* Set if the opaque region for this layer can be applied to the parent
791
* animated geometry root of this layer's animated geometry root.
792
* We set this when a PaintedLayer's animated geometry root is a scrollframe
793
* and the PaintedLayer completely fills the displayport of the scrollframe.
794
*/
795
bool mOpaqueForAnimatedGeometryRootParent;
796
/**
797
* Set if the backface of this region is hidden to the user.
798
* Content that backface is hidden should not be draw on the layer
799
* with visible backface.
800
*/
801
bool mBackfaceHidden;
802
/**
803
* Set to true if events targeting the dispatch-to-content region
804
* require target confirmation.
805
* See CompositorHitTestFlags::eRequiresTargetConfirmation and
806
* EventRegions::mDTCRequiresTargetConfirmation.
807
*/
808
bool mDTCRequiresTargetConfirmation;
809
/**
810
* Stores the pointer to the nsDisplayImage if we want to
811
* convert this to an ImageLayer.
812
*/
813
nsDisplayImageContainer* mImage;
814
/**
815
* Stores the clip that we need to apply to the image or, if there is no
816
* image, a clip for SOME item in the layer. There is no guarantee which
817
* item's clip will be stored here and mItemClip should not be used to clip
818
* the whole layer - only some part of the clip should be used, as determined
819
* by PaintedDisplayItemLayerUserData::GetCommonClipCount() - which may even
820
* be no part at all.
821
*/
822
const DisplayItemClip* mItemClip;
823
/**
824
* Index of this layer in mNewChildLayers.
825
*/
826
int32_t mNewChildLayersIndex;
827
/**
828
* The region of visible content above the layer and below the
829
* next PaintedLayerData currently in the stack, if any.
830
* This is a conservative approximation: it contains the true region.
831
*/
832
nsIntRegion mVisibleAboveRegion;
833
/**
834
* All the display items that have been assigned to this painted layer.
835
* These items get added by Accumulate().
836
*/
837
std::vector<AssignedDisplayItem> mAssignedDisplayItems;
838
839
#ifdef DEBUG
840
/**
841
* Tracks the level of transform to ensure balanced PUSH/POP markers.
842
*/
843
int mTransformLevel;
844
#endif
845
};
846
847
struct NewLayerEntry {
848
NewLayerEntry()
849
: mAnimatedGeometryRoot(nullptr),
850
mASR(nullptr),
851
mClipChain(nullptr),
852
mScrollMetadataASR(nullptr),
853
mLayerContentsVisibleRect(0, 0, -1, -1),
854
mLayerState(LayerState::LAYER_INACTIVE),
855
mHideAllLayersBelow(false),
856
mOpaqueForAnimatedGeometryRootParent(false),
857
mPropagateComponentAlphaFlattening(true),
858
mUntransformedVisibleRegion(false),
859
mIsFixedToRootScrollFrame(false) {}
860
// mLayer is null if the previous entry is for a PaintedLayer that hasn't
861
// been optimized to some other form (yet).
862
RefPtr<Layer> mLayer;
863
AnimatedGeometryRoot* mAnimatedGeometryRoot;
864
const ActiveScrolledRoot* mASR;
865
const DisplayItemClipChain* mClipChain;
866
const ActiveScrolledRoot* mScrollMetadataASR;
867
// If non-null, this ScrollMetadata is set to the be the first ScrollMetadata
868
// on the layer.
869
UniquePtr<ScrollMetadata> mBaseScrollMetadata;
870
// The following are only used for retained layers (for occlusion
871
// culling of those layers). These regions are all relative to the
872
// container reference frame.
873
nsIntRegion mVisibleRegion;
874
nsIntRegion mOpaqueRegion;
875
// This rect is in the layer's own coordinate space. The computed visible
876
// region for the layer cannot extend beyond this rect.
877
nsIntRect mLayerContentsVisibleRect;
878
LayerState mLayerState;
879
bool mHideAllLayersBelow;
880
// When mOpaqueForAnimatedGeometryRootParent is true, the opaque region of
881
// this layer is opaque in the same position even subject to the animation of
882
// geometry of mAnimatedGeometryRoot. For example when mAnimatedGeometryRoot
883
// is a scrolled frame and the scrolled content is opaque everywhere in the
884
// displayport, we can set this flag.
885
// When this flag is set, we can treat this opaque region as covering
886
// content whose animated geometry root is the animated geometry root for
887
// mAnimatedGeometryRoot->GetParent().
888
bool mOpaqueForAnimatedGeometryRootParent;
889
890
// If true, then the content flags for this layer should contribute
891
// to our decision to flatten component alpha layers, false otherwise.
892
bool mPropagateComponentAlphaFlattening;
893
// mVisibleRegion is relative to the associated frame before
894
// transform.
895
bool mUntransformedVisibleRegion;
896
bool mIsFixedToRootScrollFrame;
897
};
898
899
class PaintedLayerDataTree;
900
901
/**
902
* This is tree node type for PaintedLayerDataTree.
903
* Each node corresponds to a different animated geometry root, and contains
904
* a stack of PaintedLayerDatas, in bottom-to-top order.
905
* There is at most one node per animated geometry root. The ancestor and
906
* descendant relations in PaintedLayerDataTree tree mirror those in the frame
907
* tree.
908
* Each node can have clip that describes the potential extents that items in
909
* this node can cover. If mHasClip is false, it means that the node's contents
910
* can move anywhere.
911
* Testing against the clip instead of the node's actual contents has the
912
* advantage that the node's contents can move or animate without affecting
913
* content in other nodes. So we don't need to re-layerize during animations
914
* (sync or async), and during async animations everything is guaranteed to
915
* look correct.
916
* The contents of a node's PaintedLayerData stack all share the node's
917
* animated geometry root. The child nodes are on top of the PaintedLayerData
918
* stack, in z-order, and the clip rects of the child nodes are allowed to
919
* intersect with the visible region or visible above region of their parent
920
* node's PaintedLayerDatas.
921
*/
922
class PaintedLayerDataNode {
923
public:
924
PaintedLayerDataNode(PaintedLayerDataTree& aTree,
925
PaintedLayerDataNode* aParent,
926
AnimatedGeometryRoot* aAnimatedGeometryRoot);
927
~PaintedLayerDataNode();
928
929
AnimatedGeometryRoot* GetAnimatedGeometryRoot() const {
930
return mAnimatedGeometryRoot;
931
}
932
933
/**
934
* Whether this node's contents can potentially intersect aRect.
935
* aRect is in our tree's ContainerState's coordinate space.
936
*/
937
bool Intersects(const nsIntRect& aRect) const {
938
return !mHasClip || mClipRect.Intersects(aRect);
939
}
940
941
/**
942
* Create a PaintedLayerDataNode for aAnimatedGeometryRoot, add it to our
943
* children, and return it.
944
*/
945
PaintedLayerDataNode* AddChildNodeFor(
946
AnimatedGeometryRoot* aAnimatedGeometryRoot);
947
948
/**
949
* Find a PaintedLayerData in our mPaintedLayerDataStack that aItem can be
950
* added to. Creates a new PaintedLayerData by calling
951
* aNewPaintedLayerCallback if necessary.
952
*/
953
template <typename NewPaintedLayerCallbackType>
954
PaintedLayerData* FindPaintedLayerFor(
955
const nsIntRect& aVisibleRect, bool aBackfaceHidden,
956
const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain,
957
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
958
959
/**
960
* Find an opaque background color for aRegion. Pulls a color from the parent
961
* geometry root if appropriate, but only if that color is present underneath
962
* the whole clip of this node, so that this node's contents can animate or
963
* move (possibly async) without having to change the background color.
964
* @param aUnderIndex Searching will start in mPaintedLayerDataStack right
965
* below aUnderIndex.
966
*/
967
enum { ABOVE_TOP = -1 };
968
nscolor FindOpaqueBackgroundColor(const nsIntRegion& aRegion,
969
int32_t aUnderIndex = ABOVE_TOP) const;
970
/**
971
* Same as FindOpaqueBackgroundColor, but only returns a color if absolutely
972
* nothing is in between, so that it can be used for a layer that can move
973
* anywhere inside our clip.
974
*/
975
nscolor FindOpaqueBackgroundColorCoveringEverything() const;
976
977
/**
978
* Adds aRect to this node's top PaintedLayerData's mVisibleAboveRegion,
979
* or mVisibleAboveBackgroundRegion if mPaintedLayerDataStack is empty.
980
*/
981
void AddToVisibleAboveRegion(const nsIntRect& aRect);
982
/**
983
* Call this if all of our existing content can potentially be covered, so
984
* nothing can merge with it and all new content needs to create new items
985
* on top. This will finish all of our children and pop our whole
986
* mPaintedLayerDataStack.
987
*/
988
void SetAllDrawingAbove();
989
990
/**
991
* Finish this node: Finish all children, finish our PaintedLayer contents,
992
* and (if requested) adjust our parent's visible above region to include
993
* our clip.
994
*/
995
void Finish(bool aParentNeedsAccurateVisibleAboveRegion);
996
997
/**
998
* Finish any children that intersect aRect.
999
*/
1000
void FinishChildrenIntersecting(const nsIntRect& aRect);
1001
1002
/**
1003
* Finish all children.
1004
*/
1005
void FinishAllChildren() { FinishAllChildren(true); }
1006
1007
protected:
1008
/**
1009
* Finish all items in mPaintedLayerDataStack and clear the stack.
1010
*/
1011
void PopAllPaintedLayerData();
1012
/**
1013
* Finish all of our child nodes, but don't touch mPaintedLayerDataStack.
1014
*/
1015
void FinishAllChildren(bool aThisNodeNeedsAccurateVisibleAboveRegion);
1016
/**
1017
* Pass off opaque background color searching to our parent node, if we have
1018
* one.
1019
*/
1020
nscolor FindOpaqueBackgroundColorInParentNode() const;
1021
1022
PaintedLayerDataTree& mTree;
1023
PaintedLayerDataNode* mParent;
1024
AnimatedGeometryRoot* mAnimatedGeometryRoot;
1025
1026
/**
1027
* Our contents: a PaintedLayerData stack and our child nodes.
1028
*/
1029
AutoTArray<PaintedLayerData, 3> mPaintedLayerDataStack;
1030
1031
/**
1032
* UniquePtr is used here in the sense of "unique ownership", i.e. there is
1033
* only one owner. Not in the sense of "this is the only pointer to the
1034
* node": There are two other, non-owning, pointers to our child nodes: The
1035
* node's respective children point to their parent node with their mParent
1036
* pointer, and the tree keeps a map of animated geometry root to node in its
1037
* mNodes member. These outside pointers are the reason that mChildren isn't
1038
* just an nsTArray<PaintedLayerDataNode> (since the pointers would become
1039
* invalid whenever the array expands its capacity).
1040
*/
1041
nsTArray<UniquePtr<PaintedLayerDataNode>> mChildren;
1042
1043
/**
1044
* The region that's covered between our "background" and the bottom of
1045
* mPaintedLayerDataStack. This is used to indicate whether we can pull
1046
* a background color from our parent node. If mVisibleAboveBackgroundRegion
1047
* should be considered infinite, mAllDrawingAboveBackground will be true and
1048
* the value of mVisibleAboveBackgroundRegion will be meaningless.
1049
*/
1050
nsIntRegion mVisibleAboveBackgroundRegion;
1051
1052
/**
1053
* Our clip, if we have any. If not, that means we can move anywhere, and
1054
* mHasClip will be false and mClipRect will be meaningless.
1055
*/
1056
nsIntRect mClipRect;
1057
bool mHasClip;
1058
1059
/**
1060
* Whether mVisibleAboveBackgroundRegion should be considered infinite.
1061
*/
1062
bool mAllDrawingAboveBackground;
1063
};
1064
1065
class ContainerState;
1066
1067
/**
1068
* A tree of PaintedLayerDataNodes. At any point in time, the tree only
1069
* contains nodes for animated geometry roots that new items can potentially
1070
* merge into. Any time content is added on top that overlaps existing things
1071
* in such a way that we no longer want to merge new items with some existing
1072
* content, that existing content gets "finished".
1073
* The public-facing methods of this class are FindPaintedLayerFor,
1074
* AddingOwnLayer, and Finish. The other public methods are for
1075
* PaintedLayerDataNode.
1076
* The tree calls out to its containing ContainerState for some things.
1077
* All coordinates / rects in the tree or the tree nodes are in the
1078
* ContainerState's coordinate space, i.e. relative to the reference frame and
1079
* in layer pixels.
1080
* The clip rects of sibling nodes never overlap. This is ensured by finishing
1081
* existing nodes before adding new ones, if this property were to be violated.
1082
* The root tree node doesn't get finished until the ContainerState is
1083
* finished.
1084
* The tree's root node is always the root reference frame of the builder. We
1085
* don't stop at the container state's mContainerAnimatedGeometryRoot because
1086
* some of our contents can have animated geometry roots that are not
1087
* descendants of the container's animated geometry root. Every animated
1088
* geometry root we encounter for our contents needs to have a defined place in
1089
* the tree.
1090
*/
1091
class PaintedLayerDataTree {
1092
public:
1093
PaintedLayerDataTree(ContainerState& aContainerState,
1094
nscolor& aBackgroundColor)
1095
: mContainerState(aContainerState),
1096
mContainerUniformBackgroundColor(aBackgroundColor),
1097
mForInactiveLayer(false) {}
1098
1099
~PaintedLayerDataTree() {
1100
MOZ_ASSERT(!mRoot);
1101
MOZ_ASSERT(mNodes.Count() == 0);
1102
}
1103
1104
void InitializeForInactiveLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot);
1105
1106
/**
1107
* Notify our contents that some non-PaintedLayer content has been added.
1108
* *aRect needs to be a rectangle that doesn't move with respect to
1109
* aAnimatedGeometryRoot and that contains the added item.
1110
* If aRect is null, the extents will be considered infinite.
1111
* If aOutUniformBackgroundColor is non-null, it will be set to an opaque
1112
* color that can be pulled into the background of the added content, or
1113
* transparent if that is not possible.
1114
*/
1115
void AddingOwnLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot,
1116
const nsIntRect* aRect,
1117
nscolor* aOutUniformBackgroundColor);
1118
1119
/**
1120
* Find a PaintedLayerData for aItem. This can either be an existing
1121
* PaintedLayerData from inside a node in our tree, or a new one that gets
1122
* created by a call out to aNewPaintedLayerCallback.
1123
*/
1124
template <typename NewPaintedLayerCallbackType>
1125
PaintedLayerData* FindPaintedLayerFor(
1126
AnimatedGeometryRoot* aAnimatedGeometryRoot,
1127
const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain,
1128
const nsIntRect& aVisibleRect, const bool aBackfaceHidden,
1129
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
1130
1131
/**
1132
* Finish everything.
1133
*/
1134
void Finish();
1135
1136
/**
1137
* Get the parent animated geometry root of aAnimatedGeometryRoot.
1138
* That's either aAnimatedGeometryRoot's animated geometry root, or, if
1139
* that's aAnimatedGeometryRoot itself, then it's the animated geometry
1140
* root for aAnimatedGeometryRoot's cross-doc parent frame.
1141
*/
1142
AnimatedGeometryRoot* GetParentAnimatedGeometryRoot(
1143
AnimatedGeometryRoot* aAnimatedGeometryRoot);
1144
1145
/**
1146
* Whether aAnimatedGeometryRoot has an intrinsic clip that doesn't move with
1147
* respect to aAnimatedGeometryRoot's parent animated geometry root.
1148
* If aAnimatedGeometryRoot is a scroll frame, this will be the scroll frame's
1149
* scroll port, otherwise there is no clip.
1150
* This method doesn't have much to do with PaintedLayerDataTree, but this is
1151
* where we have easy access to a display list builder, which we use to get
1152
* the clip rect result into the right coordinate space.
1153
*/
1154
bool IsClippedWithRespectToParentAnimatedGeometryRoot(
1155
AnimatedGeometryRoot* aAnimatedGeometryRoot, nsIntRect* aOutClip);
1156
1157
/**
1158
* Called by PaintedLayerDataNode when it is finished, so that we can drop
1159
* our pointers to it.
1160
*/
1161
void NodeWasFinished(AnimatedGeometryRoot* aAnimatedGeometryRoot);
1162
1163
nsDisplayListBuilder* Builder() const;
1164
ContainerState& ContState() const { return mContainerState; }
1165
nscolor UniformBackgroundColor() const {
1166
return mContainerUniformBackgroundColor;
1167
}
1168
1169
protected:
1170
/**
1171
* Finish all nodes that potentially intersect *aRect, where *aRect is a rect
1172
* that doesn't move with respect to aAnimatedGeometryRoot.
1173
* If aRect is null, *aRect will be considered infinite.
1174
*/
1175
void FinishPotentiallyIntersectingNodes(
1176
AnimatedGeometryRoot* aAnimatedGeometryRoot, const nsIntRect* aRect);
1177
1178
/**
1179
* Make sure that there is a node for aAnimatedGeometryRoot and all of its
1180
* ancestor geometry roots. Return the node for aAnimatedGeometryRoot.
1181
*/
1182
PaintedLayerDataNode* EnsureNodeFor(
1183
AnimatedGeometryRoot* aAnimatedGeometryRoot);
1184
1185
/**
1186
* Find an existing node in the tree for an ancestor of aAnimatedGeometryRoot.
1187
* *aOutAncestorChild will be set to the last ancestor that was encountered
1188
* in the search up from aAnimatedGeometryRoot; it will be a child animated
1189
* geometry root of the result, if neither are null.
1190
*/
1191
PaintedLayerDataNode* FindNodeForAncestorAnimatedGeometryRoot(
1192
AnimatedGeometryRoot* aAnimatedGeometryRoot,
1193
AnimatedGeometryRoot** aOutAncestorChild);
1194
1195
ContainerState& mContainerState;
1196
Maybe<PaintedLayerDataNode> mRoot;
1197
1198
/**
1199
* The uniform opaque color from behind this container layer, or
1200
* NS_RGBA(0,0,0,0) if the background behind this container layer is not
1201
* uniform and opaque. This color can be pulled into PaintedLayers that are
1202
* directly above the background.
1203
*/
1204
nscolor mContainerUniformBackgroundColor;
1205
1206
/**
1207
* A hash map for quick access the node belonging to a particular animated
1208
* geometry root.
1209
*/
1210
nsDataHashtable<nsPtrHashKey<AnimatedGeometryRoot>, PaintedLayerDataNode*>
1211
mNodes;
1212
1213
bool mForInactiveLayer;
1214
};
1215
1216
/**
1217
* This is a helper object used to build up the layer children for
1218
* a ContainerLayer.
1219
*/
1220
class ContainerState {
1221
public:
1222
ContainerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager,
1223
FrameLayerBuilder* aLayerBuilder, nsIFrame* aContainerFrame,
1224
nsDisplayItem* aContainerItem, const nsRect& aContainerBounds,
1225
ContainerLayer* aContainerLayer,
1226
const ContainerLayerParameters& aParameters,
1227
nscolor aBackgroundColor,
1228
const ActiveScrolledRoot* aContainerASR,
1229
const ActiveScrolledRoot* aContainerScrollMetadataASR,
1230
const ActiveScrolledRoot* aContainerCompositorASR)
1231
: mBuilder(aBuilder),
1232
mManager(aManager),
1233
mLayerBuilder(aLayerBuilder),
1234
mContainerFrame(aContainerFrame),
1235
mContainerLayer(aContainerLayer),
1236
mContainerBounds(aContainerBounds),
1237
mContainerASR(aContainerASR),
1238
mContainerScrollMetadataASR(aContainerScrollMetadataASR),
1239
mContainerCompositorASR(aContainerCompositorASR),
1240
mParameters(aParameters),
1241
mPaintedLayerDataTree(*this, aBackgroundColor),
1242
mLastDisplayPortAGR(nullptr),
1243
mContainerItem(aContainerItem) {
1244
nsPresContext* presContext = aContainerFrame->PresContext();
1245
mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
1246
mContainerReferenceFrame = const_cast<nsIFrame*>(
1247
aContainerItem ? aContainerItem->ReferenceFrameForChildren()
1248
: mBuilder->FindReferenceFrameFor(mContainerFrame));
1249
bool isAtRoot = !aContainerItem ||
1250
(aContainerItem->Frame() == mBuilder->RootReferenceFrame());
1251
MOZ_ASSERT(!isAtRoot ||
1252
mContainerReferenceFrame == mBuilder->RootReferenceFrame());
1253
mContainerAnimatedGeometryRoot =
1254
isAtRoot ? aBuilder->GetRootAnimatedGeometryRoot()
1255
: aContainerItem->GetAnimatedGeometryRoot();
1256
MOZ_ASSERT(
1257
!mBuilder->IsPaintingToWindow() ||
1258
nsLayoutUtils::IsAncestorFrameCrossDoc(
1259
mBuilder->RootReferenceFrame(), *mContainerAnimatedGeometryRoot));
1260
// When AllowResidualTranslation is false, display items will be drawn
1261
// scaled with a translation by integer pixels, so we know how the snapping
1262
// will work.
1263
mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() &&
1264
!mParameters.AllowResidualTranslation();
1265
CollectOldLayers();
1266
}
1267
1268
/**
1269
* This is the method that actually walks a display list and builds
1270
* the child layers.
1271
*/
1272
void ProcessDisplayItems(nsDisplayList* aList);
1273
/**
1274
* This finalizes all the open PaintedLayers by popping every element off
1275
* mPaintedLayerDataStack, then sets the children of the container layer
1276
* to be all the layers in mNewChildLayers in that order and removes any
1277
* layers as children of the container that aren't in mNewChildLayers.
1278
* @param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA,
1279
* set *aTextContentFlags to CONTENT_COMPONENT_ALPHA
1280
*/
1281
void Finish(uint32_t* aTextContentFlags,
1282
const nsIntRect& aContainerPixelBounds,
1283
nsDisplayList* aChildItems);
1284
1285
nscoord GetAppUnitsPerDevPixel() { return mAppUnitsPerDevPixel; }
1286
1287
nsIntRect ScaleToNearestPixels(const nsRect& aRect) const {
1288
return aRect.ScaleToNearestPixels(mParameters.mXScale, mParameters.mYScale,
1289
mAppUnitsPerDevPixel);
1290
}
1291
nsIntRect ScaleToOutsidePixels(const nsRect& aRect,
1292
bool aSnap = false) const {
1293
if (aRect.IsEmpty()) {
1294
return nsIntRect();
1295
}
1296
if (aSnap && mSnappingEnabled) {
1297
return ScaleToNearestPixels(aRect);
1298
}
1299
return aRect.ScaleToOutsidePixels(mParameters.mXScale, mParameters.mYScale,
1300
mAppUnitsPerDevPixel);
1301
}
1302
nsIntRect ScaleToInsidePixels(const nsRect& aRect, bool aSnap = false) const {
1303
if (aSnap && mSnappingEnabled) {
1304
return ScaleToNearestPixels(aRect);
1305
}
1306
return aRect.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale,
1307
mAppUnitsPerDevPixel);
1308
}
1309
nsIntRegion ScaleRegionToNearestPixels(const nsRegion& aRegion) const {
1310
return aRegion.ScaleToNearestPixels(
1311
mParameters.mXScale, mParameters.mYScale, mAppUnitsPerDevPixel);
1312
}
1313
nsIntRegion ScaleRegionToInsidePixels(const nsRegion& aRegion,
1314
bool aSnap = false) const {
1315
if (aSnap && mSnappingEnabled) {
1316
return ScaleRegionToNearestPixels(aRegion);
1317
}
1318
return aRegion.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale,
1319
mAppUnitsPerDevPixel);
1320
}
1321
1322
nsIntRegion ScaleRegionToOutsidePixels(const nsRegion& aRegion,
1323
bool aSnap = false) const {
1324
if (aRegion.IsEmpty()) {
1325
return nsIntRegion();
1326
}
1327
if (aSnap && mSnappingEnabled) {
1328
return ScaleRegionToNearestPixels(aRegion);
1329
}
1330
return aRegion.ScaleToOutsidePixels(
1331
mParameters.mXScale, mParameters.mYScale, mAppUnitsPerDevPixel);
1332
}
1333
1334
nsIFrame* GetContainerFrame() const { return mContainerFrame; }
1335
nsDisplayListBuilder* Builder() const { return mBuilder; }
1336
FrameLayerBuilder* LayerBuilder() const { return mLayerBuilder; }
1337
1338
/**
1339
* Check if we are currently inside an inactive layer.
1340
*/
1341
bool IsInInactiveLayer() const {
1342
return mLayerBuilder->GetContainingPaintedLayerData();
1343
}
1344
1345
/**
1346
* Sets aOuterVisibleRegion as aLayer's visible region.
1347
* @param aOuterVisibleRegion
1348
* is in the coordinate space of the container reference frame.
1349
* @param aLayerContentsVisibleRect, if non-null, is in the layer's own
1350
* coordinate system.
1351
* @param aOuterUntransformed is true if the given aOuterVisibleRegion
1352
* is already untransformed with the matrix of the layer.
1353
*/
1354
void SetOuterVisibleRegionForLayer(
1355
Layer* aLayer, const nsIntRegion& aOuterVisibleRegion,
1356
const nsIntRect* aLayerContentsVisibleRect = nullptr,
1357
bool aOuterUntransformed = false) const;
1358
1359
/**
1360
* Try to determine whether the PaintedLayer aData has a single opaque color
1361
* covering aRect. If successful, return that color, otherwise return
1362
* NS_RGBA(0,0,0,0).
1363
* If aRect turns out not to intersect any content in the layer,
1364
* *aOutIntersectsLayer will be set to false.
1365
*/
1366
nscolor FindOpaqueBackgroundColorInLayer(const PaintedLayerData* aData,
1367
const nsIntRect& aRect,
1368
bool* aOutIntersectsLayer) const;
1369
1370
/**
1371
* Indicate that we are done adding items to the PaintedLayer represented by
1372
* aData. Make sure that a real PaintedLayer exists for it, and set the final
1373
* visible region and opaque-content.
1374
*/
1375
template <typename FindOpaqueBackgroundColorCallbackType>
1376
void FinishPaintedLayerData(
1377
PaintedLayerData& aData,
1378
FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor);
1379
1380
protected:
1381
friend class PaintedLayerData;
1382
friend class FLBDisplayListIterator;
1383
1384
LayerManager::PaintedLayerCreationHint GetLayerCreationHint(
1385
AnimatedGeometryRoot* aAnimatedGeometryRoot);
1386
1387
/**
1388
* Creates a new PaintedLayer and sets up the transform on the PaintedLayer
1389
* to account for scrolling.
1390
*/
1391
already_AddRefed<PaintedLayer> CreatePaintedLayer(PaintedLayerData* aData);
1392
1393
/**
1394
* Find a PaintedLayer for recycling, recycle it and prepare it for use, or
1395
* return null if no suitable layer was found.
1396
*/
1397
already_AddRefed<PaintedLayer> AttemptToRecyclePaintedLayer(
1398
AnimatedGeometryRoot* aAnimatedGeometryRoot, nsDisplayItem* aItem,
1399
const nsPoint& aTopLeft, const nsIFrame* aReferenceFrame);
1400
/**
1401
* Recycle aLayer and do any necessary invalidation.
1402
*/
1403
PaintedDisplayItemLayerUserData* RecyclePaintedLayer(
1404
PaintedLayer* aLayer, AnimatedGeometryRoot* aAnimatedGeometryRoot,
1405
bool& didResetScrollPositionForLayerPixelAlignment);
1406
1407
/**
1408
* Perform the last step of CreatePaintedLayer / AttemptToRecyclePaintedLayer:
1409
* Initialize aData, set up the layer's transform for scrolling, and
1410
* invalidate the layer for layer pixel alignment changes if necessary.
1411
*/
1412
void PreparePaintedLayerForUse(
1413
PaintedLayer* aLayer, PaintedDisplayItemLayerUserData* aData,
1414
AnimatedGeometryRoot* aAnimatedGeometryRoot,
1415
const nsIFrame* aReferenceFrame, const nsPoint& aTopLeft,
1416
bool aDidResetScrollPositionForLayerPixelAlignment);
1417
1418
/**
1419
* Attempt to prepare an ImageLayer based upon the provided PaintedLayerData.
1420
* Returns nullptr on failure.
1421
*/
1422
already_AddRefed<Layer> PrepareImageLayer(PaintedLayerData* aData);
1423
1424
/**
1425
* Attempt to prepare a ColorLayer based upon the provided PaintedLayerData.
1426
* Returns nullptr on failure.
1427
*/
1428
already_AddRefed<Layer> PrepareColorLayer(PaintedLayerData* aData);
1429
1430
/**
1431
* Grab the next recyclable ColorLayer, or create one if there are no
1432
* more recyclable ColorLayers.
1433
*/
1434
already_AddRefed<ColorLayer> CreateOrRecycleColorLayer(
1435
PaintedLayer* aPainted);
1436
/**
1437
* Grab the next recyclable ImageLayer, or create one if there are no
1438
* more recyclable ImageLayers.
1439
*/
1440
already_AddRefed<ImageLayer> CreateOrRecycleImageLayer(
1441
PaintedLayer* aPainted);
1442
/**
1443
* Grab a recyclable ImageLayer for use as a mask layer for aLayer (that is a
1444
* mask layer which has been used for aLayer before), or create one if such
1445
* a layer doesn't exist.
1446
*
1447
* Since mask layers can exist either on the layer directly, or as a side-
1448
* attachment to FrameMetrics (for ancestor scrollframe clips), we key the
1449
* recycle operation on both the originating layer and the mask layer's
1450
* index in the layer, if any.
1451
*/
1452
struct MaskLayerKey;
1453
template <typename UserData>
1454
already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(
1455
const MaskLayerKey& aKey, UserData* (*aGetUserData)(Layer* aLayer),
1456
void (*aSetDefaultUserData)(Layer* aLayer));
1457
/**
1458
* Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes
1459
* them available for recycling.
1460
*/
1461
void CollectOldLayers();
1462
/**
1463
* If aItem used to belong to a PaintedLayer, invalidates the area of
1464
* aItem in that layer. If aNewLayer is a PaintedLayer, invalidates the area
1465
* of aItem in that layer.
1466
*/
1467
void InvalidateForLayerChange(nsDisplayItem* aItem, PaintedLayer* aNewLayer,
1468
DisplayItemData* aData);
1469
/**
1470
* Returns true if aItem's opaque area (in aOpaque) covers the entire
1471
* scrollable area of its presshell.
1472
*/
1473
bool ItemCoversScrollableArea(nsDisplayItem* aItem, const nsRegion& aOpaque);
1474
1475
/**
1476
* Set ScrollMetadata and scroll-induced clipping on aEntry's layer.
1477
*/
1478
void SetupScrollingMetadata(NewLayerEntry* aEntry);
1479
1480
/**
1481
* Applies occlusion culling.
1482
* For each layer in mNewChildLayers, remove from its visible region the
1483
* opaque regions of the layers at higher z-index, but only if they have
1484
* the same animated geometry root and fixed-pos frame ancestor.
1485
* The opaque region for the child layers that share the same animated
1486
* geometry root as the container frame is returned in
1487
* *aOpaqueRegionForContainer.
1488
*
1489
* Also sets scroll metadata on the layers.
1490
*/
1491
void PostprocessRetainedLayers(nsIntRegion* aOpaqueRegionForContainer);
1492
1493
/**
1494
* Computes the snapped opaque area of aItem. Sets aList's opaque flag
1495
* if it covers the entire list bounds. Sets *aHideAllLayersBelow to true
1496
* this item covers the entire viewport so that all layers below are
1497
* permanently invisible.
1498
*/
1499
nsIntRegion ComputeOpaqueRect(nsDisplayItem* aItem,
1500
AnimatedGeometryRoot* aAnimatedGeometryRoot,
1501
const ActiveScrolledRoot* aASR,
1502
const DisplayItemClip& aClip,
1503
nsDisplayList* aList, bool* aHideAllLayersBelow,
1504
bool* aOpaqueForAnimatedGeometryRootParent);
1505
1506
/**
1507
* Fills a PaintedLayerData object that is initialized for a layer that the
1508
* current item will be assigned to. Also creates mNewChildLayers entries.
1509
* @param aData The PaintedLayerData that will be filled.
1510
* @param aVisibleRect The visible rect of the item.
1511
* @param aAnimatedGeometryRoot The item's animated geometry root.
1512
* @param aASR The active scrolled root that moves this
1513
* PaintedLayer.
1514
* @param aClipChain The clip chain that the compositor needs to
1515
* apply to this layer.
1516
* @param aScrollMetadataASR The leaf ASR for which scroll metadata needs
1517
* to be set on the layer, because either the layer itself or its scrolled
1518
* clip need to move with that ASR.
1519
* @param aTopLeft The offset between aAnimatedGeometryRoot and
1520
* the reference frame.
1521
* @param aReferenceFrame The reference frame for the item.
1522
* @param aBackfaceHidden The backface visibility for the item frame.
1523
*/
1524
void NewPaintedLayerData(
1525
PaintedLayerData* aData, AnimatedGeometryRoot* aAnimatedGeometryRoot,
1526
const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain,
1527
const ActiveScrolledRoot* aScrollMetadataASR, const nsPoint& aTopLeft,
1528
const nsIFrame* aReferenceFrame, const bool aBackfaceHidden);
1529
1530
/* Build a mask layer to represent the clipping region. Will return null if
1531
* there is no clipping specified or a mask layer cannot be built.
1532
* Builds an ImageLayer for the appropriate backend; the mask is relative to
1533
* aLayer's visible region.
1534
* aLayer is the layer to be clipped.
1535
* relative to the container reference frame
1536
* aRoundedRectClipCount is used when building mask layers for PaintedLayers,
1537
*/
1538
void SetupMaskLayer(Layer* aLayer, const DisplayItemClip& aClip);
1539
1540
/**
1541
* If |aClip| has rounded corners, create a mask layer for them, and
1542
* add it to |aLayer|'s ancestor mask layers, returning an index into
1543
* the array of ancestor mask layers. Returns an empty Maybe if
1544
* |aClip| does not have rounded corners, or if no mask layer could
1545
* be created.
1546
*/
1547
Maybe<size_t> SetupMaskLayerForScrolledClip(Layer* aLayer,
1548
const DisplayItemClip& aClip);
1549
1550
/**
1551
* Create/find a mask layer with suitable size for aMaskItem to paint
1552
* css-positioned-masking onto.
1553
*/
1554
void SetupMaskLayerForCSSMask(Layer* aLayer,
1555
nsDisplayMasksAndClipPaths* aMaskItem);
1556
1557
already_AddRefed<Layer> CreateMaskLayer(
1558
Layer* aLayer, const DisplayItemClip& aClip,
1559
const Maybe<size_t>& aForAncestorMaskLayer);
1560
1561
/**
1562
* Get the display port for an AGR.
1563
* The result would be cached for later reusing.
1564
*/
1565
nsRect GetDisplayPortForAnimatedGeometryRoot(
1566
AnimatedGeometryRoot* aAnimatedGeometryRoot);
1567
1568
nsDisplayListBuilder* mBuilder;
1569
LayerManager* mManager;
1570
FrameLayerBuilder* mLayerBuilder;
1571
nsIFrame* mContainerFrame;
1572
nsIFrame* mContainerReferenceFrame;
1573
AnimatedGeometryRoot* mContainerAnimatedGeometryRoot;
1574
ContainerLayer* mContainerLayer;
1575
nsRect mContainerBounds;
1576
1577
// Due to the way we store scroll annotations in the layer tree, we need to
1578
// keep track of three (possibly different) ASRs here.
1579
// mContainerASR is the ASR of the container display item that this
1580
// ContainerState was created for.
1581
// mContainerScrollMetadataASR is the ASR of the leafmost scroll metadata
1582
// that's in effect on mContainerLayer.
1583
// mContainerCompositorASR is the ASR that mContainerLayer moves with on
1584
// the compositor / APZ side, taking into account both the scroll meta data
1585
// and the fixed position annotation on itself and its ancestors.
1586
const ActiveScrolledRoot* mContainerASR;
1587
const ActiveScrolledRoot* mContainerScrollMetadataASR;
1588
const ActiveScrolledRoot* mContainerCompositorASR;
1589
#ifdef DEBUG
1590
nsRect mAccumulatedChildBounds;
1591
#endif
1592
ContainerLayerParameters mParameters;
1593
/**
1594
* The region of PaintedLayers that should be invalidated every time
1595
* we recycle one.
1596
*/
1597
nsIntRegion mInvalidPaintedContent;
1598
PaintedLayerDataTree mPaintedLayerDataTree;
1599
/**
1600
* We collect the list of children in here. During ProcessDisplayItems,
1601
* the layers in this array either have mContainerLayer as their parent,
1602
* or no parent.
1603
* PaintedLayers have two entries in this array: the second one is used only
1604
* if the PaintedLayer is optimized away to a ColorLayer or ImageLayer. It's
1605
* essential that this array is only appended to, since PaintedLayerData
1606
* records the index of its PaintedLayer in this array.
1607
*/
1608
typedef AutoTArray<NewLayerEntry, 1> AutoLayersArray;
1609
AutoLayersArray mNewChildLayers;
1610
nsTHashtable<nsRefPtrHashKey<PaintedLayer>>
1611
mPaintedLayersAvailableForRecycling;
1612
nscoord mAppUnitsPerDevPixel;
1613
bool mSnappingEnabled;
1614
1615
struct MaskLayerKey {
1616
MaskLayerKey() : mLayer(nullptr) {}
1617
MaskLayerKey(Layer* aLayer, const Maybe<size_t>& aAncestorIndex)
1618
: mLayer(aLayer), mAncestorIndex(aAncestorIndex) {}
1619
1620
PLDHashNumber Hash() const {
1621
// Hash the layer and add the layer index to the hash.
1622
return (NS_PTR_TO_UINT32(mLayer) >> 2) +
1623
(mAncestorIndex ? (*mAncestorIndex + 1) : 0);
1624
}
1625
bool operator==(const MaskLayerKey& aOther) const {
1626
return mLayer == aOther.mLayer && mAncestorIndex == aOther.mAncestorIndex;
1627
}
1628
1629
Layer* mLayer;
1630
Maybe<size_t> mAncestorIndex;
1631
};
1632
1633
nsDataHashtable<nsGenericHashKey<MaskLayerKey>, RefPtr<ImageLayer>>
1634
mRecycledMaskImageLayers;
1635
// Keep display port of AGR to avoid wasting time on doing the same
1636
// thing repeatly.
1637
AnimatedGeometryRoot* mLastDisplayPortAGR;
1638
nsRect mLastDisplayPortRect;
1639
1640
nsDisplayItem* mContainerItem;
1641
1642
// Cache ScrollMetadata so it doesn't need recomputed if the ASR and clip are
1643
// unchanged. If mASR == nullptr then mMetadata is not valid.
1644
struct CachedScrollMetadata {
1645
const ActiveScrolledRoot* mASR;
1646
const DisplayItemClip* mClip;
1647
Maybe<ScrollMetadata> mMetadata;
1648
1649
CachedScrollMetadata() : mASR(nullptr), mClip(nullptr) {}
1650
};
1651
CachedScrollMetadata mCachedScrollMetadata;
1652
};
1653
1654
class FLBDisplayListIterator : public FlattenedDisplayListIterator {
1655
public:
1656
FLBDisplayListIterator(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
1657
ContainerState* aState)
1658
: FlattenedDisplayListIterator(aBuilder, aList, false), mState(aState) {
1659
MOZ_ASSERT(mState);
1660
1661
if (mState->mContainerItem) {
1662
// Add container item hit test information for processing, if needed.
1663
AddHitTestMarkerIfNeeded(mState->mContainerItem);
1664
}
1665
1666
ResolveFlattening();
1667
}
1668
1669
DisplayItemEntry GetNextEntry() {
1670
if (!mMarkers.empty()) {
1671
DisplayItemEntry entry = mMarkers.front();
1672
mMarkers.pop_front();
1673
return entry;
1674
}
1675
1676
return DisplayItemEntry{GetNextItem(), DisplayItemEntryType::Item};
1677
}
1678
1679
bool HasNext() const override {
1680
return FlattenedDisplayListIterator::HasNext() || !mMarkers.empty();
1681
}
1682
1683
private:
1684
void AddHitTestMarkerIfNeeded(nsDisplayItem* aItem) {
1685
if (aItem->HasHitTestInfo()) {
1686
mMarkers.emplace_back(aItem, DisplayItemEntryType::HitTestInfo);
1687
}
1688
}
1689
1690
bool ShouldFlattenNextItem() override {
1691
if (!FlattenedDisplayListIterator::ShouldFlattenNextItem()) {
1692
return false;
1693
}
1694
1695
nsDisplayItem* next = PeekNext();
1696
const DisplayItemType type = next->GetType();
1697
1698
if (type == DisplayItemType::TYPE_SVG_WRAPPER) {
1699
// We mark SetContainsSVG for the CONTENT_FRAME_TIME_WITH_SVG metric
1700
if (RefPtr<LayerManager> lm = mState->mBuilder->GetWidgetLayerManager()) {
1701
lm->SetContainsSVG(true);
1702
}
1703
}
1704
1705
if (!SupportsFlatteningWithMarkers(type)) {
1706
return true;
1707
}
1708
1709
if (type == DisplayItemType::TYPE_OPACITY &&
1710
IsOpacityAppliedToChildren(next)) {
1711
// This is the previous opacity flattening path, where the opacity has
1712
// been applied to children.
1713
return true;
1714
}
1715
1716
if (mState->IsInInactiveLayer() || !ItemWantsInactiveLayer(next)) {
1717
// Do not flatten nested inactive display items, or display items that
1718
// want an active layer.
1719
return false;
1720
}
1721
1722
// If we reach here, we will emit an effect start marker for
1723
// nsDisplayTransform or nsDisplayOpacity.
1724
MOZ_ASSERT(type == DisplayItemType::TYPE_TRANSFORM ||
1725
!IsOpacityAppliedToChildren(next));
1726
return true;
1727
}
1728
1729
void EnterChildList(nsDisplayItem* aContainerItem) override {
1730
mFlattenedLists.AppendElement(aContainerItem);
1731
AddMarkerIfNeeded<MarkerType::StartMarker>(aContainerItem, mMarkers);
1732
AddHitTestMarkerIfNeeded(aContainerItem);
1733
}
1734
1735
void ExitChildList() override {
1736
MOZ_ASSERT(!mFlattenedLists.IsEmpty());
1737
nsDisplayItem* aContainerItem = mFlattenedLists.PopLastElement();
1738
AddMarkerIfNeeded<MarkerType::EndMarker>(aContainerItem, mMarkers);
1739
}
1740
1741
bool ItemWantsInactiveLayer(nsDisplayItem* aItem) {
1742
const LayerState layerState = aItem->GetLayerState(
1743
mState->mBuilder, mState->mManager, mState->mParameters);
1744
1745
return layerState == LayerState::LAYER_INACTIVE;
1746
}
1747
1748
std::deque<DisplayItemEntry> mMarkers;
1749
AutoTArray<nsDisplayItem*, 16> mFlattenedLists;
1750
ContainerState* mState;
1751
};
1752
1753
class PaintedDisplayItemLayerUserData : public LayerUserData {
1754
public:
1755
PaintedDisplayItemLayerUserData()
1756
: mForcedBackgroundColor(NS_RGBA(0, 0, 0, 0)),
1757
mXScale(1.f),
1758
mYScale(1.f),
1759
mAppUnitsPerDevPixel(0),
1760
mTranslation(0, 0),
1761
mAnimatedGeometryRootPosition(0, 0),
1762
mLastItemCount(0),
1763
mContainerLayerFrame(nullptr),
1764
mHasExplicitLastPaintOffset(false),
1765
mDisabledAlpha(false) {}
1766
1767
NS_INLINE_DECL_REFCOUNTING(PaintedDisplayItemLayerUserData);
1768
1769
/**
1770
* A color that should be painted over the bounds of the layer's visible
1771
* region before any other content is painted.
1772
*/
1773
nscolor mForcedBackgroundColor;
1774
1775
/**
1776
* The resolution scale used.
1777
*/
1778
float mXScale, mYScale;
1779
1780
/**
1781
* The appunits per dev pixel for the items in this layer.
1782
*/
1783
nscoord mAppUnitsPerDevPixel;
1784
1785
/**
1786
* The offset from the PaintedLayer's 0,0 to the
1787
* reference frame. This isn't necessarily the same as the transform
1788
* set on the PaintedLayer since we might also be applying an extra
1789
* offset specified by the parent ContainerLayer/
1790
*/
1791
nsIntPoint mTranslation;
1792
1793
/**
1794
* We try to make 0,0 of the PaintedLayer be the top-left of the
1795
* border-box of the "active scrolled root" frame (i.e. the nearest ancestor
1796
* frame for the display items that is being actively scrolled). But
1797
* we force the PaintedLayer transform to be an integer translation, and we
1798
* may have a resolution scale, so we have to snap the PaintedLayer transform,
1799
* so 0,0 may not be exactly the top-left of the active scrolled root. Here we
1800
* store the coordinates in PaintedLayer space of the top-left of the
1801
* active scrolled root.
1802
*/
1803
gfxPoint mAnimatedGeometryRootPosition;
1804
1805
nsIntRegion mRegionToInvalidate;
1806
1807
// The offset between the active scrolled root of this layer
1808
// and the root of the container for the previous and current
1809
// paints respectively.
1810
nsPoint mLastAnimatedGeometryRootOrigin;
1811
nsPoint mAnimatedGeometryRootOrigin;
1812
1813
RefPtr<ColorLayer> mColorLayer;
1814
RefPtr<ImageLayer> mImageLayer;
1815
1816
// The region for which display item visibility for this layer has already
1817
// been calculated. Used to reduce the number of calls to
1818
// RecomputeVisibilityForItems if it is known in advance that a larger
1819
// region will be painted during a transaction than in a single call to
1820
// DrawPaintedLayer, for example when progressive paint is enabled.
1821
nsIntRegion mVisibilityComputedRegion;
1822
1823
// The area for which we called RecomputeVisibilityForItems on the
1824
// previous paint.
1825
nsRect mPreviousRecomputeVisibilityRect;
1826
1827
// The number of items assigned to this layer on the previous paint.
1828
size_t mLastItemCount;
1829
1830
// The translation set on this PaintedLayer before we started updating the
1831
// layer tree.
1832
nsIntPoint mLastPaintOffset;
1833
1834
// Temporary state only valid during the FrameLayerBuilder's lifetime.
1835
// FLB's mPaintedLayerItems is responsible for cleaning these up when
1836
// we finish painting to avoid dangling pointers.
1837
std::vector<AssignedDisplayItem> mItems;
1838
nsIFrame* mContainerLayerFrame;
1839
1840
bool mHasExplicitLastPaintOffset;
1841
1842
/**
1843
* This is set when the painted layer has no component alpha.
1844
*/
1845
bool mDisabledAlpha;
1846
1847
protected:
1848
~PaintedDisplayItemLayerUserData() override = default;
1849
};
1850
1851
FrameLayerBuilder::FrameLayerBuilder()
1852
: mRetainingManager(nullptr),
1853
mDisplayListBuilder(nullptr),
1854
mContainingPaintedLayer(nullptr),
1855
mInactiveLayerClip(nullptr),
1856
mInvalidateAllLayers(false),
1857
mInLayerTreeCompressionMode(false),
1858
mIsInactiveLayerManager(false) {
1859
MOZ_COUNT_CTOR(FrameLayerBuilder);
1860
}
1861
1862
FrameLayerBuilder::~FrameLayerBuilder() {
1863
GetMaskLayerImageCache()->Sweep();
1864
for (PaintedDisplayItemLayerUserData* userData : mPaintedLayerItems) {
1865
userData->mItems.clear();
1866
userData->mContainerLayerFrame = nullptr;
1867
}
1868
MOZ_COUNT_DTOR(FrameLayerBuilder);
1869
}
1870
1871
void FrameLayerBuilder::AddPaintedLayerItemsEntry(
1872
PaintedDisplayItemLayerUserData* aData) {
1873
mPaintedLayerItems.AppendElement(aData);
1874
}
1875
1876
/*
1877
* User data for layers which will be used as masks.
1878
*/
1879
struct MaskLayerUserData : public LayerUserData {
1880
MaskLayerUserData()
1881
: mScaleX(-1.0f), mScaleY(-1.0f), mAppUnitsPerDevPixel(-1) {}
1882
MaskLayerUserData(const DisplayItemClip& aClip, int32_t aAppUnitsPerDevPixel,
1883
const ContainerLayerParameters& aParams)
1884
: mScaleX(aParams.mXScale),
1885
mScaleY(aParams.mYScale),
1886
mOffset(aParams.mOffset),
1887
mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) {
1888
aClip.AppendRoundedRects(&mRoundedClipRects);
1889
}
1890
1891
void operator=(MaskLayerUserData&& aOther) {
1892
mScaleX = aOther.mScaleX;
1893
mScaleY = aOther.mScaleY;
1894
mOffset = aOther.mOffset;
1895
mAppUnitsPerDevPixel = aOther.mAppUnitsPerDevPixel;
1896
mRoundedClipRects.SwapElements(aOther.mRoundedClipRects);
1897
}
1898
1899
bool operator==(const MaskLayerUserData& aOther) const {
1900
return mRoundedClipRects == aOther.mRoundedClipRects &&
1901
mScaleX == aOther.mScaleX && mScaleY == aOther.mScaleY &&
1902
mOffset == aOther.mOffset &&
1903