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