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
8
/*
9
* structures that represent things to be painted (ordered in z-order),
10
* used during painting and hit testing
11
*/
12
13
#ifndef NSDISPLAYLIST_H_
14
#define NSDISPLAYLIST_H_
15
16
#include "mozilla/Attributes.h"
17
#include "gfxContext.h"
18
#include "mozilla/ArenaAllocator.h"
19
#include "mozilla/Assertions.h"
20
#include "mozilla/Array.h"
21
#include "mozilla/DebugOnly.h"
22
#include "mozilla/EnumSet.h"
23
#include "mozilla/Maybe.h"
24
#include "mozilla/RefPtr.h"
25
#include "mozilla/TemplateLib.h" // mozilla::tl::Max
26
#include "nsCOMPtr.h"
27
#include "nsContainerFrame.h"
28
#include "nsPoint.h"
29
#include "nsRect.h"
30
#include "nsRegion.h"
31
#include "nsDisplayListInvalidation.h"
32
#include "DisplayItemClipChain.h"
33
#include "DisplayListClipState.h"
34
#include "LayerState.h"
35
#include "FrameMetrics.h"
36
#include "ImgDrawResult.h"
37
#include "mozilla/dom/EffectsInfo.h"
38
#include "mozilla/dom/RemoteBrowser.h"
39
#include "mozilla/EffectCompositor.h"
40
#include "mozilla/EnumeratedArray.h"
41
#include "mozilla/UniquePtr.h"
42
#include "mozilla/TimeStamp.h"
43
#include "mozilla/gfx/UserData.h"
44
#include "mozilla/layers/LayerAttributes.h"
45
#include "mozilla/layers/RenderRootBoundary.h"
46
#include "mozilla/layers/ScrollableLayerGuid.h"
47
#include "nsCSSRenderingBorders.h"
48
#include "nsPresArena.h"
49
#include "nsAutoLayoutPhase.h"
50
#include "nsDisplayItemTypes.h"
51
#include "RetainedDisplayListHelpers.h"
52
53
#include <stdint.h>
54
#include "nsTHashtable.h"
55
56
#include <stdlib.h>
57
#include <algorithm>
58
#include <unordered_set>
59
60
class gfxContext;
61
class nsIContent;
62
class nsDisplayList;
63
class nsDisplayTableItem;
64
class nsIScrollableFrame;
65
class nsSubDocumentFrame;
66
class nsDisplayCompositorHitTestInfo;
67
class nsDisplayScrollInfoLayer;
68
class nsDisplayTableBackgroundSet;
69
class nsCaret;
70
enum class nsDisplayOwnLayerFlags;
71
struct WrFiltersHolder;
72
73
namespace mozilla {
74
class FrameLayerBuilder;
75
class PresShell;
76
struct MotionPathData;
77
namespace layers {
78
struct FrameMetrics;
79
class RenderRootStateManager;
80
class Layer;
81
class ImageLayer;
82
class ImageContainer;
83
class StackingContextHelper;
84
class WebRenderCommand;
85
class WebRenderScrollData;
86
class WebRenderLayerScrollData;
87
} // namespace layers
88
namespace wr {
89
class DisplayListBuilder;
90
} // namespace wr
91
namespace dom {
92
class Selection;
93
} // namespace dom
94
95
enum class DisplayListArenaObjectId {
96
#define DISPLAY_LIST_ARENA_OBJECT(name_) name_,
97
#include "nsDisplayListArenaTypes.h"
98
#undef DISPLAY_LIST_ARENA_OBJECT
99
COUNT
100
};
101
102
} // namespace mozilla
103
104
/*
105
* An nsIFrame can have many different visual parts. For example an image frame
106
* can have a background, border, and outline, the image itself, and a
107
* translucent selection overlay. In general these parts can be drawn at
108
* discontiguous z-levels; see CSS2.1 appendix E:
110
*
111
* We construct a display list for a frame tree that contains one item
112
* for each visual part. The display list is itself a tree since some items
113
* are containers for other items; however, its structure does not match
114
* the structure of its source frame tree. The display list items are sorted
115
* by z-order. A display list can be used to paint the frames, to determine
116
* which frame is the target of a mouse event, and to determine what areas
117
* need to be repainted when scrolling. The display lists built for each task
118
* may be different for efficiency; in particular some frames need special
119
* display list items only for event handling, and do not create these items
120
* when the display list will be used for painting (the common case). For
121
* example, when painting we avoid creating nsDisplayBackground items for
122
* frames that don't display a visible background, but for event handling
123
* we need those backgrounds because they are not transparent to events.
124
*
125
* We could avoid constructing an explicit display list by traversing the
126
* frame tree multiple times in clever ways. However, reifying the display list
127
* reduces code complexity and reduces the number of times each frame must be
128
* traversed to one, which seems to be good for performance. It also means
129
* we can share code for painting, event handling and scroll analysis.
130
*
131
* Display lists are short-lived; content and frame trees cannot change
132
* between a display list being created and destroyed. Display lists should
133
* not be created during reflow because the frame tree may be in an
134
* inconsistent state (e.g., a frame's stored overflow-area may not include
135
* the bounds of all its children). However, it should be fine to create
136
* a display list while a reflow is pending, before it starts.
137
*
138
* A display list covers the "extended" frame tree; the display list for
139
* a frame tree containing FRAME/IFRAME elements can include frames from
140
* the subdocuments.
141
*
142
* Display item's coordinates are relative to their nearest reference frame
143
* ancestor. Both the display root and any frame with a transform act as a
144
* reference frame for their frame subtrees.
145
*/
146
147
/**
148
* Represents a frame that is considered to have (or will have) "animated
149
* geometry" for itself and descendant frames.
150
*
151
* For example the scrolled frames of scrollframes which are actively being
152
* scrolled fall into this category. Frames with certain CSS properties that are
153
* being animated (e.g. 'left'/'top' etc) are also placed in this category.
154
* Frames with different active geometry roots are in different PaintedLayers,
155
* so that we can animate the geometry root by changing its transform (either on
156
* the main thread or in the compositor).
157
*
158
* nsDisplayListBuilder constructs a tree of these (for fast traversals) and
159
* assigns one for each display item.
160
*
161
* The animated geometry root for a display item is required to be a descendant
162
* (or equal to) the item's ReferenceFrame(), which means that we will fall back
163
* to returning aItem->ReferenceFrame() when we can't find another animated
164
* geometry root.
165
*
166
* The animated geometry root isn't strongly defined for a frame as transforms
167
* and background-attachment:fixed can cause it to vary between display items
168
* for a given frame.
169
*/
170
struct AnimatedGeometryRoot {
171
static already_AddRefed<AnimatedGeometryRoot> CreateAGRForFrame(
172
nsIFrame* aFrame, AnimatedGeometryRoot* aParent, bool aIsAsync,
173
bool aIsRetained) {
174
RefPtr<AnimatedGeometryRoot> result;
175
if (aIsRetained) {
176
result = aFrame->GetProperty(AnimatedGeometryRootCache());
177
}
178
179
if (result) {
180
result->mParentAGR = aParent;
181
result->mIsAsync = aIsAsync;
182
} else {
183
result = new AnimatedGeometryRoot(aFrame, aParent, aIsAsync, aIsRetained);
184
}
185
return result.forget();
186
}
187
188
operator nsIFrame*() { return mFrame; }
189
190
nsIFrame* operator->() const { return mFrame; }
191
192
AnimatedGeometryRoot* GetAsyncAGR() {
193
AnimatedGeometryRoot* agr = this;
194
while (!agr->mIsAsync && agr->mParentAGR) {
195
agr = agr->mParentAGR;
196
}
197
return agr;
198
}
199
200
NS_INLINE_DECL_REFCOUNTING(AnimatedGeometryRoot)
201
202
nsIFrame* mFrame;
203
RefPtr<AnimatedGeometryRoot> mParentAGR;
204
bool mIsAsync;
205
bool mIsRetained;
206
207
protected:
208
static void DetachAGR(AnimatedGeometryRoot* aAGR) {
209
aAGR->mFrame = nullptr;
210
aAGR->mParentAGR = nullptr;
211
NS_RELEASE(aAGR);
212
}
213
214
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnimatedGeometryRootCache,
215
AnimatedGeometryRoot, DetachAGR)
216
217
AnimatedGeometryRoot(nsIFrame* aFrame, AnimatedGeometryRoot* aParent,
218
bool aIsAsync, bool aIsRetained)
219
: mFrame(aFrame),
220
mParentAGR(aParent),
221
mIsAsync(aIsAsync),
222
mIsRetained(aIsRetained) {
223
MOZ_ASSERT(mParentAGR || mIsAsync,
224
"The root AGR should always be treated as an async AGR.");
225
if (mIsRetained) {
226
NS_ADDREF(this);
227
aFrame->SetProperty(AnimatedGeometryRootCache(), this);
228
}
229
}
230
231
~AnimatedGeometryRoot() {
232
if (mFrame && mIsRetained) {
233
mFrame->DeleteProperty(AnimatedGeometryRootCache());
234
}
235
}
236
};
237
238
namespace mozilla {
239
240
/**
241
* An active scrolled root (ASR) is similar to an animated geometry root (AGR).
242
* The differences are:
243
* - ASRs are only created for async-scrollable scroll frames. This is a
244
* (hopefully) temporary restriction. In the future we will want to create
245
* ASRs for all the things that are currently creating AGRs, and then
246
* replace AGRs with ASRs and rename them from "active scrolled root" to
247
* "animated geometry root".
248
* - ASR objects are created during display list construction by the nsIFrames
249
* that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter.
250
* The current ASR is returned by
251
* nsDisplayListBuilder::CurrentActiveScrolledRoot().
252
* - There is no way to go from an nsIFrame pointer to the ASR of that frame.
253
* If you need to look up an ASR after display list construction, you need
254
* to store it while the AutoCurrentActiveScrolledRootSetter that creates it
255
* is on the stack.
256
*/
257
struct ActiveScrolledRoot {
258
static already_AddRefed<ActiveScrolledRoot> CreateASRForFrame(
259
const ActiveScrolledRoot* aParent, nsIScrollableFrame* aScrollableFrame,
260
bool aIsRetained) {
261
nsIFrame* f = do_QueryFrame(aScrollableFrame);
262
263
RefPtr<ActiveScrolledRoot> asr;
264
if (aIsRetained) {
265
asr = f->GetProperty(ActiveScrolledRootCache());
266
}
267
268
if (!asr) {
269
asr = new ActiveScrolledRoot();
270
271
if (aIsRetained) {
272
RefPtr<ActiveScrolledRoot> ref = asr;
273
f->SetProperty(ActiveScrolledRootCache(), ref.forget().take());
274
}
275
}
276
asr->mParent = aParent;
277
asr->mScrollableFrame = aScrollableFrame;
278
asr->mViewId = Nothing();
279
asr->mDepth = aParent ? aParent->mDepth + 1 : 1;
280
asr->mRetained = aIsRetained;
281
282
return asr.forget();
283
}
284
285
static const ActiveScrolledRoot* PickAncestor(
286
const ActiveScrolledRoot* aOne, const ActiveScrolledRoot* aTwo) {
287
MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
288
return Depth(aOne) <= Depth(aTwo) ? aOne : aTwo;
289
}
290
291
static const ActiveScrolledRoot* PickDescendant(
292
const ActiveScrolledRoot* aOne, const ActiveScrolledRoot* aTwo) {
293
MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
294
return Depth(aOne) >= Depth(aTwo) ? aOne : aTwo;
295
}
296
297
static bool IsAncestor(const ActiveScrolledRoot* aAncestor,
298
const ActiveScrolledRoot* aDescendant);
299
300
static nsCString ToString(
301
const mozilla::ActiveScrolledRoot* aActiveScrolledRoot);
302
303
// Call this when inserting an ancestor.
304
void IncrementDepth() { mDepth++; }
305
306
/**
307
* Find the view ID (or generate a new one) for the content element
308
* corresponding to the ASR.
309
*/
310
mozilla::layers::ScrollableLayerGuid::ViewID GetViewId() const {
311
if (!mViewId.isSome()) {
312
nsIContent* content = mScrollableFrame->GetScrolledFrame()->GetContent();
313
mViewId = Some(nsLayoutUtils::FindOrCreateIDFor(content));
314
}
315
return *mViewId;
316
}
317
318
RefPtr<const ActiveScrolledRoot> mParent;
319
nsIScrollableFrame* mScrollableFrame;
320
321
NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot)
322
323
private:
324
ActiveScrolledRoot()
325
: mScrollableFrame(nullptr), mDepth(0), mRetained(false) {}
326
327
~ActiveScrolledRoot() {
328
if (mScrollableFrame && mRetained) {
329
nsIFrame* f = do_QueryFrame(mScrollableFrame);
330
f->DeleteProperty(ActiveScrolledRootCache());
331
}
332
}
333
334
static void DetachASR(ActiveScrolledRoot* aASR) {
335
aASR->mParent = nullptr;
336
aASR->mScrollableFrame = nullptr;
337
NS_RELEASE(aASR);
338
}
339
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache,
340
ActiveScrolledRoot, DetachASR)
341
342
static uint32_t Depth(const ActiveScrolledRoot* aActiveScrolledRoot) {
343
return aActiveScrolledRoot ? aActiveScrolledRoot->mDepth : 0;
344
}
345
346
// This field is lazily populated in GetViewId(). We don't want to do the
347
// work of populating if webrender is disabled, because it is often not
348
// needed.
349
mutable Maybe<mozilla::layers::ScrollableLayerGuid::ViewID> mViewId;
350
351
uint32_t mDepth;
352
bool mRetained;
353
};
354
} // namespace mozilla
355
356
enum class nsDisplayListBuilderMode : uint8_t {
357
Painting,
358
EventDelivery,
359
PluginGeometry,
360
FrameVisibility,
361
TransformComputation,
362
GenerateGlyph,
363
};
364
365
class nsDisplayWrapList;
366
367
/**
368
* This manages a display list and is passed as a parameter to
369
* nsIFrame::BuildDisplayList.
370
* It contains the parameters that don't change from frame to frame and manages
371
* the display list memory using an arena. It also establishes the reference
372
* coordinate system for all display list items. Some of the parameters are
373
* available from the prescontext/presshell, but we copy them into the builder
374
* for faster/more convenient access.
375
*/
376
class nsDisplayListBuilder {
377
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
378
typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize;
379
typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
380
typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
381
382
/**
383
* This manages status of a 3d context to collect visible rects of
384
* descendants and passing a dirty rect.
385
*
386
* Since some transforms maybe singular, passing visible rects or
387
* the dirty rect level by level from parent to children may get a
388
* wrong result, being different from the result of appling with
389
* effective transform directly.
390
*
391
* nsFrame::BuildDisplayListForStackingContext() uses
392
* AutoPreserves3DContext to install an instance on the builder.
393
*
394
* \see AutoAccumulateTransform, AutoAccumulateRect,
395
* AutoPreserves3DContext, Accumulate, GetCurrentTransform,
396
* StartRoot.
397
*/
398
class Preserves3DContext {
399
public:
400
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
401
402
Preserves3DContext() : mAccumulatedRectLevels(0) {}
403
404
Preserves3DContext(const Preserves3DContext& aOther)
405
: mAccumulatedTransform(),
406
mAccumulatedRect(),
407
mAccumulatedRectLevels(0),
408
mVisibleRect(aOther.mVisibleRect) {}
409
410
// Accmulate transforms of ancestors on the preserves-3d chain.
411
Matrix4x4 mAccumulatedTransform;
412
// Accmulate visible rect of descendants in the preserves-3d context.
413
nsRect mAccumulatedRect;
414
// How far this frame is from the root of the current 3d context.
415
int mAccumulatedRectLevels;
416
nsRect mVisibleRect;
417
};
418
419
/**
420
* A frame can be in one of three states of AGR.
421
* AGR_NO means the frame is not an AGR for now.
422
* AGR_YES means the frame is an AGR for now.
423
*/
424
enum AGRState { AGR_NO, AGR_YES };
425
426
public:
427
typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
428
typedef mozilla::DisplayItemClip DisplayItemClip;
429
typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
430
typedef mozilla::DisplayItemClipChainHasher DisplayItemClipChainHasher;
431
typedef mozilla::DisplayItemClipChainEqualer DisplayItemClipChainEqualer;
432
typedef mozilla::DisplayListClipState DisplayListClipState;
433
typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
434
typedef nsIWidget::ThemeGeometry ThemeGeometry;
435
typedef mozilla::layers::Layer Layer;
436
typedef mozilla::layers::FrameMetrics FrameMetrics;
437
typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
438
typedef mozilla::layers::ScrollableLayerGuid::ViewID ViewID;
439
typedef mozilla::gfx::CompositorHitTestInfo CompositorHitTestInfo;
440
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
441
typedef mozilla::Maybe<mozilla::layers::ScrollDirection> MaybeScrollDirection;
442
typedef mozilla::dom::EffectsInfo EffectsInfo;
443
typedef mozilla::layers::LayersId LayersId;
444
typedef mozilla::dom::RemoteBrowser RemoteBrowser;
445
446
/**
447
* @param aReferenceFrame the frame at the root of the subtree; its origin
448
* is the origin of the reference coordinate system for this display list
449
* @param aMode encodes what the builder is being used for.
450
* @param aBuildCaret whether or not we should include the caret in any
451
* display lists that we make.
452
*/
453
nsDisplayListBuilder(nsIFrame* aReferenceFrame,
454
nsDisplayListBuilderMode aMode, bool aBuildCaret,
455
bool aRetainingDisplayList = false);
456
~nsDisplayListBuilder();
457
458
void BeginFrame();
459
void EndFrame();
460
461
void AddTemporaryItem(nsDisplayItem* aItem) {
462
mTemporaryItems.AppendElement(aItem);
463
}
464
465
void SetWillComputePluginGeometry(bool aWillComputePluginGeometry) {
466
mWillComputePluginGeometry = aWillComputePluginGeometry;
467
}
468
469
void SetForPluginGeometry(bool aForPlugin) {
470
if (aForPlugin) {
471
NS_ASSERTION(mMode == nsDisplayListBuilderMode::Painting,
472
"Can only switch from Painting to PluginGeometry");
473
NS_ASSERTION(mWillComputePluginGeometry,
474
"Should have signalled this in advance");
475
mMode = nsDisplayListBuilderMode::PluginGeometry;
476
} else {
477
NS_ASSERTION(mMode == nsDisplayListBuilderMode::PluginGeometry,
478
"Can only switch from Painting to PluginGeometry");
479
mMode = nsDisplayListBuilderMode::Painting;
480
}
481
}
482
483
mozilla::layers::LayerManager* GetWidgetLayerManager(
484
nsView** aView = nullptr);
485
486
/**
487
* @return true if the display is being built in order to determine which
488
* frame is under the mouse position.
489
*/
490
bool IsForEventDelivery() const {
491
return mMode == nsDisplayListBuilderMode::EventDelivery;
492
}
493
494
/**
495
* Be careful with this. The display list will be built in Painting mode
496
* first and then switched to PluginGeometry before a second call to
497
* ComputeVisibility.
498
* @return true if the display list is being built to compute geometry
499
* for plugins.
500
*/
501
bool IsForPluginGeometry() const {
502
return mMode == nsDisplayListBuilderMode::PluginGeometry;
503
}
504
505
/**
506
* @return true if the display list is being built for painting.
507
*/
508
bool IsForPainting() const {
509
return mMode == nsDisplayListBuilderMode::Painting;
510
}
511
512
/**
513
* @return true if the display list is being built for determining frame
514
* visibility.
515
*/
516
bool IsForFrameVisibility() const {
517
return mMode == nsDisplayListBuilderMode::FrameVisibility;
518
}
519
520
/**
521
* @return true if the display list is being built for creating the glyph
522
* mask from text items.
523
*/
524
bool IsForGenerateGlyphMask() const {
525
return mMode == nsDisplayListBuilderMode::GenerateGlyph;
526
}
527
528
bool BuildCompositorHitTestInfo() const {
529
return mBuildCompositorHitTestInfo;
530
}
531
532
bool WillComputePluginGeometry() const { return mWillComputePluginGeometry; }
533
534
/**
535
* @return true if "painting is suppressed" during page load and we
536
* should paint only the background of the document.
537
*/
538
bool IsBackgroundOnly() {
539
NS_ASSERTION(mPresShellStates.Length() > 0,
540
"don't call this if we're not in a presshell");
541
return CurrentPresShellState()->mIsBackgroundOnly;
542
}
543
544
/**
545
* @return the root of given frame's (sub)tree, whose origin
546
* establishes the coordinate system for the child display items.
547
*/
548
const nsIFrame* FindReferenceFrameFor(const nsIFrame* aFrame,
549
nsPoint* aOffset = nullptr) const;
550
551
/**
552
* @return the root of the display list's frame (sub)tree, whose origin
553
* establishes the coordinate system for the display list
554
*/
555
nsIFrame* RootReferenceFrame() const { return mReferenceFrame; }
556
557
/**
558
* @return a point pt such that adding pt to a coordinate relative to aFrame
559
* makes it relative to ReferenceFrame(), i.e., returns
560
* aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
561
* the appunits of aFrame.
562
*/
563
const nsPoint ToReferenceFrame(const nsIFrame* aFrame) const {
564
nsPoint result;
565
FindReferenceFrameFor(aFrame, &result);
566
return result;
567
}
568
/**
569
* When building the display list, the scrollframe aFrame will be "ignored"
570
* for the purposes of clipping, and its scrollbars will be hidden. We use
571
* this to allow RenderOffscreen to render a whole document without beign
572
* clipped by the viewport or drawing the viewport scrollbars.
573
*/
574
void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
575
/**
576
* Get the scrollframe to ignore, if any.
577
*/
578
nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
579
/**
580
* Get the ViewID of the nearest scrolling ancestor frame.
581
*/
582
ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
583
/**
584
* Get and set the flag that indicates if scroll parents should have layers
585
* forcibly created. This flag is set when a deeply nested scrollframe has
586
* a displayport, and for scroll handoff to work properly the ancestor
587
* scrollframes should also get their own scrollable layers.
588
*/
589
void ForceLayerForScrollParent() { mForceLayerForScrollParent = true; }
590
/**
591
* Get the ViewID and the scrollbar flags corresponding to the scrollbar for
592
* which we are building display items at the moment.
593
*/
594
ViewID GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget; }
595
MaybeScrollDirection GetCurrentScrollbarDirection() const {
596
return mCurrentScrollbarDirection;
597
}
598
/**
599
* Returns true if building a scrollbar, and the scrollbar will not be
600
* layerized.
601
*/
602
bool IsBuildingNonLayerizedScrollbar() const {
603
return mIsBuildingScrollbar && !mCurrentScrollbarWillHaveLayer;
604
}
605
/**
606
* Calling this setter makes us include all out-of-flow descendant
607
* frames in the display list, wherever they may be positioned (even
608
* outside the dirty rects).
609
*/
610
void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
611
bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
612
/**
613
* Calling this setter makes us exclude all leaf frames that aren't
614
* selected.
615
*/
616
void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
617
bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
618
/**
619
* Calling this setter makes us compute accurate visible regions at the cost
620
* of performance if regions get very complex.
621
*/
622
bool GetAccurateVisibleRegions() {
623
return mMode == nsDisplayListBuilderMode::PluginGeometry;
624
}
625
/**
626
* @return Returns true if we should include the caret in any display lists
627
* that we make.
628
*/
629
bool IsBuildingCaret() const { return mBuildCaret; }
630
631
bool IsRetainingDisplayList() const { return mRetainingDisplayList; }
632
633
bool IsPartialUpdate() const { return mPartialUpdate; }
634
void SetPartialUpdate(bool aPartial) { mPartialUpdate = aPartial; }
635
636
bool IsBuilding() const { return mIsBuilding; }
637
void SetIsBuilding(bool aIsBuilding) { mIsBuilding = aIsBuilding; }
638
639
bool InInvalidSubtree() const { return mInInvalidSubtree; }
640
641
/**
642
* Allows callers to selectively override the regular paint suppression
643
* checks, so that methods like GetFrameForPoint work when painting is
644
* suppressed.
645
*/
646
void IgnorePaintSuppression() { mIgnoreSuppression = true; }
647
/**
648
* @return Returns if this builder will ignore paint suppression.
649
*/
650
bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
651
/**
652
* Call this if we're doing normal painting to the window.
653
*/
654
void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
655
bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
656
/**
657
* Call this if we're doing painting for WebRender
658
*/
659
void SetPaintingForWebRender(bool aForWebRender) {
660
mIsPaintingForWebRender = true;
661
}
662
bool IsPaintingForWebRender() const { return mIsPaintingForWebRender; }
663
/**
664
* Call this to prevent descending into subdocuments.
665
*/
666
void SetDescendIntoSubdocuments(bool aDescend) {
667
mDescendIntoSubdocuments = aDescend;
668
}
669
670
bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }
671
672
/**
673
* Get dirty rect relative to current frame (the frame that we're calling
674
* BuildDisplayList on right now).
675
*/
676
const nsRect& GetVisibleRect() { return mVisibleRect; }
677
const nsRect& GetDirtyRect() { return mDirtyRect; }
678
679
void SetVisibleRect(const nsRect& aVisibleRect) {
680
mVisibleRect = aVisibleRect;
681
}
682
683
void IntersectVisibleRect(const nsRect& aVisibleRect) {
684
mVisibleRect.IntersectRect(mVisibleRect, aVisibleRect);
685
}
686
687
void SetDirtyRect(const nsRect& aDirtyRect) { mDirtyRect = aDirtyRect; }
688
689
void IntersectDirtyRect(const nsRect& aDirtyRect) {
690
mDirtyRect.IntersectRect(mDirtyRect, aDirtyRect);
691
}
692
693
const nsIFrame* GetCurrentFrame() { return mCurrentFrame; }
694
const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; }
695
696
const nsPoint& GetCurrentFrameOffsetToReferenceFrame() {
697
return mCurrentOffsetToReferenceFrame;
698
}
699
700
AnimatedGeometryRoot* GetCurrentAnimatedGeometryRoot() { return mCurrentAGR; }
701
AnimatedGeometryRoot* GetRootAnimatedGeometryRoot() { return mRootAGR; }
702
703
void RecomputeCurrentAnimatedGeometryRoot();
704
705
void Check() { mPool.Check(); }
706
707
/**
708
* Returns true if merging and flattening of display lists should be
709
* performed while computing visibility.
710
*/
711
bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; }
712
void SetAllowMergingAndFlattening(bool aAllow) {
713
mAllowMergingAndFlattening = aAllow;
714
}
715
716
/**
717
* Sets the current compositor hit test area and info to |aHitTestArea| and
718
* |aHitTestInfo|.
719
* This is used during display list building to determine if the parent frame
720
* hit test info contains the same information that child frame needs.
721
*/
722
void SetCompositorHitTestInfo(const nsRect& aHitTestArea,
723
const CompositorHitTestInfo& aHitTestInfo) {
724
mHitTestArea = aHitTestArea;
725
mHitTestInfo = aHitTestInfo;
726
}
727
728
const nsRect& GetHitTestArea() const { return mHitTestArea; }
729
const CompositorHitTestInfo& GetHitTestInfo() const { return mHitTestInfo; }
730
731
/**
732
* Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
733
* needed, and adds it to the top of |aList|. If |aBuildNew| is true, the
734
* previous hit test info will not be reused.
735
*/
736
void BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
737
nsDisplayList* aList,
738
const bool aBuildNew);
739
740
bool IsInsidePointerEventsNoneDoc() {
741
return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
742
}
743
744
bool IsTouchEventPrefEnabledDoc() {
745
return CurrentPresShellState()->mTouchEventPrefEnabledDoc;
746
}
747
748
bool GetAncestorHasApzAwareEventHandler() const {
749
return mAncestorHasApzAwareEventHandler;
750
}
751
752
void SetAncestorHasApzAwareEventHandler(bool aValue) {
753
mAncestorHasApzAwareEventHandler = aValue;
754
}
755
756
bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; }
757
void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; }
758
void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = false; }
759
760
bool SetIsCompositingCheap(bool aCompositingCheap) {
761
bool temp = mIsCompositingCheap;
762
mIsCompositingCheap = aCompositingCheap;
763
return temp;
764
}
765
766
bool IsCompositingCheap() const { return mIsCompositingCheap; }
767
/**
768
* Display the caret if needed.
769
*/
770
bool DisplayCaret(nsIFrame* aFrame, nsDisplayList* aList) {
771
nsIFrame* frame = GetCaretFrame();
772
if (aFrame == frame && !IsBackgroundOnly()) {
773
frame->DisplayCaret(this, aList);
774
return true;
775
}
776
return false;
777
}
778
/**
779
* Get the frame that the caret is supposed to draw in.
780
* If the caret is currently invisible, this will be null.
781
*/
782
nsIFrame* GetCaretFrame() { return mCaretFrame; }
783
/**
784
* Get the rectangle we're supposed to draw the caret into.
785
*/
786
const nsRect& GetCaretRect() { return mCaretRect; }
787
/**
788
* Get the caret associated with the current presshell.
789
*/
790
nsCaret* GetCaret();
791
792
/**
793
* Returns the root scroll frame for the current PresShell, if the PresShell
794
* is ignoring viewport scrolling.
795
*/
796
nsIFrame* GetPresShellIgnoreScrollFrame() {
797
return CurrentPresShellState()->mPresShellIgnoreScrollFrame;
798
}
799
800
/**
801
* Notify the display list builder that we're entering a presshell.
802
* aReferenceFrame should be a frame in the new presshell.
803
* aPointerEventsNoneDoc should be set to true if the frame generating this
804
* document is pointer-events:none.
805
*/
806
void EnterPresShell(nsIFrame* aReferenceFrame,
807
bool aPointerEventsNoneDoc = false);
808
/**
809
* For print-preview documents, we sometimes need to build display items for
810
* the same frames multiple times in the same presentation, with different
811
* clipping. Between each such batch of items, call
812
* ResetMarkedFramesForDisplayList to make sure that the results of
813
* MarkFramesForDisplayList do not carry over between batches.
814
*/
815
void ResetMarkedFramesForDisplayList(nsIFrame* aReferenceFrame);
816
/**
817
* Notify the display list builder that we're leaving a presshell.
818
*/
819
void LeavePresShell(nsIFrame* aReferenceFrame,
820
nsDisplayList* aPaintedContents);
821
822
void IncrementPresShellPaintCount(mozilla::PresShell* aPresShell);
823
824
/**
825
* Returns true if we're currently building a display list that's
826
* directly or indirectly under an nsDisplayTransform.
827
*/
828
bool IsInTransform() const { return mInTransform; }
829
830
bool InEventsAndPluginsOnly() const { return mInEventsAndPluginsOnly; }
831
/**
832
* Indicate whether or not we're directly or indirectly under and
833
* nsDisplayTransform or SVG foreignObject.
834
*/
835
void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }
836
837
/**
838
* Returns true if we're currently building a display list that's
839
* under an nsDisplayFilters.
840
*/
841
bool IsInFilter() const { return mInFilter; }
842
843
bool IsInPageSequence() const { return mInPageSequence; }
844
void SetInPageSequence(bool aInPage) { mInPageSequence = aInPage; }
845
846
/**
847
* Return true if we're currently building a display list for a
848
* nested presshell.
849
*/
850
bool IsInSubdocument() { return mPresShellStates.Length() > 1; }
851
852
void SetDisablePartialUpdates(bool aDisable) {
853
mDisablePartialUpdates = aDisable;
854
}
855
bool DisablePartialUpdates() { return mDisablePartialUpdates; }
856
857
void SetPartialBuildFailed(bool aFailed) { mPartialBuildFailed = aFailed; }
858
bool PartialBuildFailed() { return mPartialBuildFailed; }
859
860
bool IsInActiveDocShell() { return mIsInActiveDocShell; }
861
void SetInActiveDocShell(bool aActive) { mIsInActiveDocShell = aActive; }
862
863
/**
864
* Return true if we're currently building a display list for the presshell
865
* of a chrome document, or if we're building the display list for a popup.
866
*/
867
bool IsInChromeDocumentOrPopup() {
868
return mIsInChromePresContext || mIsBuildingForPopup;
869
}
870
871
/**
872
* @return true if images have been set to decode synchronously.
873
*/
874
bool ShouldSyncDecodeImages() { return mSyncDecodeImages; }
875
876
/**
877
* Indicates whether we should synchronously decode images. If true, we decode
878
* and draw whatever image data has been loaded. If false, we just draw
879
* whatever has already been decoded.
880
*/
881
void SetSyncDecodeImages(bool aSyncDecodeImages) {
882
mSyncDecodeImages = aSyncDecodeImages;
883
}
884
885
nsDisplayTableBackgroundSet* SetTableBackgroundSet(
886
nsDisplayTableBackgroundSet* aTableSet) {
887
nsDisplayTableBackgroundSet* old = mTableBackgroundSet;
888
mTableBackgroundSet = aTableSet;
889
return old;
890
}
891
nsDisplayTableBackgroundSet* GetTableBackgroundSet() const {
892
return mTableBackgroundSet;
893
}
894
895
void FreeClipChains();
896
897
/*
898
* Frees the temporary display items created during merging.
899
*/
900
void FreeTemporaryItems();
901
902
/**
903
* Helper method to generate background painting flags based on the
904
* information available in the display list builder. Currently only
905
* accounts for mSyncDecodeImages.
906
*/
907
uint32_t GetBackgroundPaintFlags();
908
909
/**
910
* Helper method to generate image decoding flags based on the
911
* information available in the display list builder.
912
*/
913
uint32_t GetImageDecodeFlags() const;
914
915
/**
916
* Subtracts aRegion from *aVisibleRegion. We avoid letting
917
* aVisibleRegion become overcomplex by simplifying it if necessary.
918
*/
919
void SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
920
const nsRegion& aRegion);
921
922
void SetNeedsDisplayListBuild(mozilla::wr::RenderRoot aRenderRoot) {
923
MOZ_ASSERT(aRenderRoot != mozilla::wr::RenderRoot::Default);
924
mNeedsDisplayListBuild[aRenderRoot] = true;
925
}
926
927
void ExpandRenderRootRect(LayoutDeviceRect aRect,
928
mozilla::wr::RenderRoot aRenderRoot) {
929
mRenderRootRects[aRenderRoot] = mRenderRootRects[aRenderRoot].Union(aRect);
930
}
931
932
bool GetNeedsDisplayListBuild(mozilla::wr::RenderRoot aRenderRoot) {
933
if (aRenderRoot == mozilla::wr::RenderRoot::Default) {
934
return true;
935
}
936
return mNeedsDisplayListBuild[aRenderRoot];
937
}
938
939
void ComputeDefaultRenderRootRect(LayoutDeviceIntSize aClientSize);
940
941
LayoutDeviceRect GetRenderRootRect(mozilla::wr::RenderRoot aRenderRoot) {
942
return mRenderRootRects[aRenderRoot];
943
}
944
945
/**
946
* Mark the frames in aFrames to be displayed if they intersect aDirtyRect
947
* (which is relative to aDirtyFrame). If the frames have placeholders
948
* that might not be displayed, we mark the placeholders and their ancestors
949
* to ensure that display list construction descends into them
950
* anyway. nsDisplayListBuilder will take care of unmarking them when it is
951
* destroyed.
952
*/
953
void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
954
const nsFrameList& aFrames);
955
void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame);
956
void MarkFrameForDisplayIfVisible(nsIFrame* aFrame, nsIFrame* aStopAtFrame);
957
void AddFrameMarkedForDisplayIfVisible(nsIFrame* aFrame);
958
959
void ClearFixedBackgroundDisplayData();
960
/**
961
* Mark all child frames that Preserve3D() as needing display.
962
* Because these frames include transforms set on their parent, dirty rects
963
* for intermediate frames may be empty, yet child frames could still be
964
* visible.
965
*/
966
void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame);
967
968
/**
969
* Returns true if we need to descend into this frame when building
970
* the display list, even though it doesn't intersect the dirty
971
* rect, because it may have out-of-flows that do so.
972
*/
973
bool ShouldDescendIntoFrame(nsIFrame* aFrame, bool aVisible) const {
974
return (aFrame->GetStateBits() &
975
NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
976
(aVisible && aFrame->ForceDescendIntoIfVisible()) ||
977
GetIncludeAllOutOfFlows();
978
}
979
980
/**
981
* Returns the list of registered theme geometries.
982
*/
983
nsTArray<ThemeGeometry> GetThemeGeometries() const {
984
nsTArray<ThemeGeometry> geometries;
985
986
for (auto iter = mThemeGeometries.ConstIter(); !iter.Done(); iter.Next()) {
987
geometries.AppendElements(*iter.Data());
988
}
989
990
return geometries;
991
}
992
993
/**
994
* Notifies the builder that a particular themed widget exists
995
* at the given rectangle within the currently built display list.
996
* For certain appearance values (currently only StyleAppearance::Toolbar and
997
* StyleAppearance::WindowTitlebar) this gets called during every display list
998
* construction, for every themed widget of the right type within the
999
* display list, except for themed widgets which are transformed or have
1000
* effects applied to them (e.g. CSS opacity or filters).
1001
*
1002
* @param aWidgetType the -moz-appearance value for the themed widget
1003
* @param aItem the item associated with the theme geometry
1004
* @param aRect the device-pixel rect relative to the widget's displayRoot
1005
* for the themed widget
1006
*/
1007
void RegisterThemeGeometry(uint8_t aWidgetType, nsDisplayItem* aItem,
1008
const mozilla::LayoutDeviceIntRect& aRect) {
1009
if (!mIsPaintingToWindow) {
1010
return;
1011
}
1012
1013
nsTArray<ThemeGeometry>* geometries = mThemeGeometries.LookupOrAdd(aItem);
1014
geometries->AppendElement(ThemeGeometry(aWidgetType, aRect));
1015
}
1016
1017
/**
1018
* Removes theme geometries associated with the given display item |aItem|.
1019
*/
1020
void UnregisterThemeGeometry(nsDisplayItem* aItem) {
1021
mThemeGeometries.Remove(aItem);
1022
}
1023
1024
/**
1025
* Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
1026
* -moz-window-dragging value is |drag|, its border box is added to the
1027
* collected dragging region; if the value is |no-drag|, the border box is
1028
* subtracted from the region; if the value is |default|, that frame does
1029
* not influence the window dragging region.
1030
*/
1031
void AdjustWindowDraggingRegion(nsIFrame* aFrame);
1032
1033
LayoutDeviceIntRegion GetWindowDraggingRegion() const;
1034
1035
void RemoveModifiedWindowRegions();
1036
void ClearRetainedWindowRegions();
1037
1038
const nsDataHashtable<nsPtrHashKey<RemoteBrowser>, EffectsInfo>&
1039
GetEffectUpdates() const {
1040
return mEffectsUpdates;
1041
}
1042
1043
void AddEffectUpdate(RemoteBrowser* aBrowser, EffectsInfo aUpdate) {
1044
mEffectsUpdates.Put(aBrowser, aUpdate);
1045
}
1046
1047
/**
1048
* Allocate memory in our arena. It will only be freed when this display list
1049
* builder is destroyed. This memory holds nsDisplayItems and
1050
* DisplayItemClipChain objects.
1051
*
1052
* Destructors are called as soon as the item is no longer used.
1053
*/
1054
void* Allocate(size_t aSize, mozilla::DisplayListArenaObjectId aId) {
1055
return mPool.Allocate(aId, aSize);
1056
}
1057
void* Allocate(size_t aSize, DisplayItemType aType) {
1058
static_assert(size_t(DisplayItemType::TYPE_ZERO) ==
1059
size_t(mozilla::DisplayListArenaObjectId::CLIPCHAIN),
1060
"");
1061
#define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) \
1062
static_assert(size_t(DisplayItemType::TYPE_##name_) == \
1063
size_t(mozilla::DisplayListArenaObjectId::name_), \
1064
"");
1065
#include "nsDisplayItemTypesList.h"
1066
#undef DECLARE_DISPLAY_ITEM_TYPE
1067
return Allocate(aSize, mozilla::DisplayListArenaObjectId(size_t(aType)));
1068
}
1069
1070
void Destroy(mozilla::DisplayListArenaObjectId aId, void* aPtr) {
1071
return mPool.Free(aId, aPtr);
1072
}
1073
void Destroy(DisplayItemType aType, void* aPtr) {
1074
return Destroy(mozilla::DisplayListArenaObjectId(size_t(aType)), aPtr);
1075
}
1076
1077
/**
1078
* Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
1079
* automatically when the arena goes away.
1080
*/
1081
ActiveScrolledRoot* AllocateActiveScrolledRoot(
1082
const ActiveScrolledRoot* aParent, nsIScrollableFrame* aScrollableFrame);
1083
1084
/**
1085
* Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
1086
* up automatically when the arena goes away.
1087
*/
1088
const DisplayItemClipChain* AllocateDisplayItemClipChain(
1089
const DisplayItemClip& aClip, const ActiveScrolledRoot* aASR,
1090
const DisplayItemClipChain* aParent);
1091
1092
/**
1093
* Intersect two clip chains, allocating the new clip chain items in this
1094
* builder's arena. The result is parented to aAncestor, and no intersections
1095
* happen past aAncestor's ASR.
1096
* That means aAncestor has to be living in this builder's arena already.
1097
* aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
1098
* their values are copied into the newly-allocated intersected clip chain
1099
* and this function does not hold on to any pointers to them.
1100
*/
1101
const DisplayItemClipChain* CreateClipChainIntersection(
1102
const DisplayItemClipChain* aAncestor,
1103
const DisplayItemClipChain* aLeafClip1,
1104
const DisplayItemClipChain* aLeafClip2);
1105
1106
/**
1107
* Clone the supplied clip chain's chain items into this builder's arena.
1108
*/
1109
const DisplayItemClipChain* CopyWholeChain(
1110
const DisplayItemClipChain* aClipChain);
1111
1112
/**
1113
* Returns a new clip chain containing an intersection of all clips of
1114
* |aClipChain| up to and including |aASR|.
1115
* If there is no clip, returns nullptr.
1116
*/
1117
const DisplayItemClipChain* FuseClipChainUpTo(
1118
const DisplayItemClipChain* aClipChain, const ActiveScrolledRoot* aASR);
1119
1120
const ActiveScrolledRoot* GetFilterASR() const { return mFilterASR; }
1121
1122
/**
1123
* Transfer off main thread animations to the layer. May be called
1124
* with aBuilder and aItem both null, but only if the caller has
1125
* already checked that off main thread animations should be sent to
1126
* the layer. When they are both null, the animations are added to
1127
* the layer as pending animations.
1128
*/
1129
static void AddAnimationsAndTransitionsToLayer(Layer* aLayer,
1130
nsDisplayListBuilder* aBuilder,
1131
nsDisplayItem* aItem,
1132
nsIFrame* aFrame,
1133
DisplayItemType aType);
1134
1135
/**
1136
* Merges the display items in |aMergedItems| and returns a new temporary
1137
* display item.
1138
* The display items in |aMergedItems| have to be mergeable with each other.
1139
*/
1140
nsDisplayWrapList* MergeItems(nsTArray<nsDisplayWrapList*>& aItems);
1141
1142
/**
1143
* A helper class used to temporarily set nsDisplayListBuilder properties for
1144
* building display items.
1145
* aVisibleRect and aDirtyRect are relative to aForChild.
1146
*/
1147
class AutoBuildingDisplayList {
1148
public:
1149
AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild)
1150
: AutoBuildingDisplayList(
1151
aBuilder, aForChild, aBuilder->GetVisibleRect(),
1152
aBuilder->GetDirtyRect(), aForChild->IsTransformed()) {}
1153
1154
AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
1155
const nsRect& aVisibleRect,
1156
const nsRect& aDirtyRect)
1157
: AutoBuildingDisplayList(aBuilder, aForChild, aVisibleRect, aDirtyRect,
1158
aForChild->IsTransformed()) {}
1159
1160
AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
1161
const nsRect& aVisibleRect,
1162
const nsRect& aDirtyRect,
1163
const bool aIsTransformed);
1164
1165
void SetReferenceFrameAndCurrentOffset(const nsIFrame* aFrame,
1166
const nsPoint& aOffset) {
1167
mBuilder->mCurrentReferenceFrame = aFrame;
1168
mBuilder->mCurrentOffsetToReferenceFrame = aOffset;
1169
}
1170
1171
bool IsAnimatedGeometryRoot() const { return mCurrentAGRState == AGR_YES; }
1172
1173
void RestoreBuildingInvisibleItemsValue() {
1174
mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
1175
}
1176
1177
~AutoBuildingDisplayList() {
1178
mBuilder->mCurrentFrame = mPrevFrame;
1179
mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
1180
mBuilder->mHitTestArea = mPrevHitTestArea;
1181
mBuilder->mHitTestInfo = mPrevHitTestInfo;
1182
mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
1183
mBuilder->mVisibleRect = mPrevVisibleRect;
1184
mBuilder->mDirtyRect = mPrevDirtyRect;
1185
mBuilder->mCurrentAGR = mPrevAGR;
1186
mBuilder->mAncestorHasApzAwareEventHandler =
1187
mPrevAncestorHasApzAwareEventHandler;
1188
mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
1189
mBuilder->mInInvalidSubtree = mPrevInInvalidSubtree;
1190
}
1191
1192
private:
1193
nsDisplayListBuilder* mBuilder;
1194
AGRState mCurrentAGRState;
1195
const nsIFrame* mPrevFrame;
1196
const nsIFrame* mPrevReferenceFrame;
1197
nsRect mPrevHitTestArea;
1198
CompositorHitTestInfo mPrevHitTestInfo;
1199
nsPoint mPrevOffset;
1200
nsRect mPrevVisibleRect;
1201
nsRect mPrevDirtyRect;
1202
RefPtr<AnimatedGeometryRoot> mPrevAGR;
1203
bool mPrevAncestorHasApzAwareEventHandler;
1204
bool mPrevBuildingInvisibleItems;
1205
bool mPrevInInvalidSubtree;
1206
};
1207
1208
/**
1209
* A helper class to temporarily set the value of mInTransform.
1210
*/
1211
class AutoInTransformSetter {
1212
public:
1213
AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
1214
: mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
1215
aBuilder->mInTransform = aInTransform;
1216
}
1217
1218
~AutoInTransformSetter() { mBuilder->mInTransform = mOldValue; }
1219
1220
private:
1221
nsDisplayListBuilder* mBuilder;
1222
bool mOldValue;
1223
};
1224
1225
class AutoInEventsAndPluginsOnly {
1226
public:
1227
AutoInEventsAndPluginsOnly(nsDisplayListBuilder* aBuilder,
1228
bool aInEventsAndPluginsOnly)
1229
: mBuilder(aBuilder), mOldValue(aBuilder->mInEventsAndPluginsOnly) {
1230
aBuilder->mInEventsAndPluginsOnly |= aInEventsAndPluginsOnly;
1231
}
1232
1233
~AutoInEventsAndPluginsOnly() {
1234
mBuilder->mInEventsAndPluginsOnly = mOldValue;
1235
}
1236
1237
private:
1238
nsDisplayListBuilder* mBuilder;
1239
bool mOldValue;
1240
};
1241
1242
/**
1243
* A helper class to temporarily set the value of mFilterASR and
1244
* mInFilter.
1245
*/
1246
class AutoEnterFilter {
1247
public:
1248
AutoEnterFilter(nsDisplayListBuilder* aBuilder, bool aUsingFilter)
1249
: mBuilder(aBuilder),
1250
mOldValue(aBuilder->mFilterASR),
1251
mOldInFilter(aBuilder->mInFilter) {
1252
if (!aBuilder->mFilterASR && aUsingFilter) {
1253
aBuilder->mFilterASR = aBuilder->CurrentActiveScrolledRoot();
1254
aBuilder->mInFilter = true;
1255
}
1256
}
1257
1258
~AutoEnterFilter() {
1259
mBuilder->mFilterASR = mOldValue;
1260
mBuilder->mInFilter = mOldInFilter;
1261
}
1262
1263
private:
1264
nsDisplayListBuilder* mBuilder;
1265
const ActiveScrolledRoot* mOldValue;
1266
bool mOldInFilter;
1267
};
1268
1269
/**
1270
* A helper class to temporarily set the value of mCurrentScrollParentId.
1271
*/
1272
class AutoCurrentScrollParentIdSetter {
1273
public:
1274
AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder,
1275
ViewID aScrollId)
1276
: mBuilder(aBuilder),
1277
mOldValue(aBuilder->mCurrentScrollParentId),
1278
mOldForceLayer(aBuilder->mForceLayerForScrollParent) {
1279
// If this AutoCurrentScrollParentIdSetter has the same scrollId as the
1280
// previous one on the stack, then that means the scrollframe that
1281
// created this isn't actually scrollable and cannot participate in
1282
// scroll handoff. We set mCanBeScrollParent to false to indicate this.
1283
mCanBeScrollParent = (mOldValue != aScrollId);
1284
aBuilder->mCurrentScrollParentId = aScrollId;
1285
aBuilder->mForceLayerForScrollParent = false;
1286
}
1287
1288
bool ShouldForceLayerForScrollParent() const {
1289
// Only scrollframes participating in scroll handoff can be forced to
1290
// layerize
1291
return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent;
1292
}
1293
1294
~AutoCurrentScrollParentIdSetter() {
1295
mBuilder->mCurrentScrollParentId = mOldValue;
1296
if (mCanBeScrollParent) {
1297
// If this flag is set, caller code is responsible for having dealt
1298
// with the current value of mBuilder->mForceLayerForScrollParent, so
1299
// we can just restore the old value.
1300
mBuilder->mForceLayerForScrollParent = mOldForceLayer;
1301
} else {
1302
// Otherwise we need to keep propagating the force-layerization flag
1303
// upwards to the next ancestor scrollframe that does participate in
1304
// scroll handoff.
1305
mBuilder->mForceLayerForScrollParent |= mOldForceLayer;
1306
}
1307
}
1308
1309
private:
1310
nsDisplayListBuilder* mBuilder;
1311
ViewID mOldValue;
1312
bool mOldForceLayer;
1313
bool mCanBeScrollParent;
1314
};
1315
1316
/**
1317
* Used to update the current active scrolled root on the display list
1318
* builder, and to create new active scrolled roots.
1319
*/
1320
class AutoCurrentActiveScrolledRootSetter {
1321
public:
1322
explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder* aBuilder)
1323
: mBuilder(aBuilder),
1324
mSavedActiveScrolledRoot(aBuilder->mCurrentActiveScrolledRoot),
1325
mContentClipASR(aBuilder->ClipState().GetContentClipASR()),
1326
mDescendantsStartIndex(aBuilder->mActiveScrolledRoots.Length()),
1327
mUsed(false) {}
1328
1329
~AutoCurrentActiveScrolledRootSetter() {
1330
mBuilder->mCurrentActiveScrolledRoot = mSavedActiveScrolledRoot;
1331
}
1332
1333
void SetCurrentActiveScrolledRoot(
1334
const ActiveScrolledRoot* aActiveScrolledRoot);
1335
1336
void EnterScrollFrame(nsIScrollableFrame* aScrollableFrame) {
1337
MOZ_ASSERT(!mUsed);
1338
ActiveScrolledRoot* asr = mBuilder->AllocateActiveScrolledRoot(
1339
mBuilder->mCurrentActiveScrolledRoot, aScrollableFrame);
1340
mBuilder->mCurrentActiveScrolledRoot = asr;
1341
mUsed = true;
1342
}
1343
1344
void InsertScrollFrame(nsIScrollableFrame* aScrollableFrame);
1345
1346
private:
1347
nsDisplayListBuilder* mBuilder;
1348
/**
1349
* The builder's mCurrentActiveScrolledRoot at construction time which
1350
* needs to be restored at destruction time.
1351
*/
1352
const ActiveScrolledRoot* mSavedActiveScrolledRoot;
1353
/**
1354
* If there's a content clip on the builder at construction time, then
1355
* mContentClipASR is that content clip's ASR, otherwise null. The
1356
* assumption is that the content clip doesn't get relaxed while this
1357
* object is on the stack.
1358
*/
1359
const ActiveScrolledRoot* mContentClipASR;
1360
/**
1361
* InsertScrollFrame needs to mutate existing ASRs (those that were
1362
* created while this object was on the stack), and mDescendantsStartIndex
1363
* makes it easier to skip ASRs that were created in the past.
1364
*/
1365
size_t mDescendantsStartIndex;
1366
/**
1367
* Flag to make sure that only one of SetCurrentActiveScrolledRoot /
1368
* EnterScrollFrame / InsertScrollFrame is called per instance of this
1369
* class.
1370
*/
1371
bool mUsed;
1372
};
1373
1374
/**
1375
* Keeps track of the innermost ASR that can be used as the ASR for a
1376
* container item that wraps all items that were created while this
1377
* object was on the stack.
1378
* The rule is: all child items of the container item need to have
1379
* clipped bounds with respect to the container ASR.
1380
*/
1381
class AutoContainerASRTracker {
1382
public:
1383
explicit AutoContainerASRTracker(nsDisplayListBuilder* aBuilder)
1384
: mBuilder(aBuilder),
1385
mSavedContainerASR(aBuilder->mCurrentContainerASR) {
1386
mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickDescendant(
1387
mBuilder->ClipState().GetContentClipASR(),
1388
mBuilder->mCurrentActiveScrolledRoot);
1389
}
1390
1391
const ActiveScrolledRoot* GetContainerASR() {
1392
return mBuilder->mCurrentContainerASR;
1393
}
1394
1395
~AutoContainerASRTracker() {
1396
mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
1397
mBuilder->mCurrentContainerASR, mSavedContainerASR);
1398
}
1399
1400
private:
1401
nsDisplayListBuilder* mBuilder;
1402
const ActiveScrolledRoot* mSavedContainerASR;
1403
};
1404
1405
/**
1406
* A helper class to temporarily set the value of mCurrentScrollbarTarget
1407
* and mCurrentScrollbarFlags.
1408
*/
1409
class AutoCurrentScrollbarInfoSetter {
1410
public:
1411
AutoCurrentScrollbarInfoSetter(
1412
nsDisplayListBuilder* aBuilder, ViewID aScrollTargetID,
1413
const MaybeScrollDirection& aScrollbarDirection, bool aWillHaveLayer)
1414
: mBuilder(aBuilder) {
1415
aBuilder->mIsBuildingScrollbar = true;
1416
aBuilder->mCurrentScrollbarTarget = aScrollTargetID;
1417
aBuilder->mCurrentScrollbarDirection = aScrollbarDirection;
1418
aBuilder->mCurrentScrollbarWillHaveLayer = aWillHaveLayer;
1419
}
1420
1421
~AutoCurrentScrollbarInfoSetter() {
1422
// No need to restore old values because scrollbars cannot be nested.
1423
mBuilder->mIsBuildingScrollbar = false;
1424
mBuilder->mCurrentScrollbarTarget = ScrollableLayerGuid::NULL_SCROLL_ID;
1425
mBuilder->mCurrentScrollbarDirection.reset();
1426
mBuilder->mCurrentScrollbarWillHaveLayer = false;
1427
}
1428
1429
private:
1430
nsDisplayListBuilder* mBuilder;
1431
};
1432
1433
/**
1434
* A helper class to track current effective transform for items.
1435
*
1436
* For frames that is Combines3DTransformWithAncestors(), we need to
1437
* apply all transforms of ancestors on the same preserves3D chain
1438
* on the bounds of current frame to the coordination of the 3D
1439
* context root. The 3D context root computes it's bounds from
1440
* these transformed bounds.
1441
*/
1442
class AutoAccumulateTransform {
1443
public:
1444
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
1445
1446
explicit AutoAccumulateTransform(nsDisplayListBuilder* aBuilder)
1447
: mBuilder(aBuilder),
1448
mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform) {}
1449
1450
~AutoAccumulateTransform() {
1451
mBuilder->mPreserves3DCtx.mAccumulatedTransform = mSavedTransform;
1452
}
1453
1454
void Accumulate(const Matrix4x4& aTransform) {
1455
mBuilder->mPreserves3DCtx.mAccumulatedTransform =
1456
aTransform * mBuilder->mPreserves3DCtx.mAccumulatedTransform;
1457
}
1458
1459
const Matrix4x4& GetCurrentTransform() {
1460
return mBuilder->mPreserves3DCtx.mAccumulatedTransform;
1461
}
1462
1463
void StartRoot() {
1464
mBuilder->mPreserves3DCtx.mAccumulatedTransform = Matrix4x4();
1465
}
1466
1467
private:
1468
nsDisplayListBuilder* mBuilder;
1469
Matrix4x4 mSavedTransform;
1470
};
1471
1472
/**
1473
* A helper class to collect bounds rects of descendants.
1474
*
1475
* For a 3D context root, it's bounds is computed from the bounds of
1476
* descendants. If we transform bounds frame by frame applying
1477
* transforms, the bounds may turn to empty for any singular
1478
* transform on the path, but it is not empty for the accumulated
1479
* transform.
1480
*/
1481
class AutoAccumulateRect {
1482
public:
1483
explicit AutoAccumulateRect(nsDisplayListBuilder* aBuilder)
1484
: mBuilder(aBuilder),
1485
mSavedRect(aBuilder->mPreserves3DCtx.mAccumulatedRect) {
1486
aBuilder->mPreserves3DCtx.mAccumulatedRect = nsRect();
1487
aBuilder->mPreserves3DCtx.mAccumulatedRectLevels++;
1488
}
1489
1490
~AutoAccumulateRect() {
1491
mBuilder->mPreserves3DCtx.mAccumulatedRect = mSavedRect;
1492
mBuilder->mPreserves3DCtx.mAccumulatedRectLevels--;
1493
}
1494
1495
private:
1496
nsDisplayListBuilder* mBuilder;
1497
nsRect mSavedRect;
1498
};
1499
1500
void AccumulateRect(const nsRect& aRect) {
1501
mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect,
1502
aRect);
1503
}
1504
1505
const nsRect& GetAccumulatedRect() {
1506
return mPreserves3DCtx.mAccumulatedRect;
1507
}
1508
1509
/**
1510
* The level is increased by one for items establishing 3D rendering
1511
* context and starting a new accumulation.
1512
*/
1513
int GetAccumulatedRectLevels() {
1514
return mPreserves3DCtx.mAccumulatedRectLevels;
1515
}
1516
1517
struct OutOfFlowDisplayData {
1518
OutOfFlowDisplayData(
1519
const DisplayItemClipChain* aContainingBlockClipChain,
1520
const DisplayItemClipChain* aCombinedClipChain,
1521
const ActiveScrolledRoot* aContainingBlockActiveScrolledRoot,
1522
const nsRect& aVisibleRect, const nsRect& aDirtyRect)
1523
: mContainingBlockClipChain(aContainingBlockClipChain),
1524
mCombinedClipChain(aCombinedClipChain),
1525
mContainingBlockActiveScrolledRoot(
1526
aContainingBlockActiveScrolledRoot),
1527
mVisibleRect(aVisibleRect),
1528
mDirtyRect(aDirtyRect) {}
1529
const DisplayItemClipChain* mContainingBlockClipChain;
1530
const DisplayItemClipChain*
1531
mCombinedClipChain; // only necessary for the special case of top layer
1532
const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot;
1533
nsRect mVisibleRect;
1534
nsRect mDirtyRect;
1535
1536
static nsRect ComputeVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
1537
nsIFrame* aFrame,
1538
const nsRect& aVisibleRect,
1539
const nsRect& aDirtyRect,
1540
nsRect* aOutDirtyRect);
1541
1542
nsRect GetVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
1543
nsIFrame* aFrame, nsRect* aDirtyRect) {
1544
return ComputeVisibleRectForFrame(aBuilder, aFrame, mVisibleRect,
1545
mDirtyRect, aDirtyRect);
1546
}
1547
};
1548
1549
NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty,
1550
OutOfFlowDisplayData)
1551
1552
struct DisplayListBuildingData {
1553
RefPtr<AnimatedGeometryRoot> mModifiedAGR = nullptr;
1554
nsRect mDirtyRect;
1555
};
1556
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect,
1557
DisplayListBuildingData)
1558
1559
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect,
1560
nsRect)
1561
1562
static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame) {
1563
if (!aFrame->GetParent()) {
1564
return nullptr;
1565
}
1566
return aFrame->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
1567
}
1568
1569
nsPresContext* CurrentPresContext() {
1570
return CurrentPresShellState()->mPresShell->GetPresContext();
1571
}
1572
1573
OutOfFlowDisplayData* GetCurrentFixedBackgroundDisplayData() {
1574
auto& displayData = CurrentPresShellState()->mFixedBackgroundDisplayData;
1575
return displayData ? displayData.ptr() : nullptr;
1576
}
1577
1578
/**
1579
* Accumulates the bounds of box frames that have moz-appearance
1580
* -moz-win-exclude-glass style. Used in setting glass margins on
1581
* Windows.
1582
*
1583
* We set the window opaque region (from which glass margins are computed)
1584
* to the intersection of the glass region specified here and the opaque
1585
* region computed during painting. So the excluded glass region actually
1586
* *limits* the extent of the opaque area reported to Windows. We limit it
1587
* so that changes to the computed opaque region (which can vary based on
1588
* region optimizations and the placement of UI elements) outside the
1589
* -moz-win-exclude-glass area don't affect the glass margins reported to
1590
* Windows; changing those margins willy-nilly can cause the Windows 7 glass
1591
* haze effect to jump around disconcertingly.
1592
*/
1593
void AddWindowExcludeGlassRegion(nsIFrame* aFrame, const nsRect& aBounds) {
1594
mWindowExcludeGlassRegion.Add(aFrame, aBounds);
1595
}
1596
1597
/**
1598
* Returns the window exclude glass region.
1599
*/
1600
nsRegion GetWindowExcludeGlassRegion() const {
1601
return mWindowExcludeGlassRegion.ToRegion();
1602
}
1603
1604
/**
1605
* Accumulates opaque stuff into the window opaque region.
1606
*/
1607
void AddWindowOpaqueRegion(nsIFrame* aFrame, const nsRect& aBounds) {
1608
if (IsRetainingDisplayList()) {
1609
mRetainedWindowOpaqueRegion.Add(aFrame, aBounds);
1610
return;
1611
}
1612
mWindowOpaqueRegion.Or(mWindowOpaqueRegion, aBounds);
1613
}
1614
/**
1615
* Returns the window opaque region built so far. This may be incomplete
1616
* since the opaque region is built during layer construction.
1617
*/
1618
const nsRegion GetWindowOpaqueRegion() {
1619
return IsRetainingDisplayList() ? mRetainedWindowOpaqueRegion.ToRegion()
1620
: mWindowOpaqueRegion;
1621
}
1622
1623
void SetGlassDisplayItem(nsDisplayItem* aItem);
1624
void ClearGlassDisplayItem() { mGlassDisplayItem = nullptr; }
1625
nsDisplayItem* GetGlassDisplayItem() { return mGlassDisplayItem; }
1626
1627
bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem);
1628
1629
void SetContainsPluginItem() { mContainsPluginItem = true; }
1630
bool ContainsPluginItem() { return mContainsPluginItem; }
1631
1632
/**
1633
* mContainsBlendMode is true if we processed a display item that
1634
* has a blend mode attached. We do this so we can insert a
1635
* nsDisplayBlendContainer in the parent stacking context.
1636
*/
1637
void SetContainsBlendMode(bool aContainsBlendMode) {
1638
mContainsBlendMode = aContainsBlendMode;
1639
}
1640
bool ContainsBlendMode() const { return mContainsBlendMode; }
1641
1642
/**
1643
* mContainsBackdropFilter is true if we proccessed a display item that
1644
* has a backdrop filter set. We track this so we can insert a
1645
* nsDisplayBackdropRootContainer in the stacking context of the nearest
1646
* ancestor that forms a backdrop root.
1647
*/
1648
void SetContainsBackdropFilter(bool aContainsBackdropFilter) {
1649
mContainsBackdropFilter = aContainsBackdropFilter;
1650
}
1651
bool ContainsBackdropFilter() const { return mContainsBackdropFilter; }
1652
1653
DisplayListClipState& ClipState() { return mClipState; }
1654
const ActiveScrolledRoot* CurrentActiveScrolledRoot() {
1655
return mCurrentActiveScrolledRoot;
1656
}
1657
const ActiveScrolledRoot* CurrentAncestorASRStackingContextContents() {
1658
return mCurrentContainerASR;
1659
}
1660
1661
/**
1662
* Add the current frame to the will-change budget if possible and
1663
* remeber the outcome. Subsequent calls to IsInWillChangeBudget
1664
* will return the same value as return here.
1665
*/
1666
bool AddToWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
1667
1668
/**
1669
* This will add the current frame to the will-change budget the first
1670
* time it is seen. On subsequent calls this will return the same
1671
* answer. This effectively implements a first-come, first-served
1672
* allocation of the will-change budget.
1673
*/
1674
bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
1675
1676
void RemoveFromWillChangeBudget(nsIFrame* aFrame);
1677
1678
void ClearWillChangeBudget();
1679
1680
void EnterSVGEffectsContents(nsIFrame* aEffectsFrame,
1681
nsDisplayList* aHoistedItemsStorage);
1682
void ExitSVGEffectsContents();
1683
1684
bool ShouldBuildScrollInfoItemsForHoisting() const;
1685
1686
void AppendNewScrollInfoItemForHoisting(
1687
nsDisplayScrollInfoLayer* aScrollInfoItem);
1688
1689
/**
1690
* A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
1691
*
1692
* mPreserves3DCtx is used by class AutoAccumulateTransform &
1693
* AutoAccumulateRect to passing data between frames in the 3D
1694
* context. If a frame create a new 3D context, it should restore
1695
* the value of mPreserves3DCtx before returning back to the parent.
1696
* This class do it for the users.
1697
*/
1698
class AutoPreserves3DContext {
1699
public:
1700
explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder)
1701
: mBuilder(aBuilder), mSavedCtx(aBuilder->mPreserves3DCtx) {}
1702
1703
~AutoPreserves3DContext() { mBuilder->mPreserves3DCtx = mSavedCtx; }
1704
1705
private:
1706
nsDisplayListBuilder* mBuilder;
1707
Preserves3DContext mSavedCtx;
1708
};
1709
1710
const nsRect GetPreserves3DRect() const {
1711
return mPreserves3DCtx.mVisibleRect;
1712
}
1713
1714
void SavePreserves3DRect() { mPreserves3DCtx.mVisibleRect = mVisibleRect; }
1715
1716
bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems; }
1717
1718
void SetBuildingInvisibleItems(bool aBuildingInvisibleItems) {
1719
mBuildingInvisibleItems = aBuildingInvisibleItems;
1720
}
1721
1722
void SetBuildingExtraPagesForPageNum(uint8_t aPageNum) {
1723
mBuildingExtraPagesForPageNum = aPageNum;
1724
}
1725
uint8_t GetBuildingExtraPagesForPageNum() const {
1726
return mBuildingExtraPagesForPageNum;
1727
}
1728
1729
/**
1730
* This is a convenience function to ease the transition until AGRs and ASRs
1731
* are unified.
1732
*/
1733
AnimatedGeometryRoot* AnimatedGeometryRootForASR(
1734
const ActiveScrolledRoot* aASR);
1735
1736
bool HitTestIsForVisibility() const { return mHitTestIsForVisibility; }
1737
1738
void SetHitTestIsForVisibility(bool aHitTestIsForVisibility) {
1739
mHitTestIsForVisibility = aHitTestIsForVisibility;
1740
}
1741
1742
bool ShouldBuildAsyncZoomContainer() const {
1743
return mBuildAsyncZoomContainer;
1744
}
1745
void UpdateShouldBuildAsyncZoomContainer();
1746
1747
void UpdateShouldBuildBackdropRootContainer();
1748
1749
bool ShouldRebuildDisplayListDueToPrefChange();
1750
1751
/**
1752
* Represents a region composed of frame/rect pairs.
1753
* WeakFrames are used to track whether a rect still belongs to the region.
1754
* Modified frames and rects are removed and re-added to the region if needed.
1755
*/
1756
struct WeakFrameRegion {
1757
/**
1758
* A wrapper to store WeakFrame and the pointer to the underlying frame.
1759
* This is needed because WeakFrame does not store the frame pointer after
1760
* the frame has been deleted.
1761
*/
1762
struct WeakFrameWrapper {
1763
explicit WeakFrameWrapper(nsIFrame* aFrame)
1764
: mWeakFrame(new WeakFrame(aFrame)), mFrame(aFrame) {}
1765
1766
mozilla::UniquePtr<WeakFrame> mWeakFrame;
1767
void* mFrame;
1768
};
1769
1770
nsTHashtable<nsPtrHashKey<void>> mFrameSet;
1771
nsTArray<WeakFrameWrapper> mFrames;
1772
nsTArray<pixman_box32_t> mRects;
1773
1774
template <typename RectType>
1775
void Add(nsIFrame* aFrame, const RectType& aRect) {
1776
if (mFrameSet.Contains(aFrame)) {
1777
return;
1778
}
1779
1780
mFrameSet.PutEntry(aFrame);
1781
mFrames.AppendElement(WeakFrameWrapper(aFrame));
1782
mRects.AppendElement(nsRegion::RectToBox(aRect));
1783
}
1784
1785
void Clear() {
1786
mFrameSet.Clear();
1787
mFrames.Clear();
1788
mRects.Clear();
1789
}
1790
1791
void RemoveModifiedFramesAndRects();
1792
1793
size_t SizeOfExcludingThis(mozilla::MallocSizeOf) const;
1794
1795
typedef mozilla::gfx::ArrayView<pixman_box32_t> BoxArrayView;
1796
1797
nsRegion ToRegion() const { return nsRegion(BoxArrayView(mRects)); }
1798
1799
LayoutDeviceIntRegion ToLayoutDeviceIntRegion() const {
1800
return LayoutDeviceIntRegion(BoxArrayView(mRects));
1801
}
1802
};
1803
1804
private:
1805
bool MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame);
1806
1807
/**
1808
* Returns whether a frame acts as an animated geometry root, optionally
1809
* returning the next ancestor to check.
1810
*/
1811
AGRState IsAnimatedGeometryRoot(nsIFrame* aFrame, bool& aIsAsync,
1812
nsIFrame** aParent = nullptr);
1813
1814
/**
1815
* Returns the nearest ancestor frame to aFrame that is considered to have
1816
* (or will have) animated geometry. This can return aFrame.
1817
*/
1818
nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame, bool& aIsAsync);
1819
1820
friend class nsDisplayCanvasBackgroundImage;
1821
friend class nsDisplayBackgroundImage;
1822
friend class nsDisplayFixedPosition;
1823
friend class nsDisplayPerspective;
1824
AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsDisplayItem* aItem);
1825
1826
friend class nsDisplayItem;
1827
friend class nsDisplayOwnLayer;
1828
friend struct RetainedDisplayListBuilder;
1829
friend struct HitTestInfo;
1830
AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsIFrame* aFrame);
1831
1832
AnimatedGeometryRoot* WrapAGRForFrame(
1833
nsIFrame* aAnimatedGeometryRoot, bool aIsAsync,
1834
AnimatedGeometryRoot* aParent = nullptr);
1835
1836
nsDataHashtable<nsPtrHashKey<nsIFrame>, RefPtr<AnimatedGeometryRoot>>
1837
mFrameToAnimatedGeometryRootMap;
1838
1839
/**
1840
* Add the current frame to the AGR budget if possible and remember
1841
* the outcome. Subsequent calls will return the same value as
1842
* returned here.
1843
*/
1844
bool AddToAGRBudget(nsIFrame* aFrame);
1845
1846
struct PresShellState {
1847
mozilla::PresShell* mPresShell;
1848
#ifdef DEBUG
1849
mozilla::Maybe<nsAutoLayoutPhase> mAutoLayoutPhase;
1850
#endif
1851
mozilla::Maybe<OutOfFlowDisplayData> mFixedBackgroundDisplayData;
1852
uint32_t mFirstFrameMarkedForDisplay;
1853
uint32_t mFirstFrameWithOOFData;
1854
bool mIsBackgroundOnly;
1855
// This is a per-document flag turning off event handling for all content
1856
// in the document, and is set when we enter a subdocument for a pointer-
1857
// events:none frame.
1858
bool mInsidePointerEventsNoneDoc;
1859
bool mTouchEventPrefEnabledDoc;
1860
nsIFrame* mPresShellIgnoreScrollFrame;
1861
};
1862
1863
PresShellState* CurrentPresShellState() {
1864
NS_ASSERTION(mPresShellStates.Length() > 0,
1865
"Someone forgot to enter a presshell");
1866
return &mPresShellStates[mPresShellStates.Length() - 1];
1867
}
1868
1869
void AddSizeOfExcludingThis(nsWindowSizes&) const;
1870
1871
struct DocumentWillChangeBudget {
1872
DocumentWillChangeBudget() : mBudget(0) {}