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.h"
62
63
#include <algorithm>
64
#include <functional>
65
#include <deque>
66
67
using namespace mozilla::layers;
68
using namespace mozilla::gfx;
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(nsAutoPtr<nsDisplayItemGeometry> aGeometry) {
276
MOZ_RELEASE_ASSERT(mLayer);
277
MOZ_ASSERT(mItem);
278
MOZ_ASSERT(mGeometry || aGeometry);
279
280
if (aGeometry) {
281
mGeometry = 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
// FIXME: Bug 1530857: Add background_color.
423
if (type != DisplayItemType::TYPE_TRANSFORM &&
424
type != DisplayItemType::TYPE_OPACITY) {
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->RemoveProperty(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
mShouldPaintOnContentSide(false),
582
mDTCRequiresTargetConfirmation(false),
583
mImage(nullptr),
584
mItemClip(nullptr),
585
mNewChildLayersIndex(-1)
586
#ifdef DEBUG
587
,
588
mTransformLevel(0)
589
#endif
590
{
591
}
592
593
PaintedLayerData(PaintedLayerData&& aRhs) = default;
594
595
~PaintedLayerData() { MOZ_ASSERT(mTransformLevel == 0); }
596
597
#ifdef MOZ_DUMP_PAINTING
598
/**
599
* Keep track of important decisions for debugging.
600
*/
601
nsCString mLog;
602
603
# define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \
604
if (StaticPrefs::LayersDumpDecision()) { \
605
pld->mLog.AppendPrintf("\t\t\t\t"); \
606
pld->mLog.AppendPrintf(__VA_ARGS__); \
607
}
608
#else
609
# define FLB_LOG_PAINTED_LAYER_DECISION(...)
610
#endif
611
612
/**
613
* Disables component alpha for |aItem| if the component alpha bounds are not
614
* contained in |mOpaqueRegion|. Alternatively if possible, sets
615
* |mNeedComponentAlpha| to true for this PaintedLayerData.
616
*/
617
bool SetupComponentAlpha(ContainerState* aState, nsPaintedDisplayItem* aItem,
618
const nsIntRect& aVisibleRect,
619
const TransformClipNode* aTransform);
620
621
/**
622
* Record that an item has been added to the PaintedLayer, so we
623
* need to update our regions.
624
* @param aVisibleRect the area of the item that's visible
625
* @param aSolidColor if non-null, the visible area of the item is
626
* a constant color given by *aSolidColor
627
*/
628
void Accumulate(ContainerState* aState, nsPaintedDisplayItem* aItem,
629
const nsIntRect& aVisibleRect, const nsRect& aContentRect,
630
const DisplayItemClip& aClip, LayerState aLayerState,
631
nsDisplayList* aList, DisplayItemEntryType aType,
632
nsTArray<size_t>& aOpacityIndices,
633
const RefPtr<TransformClipNode>& aTransform);
634
635
UniquePtr<InactiveLayerData> CreateInactiveLayerData(
636
ContainerState* aState, nsPaintedDisplayItem* aItem,
637
DisplayItemData* aData);
638
639
/**
640
* Updates the status of |mTransform| and |aOpacityIndices|, based on |aType|.
641
*/
642
void UpdateEffectStatus(DisplayItemEntryType aType,
643
nsTArray<size_t>& aOpacityIndices);
644
645
AnimatedGeometryRoot* GetAnimatedGeometryRoot() {
646
return mAnimatedGeometryRoot;
647
}
648
649
/**
650
* A region including the horizontal pan, vertical pan, and no action regions.
651
*/
652
nsRegion CombinedTouchActionRegion();
653
654
/**
655
* Add the given hit test info to the hit regions for this PaintedLayer.
656
*/
657
void AccumulateHitTestItem(ContainerState* aState, nsDisplayItem* aItem,
658
const DisplayItemClip& aClip,
659
TransformClipNode* aTransform);
660
661
void HitRegionsUpdated();
662
663
/**
664
* If this represents only a nsDisplayImage, and the image type supports being
665
* optimized to an ImageLayer, returns true.
666
*/
667
bool CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
668
669
/**
670
* If this represents only a nsDisplayImage, and the image type supports being
671
* optimized to an ImageLayer, returns an ImageContainer for the underlying
672
* image if one is available.
673
*/
674
already_AddRefed<ImageContainer> GetContainerForImageLayer(
675
nsDisplayListBuilder* aBuilder);
676
677
bool VisibleAboveRegionIntersects(const nsIntRegion& aRegion) const {
678
return !mVisibleAboveRegion.Intersect(aRegion).IsEmpty();
679
}
680
bool VisibleRegionIntersects(const nsIntRegion& aRegion) const {
681
return !mVisibleRegion.Intersect(aRegion).IsEmpty();
682
}
683
684
/**
685
* The owning ContainerState that created this PaintedLayerData.
686
*/
687
ContainerState* mState;
688
689
/**
690
* The region of visible content in the layer, relative to the
691
* container layer (which is at the snapped top-left of the display
692
* list reference frame).
693
*/
694
nsIntRegion mVisibleRegion;
695
/**
696
* The region of visible content in the layer that is opaque.
697
* Same coordinate system as mVisibleRegion.
698
*/
699
nsIntRegion mOpaqueRegion;
700
/**
701
* The definitely-hit region for this PaintedLayer.
702
*/
703
nsRegion mHitRegion;
704
/**
705
* The maybe-hit region for this PaintedLayer.
706
*/
707
nsRegion mMaybeHitRegion;
708
/**
709
* The dispatch-to-content hit region for this PaintedLayer.
710
*/
711
nsRegion mDispatchToContentHitRegion;
712
/**
713
* The region for this PaintedLayer that is sensitive to events
714
* but disallows panning and zooming. This is an approximation
715
* and any deviation from the true region will be part of the
716
* mDispatchToContentHitRegion.
717
*/
718
nsRegion mNoActionRegion;
719
/**
720
* The region for this PaintedLayer that is sensitive to events and
721
* allows horizontal panning but not zooming. This is an approximation
722
* and any deviation from the true region will be part of the
723
* mDispatchToContentHitRegion.
724
*/
725
nsRegion mHorizontalPanRegion;
726
/**
727
* The region for this PaintedLayer that is sensitive to events and
728
* allows vertical panning but not zooming. This is an approximation
729
* and any deviation from the true region will be part of the
730
* mDispatchToContentHitRegion.
731
*/
732
nsRegion mVerticalPanRegion;
733
734
bool mCollapsedTouchActions = false;
735
/**
736
* Scaled versions of the bounds of mHitRegion and mMaybeHitRegion.
737
* We store these because FindPaintedLayerFor() needs to consume them
738
* in this form, and it's a hot code path so we don't want to scale
739
* them inside that function.
740
*/
741
nsIntRect mScaledHitRegionBounds;
742
nsIntRect mScaledMaybeHitRegionBounds;
743
/**
744
* The "active scrolled root" for all content in the layer. Must
745
* be non-null; all content in a PaintedLayer must have the same
746
* active scrolled root.
747
*/
748
AnimatedGeometryRoot* mAnimatedGeometryRoot;
749
const ActiveScrolledRoot* mASR;
750
/**
751
* The chain of clips that should apply to this layer.
752
*/
753
const DisplayItemClipChain* mClipChain;
754
/**
755
* The offset between mAnimatedGeometryRoot and the reference frame.
756
*/
757
nsPoint mAnimatedGeometryRootOffset;
758
/**
759
* If non-null, the frame from which we'll extract "fixed positioning"
760
* metadata for this layer. This can be a position:fixed frame or a viewport
761
* frame; the latter case is used for background-attachment:fixed content.
762
*/
763
const nsIFrame* mReferenceFrame;
764
PaintedLayer* mLayer;
765
/**
766
* If mIsSolidColorInVisibleRegion is true, this is the color of the visible
767
* region.
768
*/
769
nscolor mSolidColor;
770
/**
771
* True if every pixel in mVisibleRegion will have color mSolidColor.
772
*/
773
bool mIsSolidColorInVisibleRegion;
774
/**
775
* True if there is any text visible in the layer that's over
776
* transparent pixels in the layer.
777
*/
778
bool mNeedComponentAlpha;
779
/**
780
* Set if the layer should be treated as transparent, even if its entire
781
* area is covered by opaque display items. For example, this needs to
782
* be set if something is going to "punch holes" in the layer by clearing
783
* part of its surface.
784
*/
785
bool mForceTransparentSurface;
786
/**
787
* Set if all layers below this PaintedLayer should be hidden.
788
*/
789
bool mHideAllLayersBelow;
790
/**
791
* Set if the opaque region for this layer can be applied to the parent
792
* animated geometry root of this layer's animated geometry root.
793
* We set this when a PaintedLayer's animated geometry root is a scrollframe
794
* and the PaintedLayer completely fills the displayport of the scrollframe.
795
*/
796
bool mOpaqueForAnimatedGeometryRootParent;
797
/**
798
* Set if the backface of this region is hidden to the user.
799
* Content that backface is hidden should not be draw on the layer
800
* with visible backface.
801
*/
802
bool mBackfaceHidden;
803
/**
804
* Set if it is better to render this layer on the content process, for
805
* example if it contains native theme widgets.
806
*/
807
bool mShouldPaintOnContentSide;
808
/**
809
* Set to true if events targeting the dispatch-to-content region
810
* require target confirmation.
811
* See CompositorHitTestFlags::eRequiresTargetConfirmation and
812
* EventRegions::mDTCRequiresTargetConfirmation.
813
*/
814
bool mDTCRequiresTargetConfirmation;
815
/**
816
* Stores the pointer to the nsDisplayImage if we want to
817
* convert this to an ImageLayer.
818
*/
819
nsDisplayImageContainer* mImage;
820
/**
821
* Stores the clip that we need to apply to the image or, if there is no
822
* image, a clip for SOME item in the layer. There is no guarantee which
823
* item's clip will be stored here and mItemClip should not be used to clip
824
* the whole layer - only some part of the clip should be used, as determined
825
* by PaintedDisplayItemLayerUserData::GetCommonClipCount() - which may even
826
* be no part at all.
827
*/
828
const DisplayItemClip* mItemClip;
829
/**
830
* Index of this layer in mNewChildLayers.
831
*/
832
int32_t mNewChildLayersIndex;
833
/**
834
* The region of visible content above the layer and below the
835
* next PaintedLayerData currently in the stack, if any.
836
* This is a conservative approximation: it contains the true region.
837
*/
838
nsIntRegion mVisibleAboveRegion;
839
/**
840
* All the display items that have been assigned to this painted layer.
841
* These items get added by Accumulate().
842
*/
843
std::vector<AssignedDisplayItem> mAssignedDisplayItems;
844
845
#ifdef DEBUG
846
/**
847
* Tracks the level of transform to ensure balanced PUSH/POP markers.
848
*/
849
int mTransformLevel;
850
#endif
851
};
852
853
struct NewLayerEntry {
854
NewLayerEntry()
855
: mAnimatedGeometryRoot(nullptr),
856
mASR(nullptr),
857
mClipChain(nullptr),
858
mScrollMetadataASR(nullptr),
859
mLayerContentsVisibleRect(0, 0, -1, -1),
860
mLayerState(LayerState::LAYER_INACTIVE),
861
mHideAllLayersBelow(false),
862
mOpaqueForAnimatedGeometryRootParent(false),
863
mPropagateComponentAlphaFlattening(true),
864
mUntransformedVisibleRegion(false),
865
mIsFixedToRootScrollFrame(false) {}
866
// mLayer is null if the previous entry is for a PaintedLayer that hasn't
867
// been optimized to some other form (yet).
868
RefPtr<Layer> mLayer;
869
AnimatedGeometryRoot* mAnimatedGeometryRoot;
870
const ActiveScrolledRoot* mASR;
871
const DisplayItemClipChain* mClipChain;
872
const ActiveScrolledRoot* mScrollMetadataASR;
873
// If non-null, this ScrollMetadata is set to the be the first ScrollMetadata
874
// on the layer.
875
UniquePtr<ScrollMetadata> mBaseScrollMetadata;
876
// The following are only used for retained layers (for occlusion
877
// culling of those layers). These regions are all relative to the
878
// container reference frame.
879
nsIntRegion mVisibleRegion;
880
nsIntRegion mOpaqueRegion;
881
// This rect is in the layer's own coordinate space. The computed visible
882
// region for the layer cannot extend beyond this rect.
883
nsIntRect mLayerContentsVisibleRect;
884
LayerState mLayerState;
885
bool mHideAllLayersBelow;
886
// When mOpaqueForAnimatedGeometryRootParent is true, the opaque region of
887
// this layer is opaque in the same position even subject to the animation of
888
// geometry of mAnimatedGeometryRoot. For example when mAnimatedGeometryRoot
889
// is a scrolled frame and the scrolled content is opaque everywhere in the
890
// displayport, we can set this flag.
891
// When this flag is set, we can treat this opaque region as covering
892
// content whose animated geometry root is the animated geometry root for
893
// mAnimatedGeometryRoot->GetParent().
894
bool mOpaqueForAnimatedGeometryRootParent;
895
896
// If true, then the content flags for this layer should contribute
897
// to our decision to flatten component alpha layers, false otherwise.
898
bool mPropagateComponentAlphaFlattening;
899
// mVisibleRegion is relative to the associated frame before
900
// transform.
901
bool mUntransformedVisibleRegion;
902
bool mIsFixedToRootScrollFrame;
903
};
904
905
class PaintedLayerDataTree;
906
907
/**
908
* This is tree node type for PaintedLayerDataTree.
909
* Each node corresponds to a different animated geometry root, and contains
910
* a stack of PaintedLayerDatas, in bottom-to-top order.
911
* There is at most one node per animated geometry root. The ancestor and
912
* descendant relations in PaintedLayerDataTree tree mirror those in the frame
913
* tree.
914
* Each node can have clip that describes the potential extents that items in
915
* this node can cover. If mHasClip is false, it means that the node's contents
916
* can move anywhere.
917
* Testing against the clip instead of the node's actual contents has the
918
* advantage that the node's contents can move or animate without affecting
919
* content in other nodes. So we don't need to re-layerize during animations
920
* (sync or async), and during async animations everything is guaranteed to
921
* look correct.
922
* The contents of a node's PaintedLayerData stack all share the node's
923
* animated geometry root. The child nodes are on top of the PaintedLayerData
924
* stack, in z-order, and the clip rects of the child nodes are allowed to
925
* intersect with the visible region or visible above region of their parent
926
* node's PaintedLayerDatas.
927
*/
928
class PaintedLayerDataNode {
929
public:
930
PaintedLayerDataNode(PaintedLayerDataTree& aTree,
931
PaintedLayerDataNode* aParent,
932
AnimatedGeometryRoot* aAnimatedGeometryRoot);
933
~PaintedLayerDataNode();
934
935
AnimatedGeometryRoot* GetAnimatedGeometryRoot() const {
936
return mAnimatedGeometryRoot;
937
}
938
939
/**
940
* Whether this node's contents can potentially intersect aRect.
941
* aRect is in our tree's ContainerState's coordinate space.
942
*/
943
bool Intersects(const nsIntRect& aRect) const {
944
return !mHasClip || mClipRect.Intersects(aRect);
945
}
946
947
/**
948
* Create a PaintedLayerDataNode for aAnimatedGeometryRoot, add it to our
949
* children, and return it.
950
*/
951
PaintedLayerDataNode* AddChildNodeFor(
952
AnimatedGeometryRoot* aAnimatedGeometryRoot);
953
954
/**
955
* Find a PaintedLayerData in our mPaintedLayerDataStack that aItem can be
956
* added to. Creates a new PaintedLayerData by calling
957
* aNewPaintedLayerCallback if necessary.
958
*/
959
template <typename NewPaintedLayerCallbackType>
960
PaintedLayerData* FindPaintedLayerFor(
961
const nsIntRect& aVisibleRect, bool aBackfaceHidden,
962
const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain,
963
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
964
965
/**
966
* Find an opaque background color for aRegion. Pulls a color from the parent
967
* geometry root if appropriate, but only if that color is present underneath
968
* the whole clip of this node, so that this node's contents can animate or
969
* move (possibly async) without having to change the background color.
970
* @param aUnderIndex Searching will start in mPaintedLayerDataStack right
971
* below aUnderIndex.
972
*/
973
enum { ABOVE_TOP = -1 };
974
nscolor FindOpaqueBackgroundColor(const nsIntRegion& aRegion,
975
int32_t aUnderIndex = ABOVE_TOP) const;
976
/**
977
* Same as FindOpaqueBackgroundColor, but only returns a color if absolutely
978
* nothing is in between, so that it can be used for a layer that can move
979
* anywhere inside our clip.
980
*/
981
nscolor FindOpaqueBackgroundColorCoveringEverything() const;
982
983
/**
984
* Adds aRect to this node's top PaintedLayerData's mVisibleAboveRegion,
985
* or mVisibleAboveBackgroundRegion if mPaintedLayerDataStack is empty.
986
*/
987
void AddToVisibleAboveRegion(const nsIntRect& aRect);
988
/**
989
* Call this if all of our existing content can potentially be covered, so
990
* nothing can merge with it and all new content needs to create new items
991
* on top. This will finish all of our children and pop our whole
992
* mPaintedLayerDataStack.
993
*/
994
void SetAllDrawingAbove();
995
996
/**
997
* Finish this node: Finish all children, finish our PaintedLayer contents,
998
* and (if requested) adjust our parent's visible above region to include
999
* our clip.
1000
*/
1001
void Finish(bool aParentNeedsAccurateVisibleAboveRegion);
1002
1003
/**
1004
* Finish any children that intersect aRect.
1005
*/
1006
void FinishChildrenIntersecting(const nsIntRect& aRect);
1007
1008
/**
1009
* Finish all children.
1010
*/
1011
void FinishAllChildren() { FinishAllChildren(true); }
1012
1013
protected:
1014
/**
1015
* Finish all items in mPaintedLayerDataStack and clear the stack.
1016
*/
1017
void PopAllPaintedLayerData();
1018
/**
1019
* Finish all of our child nodes, but don't touch mPaintedLayerDataStack.
1020
*/
1021
void FinishAllChildren(bool aThisNodeNeedsAccurateVisibleAboveRegion);
1022
/**
1023
* Pass off opaque background color searching to our parent node, if we have
1024
* one.
1025
*/
1026
nscolor FindOpaqueBackgroundColorInParentNode() const;
1027
1028
PaintedLayerDataTree& mTree;
1029
PaintedLayerDataNode* mParent;
1030
AnimatedGeometryRoot* mAnimatedGeometryRoot;
1031
1032
/**
1033
* Our contents: a PaintedLayerData stack and our child nodes.
1034
*/
1035
AutoTArray<PaintedLayerData, 3> mPaintedLayerDataStack;
1036
1037
/**
1038
* UniquePtr is used here in the sense of "unique ownership", i.e. there is
1039
* only one owner. Not in the sense of "this is the only pointer to the
1040
* node": There are two other, non-owning, pointers to our child nodes: The
1041
* node's respective children point to their parent node with their mParent
1042
* pointer, and the tree keeps a map of animated geometry root to node in its
1043
* mNodes member. These outside pointers are the reason that mChildren isn't
1044
* just an nsTArray<PaintedLayerDataNode> (since the pointers would become
1045
* invalid whenever the array expands its capacity).
1046
*/
1047
nsTArray<UniquePtr<PaintedLayerDataNode>> mChildren;
1048
1049
/**
1050
* The region that's covered between our "background" and the bottom of
1051
* mPaintedLayerDataStack. This is used to indicate whether we can pull
1052
* a background color from our parent node. If mVisibleAboveBackgroundRegion
1053
* should be considered infinite, mAllDrawingAboveBackground will be true and
1054
* the value of mVisibleAboveBackgroundRegion will be meaningless.
1055
*/
1056
nsIntRegion mVisibleAboveBackgroundRegion;
1057
1058
/**
1059
* Our clip, if we have any. If not, that means we can move anywhere, and
1060
* mHasClip will be false and mClipRect will be meaningless.
1061
*/
1062
nsIntRect mClipRect;
1063
bool mHasClip;
1064
1065
/**
1066
* Whether mVisibleAboveBackgroundRegion should be considered infinite.
1067
*/
1068
bool mAllDrawingAboveBackground;
1069
};
1070
1071
class ContainerState;
1072
1073
/**
1074
* A tree of PaintedLayerDataNodes. At any point in time, the tree only
1075
* contains nodes for animated geometry roots that new items can potentially
1076
* merge into. Any time content is added on top that overlaps existing things
1077
* in such a way that we no longer want to merge new items with some existing
1078
* content, that existing content gets "finished".
1079
* The public-facing methods of this class are FindPaintedLayerFor,
1080
* AddingOwnLayer, and Finish. The other public methods are for
1081
* PaintedLayerDataNode.
1082
* The tree calls out to its containing ContainerState for some things.
1083
* All coordinates / rects in the tree or the tree nodes are in the
1084
* ContainerState's coordinate space, i.e. relative to the reference frame and
1085
* in layer pixels.
1086
* The clip rects of sibling nodes never overlap. This is ensured by finishing
1087
* existing nodes before adding new ones, if this property were to be violated.
1088
* The root tree node doesn't get finished until the ContainerState is
1089
* finished.
1090
* The tree's root node is always the root reference frame of the builder. We
1091
* don't stop at the container state's mContainerAnimatedGeometryRoot because
1092
* some of our contents can have animated geometry roots that are not
1093
* descendants of the container's animated geometry root. Every animated
1094
* geometry root we encounter for our contents needs to have a defined place in
1095
* the tree.
1096
*/
1097
class PaintedLayerDataTree {
1098
public:
1099
PaintedLayerDataTree(ContainerState& aContainerState,
1100
nscolor& aBackgroundColor)
1101
: mContainerState(aContainerState),
1102
mContainerUniformBackgroundColor(aBackgroundColor),
1103
mForInactiveLayer(false) {}
1104
1105
~PaintedLayerDataTree() {
1106
MOZ_ASSERT(!mRoot);
1107
MOZ_ASSERT(mNodes.Count() == 0);
1108
}
1109
1110
void InitializeForInactiveLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot);
1111
1112
/**
1113
* Notify our contents that some non-PaintedLayer content has been added.
1114
* *aRect needs to be a rectangle that doesn't move with respect to
1115
* aAnimatedGeometryRoot and that contains the added item.
1116
* If aRect is null, the extents will be considered infinite.
1117
* If aOutUniformBackgroundColor is non-null, it will be set to an opaque
1118
* color that can be pulled into the background of the added content, or
1119
* transparent if that is not possible.
1120
*/
1121
void AddingOwnLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot,
1122
const nsIntRect* aRect,
1123
nscolor* aOutUniformBackgroundColor);
1124
1125
/**
1126
* Find a PaintedLayerData for aItem. This can either be an existing
1127
* PaintedLayerData from inside a node in our tree, or a new one that gets
1128
* created by a call out to aNewPaintedLayerCallback.
1129
*/
1130
template <typename NewPaintedLayerCallbackType>
1131
PaintedLayerData* FindPaintedLayerFor(
1132
AnimatedGeometryRoot* aAnimatedGeometryRoot,
1133
const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain,
1134
const nsIntRect& aVisibleRect, const bool aBackfaceHidden,
1135
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
1136
1137
/**
1138
* Finish everything.
1139
*/
1140
void Finish();
1141
1142
/**
1143
* Get the parent animated geometry root of aAnimatedGeometryRoot.
1144
* That's either aAnimatedGeometryRoot's animated geometry root, or, if
1145
* that's aAnimatedGeometryRoot itself, then it's the animated geometry
1146
* root for aAnimatedGeometryRoot's cross-doc parent frame.
1147
*/
1148
AnimatedGeometryRoot* GetParentAnimatedGeometryRoot(
1149
AnimatedGeometryRoot* aAnimatedGeometryRoot);
1150
1151
/**
1152
* Whether aAnimatedGeometryRoot has an intrinsic clip that doesn't move with
1153
* respect to aAnimatedGeometryRoot's parent animated geometry root.
1154
* If aAnimatedGeometryRoot is a scroll frame, this will be the scroll frame's
1155
* scroll port, otherwise there is no clip.
1156
* This method doesn't have much to do with PaintedLayerDataTree, but this is
1157
* where we have easy access to a display list builder, which we use to get
1158
* the clip rect result into the right coordinate space.
1159
*/
1160
bool IsClippedWithRespectToParentAnimatedGeometryRoot(
1161
AnimatedGeometryRoot* aAnimatedGeometryRoot, nsIntRect* aOutClip);
1162
1163
/**
1164
* Called by PaintedLayerDataNode when it is finished, so that we can drop
1165
* our pointers to it.
1166
*/
1167
void NodeWasFinished(AnimatedGeometryRoot* aAnimatedGeometryRoot);
1168
1169
nsDisplayListBuilder* Builder() const;
1170
ContainerState& ContState() const { return mContainerState; }
1171
nscolor UniformBackgroundColor() const {
1172
return mContainerUniformBackgroundColor;
1173
}
1174
1175
protected:
1176
/**
1177
* Finish all nodes that potentially intersect *aRect, where *aRect is a rect
1178
* that doesn't move with respect to aAnimatedGeometryRoot.
1179
* If aRect is null, *aRect will be considered infinite.
1180
*/
1181
void FinishPotentiallyIntersectingNodes(
1182
AnimatedGeometryRoot* aAnimatedGeometryRoot, const nsIntRect* aRect);
1183
1184
/**
1185
* Make sure that there is a node for aAnimatedGeometryRoot and all of its
1186
* ancestor geometry roots. Return the node for aAnimatedGeometryRoot.
1187
*/
1188
PaintedLayerDataNode* EnsureNodeFor(
1189
AnimatedGeometryRoot* aAnimatedGeometryRoot);
1190
1191
/**
1192
* Find an existing node in the tree for an ancestor of aAnimatedGeometryRoot.
1193
* *aOutAncestorChild will be set to the last ancestor that was encountered
1194
* in the search up from aAnimatedGeometryRoot; it will be a child animated
1195
* geometry root of the result, if neither are null.
1196
*/
1197
PaintedLayerDataNode* FindNodeForAncestorAnimatedGeometryRoot(
1198
AnimatedGeometryRoot* aAnimatedGeometryRoot,
1199
AnimatedGeometryRoot** aOutAncestorChild);
1200
1201
ContainerState& mContainerState;
1202
Maybe<PaintedLayerDataNode> mRoot;
1203
1204
/**
1205
* The uniform opaque color from behind this container layer, or
1206
* NS_RGBA(0,0,0,0) if the background behind this container layer is not
1207
* uniform and opaque. This color can be pulled into PaintedLayers that are
1208
* directly above the background.
1209
*/
1210
nscolor mContainerUniformBackgroundColor;
1211
1212
/**
1213
* A hash map for quick access the node belonging to a particular animated
1214
* geometry root.
1215
*/
1216
nsDataHashtable<nsPtrHashKey<AnimatedGeometryRoot>, PaintedLayerDataNode*>
1217
mNodes;
1218
1219
bool mForInactiveLayer;
1220
};
1221
1222
/**
1223
* This is a helper object used to build up the layer children for
1224
* a ContainerLayer.
1225
*/
1226
class ContainerState {
1227
public:
1228
ContainerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager,
1229
FrameLayerBuilder* aLayerBuilder, nsIFrame* aContainerFrame,
1230
nsDisplayItem* aContainerItem, const nsRect& aContainerBounds,
1231
ContainerLayer* aContainerLayer,
1232
const ContainerLayerParameters& aParameters,
1233
nscolor aBackgroundColor,
1234
const ActiveScrolledRoot* aContainerASR,
1235
const ActiveScrolledRoot* aContainerScrollMetadataASR,
1236
const ActiveScrolledRoot* aContainerCompositorASR)
1237
: mBuilder(aBuilder),
1238
mManager(aManager),
1239
mLayerBuilder(aLayerBuilder),
1240
mContainerFrame(aContainerFrame),
1241
mContainerLayer(aContainerLayer),
1242
mContainerBounds(aContainerBounds),
1243
mContainerASR(aContainerASR),
1244
mContainerScrollMetadataASR(aContainerScrollMetadataASR),
1245
mContainerCompositorASR(aContainerCompositorASR),
1246
mParameters(aParameters),
1247
mPaintedLayerDataTree(*this, aBackgroundColor),
1248
mLastDisplayPortAGR(nullptr),
1249
mContainerItem(aContainerItem) {
1250
nsPresContext* presContext = aContainerFrame->PresContext();
1251
mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
1252
mContainerReferenceFrame = const_cast<nsIFrame*>(
1253
aContainerItem ? aContainerItem->ReferenceFrameForChildren()
1254
: mBuilder->FindReferenceFrameFor(mContainerFrame));
1255
bool isAtRoot = !aContainerItem ||
1256
(aContainerItem->Frame() == mBuilder->RootReferenceFrame());
1257
MOZ_ASSERT(!isAtRoot ||
1258
mContainerReferenceFrame == mBuilder->RootReferenceFrame());
1259
mContainerAnimatedGeometryRoot =
1260
isAtRoot ? aBuilder->GetRootAnimatedGeometryRoot()
1261
: aContainerItem->GetAnimatedGeometryRoot();
1262
MOZ_ASSERT(
1263
!mBuilder->IsPaintingToWindow() ||
1264
nsLayoutUtils::IsAncestorFrameCrossDoc(
1265
mBuilder->RootReferenceFrame(), *mContainerAnimatedGeometryRoot));
1266
// When AllowResidualTranslation is false, display items will be drawn
1267
// scaled with a translation by integer pixels, so we know how the snapping
1268
// will work.
1269
mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() &&
1270
!mParameters.AllowResidualTranslation();
1271
CollectOldLayers();
1272
}
1273
1274
/**
1275
* This is the method that actually walks a display list and builds
1276
* the child layers.
1277
*/
1278
void ProcessDisplayItems(nsDisplayList* aList);
1279
/**
1280
* This finalizes all the open PaintedLayers by popping every element off
1281
* mPaintedLayerDataStack, then sets the children of the container layer
1282
* to be all the layers in mNewChildLayers in that order and removes any
1283
* layers as children of the container that aren't in mNewChildLayers.
1284
* @param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA,
1285
* set *aTextContentFlags to CONTENT_COMPONENT_ALPHA
1286
*/
1287
void Finish(uint32_t* aTextContentFlags,
1288
const nsIntRect& aContainerPixelBounds,
1289
nsDisplayList* aChildItems);
1290
1291
nscoord GetAppUnitsPerDevPixel() { return mAppUnitsPerDevPixel; }
1292
1293
nsIntRect ScaleToNearestPixels(const nsRect& aRect) const {
1294
return aRect.ScaleToNearestPixels(mParameters.mXScale, mParameters.mYScale,
1295
mAppUnitsPerDevPixel);
1296
}
1297
nsIntRect ScaleToOutsidePixels(const nsRect& aRect,
1298
bool aSnap = false) const {
1299
if (aRect.IsEmpty()) {
1300
return nsIntRect();
1301
}
1302
if (aSnap && mSnappingEnabled) {
1303
return ScaleToNearestPixels(aRect);
1304
}
1305
return aRect.ScaleToOutsidePixels(mParameters.mXScale, mParameters.mYScale,
1306
mAppUnitsPerDevPixel);
1307
}
1308
nsIntRect ScaleToInsidePixels(const nsRect& aRect, bool aSnap = false) const {
1309
if (aSnap && mSnappingEnabled) {
1310
return ScaleToNearestPixels(aRect);
1311
}
1312
return aRect.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale,
1313
mAppUnitsPerDevPixel);
1314
}
1315
nsIntRegion ScaleRegionToNearestPixels(const nsRegion& aRegion) const {
1316
return aRegion.ScaleToNearestPixels(
1317
mParameters.mXScale, mParameters.mYScale, mAppUnitsPerDevPixel);
1318
}
1319
nsIntRegion ScaleRegionToInsidePixels(const nsRegion& aRegion,
1320
bool aSnap = false) const {
1321
if (aSnap && mSnappingEnabled) {
1322
return ScaleRegionToNearestPixels(aRegion);
1323
}
1324
return aRegion.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale,
1325
mAppUnitsPerDevPixel);
1326
}
1327
1328
nsIntRegion ScaleRegionToOutsidePixels(const nsRegion& aRegion,
1329
bool aSnap = false) const {
1330
if (aRegion.IsEmpty()) {
1331
return nsIntRegion();
1332
}
1333
if (aSnap && mSnappingEnabled) {
1334
return ScaleRegionToNearestPixels(aRegion);
1335
}
1336
return aRegion.ScaleToOutsidePixels(
1337
mParameters.mXScale, mParameters.mYScale, mAppUnitsPerDevPixel);
1338
}
1339
1340
nsIFrame* GetContainerFrame() const { return mContainerFrame; }
1341
nsDisplayListBuilder* Builder() const { return mBuilder; }
1342
FrameLayerBuilder* LayerBuilder() const { return mLayerBuilder; }
1343
1344
/**
1345
* Check if we are currently inside an inactive layer.
1346
*/
1347
bool IsInInactiveLayer() const {
1348
return mLayerBuilder->GetContainingPaintedLayerData();
1349
}
1350
1351
/**
1352
* Sets aOuterVisibleRegion as aLayer's visible region.
1353
* @param aOuterVisibleRegion
1354
* is in the coordinate space of the container reference frame.
1355
* @param aLayerContentsVisibleRect, if non-null, is in the layer's own
1356
* coordinate system.
1357
* @param aOuterUntransformed is true if the given aOuterVisibleRegion
1358
* is already untransformed with the matrix of the layer.
1359
*/
1360
void SetOuterVisibleRegionForLayer(
1361
Layer* aLayer, const nsIntRegion& aOuterVisibleRegion,
1362
const nsIntRect* aLayerContentsVisibleRect = nullptr,
1363
bool aOuterUntransformed = false) const;
1364
1365
/**
1366
* Try to determine whether the PaintedLayer aData has a single opaque color
1367
* covering aRect. If successful, return that color, otherwise return
1368
* NS_RGBA(0,0,0,0).
1369
* If aRect turns out not to intersect any content in the layer,
1370
* *aOutIntersectsLayer will be set to false.
1371
*/
1372
nscolor FindOpaqueBackgroundColorInLayer(const PaintedLayerData* aData,
1373
const nsIntRect& aRect,
1374
bool* aOutIntersectsLayer) const;
1375
1376
/**
1377
* Indicate that we are done adding items to the PaintedLayer represented by
1378
* aData. Make sure that a real PaintedLayer exists for it, and set the final
1379
* visible region and opaque-content.
1380
*/
1381
template <typename FindOpaqueBackgroundColorCallbackType>
1382
void FinishPaintedLayerData(
1383
PaintedLayerData& aData,
1384
FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor);
1385
1386
protected:
1387
friend class PaintedLayerData;
1388
friend class FLBDisplayListIterator;
1389
1390
LayerManager::PaintedLayerCreationHint GetLayerCreationHint(
1391
AnimatedGeometryRoot* aAnimatedGeometryRoot);
1392
1393
/**
1394
* Creates a new PaintedLayer and sets up the transform on the PaintedLayer
1395
* to account for scrolling.
1396
*/
1397
already_AddRefed<PaintedLayer> CreatePaintedLayer(PaintedLayerData* aData);
1398
1399
/**
1400
* Find a PaintedLayer for recycling, recycle it and prepare it for use, or
1401
* return null if no suitable layer was found.
1402
*/
1403
already_AddRefed<PaintedLayer> AttemptToRecyclePaintedLayer(
1404
AnimatedGeometryRoot* aAnimatedGeometryRoot, nsDisplayItem* aItem,
1405
const nsPoint& aTopLeft, const nsIFrame* aReferenceFrame);
1406
/**
1407
* Recycle aLayer and do any necessary invalidation.
1408
*/
1409
PaintedDisplayItemLayerUserData* RecyclePaintedLayer(
1410
PaintedLayer* aLayer, AnimatedGeometryRoot* aAnimatedGeometryRoot,
1411
bool& didResetScrollPositionForLayerPixelAlignment);
1412
1413
/**
1414
* Perform the last step of CreatePaintedLayer / AttemptToRecyclePaintedLayer:
1415
* Initialize aData, set up the layer's transform for scrolling, and
1416
* invalidate the layer for layer pixel alignment changes if necessary.
1417
*/
1418
void PreparePaintedLayerForUse(
1419
PaintedLayer* aLayer, PaintedDisplayItemLayerUserData* aData,
1420
AnimatedGeometryRoot* aAnimatedGeometryRoot,
1421
const nsIFrame* aReferenceFrame, const nsPoint& aTopLeft,
1422
bool aDidResetScrollPositionForLayerPixelAlignment);
1423
1424
/**
1425
* Attempt to prepare an ImageLayer based upon the provided PaintedLayerData.
1426
* Returns nullptr on failure.
1427
*/
1428
already_AddRefed<Layer> PrepareImageLayer(PaintedLayerData* aData);
1429
1430
/**
1431
* Attempt to prepare a ColorLayer based upon the provided PaintedLayerData.
1432
* Returns nullptr on failure.
1433
*/
1434
already_AddRefed<Layer> PrepareColorLayer(PaintedLayerData* aData);
1435
1436
/**
1437
* Grab the next recyclable ColorLayer, or create one if there are no
1438
* more recyclable ColorLayers.
1439
*/
1440
already_AddRefed<ColorLayer> CreateOrRecycleColorLayer(
1441
PaintedLayer* aPainted);
1442
/**
1443
* Grab the next recyclable ImageLayer, or create one if there are no
1444
* more recyclable ImageLayers.
1445
*/
1446
already_AddRefed<ImageLayer> CreateOrRecycleImageLayer(
1447
PaintedLayer* aPainted);
1448
/**
1449
* Grab a recyclable ImageLayer for use as a mask layer for aLayer (that is a
1450
* mask layer which has been used for aLayer before), or create one if such
1451
* a layer doesn't exist.
1452
*
1453
* Since mask layers can exist either on the layer directly, or as a side-
1454
* attachment to FrameMetrics (for ancestor scrollframe clips), we key the
1455
* recycle operation on both the originating layer and the mask layer's
1456
* index in the layer, if any.
1457
*/
1458
struct MaskLayerKey;
1459
template <typename UserData>
1460
already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(
1461
const MaskLayerKey& aKey, UserData* (*aGetUserData)(Layer* aLayer),
1462
void (*aSetDefaultUserData)(Layer* aLayer));
1463
/**
1464
* Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes
1465
* them available for recycling.
1466
*/
1467
void CollectOldLayers();
1468
/**
1469
* If aItem used to belong to a PaintedLayer, invalidates the area of
1470
* aItem in that layer. If aNewLayer is a PaintedLayer, invalidates the area
1471
* of aItem in that layer.
1472
*/
1473
void InvalidateForLayerChange(nsDisplayItem* aItem, PaintedLayer* aNewLayer,
1474
DisplayItemData* aData);
1475
/**
1476
* Returns true if aItem's opaque area (in aOpaque) covers the entire
1477
* scrollable area of its presshell.
1478
*/
1479
bool ItemCoversScrollableArea(nsDisplayItem* aItem, const nsRegion& aOpaque);
1480
1481
/**
1482
* Set ScrollMetadata and scroll-induced clipping on aEntry's layer.
1483
*/
1484
void SetupScrollingMetadata(NewLayerEntry* aEntry);
1485
1486
/**
1487
* Applies occlusion culling.
1488
* For each layer in mNewChildLayers, remove from its visible region the
1489
* opaque regions of the layers at higher z-index, but only if they have
1490
* the same animated geometry root and fixed-pos frame ancestor.
1491
* The opaque region for the child layers that share the same animated
1492
* geometry root as the container frame is returned in
1493
* *aOpaqueRegionForContainer.
1494
*
1495
* Also sets scroll metadata on the layers.
1496
*/
1497
void PostprocessRetainedLayers(nsIntRegion* aOpaqueRegionForContainer);
1498
1499
/**
1500
* Computes the snapped opaque area of aItem. Sets aList's opaque flag
1501
* if it covers the entire list bounds. Sets *aHideAllLayersBelow to true
1502
* this item covers the entire viewport so that all layers below are
1503
* permanently invisible.
1504
*/
1505
nsIntRegion ComputeOpaqueRect(nsDisplayItem* aItem,
1506
AnimatedGeometryRoot* aAnimatedGeometryRoot,
1507
const ActiveScrolledRoot* aASR,
1508
const DisplayItemClip& aClip,
1509
nsDisplayList* aList, bool* aHideAllLayersBelow,
1510
bool* aOpaqueForAnimatedGeometryRootParent);
1511
1512
/**
1513
* Fills a PaintedLayerData object that is initialized for a layer that the
1514
* current item will be assigned to. Also creates mNewChildLayers entries.
1515
* @param aData The PaintedLayerData that will be filled.
1516
* @param aVisibleRect The visible rect of the item.
1517
* @param aAnimatedGeometryRoot The item's animated geometry root.
1518
* @param aASR The active scrolled root that moves this
1519
* PaintedLayer.
1520
* @param aClipChain The clip chain that the compositor needs to
1521
* apply to this layer.
1522
* @param aScrollMetadataASR The leaf ASR for which scroll metadata needs
1523
* to be set on the layer, because either the layer itself or its scrolled
1524
* clip need to move with that ASR.
1525
* @param aTopLeft The offset between aAnimatedGeometryRoot and
1526
* the reference frame.
1527
* @param aReferenceFrame The reference frame for the item.
1528
* @param aBackfaceHidden The backface visibility for the item frame.
1529
*/
1530
void NewPaintedLayerData(
1531
PaintedLayerData* aData, AnimatedGeometryRoot* aAnimatedGeometryRoot,
1532
const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aClipChain,
1533
const ActiveScrolledRoot* aScrollMetadataASR, const nsPoint& aTopLeft,
1534
const nsIFrame* aReferenceFrame, const bool aBackfaceHidden);
1535
1536
/* Build a mask layer to represent the clipping region. Will return null if
1537
* there is no clipping specified or a mask layer cannot be built.
1538
* Builds an ImageLayer for the appropriate backend; the mask is relative to
1539
* aLayer's visible region.
1540
* aLayer is the layer to be clipped.
1541
* relative to the container reference frame
1542
* aRoundedRectClipCount is used when building mask layers for PaintedLayers,
1543
*/
1544
void SetupMaskLayer(Layer* aLayer, const DisplayItemClip& aClip);
1545
1546
/**
1547
* If |aClip| has rounded corners, create a mask layer for them, and
1548
* add it to |aLayer|'s ancestor mask layers, returning an index into
1549
* the array of ancestor mask layers. Returns an empty Maybe if
1550
* |aClip| does not have rounded corners, or if no mask layer could
1551
* be created.
1552
*/
1553
Maybe<size_t> SetupMaskLayerForScrolledClip(Layer* aLayer,
1554
const DisplayItemClip& aClip);
1555
1556
/**
1557
* Create/find a mask layer with suitable size for aMaskItem to paint
1558
* css-positioned-masking onto.
1559
*/
1560
void SetupMaskLayerForCSSMask(Layer* aLayer,
1561
nsDisplayMasksAndClipPaths* aMaskItem);
1562
1563
already_AddRefed<Layer> CreateMaskLayer(
1564
Layer* aLayer, const DisplayItemClip& aClip,
1565
const Maybe<size_t>& aForAncestorMaskLayer);
1566
1567
/**
1568
* Get the display port for an AGR.
1569
* The result would be cached for later reusing.
1570
*/
1571
nsRect GetDisplayPortForAnimatedGeometryRoot(
1572
AnimatedGeometryRoot* aAnimatedGeometryRoot);
1573
1574
nsDisplayListBuilder* mBuilder;
1575
LayerManager* mManager;
1576
FrameLayerBuilder* mLayerBuilder;
1577
nsIFrame* mContainerFrame;
1578
nsIFrame* mContainerReferenceFrame;
1579
AnimatedGeometryRoot* mContainerAnimatedGeometryRoot;
1580
ContainerLayer* mContainerLayer;
1581
nsRect mContainerBounds;
1582
1583
// Due to the way we store scroll annotations in the layer tree, we need to
1584
// keep track of three (possibly different) ASRs here.
1585
// mContainerASR is the ASR of the container display item that this
1586
// ContainerState was created for.
1587
// mContainerScrollMetadataASR is the ASR of the leafmost scroll metadata
1588
// that's in effect on mContainerLayer.
1589
// mContainerCompositorASR is the ASR that mContainerLayer moves with on
1590
// the compositor / APZ side, taking into account both the scroll meta data
1591
// and the fixed position annotation on itself and its ancestors.
1592
const ActiveScrolledRoot* mContainerASR;
1593
const ActiveScrolledRoot* mContainerScrollMetadataASR;
1594
const ActiveScrolledRoot* mContainerCompositorASR;
1595
#ifdef DEBUG
1596
nsRect mAccumulatedChildBounds;
1597
#endif
1598
ContainerLayerParameters mParameters;
1599
/**
1600
* The region of PaintedLayers that should be invalidated every time
1601
* we recycle one.
1602
*/
1603
nsIntRegion mInvalidPaintedContent;
1604
PaintedLayerDataTree mPaintedLayerDataTree;
1605
/**
1606
* We collect the list of children in here. During ProcessDisplayItems,
1607
* the layers in this array either have mContainerLayer as their parent,
1608
* or no parent.
1609
* PaintedLayers have two entries in this array: the second one is used only
1610
* if the PaintedLayer is optimized away to a ColorLayer or ImageLayer. It's
1611
* essential that this array is only appended to, since PaintedLayerData
1612
* records the index of its PaintedLayer in this array.
1613
*/
1614
typedef AutoTArray<NewLayerEntry, 1> AutoLayersArray;
1615
AutoLayersArray mNewChildLayers;
1616
nsTHashtable<nsRefPtrHashKey<PaintedLayer>>
1617
mPaintedLayersAvailableForRecycling;
1618
nscoord mAppUnitsPerDevPixel;
1619
bool mSnappingEnabled;
1620
1621
struct MaskLayerKey {
1622
MaskLayerKey() : mLayer(nullptr) {}
1623
MaskLayerKey(Layer* aLayer, const Maybe<size_t>& aAncestorIndex)
1624
: mLayer(aLayer), mAncestorIndex(aAncestorIndex) {}
1625
1626
PLDHashNumber Hash() const {
1627
// Hash the layer and add the layer index to the hash.
1628
return (NS_PTR_TO_UINT32(mLayer) >> 2) +
1629
(mAncestorIndex ? (*mAncestorIndex + 1) : 0);
1630
}
1631
bool operator==(const MaskLayerKey& aOther) const {
1632
return mLayer == aOther.mLayer && mAncestorIndex == aOther.mAncestorIndex;
1633
}
1634
1635
Layer* mLayer;
1636
Maybe<size_t> mAncestorIndex;
1637
};
1638
1639
nsDataHashtable<nsGenericHashKey<MaskLayerKey>, RefPtr<ImageLayer>>
1640
mRecycledMaskImageLayers;
1641
// Keep display port of AGR to avoid wasting time on doing the same
1642
// thing repeatly.
1643
AnimatedGeometryRoot* mLastDisplayPortAGR;
1644
nsRect mLastDisplayPortRect;
1645
1646
nsDisplayItem* mContainerItem;
1647
1648
// Cache ScrollMetadata so it doesn't need recomputed if the ASR and clip are
1649
// unchanged. If mASR == nullptr then mMetadata is not valid.
1650
struct CachedScrollMetadata {
1651
const ActiveScrolledRoot* mASR;
1652
const DisplayItemClip* mClip;
1653
Maybe<ScrollMetadata> mMetadata;
1654
1655
CachedScrollMetadata() : mASR(nullptr), mClip(nullptr) {}
1656
};
1657
CachedScrollMetadata mCachedScrollMetadata;
1658
};
1659
1660
class FLBDisplayListIterator : public FlattenedDisplayListIterator {
1661
public:
1662
FLBDisplayListIterator(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
1663
ContainerState* aState)
1664
: FlattenedDisplayListIterator(aBuilder, aList, false), mState(aState) {
1665
MOZ_ASSERT(mState);
1666
1667
if (mState->mContainerItem) {
1668
// Add container item hit test information for processing, if needed.
1669
AddHitTestMarkerIfNeeded(mState->mContainerItem);
1670
}
1671
1672
ResolveFlattening();
1673
}
1674
1675
DisplayItemEntry GetNextEntry() {
1676
if (!mMarkers.empty()) {
1677
DisplayItemEntry entry = mMarkers.front();
1678
mMarkers.pop_front();
1679
return entry;
1680
}
1681
1682
return DisplayItemEntry{GetNextItem(), DisplayItemEntryType::Item};
1683
}
1684
1685
bool HasNext() const override {
1686
return FlattenedDisplayListIterator::HasNext() || !mMarkers.empty();
1687
}
1688
1689
private:
1690
void AddHitTestMarkerIfNeeded(nsDisplayItem* aItem) {
1691
if (aItem->HasHitTestInfo()) {
1692
mMarkers.emplace_back(aItem, DisplayItemEntryType::HitTestInfo);
1693
}
1694
}
1695
1696
bool ShouldFlattenNextItem() override {
1697
if (!FlattenedDisplayListIterator::ShouldFlattenNextItem()) {
1698
return false;
1699
}
1700
1701
nsDisplayItem* next = PeekNext();
1702
const DisplayItemType type = next->GetType();
1703
1704
if (type == DisplayItemType::TYPE_SVG_WRAPPER) {
1705
// We mark SetContainsSVG for the CONTENT_FRAME_TIME_WITH_SVG metric
1706
if (RefPtr<LayerManager> lm = mState->mBuilder->GetWidgetLayerManager()) {
1707
lm->SetContainsSVG(true);
1708
}
1709
}
1710
1711
if (!SupportsFlatteningWithMarkers(type)) {
1712
return true;
1713
}
1714
1715
if (type == DisplayItemType::TYPE_OPACITY &&
1716
IsOpacityAppliedToChildren(next)) {
1717
// This is the previous opacity flattening path, where the opacity has
1718
// been applied to children.
1719
return true;
1720
}
1721
1722
if (mState->IsInInactiveLayer() || !ItemWantsInactiveLayer(next)) {
1723
// Do not flatten nested inactive display items, or display items that
1724
// want an active layer.
1725
return false;
1726
}
1727
1728
// If we reach here, we will emit an effect start marker for
1729
// nsDisplayTransform or nsDisplayOpacity.
1730
MOZ_ASSERT(type == DisplayItemType::TYPE_TRANSFORM ||
1731
!IsOpacityAppliedToChildren(next));
1732
return true;
1733
}
1734
1735
void EnterChildList(nsDisplayItem* aContainerItem) override {
1736
mFlattenedLists.AppendElement(aContainerItem);
1737
AddMarkerIfNeeded<MarkerType::StartMarker>(aContainerItem, mMarkers);
1738
AddHitTestMarkerIfNeeded(aContainerItem);
1739
}
1740
1741
void ExitChildList() override {
1742
MOZ_ASSERT(!mFlattenedLists.IsEmpty());
1743
nsDisplayItem* aContainerItem = mFlattenedLists.PopLastElement();
1744
AddMarkerIfNeeded<MarkerType::EndMarker>(aContainerItem, mMarkers);
1745
}
1746
1747
bool ItemWantsInactiveLayer(nsDisplayItem* aItem) {
1748
const LayerState layerState = aItem->GetLayerState(
1749
mState->mBuilder, mState->mManager, mState->mParameters);
1750
1751
return layerState == LayerState::LAYER_INACTIVE;
1752
}
1753
1754
std::deque<DisplayItemEntry> mMarkers;
1755
AutoTArray<nsDisplayItem*, 16> mFlattenedLists;
1756
ContainerState* mState;
1757
};
1758
1759
class PaintedDisplayItemLayerUserData : public LayerUserData {
1760
public:
1761
PaintedDisplayItemLayerUserData()
1762
: mForcedBackgroundColor(NS_RGBA(0, 0, 0, 0)),
1763
mXScale(1.f),
1764
mYScale(1.f),
1765
mAppUnitsPerDevPixel(0),
1766
mTranslation(0, 0),
1767
mAnimatedGeometryRootPosition(0, 0),
1768
mLastItemCount(0),
1769
mContainerLayerFrame(nullptr),
1770
mHasExplicitLastPaintOffset(false),
1771
mDisabledAlpha(false) {}
1772
1773
NS_INLINE_DECL_REFCOUNTING(PaintedDisplayItemLayerUserData);
1774
1775
/**
1776
* A color that should be painted over the bounds of the layer's visible
1777
* region before any other content is painted.
1778
*/
1779
nscolor mForcedBackgroundColor;
1780
1781
/**
1782
* The resolution scale used.
1783
*/
1784
float mXScale, mYScale;
1785
1786
/**
1787
* The appunits per dev pixel for the items in this layer.
1788
*/
1789
nscoord mAppUnitsPerDevPixel;
1790
1791
/**
1792
* The offset from the PaintedLayer's 0,0 to the
1793
* reference frame. This isn't necessarily the same as the transform
1794
* set on the PaintedLayer since we might also be applying an extra
1795
* offset specified by the parent ContainerLayer/
1796
*/
1797
nsIntPoint mTranslation;
1798
1799
/**
1800
* We try to make 0,0 of the PaintedLayer be the top-left of the
1801
* border-box of the "active scrolled root" frame (i.e. the nearest ancestor
1802
* frame for the display items that is being actively scrolled). But
1803
* we force the PaintedLayer transform to be an integer translation, and we
1804
* may have a resolution scale, so we have to snap the PaintedLayer transform,
1805
* so 0,0 may not be exactly the top-left of the active scrolled root. Here we
1806
* store the coordinates in PaintedLayer space of the top-left of the
1807
* active scrolled root.
1808
*/
1809
gfxPoint mAnimatedGeometryRootPosition;
1810
1811
nsIntRegion mRegionToInvalidate;
1812
1813
// The offset between the active scrolled root of this layer
1814
// and the root of the container for the previous and current
1815
// paints respectively.
1816
nsPoint mLastAnimatedGeometryRootOrigin;
1817
nsPoint mAnimatedGeometryRootOrigin;
1818
1819
RefPtr<ColorLayer> mColorLayer;
1820
RefPtr<ImageLayer> mImageLayer;
1821
1822
// The region for which display item visibility for this layer has already
1823
// been calculated. Used to reduce the number of calls to
1824
// RecomputeVisibilityForItems if it is known in advance that a larger
1825
// region will be painted during a transaction than in a single call to
1826
// DrawPaintedLayer, for example when progressive paint is enabled.
1827
nsIntRegion mVisibilityComputedRegion;
1828
1829
// The area for which we called RecomputeVisibilityForItems on the
1830
// previous paint.
1831
nsRect mPreviousRecomputeVisibilityRect;
1832
1833
// The number of items assigned to this layer on the previous paint.
1834
size_t mLastItemCount;
1835
1836
// The translation set on this PaintedLayer before we started updating the
1837
// layer tree.
1838
nsIntPoint mLastPaintOffset;
1839
1840
// Temporary state only valid during the FrameLayerBuilder's lifetime.
1841
// FLB's mPaintedLayerItems is responsible for cleaning these up when
1842
// we finish painting to avoid dangling pointers.
1843
std::vector<AssignedDisplayItem> mItems;
1844
nsIFrame* mContainerLayerFrame;
1845
1846
bool mHasExplicitLastPaintOffset;
1847
1848
/**
1849
* This is set when the painted layer has no component alpha.
1850
*/
1851
bool mDisabledAlpha;
1852
1853
protected:
1854
~PaintedDisplayItemLayerUserData() override = default;
1855
};
1856
1857
FrameLayerBuilder::FrameLayerBuilder()
1858
: mRetainingManager(nullptr),
1859
mDisplayListBuilder(nullptr),
1860
mContainingPaintedLayer(nullptr),
1861
mInactiveLayerClip(nullptr),
1862
mInvalidateAllLayers(false),
1863
mInLayerTreeCompressionMode(false),
1864
mIsInactiveLayerManager(false) {
1865
MOZ_COUNT_CTOR(FrameLayerBuilder);
1866
}
1867
1868
FrameLayerBuilder::~FrameLayerBuilder() {
1869
GetMaskLayerImageCache()->Sweep();
1870
for (PaintedDisplayItemLayerUserData* userData : mPaintedLayerItems) {
1871
userData->mItems.clear();
1872
userData->mContainerLayerFrame = nullptr;
1873
}
1874
MOZ_COUNT_DTOR(FrameLayerBuilder);
1875
}
1876
1877
void FrameLayerBuilder::AddPaintedLayerItemsEntry(
1878
PaintedDisplayItemLayerUserData* aData) {
1879
mPaintedLayerItems.AppendElement(aData);
1880
}
1881
1882
/*
1883
* User data for layers which will be used as masks.
1884
*/
1885
struct MaskLayerUserData : public LayerUserData {
1886
MaskLayerUserData()
1887
: mScaleX(-1.0f), mScaleY(-1.0f), mAppUnitsPerDevPixel(-1) {}
1888
MaskLayerUserData(const DisplayItemClip& aClip, int32_t aAppUnitsPerDevPixel,
1889
const ContainerLayerParameters& aParams)
1890
: mScaleX(aParams.mXScale),
1891
mScaleY(aParams.mYScale),
1892
mOffset(aParams.mOffset),
1893
mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) {
1894
aClip.AppendRoundedRects(&mRoundedClipRects);
1895
}
1896
1897
void operator=(MaskLayerUserData&& aOther) {
1898
mScaleX = aOther.mScaleX;
1899
mScaleY = aOther.mScaleY;
1900
mOffset = aOther.mOffset;
1901
mAppUnitsPerDevPixel = aOther.mAppUnitsPerDevPixel;
1902
mRoundedClipRects.SwapElements(aOther.mRoundedClipRects);