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/.
9 * structures that represent things to be painted (ordered in z-order),
10 * used during painting and hit testing
13 #ifndef NSDISPLAYLIST_H_
14 #define NSDISPLAYLIST_H_
16 #include "DisplayItemClipChain.h"
17 #include "DisplayListClipState.h"
18 #include "FrameMetrics.h"
19 #include "HitTestInfo.h"
20 #include "ImgDrawResult.h"
21 #include "RetainedDisplayListHelpers.h"
23 #include "gfxContext.h"
24 #include "mozilla/ArenaAllocator.h"
25 #include "mozilla/Array.h"
26 #include "mozilla/ArrayIterator.h"
27 #include "mozilla/Assertions.h"
28 #include "mozilla/Attributes.h"
29 #include "mozilla/DebugOnly.h"
30 #include "mozilla/EffectCompositor.h"
31 #include "mozilla/EnumSet.h"
32 #include "mozilla/EnumeratedArray.h"
33 #include "mozilla/Logging.h"
34 #include "mozilla/Maybe.h"
35 #include "mozilla/MotionPathUtils.h"
36 #include "mozilla/RefPtr.h"
37 #include "mozilla/TemplateLib.h"
38 #include "mozilla/TimeStamp.h"
39 #include "mozilla/UniquePtr.h"
40 #include "mozilla/dom/EffectsInfo.h"
41 #include "mozilla/gfx/UserData.h"
42 #include "mozilla/layers/BSPTree.h"
43 #include "mozilla/layers/ScrollableLayerGuid.h"
44 #include "mozilla/layers/ScrollbarData.h"
45 #include "nsAutoLayoutPhase.h"
47 #include "nsCSSRenderingBorders.h"
48 #include "nsContainerFrame.h"
49 #include "nsDisplayItemTypes.h"
50 #include "nsDisplayListInvalidation.h"
52 #include "nsPresArena.h"
55 #include "nsClassHashtable.h"
56 #include "nsTHashSet.h"
57 #include "nsTHashMap.h"
60 #include <unordered_set>
62 // XXX Includes that could be avoided by moving function implementations to the
64 #include "gfxPlatform.h"
68 class nsIScrollableFrame
;
69 class nsSubDocumentFrame
;
71 struct WrFiltersHolder
;
73 namespace nsStyleTransformMatrix
{
74 class TransformReferenceBox
;
79 enum class nsDisplayOwnLayerFlags
;
80 class nsDisplayCompositorHitTestInfo
;
81 class nsDisplayScrollInfoLayer
;
83 class StickyScrollContainer
;
87 class RenderRootStateManager
;
90 class StackingContextHelper
;
91 class WebRenderScrollData
;
92 class WebRenderLayerScrollData
;
93 class WebRenderLayerManager
;
97 class DisplayListBuilder
;
105 enum class DisplayListArenaObjectId
{
106 #define DISPLAY_LIST_ARENA_OBJECT(name_) name_,
107 #include "nsDisplayListArenaTypes.h"
108 #undef DISPLAY_LIST_ARENA_OBJECT
112 extern LazyLogModule sContentDisplayListLog
;
113 extern LazyLogModule sParentDisplayListLog
;
115 LazyLogModule
& GetLoggerByProcess();
117 #define DL_LOG(lvl, ...) MOZ_LOG(GetLoggerByProcess(), lvl, (__VA_ARGS__))
118 #define DL_LOGI(...) DL_LOG(LogLevel::Info, __VA_ARGS__)
119 #define DL_LOG_TEST(lvl) MOZ_LOG_TEST(GetLoggerByProcess(), lvl)
122 # define DL_LOGD(...) DL_LOG(LogLevel::Debug, __VA_ARGS__)
123 # define DL_LOGV(...) DL_LOG(LogLevel::Verbose, __VA_ARGS__)
125 // Disable Debug and Verbose logs for release builds.
126 # define DL_LOGD(...)
127 # define DL_LOGV(...)
131 * An nsIFrame can have many different visual parts. For example an image frame
132 * can have a background, border, and outline, the image itself, and a
133 * translucent selection overlay. In general these parts can be drawn at
134 * discontiguous z-levels; see CSS2.1 appendix E:
135 * http://www.w3.org/TR/CSS21/zindex.html
137 * We construct a display list for a frame tree that contains one item
138 * for each visual part. The display list is itself a tree since some items
139 * are containers for other items; however, its structure does not match
140 * the structure of its source frame tree. The display list items are sorted
141 * by z-order. A display list can be used to paint the frames, to determine
142 * which frame is the target of a mouse event, and to determine what areas
143 * need to be repainted when scrolling. The display lists built for each task
144 * may be different for efficiency; in particular some frames need special
145 * display list items only for event handling, and do not create these items
146 * when the display list will be used for painting (the common case). For
147 * example, when painting we avoid creating nsDisplayBackground items for
148 * frames that don't display a visible background, but for event handling
149 * we need those backgrounds because they are not transparent to events.
151 * We could avoid constructing an explicit display list by traversing the
152 * frame tree multiple times in clever ways. However, reifying the display list
153 * reduces code complexity and reduces the number of times each frame must be
154 * traversed to one, which seems to be good for performance. It also means
155 * we can share code for painting, event handling and scroll analysis.
157 * Display lists are short-lived; content and frame trees cannot change
158 * between a display list being created and destroyed. Display lists should
159 * not be created during reflow because the frame tree may be in an
160 * inconsistent state (e.g., a frame's stored overflow-area may not include
161 * the bounds of all its children). However, it should be fine to create
162 * a display list while a reflow is pending, before it starts.
164 * A display list covers the "extended" frame tree; the display list for
165 * a frame tree containing FRAME/IFRAME elements can include frames from
168 * Display item's coordinates are relative to their nearest reference frame
169 * ancestor. Both the display root and any frame with a transform act as a
170 * reference frame for their frame subtrees.
174 * An active scrolled root (ASR) is similar to an animated geometry root (AGR).
175 * The differences are:
176 * - ASRs are only created for async-scrollable scroll frames. This is a
177 * (hopefully) temporary restriction. In the future we will want to create
178 * ASRs for all the things that are currently creating AGRs, and then
179 * replace AGRs with ASRs and rename them from "active scrolled root" to
180 * "animated geometry root".
181 * - ASR objects are created during display list construction by the nsIFrames
182 * that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter.
183 * The current ASR is returned by
184 * nsDisplayListBuilder::CurrentActiveScrolledRoot().
185 * - There is no way to go from an nsIFrame pointer to the ASR of that frame.
186 * If you need to look up an ASR after display list construction, you need
187 * to store it while the AutoCurrentActiveScrolledRootSetter that creates it
190 struct ActiveScrolledRoot
{
191 static already_AddRefed
<ActiveScrolledRoot
> CreateASRForFrame(
192 const ActiveScrolledRoot
* aParent
, nsIScrollableFrame
* aScrollableFrame
,
195 static const ActiveScrolledRoot
* PickAncestor(
196 const ActiveScrolledRoot
* aOne
, const ActiveScrolledRoot
* aTwo
) {
197 MOZ_ASSERT(IsAncestor(aOne
, aTwo
) || IsAncestor(aTwo
, aOne
));
198 return Depth(aOne
) <= Depth(aTwo
) ? aOne
: aTwo
;
201 static const ActiveScrolledRoot
* PickDescendant(
202 const ActiveScrolledRoot
* aOne
, const ActiveScrolledRoot
* aTwo
) {
203 MOZ_ASSERT(IsAncestor(aOne
, aTwo
) || IsAncestor(aTwo
, aOne
));
204 return Depth(aOne
) >= Depth(aTwo
) ? aOne
: aTwo
;
207 static bool IsAncestor(const ActiveScrolledRoot
* aAncestor
,
208 const ActiveScrolledRoot
* aDescendant
);
209 static bool IsProperAncestor(const ActiveScrolledRoot
* aAncestor
,
210 const ActiveScrolledRoot
* aDescendant
);
212 static nsCString
ToString(const ActiveScrolledRoot
* aActiveScrolledRoot
);
214 // Call this when inserting an ancestor.
215 void IncrementDepth() { mDepth
++; }
218 * Find the view ID (or generate a new one) for the content element
219 * corresponding to the ASR.
221 layers::ScrollableLayerGuid::ViewID
GetViewId() const {
222 if (!mViewId
.isSome()) {
223 mViewId
= Some(ComputeViewId());
228 RefPtr
<const ActiveScrolledRoot
> mParent
;
229 nsIScrollableFrame
* mScrollableFrame
;
231 NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot
)
235 : mScrollableFrame(nullptr), mDepth(0), mRetained(false) {}
237 ~ActiveScrolledRoot();
239 static void DetachASR(ActiveScrolledRoot
* aASR
) {
240 aASR
->mParent
= nullptr;
241 aASR
->mScrollableFrame
= nullptr;
244 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache
,
245 ActiveScrolledRoot
, DetachASR
)
247 static uint32_t Depth(const ActiveScrolledRoot
* aActiveScrolledRoot
) {
248 return aActiveScrolledRoot
? aActiveScrolledRoot
->mDepth
: 0;
251 layers::ScrollableLayerGuid::ViewID
ComputeViewId() const;
253 // This field is lazily populated in GetViewId(). We don't want to do the
254 // work of populating if webrender is disabled, because it is often not
256 mutable Maybe
<layers::ScrollableLayerGuid::ViewID
> mViewId
;
262 enum class nsDisplayListBuilderMode
: uint8_t {
270 using ListArenaAllocator
= ArenaAllocator
<4096, 8>;
273 class nsPaintedDisplayItem
;
275 class nsDisplayWrapList
;
276 class nsDisplayTableBackgroundSet
;
277 class nsDisplayTableItem
;
279 class RetainedDisplayList
;
282 * This manages a display list and is passed as a parameter to
283 * nsIFrame::BuildDisplayList.
284 * It contains the parameters that don't change from frame to frame and manages
285 * the display list memory using an arena. It also establishes the reference
286 * coordinate system for all display list items. Some of the parameters are
287 * available from the prescontext/presshell, but we copy them into the builder
288 * for faster/more convenient access.
290 class nsDisplayListBuilder
{
292 * This manages status of a 3d context to collect visible rects of
293 * descendants and passing a dirty rect.
295 * Since some transforms maybe singular, passing visible rects or
296 * the dirty rect level by level from parent to children may get a
297 * wrong result, being different from the result of appling with
298 * effective transform directly.
300 * nsIFrame::BuildDisplayListForStackingContext() uses
301 * AutoPreserves3DContext to install an instance on the builder.
303 * \see AutoAccumulateTransform, AutoAccumulateRect,
304 * AutoPreserves3DContext, Accumulate, GetCurrentTransform,
307 class Preserves3DContext
{
310 : mAccumulatedRectLevels(0), mAllowAsyncAnimation(true) {}
312 Preserves3DContext(const Preserves3DContext
& aOther
)
313 : mAccumulatedRectLevels(0),
314 mVisibleRect(aOther
.mVisibleRect
),
315 mAllowAsyncAnimation(aOther
.mAllowAsyncAnimation
) {}
317 // Accmulate transforms of ancestors on the preserves-3d chain.
318 gfx::Matrix4x4 mAccumulatedTransform
;
319 // Accmulate visible rect of descendants in the preserves-3d context.
320 nsRect mAccumulatedRect
;
321 // How far this frame is from the root of the current 3d context.
322 int mAccumulatedRectLevels
;
324 // Allow async animation for this 3D context.
325 bool mAllowAsyncAnimation
;
329 using ViewID
= layers::ScrollableLayerGuid::ViewID
;
332 * @param aReferenceFrame the frame at the root of the subtree; its origin
333 * is the origin of the reference coordinate system for this display list
334 * @param aMode encodes what the builder is being used for.
335 * @param aBuildCaret whether or not we should include the caret in any
336 * display lists that we make.
338 nsDisplayListBuilder(nsIFrame
* aReferenceFrame
,
339 nsDisplayListBuilderMode aMode
, bool aBuildCaret
,
340 bool aRetainingDisplayList
= false);
341 ~nsDisplayListBuilder();
346 void AddTemporaryItem(nsDisplayItem
* aItem
) {
347 mTemporaryItems
.AppendElement(aItem
);
350 WindowRenderer
* GetWidgetWindowRenderer(nsView
** aView
= nullptr);
351 layers::WebRenderLayerManager
* GetWidgetLayerManager(
352 nsView
** aView
= nullptr);
355 * @return true if the display is being built in order to determine which
356 * frame is under the mouse position.
358 bool IsForEventDelivery() const {
359 return mMode
== nsDisplayListBuilderMode::EventDelivery
;
363 * @return true if the display list is being built for painting. This
364 * includes both painting to a window or other buffer and painting to
365 * a print/pdf destination.
367 bool IsForPainting() const {
368 return mMode
== nsDisplayListBuilderMode::Painting
||
369 mMode
== nsDisplayListBuilderMode::PaintForPrinting
;
373 * @return true if the display list is being built specifically for printing.
375 bool IsForPrinting() const {
376 return mMode
== nsDisplayListBuilderMode::PaintForPrinting
;
380 * @return true if the display list is being built for determining frame
383 bool IsForFrameVisibility() const {
384 return mMode
== nsDisplayListBuilderMode::FrameVisibility
;
388 * @return true if the display list is being built for creating the glyph
389 * mask from text items.
391 bool IsForGenerateGlyphMask() const {
392 return mMode
== nsDisplayListBuilderMode::GenerateGlyph
;
395 bool BuildCompositorHitTestInfo() const {
396 return mBuildCompositorHitTestInfo
;
400 * @return true if "painting is suppressed" during page load and we
401 * should paint only the background of the document.
403 bool IsBackgroundOnly() {
404 NS_ASSERTION(mPresShellStates
.Length() > 0,
405 "don't call this if we're not in a presshell");
406 return CurrentPresShellState()->mIsBackgroundOnly
;
410 * @return the root of given frame's (sub)tree, whose origin
411 * establishes the coordinate system for the child display items.
413 const nsIFrame
* FindReferenceFrameFor(const nsIFrame
* aFrame
,
414 nsPoint
* aOffset
= nullptr) const;
416 const Maybe
<nsPoint
>& AdditionalOffset() const { return mAdditionalOffset
; }
419 * @return the root of the display list's frame (sub)tree, whose origin
420 * establishes the coordinate system for the display list
422 nsIFrame
* RootReferenceFrame() const { return mReferenceFrame
; }
425 * @return a point pt such that adding pt to a coordinate relative to aFrame
426 * makes it relative to ReferenceFrame(), i.e., returns
427 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
428 * the appunits of aFrame.
430 const nsPoint
ToReferenceFrame(const nsIFrame
* aFrame
) const {
432 FindReferenceFrameFor(aFrame
, &result
);
436 * When building the display list, the scrollframe aFrame will be "ignored"
437 * for the purposes of clipping, and its scrollbars will be hidden. We use
438 * this to allow RenderOffscreen to render a whole document without beign
439 * clipped by the viewport or drawing the viewport scrollbars.
441 void SetIgnoreScrollFrame(nsIFrame
* aFrame
) { mIgnoreScrollFrame
= aFrame
; }
443 * Get the scrollframe to ignore, if any.
445 nsIFrame
* GetIgnoreScrollFrame() { return mIgnoreScrollFrame
; }
446 void SetIsRelativeToLayoutViewport();
447 bool IsRelativeToLayoutViewport() const {
448 return mIsRelativeToLayoutViewport
;
451 * Get the ViewID of the nearest scrolling ancestor frame.
453 ViewID
GetCurrentScrollParentId() const { return mCurrentScrollParentId
; }
455 * Get and set the flag that indicates if scroll parents should have layers
456 * forcibly created. This flag is set when a deeply nested scrollframe has
457 * a displayport, and for scroll handoff to work properly the ancestor
458 * scrollframes should also get their own scrollable layers.
460 void ForceLayerForScrollParent();
461 uint32_t GetNumActiveScrollframesEncountered() const {
462 return mNumActiveScrollframesEncountered
;
465 * Set the flag that indicates there is a non-minimal display port in the
466 * current subtree. This is used to determine display port expiry.
468 void SetContainsNonMinimalDisplayPort() {
469 mContainsNonMinimalDisplayPort
= true;
472 * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
473 * which we are building display items at the moment.
475 ViewID
GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget
; }
476 Maybe
<layers::ScrollDirection
> GetCurrentScrollbarDirection() const {
477 return mCurrentScrollbarDirection
;
480 * Returns true if building a scrollbar, and the scrollbar will not be
483 bool IsBuildingNonLayerizedScrollbar() const {
484 return mIsBuildingScrollbar
&& !mCurrentScrollbarWillHaveLayer
;
487 * Calling this setter makes us include all out-of-flow descendant
488 * frames in the display list, wherever they may be positioned (even
489 * outside the dirty rects).
491 void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows
= true; }
492 bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows
; }
494 * Calling this setter makes us exclude all leaf frames that aren't
497 void SetSelectedFramesOnly() { mSelectedFramesOnly
= true; }
498 bool GetSelectedFramesOnly() { return mSelectedFramesOnly
; }
500 * @return Returns true if we should include the caret in any display lists
503 bool IsBuildingCaret() const { return mBuildCaret
; }
505 bool IsRetainingDisplayList() const { return mRetainingDisplayList
; }
507 bool IsPartialUpdate() const { return mPartialUpdate
; }
508 void SetPartialUpdate(bool aPartial
) { mPartialUpdate
= aPartial
; }
510 bool IsBuilding() const { return mIsBuilding
; }
511 void SetIsBuilding(bool aIsBuilding
) { mIsBuilding
= aIsBuilding
; }
513 bool InInvalidSubtree() const { return mInInvalidSubtree
; }
516 * Allows callers to selectively override the regular paint suppression
517 * checks, so that methods like GetFrameForPoint work when painting is
520 void IgnorePaintSuppression() { mIgnoreSuppression
= true; }
522 * @return Returns if this builder will ignore paint suppression.
524 bool IsIgnoringPaintSuppression() { return mIgnoreSuppression
; }
526 * Call this if we're doing normal painting to the window.
528 void SetPaintingToWindow(bool aToWindow
) { mIsPaintingToWindow
= aToWindow
; }
529 bool IsPaintingToWindow() const { return mIsPaintingToWindow
; }
531 * Call this if we're using high quality scaling for image decoding.
532 * It is also implied by IsPaintingToWindow.
534 void SetUseHighQualityScaling(bool aUseHighQualityScaling
) {
535 mUseHighQualityScaling
= aUseHighQualityScaling
;
537 bool UseHighQualityScaling() const {
538 return mIsPaintingToWindow
|| mUseHighQualityScaling
;
541 * Call this if we're doing painting for WebRender
543 void SetPaintingForWebRender(bool aForWebRender
) {
544 mIsPaintingForWebRender
= true;
546 bool IsPaintingForWebRender() const { return mIsPaintingForWebRender
; }
548 * Call this to prevent descending into subdocuments.
550 void SetDescendIntoSubdocuments(bool aDescend
) {
551 mDescendIntoSubdocuments
= aDescend
;
554 bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments
; }
557 * Get dirty rect relative to current frame (the frame that we're calling
558 * BuildDisplayList on right now).
560 const nsRect
& GetVisibleRect() { return mVisibleRect
; }
561 const nsRect
& GetDirtyRect() { return mDirtyRect
; }
563 void SetVisibleRect(const nsRect
& aVisibleRect
) {
564 mVisibleRect
= aVisibleRect
;
567 void IntersectVisibleRect(const nsRect
& aVisibleRect
) {
568 mVisibleRect
.IntersectRect(mVisibleRect
, aVisibleRect
);
571 void SetDirtyRect(const nsRect
& aDirtyRect
) { mDirtyRect
= aDirtyRect
; }
573 void IntersectDirtyRect(const nsRect
& aDirtyRect
) {
574 mDirtyRect
.IntersectRect(mDirtyRect
, aDirtyRect
);
577 const nsIFrame
* GetCurrentFrame() { return mCurrentFrame
; }
578 const nsIFrame
* GetCurrentReferenceFrame() { return mCurrentReferenceFrame
; }
580 const nsPoint
& GetCurrentFrameOffsetToReferenceFrame() const {
581 return mCurrentOffsetToReferenceFrame
;
584 void Check() { mPool
.Check(); }
587 * Get the paint sequence number of the current paint.
589 static uint32_t GetPaintSequenceNumber() { return sPaintSequenceNumber
; }
592 * Increment the paint sequence number.
594 static void IncrementPaintSequenceNumber() { ++sPaintSequenceNumber
; }
597 * Returns true if merging and flattening of display lists should be
598 * performed while computing visibility.
600 bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening
; }
601 void SetAllowMergingAndFlattening(bool aAllow
) {
602 mAllowMergingAndFlattening
= aAllow
;
605 void SetCompositorHitTestInfo(const gfx::CompositorHitTestInfo
& aInfo
) {
606 mCompositorHitTestInfo
= aInfo
;
609 const gfx::CompositorHitTestInfo
& GetCompositorHitTestInfo() const {
610 return mCompositorHitTestInfo
;
614 * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
615 * needed, and adds it to the top of |aList|.
617 void BuildCompositorHitTestInfoIfNeeded(nsIFrame
* aFrame
,
618 nsDisplayList
* aList
);
620 bool IsInsidePointerEventsNoneDoc() {
621 return CurrentPresShellState()->mInsidePointerEventsNoneDoc
;
624 bool IsTouchEventPrefEnabledDoc() {
625 return CurrentPresShellState()->mTouchEventPrefEnabledDoc
;
628 bool GetAncestorHasApzAwareEventHandler() const {
629 return mAncestorHasApzAwareEventHandler
;
632 void SetAncestorHasApzAwareEventHandler(bool aValue
) {
633 mAncestorHasApzAwareEventHandler
= aValue
;
636 bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort
; }
637 void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort
= true; }
638 void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort
= false; }
640 bool SetIsCompositingCheap(bool aCompositingCheap
) {
641 bool temp
= mIsCompositingCheap
;
642 mIsCompositingCheap
= aCompositingCheap
;
646 bool IsCompositingCheap() const { return mIsCompositingCheap
; }
648 * Display the caret if needed.
650 bool DisplayCaret(nsIFrame
* aFrame
, nsDisplayList
* aList
) {
651 nsIFrame
* frame
= GetCaretFrame();
652 if (aFrame
== frame
&& !IsBackgroundOnly()) {
653 frame
->DisplayCaret(this, aList
);
659 * Get the frame that the caret is supposed to draw in.
660 * If the caret is currently invisible, this will be null.
662 nsIFrame
* GetCaretFrame() { return CurrentPresShellState()->mCaretFrame
; }
664 * Get the rectangle we're supposed to draw the caret into.
666 const nsRect
& GetCaretRect() { return mCaretRect
; }
668 * Get the caret associated with the current presshell.
673 * Returns the root scroll frame for the current PresShell, if the PresShell
674 * is ignoring viewport scrolling.
676 nsIFrame
* GetPresShellIgnoreScrollFrame() {
677 return CurrentPresShellState()->mPresShellIgnoreScrollFrame
;
681 * Notify the display list builder that we're entering a presshell.
682 * aReferenceFrame should be a frame in the new presshell.
683 * aPointerEventsNoneDoc should be set to true if the frame generating this
684 * document is pointer-events:none.
686 void EnterPresShell(const nsIFrame
* aReferenceFrame
,
687 bool aPointerEventsNoneDoc
= false);
689 * For print-preview documents, we sometimes need to build display items for
690 * the same frames multiple times in the same presentation, with different
691 * clipping. Between each such batch of items, call
692 * ResetMarkedFramesForDisplayList to make sure that the results of
693 * MarkFramesForDisplayList do not carry over between batches.
695 void ResetMarkedFramesForDisplayList(const nsIFrame
* aReferenceFrame
);
697 * Notify the display list builder that we're leaving a presshell.
699 void LeavePresShell(const nsIFrame
* aReferenceFrame
,
700 nsDisplayList
* aPaintedContents
);
702 void IncrementPresShellPaintCount(PresShell
* aPresShell
);
705 * Returns true if we're currently building a display list that's
706 * directly or indirectly under an nsDisplayTransform.
708 bool IsInTransform() const { return mInTransform
; }
710 bool InEventsOnly() const { return mInEventsOnly
; }
712 * Indicate whether or not we're directly or indirectly under and
713 * nsDisplayTransform or SVG foreignObject.
715 void SetInTransform(bool aInTransform
) { mInTransform
= aInTransform
; }
718 * Returns true if we're currently building a display list that's
719 * under an nsDisplayFilters.
721 bool IsInFilter() const { return mInFilter
; }
724 * Return true if we're currently building a display list for a
727 bool IsInSubdocument() const { return mPresShellStates
.Length() > 1; }
729 void SetDisablePartialUpdates(bool aDisable
) {
730 mDisablePartialUpdates
= aDisable
;
732 bool DisablePartialUpdates() const { return mDisablePartialUpdates
; }
734 void SetPartialBuildFailed(bool aFailed
) { mPartialBuildFailed
= aFailed
; }
735 bool PartialBuildFailed() const { return mPartialBuildFailed
; }
737 bool IsInActiveDocShell() const { return mIsInActiveDocShell
; }
738 void SetInActiveDocShell(bool aActive
) { mIsInActiveDocShell
= aActive
; }
741 * Return true if we're currently building a display list for the presshell
742 * of a chrome document, or if we're building the display list for a popup.
744 bool IsInChromeDocumentOrPopup() const {
745 return mIsInChromePresContext
|| mIsBuildingForPopup
;
749 * @return true if images have been set to decode synchronously.
751 bool ShouldSyncDecodeImages() const { return mSyncDecodeImages
; }
754 * Indicates whether we should synchronously decode images. If true, we decode
755 * and draw whatever image data has been loaded. If false, we just draw
756 * whatever has already been decoded.
758 void SetSyncDecodeImages(bool aSyncDecodeImages
) {
759 mSyncDecodeImages
= aSyncDecodeImages
;
762 nsDisplayTableBackgroundSet
* SetTableBackgroundSet(
763 nsDisplayTableBackgroundSet
* aTableSet
) {
764 nsDisplayTableBackgroundSet
* old
= mTableBackgroundSet
;
765 mTableBackgroundSet
= aTableSet
;
768 nsDisplayTableBackgroundSet
* GetTableBackgroundSet() const {
769 return mTableBackgroundSet
;
772 void FreeClipChains();
775 * Frees the temporary display items created during merging.
777 void FreeTemporaryItems();
780 * Helper method to generate background painting flags based on the
781 * information available in the display list builder.
783 uint32_t GetBackgroundPaintFlags();
786 * Helper method to generate nsImageRenderer flags based on the information
787 * available in the display list builder.
789 uint32_t GetImageRendererFlags() const;
792 * Helper method to generate image decoding flags based on the
793 * information available in the display list builder.
795 uint32_t GetImageDecodeFlags() const;
798 * Subtracts aRegion from *aVisibleRegion. We avoid letting
799 * aVisibleRegion become overcomplex by simplifying it if necessary.
801 void SubtractFromVisibleRegion(nsRegion
* aVisibleRegion
,
802 const nsRegion
& aRegion
);
805 * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
806 * (which is relative to aDirtyFrame). If the frames have placeholders
807 * that might not be displayed, we mark the placeholders and their ancestors
808 * to ensure that display list construction descends into them
809 * anyway. nsDisplayListBuilder will take care of unmarking them when it is
812 void MarkFramesForDisplayList(nsIFrame
* aDirtyFrame
,
813 const nsFrameList
& aFrames
);
814 void MarkFrameForDisplay(nsIFrame
* aFrame
, const nsIFrame
* aStopAtFrame
);
815 void MarkFrameForDisplayIfVisible(nsIFrame
* aFrame
,
816 const nsIFrame
* aStopAtFrame
);
817 void AddFrameMarkedForDisplayIfVisible(nsIFrame
* aFrame
);
819 void ClearFixedBackgroundDisplayData();
821 * Mark all child frames that Preserve3D() as needing display.
822 * Because these frames include transforms set on their parent, dirty rects
823 * for intermediate frames may be empty, yet child frames could still be
826 void MarkPreserve3DFramesForDisplayList(nsIFrame
* aDirtyFrame
);
829 * Returns true if we need to descend into this frame when building
830 * the display list, even though it doesn't intersect the dirty
831 * rect, because it may have out-of-flows that do so.
833 bool ShouldDescendIntoFrame(nsIFrame
* aFrame
, bool aVisible
) const {
834 return aFrame
->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO
) ||
835 (aVisible
&& aFrame
->ForceDescendIntoIfVisible()) ||
836 GetIncludeAllOutOfFlows();
840 * Returns the list of registered theme geometries.
842 nsTArray
<nsIWidget::ThemeGeometry
> GetThemeGeometries() const {
843 nsTArray
<nsIWidget::ThemeGeometry
> geometries
;
845 for (const auto& data
: mThemeGeometries
.Values()) {
846 geometries
.AppendElements(*data
);
853 * Notifies the builder that a particular themed widget exists
854 * at the given rectangle within the currently built display list.
855 * For certain appearance values (currently only
856 * StyleAppearance::MozWindowTitlebar) this gets called during every display
857 * list construction, for every themed widget of the right type within the
858 * display list, except for themed widgets which are transformed or have
859 * effects applied to them (e.g. CSS opacity or filters).
861 * @param aWidgetType the -moz-appearance value for the themed widget
862 * @param aItem the item associated with the theme geometry
863 * @param aRect the device-pixel rect relative to the widget's displayRoot
864 * for the themed widget
866 void RegisterThemeGeometry(uint8_t aWidgetType
, nsDisplayItem
* aItem
,
867 const LayoutDeviceIntRect
& aRect
) {
868 if (!mIsPaintingToWindow
) {
872 nsTArray
<nsIWidget::ThemeGeometry
>* geometries
=
873 mThemeGeometries
.GetOrInsertNew(aItem
);
874 geometries
->AppendElement(nsIWidget::ThemeGeometry(aWidgetType
, aRect
));
878 * Removes theme geometries associated with the given display item |aItem|.
880 void UnregisterThemeGeometry(nsDisplayItem
* aItem
) {
881 mThemeGeometries
.Remove(aItem
);
885 * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
886 * -moz-window-dragging value is |drag|, its border box is added to the
887 * collected dragging region; if the value is |no-drag|, the border box is
888 * subtracted from the region; if the value is |default|, that frame does
889 * not influence the window dragging region.
891 void AdjustWindowDraggingRegion(nsIFrame
* aFrame
);
893 LayoutDeviceIntRegion
GetWindowDraggingRegion() const;
895 void RemoveModifiedWindowRegions();
896 void ClearRetainedWindowRegions();
898 const nsTHashMap
<nsPtrHashKey
<dom::RemoteBrowser
>, dom::EffectsInfo
>&
899 GetEffectUpdates() const {
900 return mEffectsUpdates
;
903 void AddEffectUpdate(dom::RemoteBrowser
* aBrowser
,
904 const dom::EffectsInfo
& aUpdate
);
907 * Invalidates the caret frames from previous paints, if they have changed.
909 void InvalidateCaretFramesIfNeeded();
912 * Allocate memory in our arena. It will only be freed when this display list
913 * builder is destroyed. This memory holds nsDisplayItems and
914 * DisplayItemClipChain objects.
916 * Destructors are called as soon as the item is no longer used.
918 void* Allocate(size_t aSize
, DisplayListArenaObjectId aId
) {
919 return mPool
.Allocate(aId
, aSize
);
921 void* Allocate(size_t aSize
, DisplayItemType aType
) {
922 #define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) \
923 static_assert(size_t(DisplayItemType::TYPE_##name_) == \
924 size_t(DisplayListArenaObjectId::name_), \
926 #include "nsDisplayItemTypesList.h"
927 static_assert(size_t(DisplayItemType::TYPE_MAX
) ==
928 size_t(DisplayListArenaObjectId::CLIPCHAIN
),
930 static_assert(size_t(DisplayItemType::TYPE_MAX
) + 1 ==
931 size_t(DisplayListArenaObjectId::LISTNODE
),
933 #undef DECLARE_DISPLAY_ITEM_TYPE
934 return Allocate(aSize
, DisplayListArenaObjectId(size_t(aType
)));
937 void Destroy(DisplayListArenaObjectId aId
, void* aPtr
) {
938 return mPool
.Free(aId
, aPtr
);
940 void Destroy(DisplayItemType aType
, void* aPtr
) {
941 return Destroy(DisplayListArenaObjectId(size_t(aType
)), aPtr
);
945 * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
946 * automatically when the arena goes away.
948 ActiveScrolledRoot
* AllocateActiveScrolledRoot(
949 const ActiveScrolledRoot
* aParent
, nsIScrollableFrame
* aScrollableFrame
);
952 * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
953 * up automatically when the arena goes away.
955 const DisplayItemClipChain
* AllocateDisplayItemClipChain(
956 const DisplayItemClip
& aClip
, const ActiveScrolledRoot
* aASR
,
957 const DisplayItemClipChain
* aParent
);
960 * Intersect two clip chains, allocating the new clip chain items in this
961 * builder's arena. The result is parented to aAncestor, and no intersections
962 * happen past aAncestor's ASR.
963 * That means aAncestor has to be living in this builder's arena already.
964 * aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
965 * their values are copied into the newly-allocated intersected clip chain
966 * and this function does not hold on to any pointers to them.
968 const DisplayItemClipChain
* CreateClipChainIntersection(
969 const DisplayItemClipChain
* aAncestor
,
970 const DisplayItemClipChain
* aLeafClip1
,
971 const DisplayItemClipChain
* aLeafClip2
);
974 * Same as above, except aAncestor is computed as the nearest common
975 * ancestor of the two provided clips.
977 const DisplayItemClipChain
* CreateClipChainIntersection(
978 const DisplayItemClipChain
* aLeafClip1
,
979 const DisplayItemClipChain
* aLeafClip2
);
982 * Clone the supplied clip chain's chain items into this builder's arena.
984 const DisplayItemClipChain
* CopyWholeChain(
985 const DisplayItemClipChain
* aClipChain
);
987 const ActiveScrolledRoot
* GetFilterASR() const { return mFilterASR
; }
990 * Merges the display items in |aMergedItems| and returns a new temporary
992 * The display items in |aMergedItems| have to be mergeable with each other.
994 nsDisplayWrapList
* MergeItems(nsTArray
<nsDisplayItem
*>& aItems
);
997 * A helper class used to temporarily set nsDisplayListBuilder properties for
998 * building display items.
999 * aVisibleRect and aDirtyRect are relative to aForChild.
1001 class AutoBuildingDisplayList
{
1003 AutoBuildingDisplayList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aForChild
,
1004 const nsRect
& aVisibleRect
,
1005 const nsRect
& aDirtyRect
)
1006 : AutoBuildingDisplayList(aBuilder
, aForChild
, aVisibleRect
, aDirtyRect
,
1007 aForChild
->IsTransformed()) {}
1009 AutoBuildingDisplayList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aForChild
,
1010 const nsRect
& aVisibleRect
,
1011 const nsRect
& aDirtyRect
,
1012 const bool aIsTransformed
);
1014 void SetReferenceFrameAndCurrentOffset(const nsIFrame
* aFrame
,
1015 const nsPoint
& aOffset
) {
1016 mBuilder
->mCurrentReferenceFrame
= aFrame
;
1017 mBuilder
->mCurrentOffsetToReferenceFrame
= aOffset
;
1020 void SetAdditionalOffset(const nsPoint
& aOffset
) {
1021 MOZ_ASSERT(!mBuilder
->mAdditionalOffset
);
1022 mBuilder
->mAdditionalOffset
= Some(aOffset
);
1024 mBuilder
->mCurrentOffsetToReferenceFrame
+= aOffset
;
1027 void RestoreBuildingInvisibleItemsValue() {
1028 mBuilder
->mBuildingInvisibleItems
= mPrevBuildingInvisibleItems
;
1031 ~AutoBuildingDisplayList() {
1032 mBuilder
->mCurrentFrame
= mPrevFrame
;
1033 mBuilder
->mCurrentReferenceFrame
= mPrevReferenceFrame
;
1034 mBuilder
->mCurrentOffsetToReferenceFrame
= mPrevOffset
;
1035 mBuilder
->mVisibleRect
= mPrevVisibleRect
;
1036 mBuilder
->mDirtyRect
= mPrevDirtyRect
;
1037 mBuilder
->mAncestorHasApzAwareEventHandler
=
1038 mPrevAncestorHasApzAwareEventHandler
;
1039 mBuilder
->mBuildingInvisibleItems
= mPrevBuildingInvisibleItems
;
1040 mBuilder
->mInInvalidSubtree
= mPrevInInvalidSubtree
;
1041 mBuilder
->mAdditionalOffset
= mPrevAdditionalOffset
;
1042 mBuilder
->mCompositorHitTestInfo
= mPrevCompositorHitTestInfo
;
1046 nsDisplayListBuilder
* mBuilder
;
1047 const nsIFrame
* mPrevFrame
;
1048 const nsIFrame
* mPrevReferenceFrame
;
1049 nsPoint mPrevOffset
;
1050 Maybe
<nsPoint
> mPrevAdditionalOffset
;
1051 nsRect mPrevVisibleRect
;
1052 nsRect mPrevDirtyRect
;
1053 gfx::CompositorHitTestInfo mPrevCompositorHitTestInfo
;
1054 bool mPrevAncestorHasApzAwareEventHandler
;
1055 bool mPrevBuildingInvisibleItems
;
1056 bool mPrevInInvalidSubtree
;
1060 * A helper class to temporarily set the value of mInTransform.
1062 class AutoInTransformSetter
{
1064 AutoInTransformSetter(nsDisplayListBuilder
* aBuilder
, bool aInTransform
)
1065 : mBuilder(aBuilder
), mOldValue(aBuilder
->mInTransform
) {
1066 aBuilder
->mInTransform
= aInTransform
;
1069 ~AutoInTransformSetter() { mBuilder
->mInTransform
= mOldValue
; }
1072 nsDisplayListBuilder
* mBuilder
;
1076 class AutoInEventsOnly
{
1078 AutoInEventsOnly(nsDisplayListBuilder
* aBuilder
, bool aInEventsOnly
)
1079 : mBuilder(aBuilder
), mOldValue(aBuilder
->mInEventsOnly
) {
1080 aBuilder
->mInEventsOnly
|= aInEventsOnly
;
1083 ~AutoInEventsOnly() { mBuilder
->mInEventsOnly
= mOldValue
; }
1086 nsDisplayListBuilder
* mBuilder
;
1091 * A helper class to temporarily set the value of mFilterASR and
1094 class AutoEnterFilter
{
1096 AutoEnterFilter(nsDisplayListBuilder
* aBuilder
, bool aUsingFilter
)
1097 : mBuilder(aBuilder
),
1098 mOldValue(aBuilder
->mFilterASR
),
1099 mOldInFilter(aBuilder
->mInFilter
) {
1100 if (!aBuilder
->mFilterASR
&& aUsingFilter
) {
1101 aBuilder
->mFilterASR
= aBuilder
->CurrentActiveScrolledRoot();
1102 aBuilder
->mInFilter
= true;
1106 ~AutoEnterFilter() {
1107 mBuilder
->mFilterASR
= mOldValue
;
1108 mBuilder
->mInFilter
= mOldInFilter
;
1112 nsDisplayListBuilder
* mBuilder
;
1113 const ActiveScrolledRoot
* mOldValue
;
1118 * Used to update the current active scrolled root on the display list
1119 * builder, and to create new active scrolled roots.
1121 class AutoCurrentActiveScrolledRootSetter
{
1123 explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder
* aBuilder
)
1124 : mBuilder(aBuilder
),
1125 mSavedActiveScrolledRoot(aBuilder
->mCurrentActiveScrolledRoot
),
1126 mContentClipASR(aBuilder
->ClipState().GetContentClipASR()),
1127 mDescendantsStartIndex(aBuilder
->mActiveScrolledRoots
.Length()),
1129 mOldScrollParentId(aBuilder
->mCurrentScrollParentId
),
1130 mOldForceLayer(aBuilder
->mForceLayerForScrollParent
),
1131 mOldContainsNonMinimalDisplayPort(
1132 mBuilder
->mContainsNonMinimalDisplayPort
),
1133 mCanBeScrollParent(false) {}
1135 void SetCurrentScrollParentId(ViewID aScrollId
) {
1136 // Update the old scroll parent id.
1137 mOldScrollParentId
= mBuilder
->mCurrentScrollParentId
;
1138 // If this AutoCurrentActiveScrolledRootSetter has the same aScrollId as
1139 // the previous one on the stack, then that means the scrollframe that
1140 // created this isn't actually scrollable and cannot participate in
1141 // scroll handoff. We set mCanBeScrollParent to false to indicate this.
1142 mCanBeScrollParent
= (mOldScrollParentId
!= aScrollId
);
1143 mBuilder
->mCurrentScrollParentId
= aScrollId
;
1144 mBuilder
->mForceLayerForScrollParent
= false;
1145 mBuilder
->mContainsNonMinimalDisplayPort
= false;
1148 bool ShouldForceLayerForScrollParent() const {
1149 // Only scrollframes participating in scroll handoff can be forced to
1151 return mCanBeScrollParent
&& mBuilder
->mForceLayerForScrollParent
;
1154 bool GetContainsNonMinimalDisplayPort() const {
1155 // Only for scrollframes participating in scroll handoff can we return
1157 return mCanBeScrollParent
&& mBuilder
->mContainsNonMinimalDisplayPort
;
1160 ~AutoCurrentActiveScrolledRootSetter() {
1161 mBuilder
->mCurrentActiveScrolledRoot
= mSavedActiveScrolledRoot
;
1162 mBuilder
->mCurrentScrollParentId
= mOldScrollParentId
;
1163 if (mCanBeScrollParent
) {
1164 // If this flag is set, caller code is responsible for having dealt
1165 // with the current value of mBuilder->mForceLayerForScrollParent, so
1166 // we can just restore the old value.
1167 mBuilder
->mForceLayerForScrollParent
= mOldForceLayer
;
1169 // Otherwise we need to keep propagating the force-layerization flag
1170 // upwards to the next ancestor scrollframe that does participate in
1172 mBuilder
->mForceLayerForScrollParent
|= mOldForceLayer
;
1174 mBuilder
->mContainsNonMinimalDisplayPort
|=
1175 mOldContainsNonMinimalDisplayPort
;
1178 void SetCurrentActiveScrolledRoot(
1179 const ActiveScrolledRoot
* aActiveScrolledRoot
);
1181 void EnterScrollFrame(nsIScrollableFrame
* aScrollableFrame
) {
1183 ActiveScrolledRoot
* asr
= mBuilder
->AllocateActiveScrolledRoot(
1184 mBuilder
->mCurrentActiveScrolledRoot
, aScrollableFrame
);
1185 mBuilder
->mCurrentActiveScrolledRoot
= asr
;
1189 void InsertScrollFrame(nsIScrollableFrame
* aScrollableFrame
);
1192 nsDisplayListBuilder
* mBuilder
;
1194 * The builder's mCurrentActiveScrolledRoot at construction time which
1195 * needs to be restored at destruction time.
1197 const ActiveScrolledRoot
* mSavedActiveScrolledRoot
;
1199 * If there's a content clip on the builder at construction time, then
1200 * mContentClipASR is that content clip's ASR, otherwise null. The
1201 * assumption is that the content clip doesn't get relaxed while this
1202 * object is on the stack.
1204 const ActiveScrolledRoot
* mContentClipASR
;
1206 * InsertScrollFrame needs to mutate existing ASRs (those that were
1207 * created while this object was on the stack), and mDescendantsStartIndex
1208 * makes it easier to skip ASRs that were created in the past.
1210 size_t mDescendantsStartIndex
;
1212 * Flag to make sure that only one of SetCurrentActiveScrolledRoot /
1213 * EnterScrollFrame / InsertScrollFrame is called per instance of this
1217 ViewID mOldScrollParentId
;
1218 bool mOldForceLayer
;
1219 bool mOldContainsNonMinimalDisplayPort
;
1220 bool mCanBeScrollParent
;
1224 * Keeps track of the innermost ASR that can be used as the ASR for a
1225 * container item that wraps all items that were created while this
1226 * object was on the stack.
1227 * The rule is: all child items of the container item need to have
1228 * clipped bounds with respect to the container ASR.
1230 class AutoContainerASRTracker
{
1232 explicit AutoContainerASRTracker(nsDisplayListBuilder
* aBuilder
);
1234 const ActiveScrolledRoot
* GetContainerASR() {
1235 return mBuilder
->mCurrentContainerASR
;
1238 ~AutoContainerASRTracker() {
1239 mBuilder
->mCurrentContainerASR
= ActiveScrolledRoot::PickAncestor(
1240 mBuilder
->mCurrentContainerASR
, mSavedContainerASR
);
1244 nsDisplayListBuilder
* mBuilder
;
1245 const ActiveScrolledRoot
* mSavedContainerASR
;
1249 * A helper class to temporarily set the value of mCurrentScrollbarTarget
1250 * and mCurrentScrollbarFlags.
1252 class AutoCurrentScrollbarInfoSetter
{
1254 AutoCurrentScrollbarInfoSetter(
1255 nsDisplayListBuilder
* aBuilder
, ViewID aScrollTargetID
,
1256 const Maybe
<layers::ScrollDirection
>& aScrollbarDirection
,
1257 bool aWillHaveLayer
)
1258 : mBuilder(aBuilder
) {
1259 aBuilder
->mIsBuildingScrollbar
= true;
1260 aBuilder
->mCurrentScrollbarTarget
= aScrollTargetID
;
1261 aBuilder
->mCurrentScrollbarDirection
= aScrollbarDirection
;
1262 aBuilder
->mCurrentScrollbarWillHaveLayer
= aWillHaveLayer
;
1265 ~AutoCurrentScrollbarInfoSetter() {
1266 // No need to restore old values because scrollbars cannot be nested.
1267 mBuilder
->mIsBuildingScrollbar
= false;
1268 mBuilder
->mCurrentScrollbarTarget
=
1269 layers::ScrollableLayerGuid::NULL_SCROLL_ID
;
1270 mBuilder
->mCurrentScrollbarDirection
.reset();
1271 mBuilder
->mCurrentScrollbarWillHaveLayer
= false;
1275 nsDisplayListBuilder
* mBuilder
;
1279 * A helper class to temporarily set mBuildingExtraPagesForPageNum.
1281 class MOZ_RAII AutoPageNumberSetter
{
1283 AutoPageNumberSetter(nsDisplayListBuilder
* aBuilder
, const uint8_t aPageNum
)
1284 : mBuilder(aBuilder
),
1285 mOldPageNum(aBuilder
->GetBuildingExtraPagesForPageNum()) {
1286 mBuilder
->SetBuildingExtraPagesForPageNum(aPageNum
);
1288 ~AutoPageNumberSetter() {
1289 mBuilder
->SetBuildingExtraPagesForPageNum(mOldPageNum
);
1293 nsDisplayListBuilder
* mBuilder
;
1294 uint8_t mOldPageNum
;
1298 * A helper class to track current effective transform for items.
1300 * For frames that is Combines3DTransformWithAncestors(), we need to
1301 * apply all transforms of ancestors on the same preserves3D chain
1302 * on the bounds of current frame to the coordination of the 3D
1303 * context root. The 3D context root computes it's bounds from
1304 * these transformed bounds.
1306 class AutoAccumulateTransform
{
1308 explicit AutoAccumulateTransform(nsDisplayListBuilder
* aBuilder
)
1309 : mBuilder(aBuilder
),
1310 mSavedTransform(aBuilder
->mPreserves3DCtx
.mAccumulatedTransform
) {}
1312 ~AutoAccumulateTransform() {
1313 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
= mSavedTransform
;
1316 void Accumulate(const gfx::Matrix4x4
& aTransform
) {
1317 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
=
1318 aTransform
* mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
;
1321 const gfx::Matrix4x4
& GetCurrentTransform() {
1322 return mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
;
1326 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
= gfx::Matrix4x4();
1330 nsDisplayListBuilder
* mBuilder
;
1331 gfx::Matrix4x4 mSavedTransform
;
1335 * A helper class to collect bounds rects of descendants.
1337 * For a 3D context root, it's bounds is computed from the bounds of
1338 * descendants. If we transform bounds frame by frame applying
1339 * transforms, the bounds may turn to empty for any singular
1340 * transform on the path, but it is not empty for the accumulated
1343 class AutoAccumulateRect
{
1345 explicit AutoAccumulateRect(nsDisplayListBuilder
* aBuilder
)
1346 : mBuilder(aBuilder
),
1347 mSavedRect(aBuilder
->mPreserves3DCtx
.mAccumulatedRect
) {
1348 aBuilder
->mPreserves3DCtx
.mAccumulatedRect
= nsRect();
1349 aBuilder
->mPreserves3DCtx
.mAccumulatedRectLevels
++;
1352 ~AutoAccumulateRect() {
1353 mBuilder
->mPreserves3DCtx
.mAccumulatedRect
= mSavedRect
;
1354 mBuilder
->mPreserves3DCtx
.mAccumulatedRectLevels
--;
1358 nsDisplayListBuilder
* mBuilder
;
1362 void AccumulateRect(const nsRect
& aRect
) {
1363 mPreserves3DCtx
.mAccumulatedRect
.UnionRect(mPreserves3DCtx
.mAccumulatedRect
,
1367 const nsRect
& GetAccumulatedRect() {
1368 return mPreserves3DCtx
.mAccumulatedRect
;
1372 * The level is increased by one for items establishing 3D rendering
1373 * context and starting a new accumulation.
1375 int GetAccumulatedRectLevels() {
1376 return mPreserves3DCtx
.mAccumulatedRectLevels
;
1379 struct OutOfFlowDisplayData
{
1380 OutOfFlowDisplayData(
1381 const DisplayItemClipChain
* aContainingBlockClipChain
,
1382 const DisplayItemClipChain
* aCombinedClipChain
,
1383 const ActiveScrolledRoot
* aContainingBlockActiveScrolledRoot
,
1384 const ViewID
& aScrollParentId
, const nsRect
& aVisibleRect
,
1385 const nsRect
& aDirtyRect
)
1386 : mContainingBlockClipChain(aContainingBlockClipChain
),
1387 mCombinedClipChain(aCombinedClipChain
),
1388 mContainingBlockActiveScrolledRoot(
1389 aContainingBlockActiveScrolledRoot
),
1390 mVisibleRect(aVisibleRect
),
1391 mDirtyRect(aDirtyRect
),
1392 mScrollParentId(aScrollParentId
) {}
1393 const DisplayItemClipChain
* mContainingBlockClipChain
;
1394 const DisplayItemClipChain
*
1395 mCombinedClipChain
; // only necessary for the special case of top layer
1396 const ActiveScrolledRoot
* mContainingBlockActiveScrolledRoot
;
1398 // If this OutOfFlowDisplayData is associated with the ViewportFrame
1399 // of a document that has a resolution (creating separate visual and
1400 // layout viewports with their own coordinate spaces), these rects
1401 // are in layout coordinates. Similarly, GetVisibleRectForFrame() in
1402 // such a case returns a quantity in layout coordinates.
1403 nsRect mVisibleRect
;
1405 ViewID mScrollParentId
;
1407 static nsRect
ComputeVisibleRectForFrame(nsDisplayListBuilder
* aBuilder
,
1409 const nsRect
& aVisibleRect
,
1410 const nsRect
& aDirtyRect
,
1411 nsRect
* aOutDirtyRect
);
1413 nsRect
GetVisibleRectForFrame(nsDisplayListBuilder
* aBuilder
,
1414 nsIFrame
* aFrame
, nsRect
* aDirtyRect
) {
1415 return ComputeVisibleRectForFrame(aBuilder
, aFrame
, mVisibleRect
,
1416 mDirtyRect
, aDirtyRect
);
1420 NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty
,
1421 OutOfFlowDisplayData
)
1423 struct DisplayListBuildingData
{
1424 nsIFrame
* mModifiedAGR
= nullptr;
1427 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect
,
1428 DisplayListBuildingData
)
1430 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect
,
1433 static OutOfFlowDisplayData
* GetOutOfFlowData(nsIFrame
* aFrame
) {
1434 if (!aFrame
->GetParent()) {
1437 return aFrame
->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
1440 nsPresContext
* CurrentPresContext();
1442 OutOfFlowDisplayData
* GetCurrentFixedBackgroundDisplayData() {
1443 auto& displayData
= CurrentPresShellState()->mFixedBackgroundDisplayData
;
1444 return displayData
? displayData
.ptr() : nullptr;
1448 * Accumulates opaque stuff into the window opaque region.
1450 void AddWindowOpaqueRegion(nsIFrame
* aFrame
, const nsRect
& aBounds
) {
1451 if (IsRetainingDisplayList()) {
1452 mRetainedWindowOpaqueRegion
.Add(aFrame
, aBounds
);
1455 mWindowOpaqueRegion
.Or(mWindowOpaqueRegion
, aBounds
);
1458 * Returns the window opaque region built so far. This may be incomplete
1459 * since the opaque region is built during layer construction.
1461 const nsRegion
GetWindowOpaqueRegion() {
1462 return IsRetainingDisplayList() ? mRetainedWindowOpaqueRegion
.ToRegion()
1463 : mWindowOpaqueRegion
;
1467 * mContainsBlendMode is true if we processed a display item that
1468 * has a blend mode attached. We do this so we can insert a
1469 * nsDisplayBlendContainer in the parent stacking context.
1471 void SetContainsBlendMode(bool aContainsBlendMode
) {
1472 mContainsBlendMode
= aContainsBlendMode
;
1474 bool ContainsBlendMode() const { return mContainsBlendMode
; }
1476 DisplayListClipState
& ClipState() { return mClipState
; }
1477 const ActiveScrolledRoot
* CurrentActiveScrolledRoot() {
1478 return mCurrentActiveScrolledRoot
;
1480 const ActiveScrolledRoot
* CurrentAncestorASRStackingContextContents() {
1481 return mCurrentContainerASR
;
1485 * Add the current frame to the will-change budget if possible and
1486 * remeber the outcome. Subsequent calls to IsInWillChangeBudget
1487 * will return the same value as return here.
1489 bool AddToWillChangeBudget(nsIFrame
* aFrame
, const nsSize
& aSize
);
1492 * This will add the current frame to the will-change budget the first
1493 * time it is seen. On subsequent calls this will return the same
1494 * answer. This effectively implements a first-come, first-served
1495 * allocation of the will-change budget.
1497 bool IsInWillChangeBudget(nsIFrame
* aFrame
, const nsSize
& aSize
);
1500 * Clears the will-change budget status for the given |aFrame|.
1501 * This will also remove the frame from will-change budgets.
1503 void ClearWillChangeBudgetStatus(nsIFrame
* aFrame
);
1506 * Removes the given |aFrame| from will-change budgets.
1508 void RemoveFromWillChangeBudgets(const nsIFrame
* aFrame
);
1511 * Clears the will-change budgets.
1513 void ClearWillChangeBudgets();
1515 void EnterSVGEffectsContents(nsIFrame
* aEffectsFrame
,
1516 nsDisplayList
* aHoistedItemsStorage
);
1517 void ExitSVGEffectsContents();
1519 bool ShouldBuildScrollInfoItemsForHoisting() const;
1521 void AppendNewScrollInfoItemForHoisting(
1522 nsDisplayScrollInfoLayer
* aScrollInfoItem
);
1525 * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
1527 * mPreserves3DCtx is used by class AutoAccumulateTransform &
1528 * AutoAccumulateRect to passing data between frames in the 3D
1529 * context. If a frame create a new 3D context, it should restore
1530 * the value of mPreserves3DCtx before returning back to the parent.
1531 * This class do it for the users.
1533 class AutoPreserves3DContext
{
1535 explicit AutoPreserves3DContext(nsDisplayListBuilder
* aBuilder
)
1536 : mBuilder(aBuilder
), mSavedCtx(aBuilder
->mPreserves3DCtx
) {}
1538 ~AutoPreserves3DContext() { mBuilder
->mPreserves3DCtx
= mSavedCtx
; }
1541 nsDisplayListBuilder
* mBuilder
;
1542 Preserves3DContext mSavedCtx
;
1545 const nsRect
GetPreserves3DRect() const {
1546 return mPreserves3DCtx
.mVisibleRect
;
1549 void SavePreserves3DRect() { mPreserves3DCtx
.mVisibleRect
= mVisibleRect
; }
1551 void SavePreserves3DAllowAsyncAnimation(bool aValue
) {
1552 mPreserves3DCtx
.mAllowAsyncAnimation
= aValue
;
1555 bool GetPreserves3DAllowAsyncAnimation() const {
1556 return mPreserves3DCtx
.mAllowAsyncAnimation
;
1559 bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems
; }
1561 void SetBuildingInvisibleItems(bool aBuildingInvisibleItems
) {
1562 mBuildingInvisibleItems
= aBuildingInvisibleItems
;
1565 void SetBuildingExtraPagesForPageNum(uint8_t aPageNum
) {
1566 mBuildingExtraPagesForPageNum
= aPageNum
;
1568 uint8_t GetBuildingExtraPagesForPageNum() const {
1569 return mBuildingExtraPagesForPageNum
;
1572 bool HitTestIsForVisibility() const { return mVisibleThreshold
.isSome(); }
1574 float VisibilityThreshold() const {
1575 MOZ_DIAGNOSTIC_ASSERT(HitTestIsForVisibility());
1576 return mVisibleThreshold
.valueOr(1.0f
);
1579 void SetHitTestIsForVisibility(float aVisibleThreshold
) {
1580 mVisibleThreshold
= Some(aVisibleThreshold
);
1583 bool ShouldBuildAsyncZoomContainer() const {
1584 return mBuildAsyncZoomContainer
;
1586 void UpdateShouldBuildAsyncZoomContainer();
1588 void UpdateShouldBuildBackdropRootContainer();
1590 bool ShouldRebuildDisplayListDueToPrefChange();
1593 * Represents a region composed of frame/rect pairs.
1594 * WeakFrames are used to track whether a rect still belongs to the region.
1595 * Modified frames and rects are removed and re-added to the region if needed.
1597 struct WeakFrameRegion
{
1599 * A wrapper to store WeakFrame and the pointer to the underlying frame.
1600 * This is needed because WeakFrame does not store the frame pointer after
1601 * the frame has been deleted.
1603 struct WeakFrameWrapper
{
1604 explicit WeakFrameWrapper(nsIFrame
* aFrame
)
1605 : mWeakFrame(new WeakFrame(aFrame
)), mFrame(aFrame
) {}
1607 UniquePtr
<WeakFrame
> mWeakFrame
;
1611 nsTHashSet
<void*> mFrameSet
;
1612 nsTArray
<WeakFrameWrapper
> mFrames
;
1613 nsTArray
<pixman_box32_t
> mRects
;
1615 template <typename RectType
>
1616 void Add(nsIFrame
* aFrame
, const RectType
& aRect
) {
1617 if (mFrameSet
.Contains(aFrame
)) {
1621 mFrameSet
.Insert(aFrame
);
1622 mFrames
.AppendElement(WeakFrameWrapper(aFrame
));
1623 mRects
.AppendElement(nsRegion::RectToBox(aRect
));
1632 void RemoveModifiedFramesAndRects();
1634 size_t SizeOfExcludingThis(MallocSizeOf
) const;
1636 typedef gfx::ArrayView
<pixman_box32_t
> BoxArrayView
;
1638 nsRegion
ToRegion() const { return nsRegion(BoxArrayView(mRects
)); }
1640 LayoutDeviceIntRegion
ToLayoutDeviceIntRegion() const {
1641 return LayoutDeviceIntRegion(BoxArrayView(mRects
));
1645 void AddScrollFrameToNotify(nsIScrollableFrame
* aScrollFrame
);
1646 void NotifyAndClearScrollFrames();
1648 // Helper class to find what link spec (if any) to associate with a frame,
1649 // recording it in the builder, and generate the corresponding DisplayItem.
1650 // This also takes care of generating a named destination for internal links
1651 // if the element has an id or name attribute.
1654 Linkifier(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
1655 nsDisplayList
* aList
);
1658 if (mBuilderToReset
) {
1659 mBuilderToReset
->mLinkSpec
.Truncate(0);
1663 void MaybeAppendLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
1666 nsDisplayListBuilder
* mBuilderToReset
= nullptr;
1667 nsDisplayList
* mList
;
1671 * Returns the nearest ancestor frame to aFrame that is considered to have
1672 * (or will have) animated geometry. This can return aFrame.
1674 nsIFrame
* FindAnimatedGeometryRootFrameFor(nsIFrame
* aFrame
);
1677 * Returns true if this is a retained builder and reuse stacking contexts
1678 * mode is enabled by pref.
1680 bool IsReusingStackingContextItems() const {
1681 return mIsReusingStackingContextItems
;
1685 * Adds display item |aItem| to the reuseable display items set.
1687 void AddReusableDisplayItem(nsDisplayItem
* aItem
);
1690 * Removes display item |aItem| from the reuseable display items set.
1691 * This is needed because display items are sometimes deleted during
1692 * display list building.
1693 * Called by |nsDisplayItem::Destroy()| when the item has been reused.
1695 void RemoveReusedDisplayItem(nsDisplayItem
* aItem
);
1698 * Clears the reuseable display items set.
1700 void ClearReuseableDisplayItems();
1703 * Marks the given display item |aItem| as reused, and updates the necessary
1704 * display list builder state.
1706 void ReuseDisplayItem(nsDisplayItem
* aItem
);
1709 bool MarkOutOfFlowFrameForDisplay(nsIFrame
* aDirtyFrame
, nsIFrame
* aFrame
,
1710 const nsRect
& aVisibleRect
,
1711 const nsRect
& aDirtyRect
);
1713 friend class nsDisplayBackgroundImage
;
1714 friend class RetainedDisplayListBuilder
;
1717 * Returns whether a frame acts as an animated geometry root, optionally
1718 * returning the next ancestor to check.
1720 bool IsAnimatedGeometryRoot(nsIFrame
* aFrame
, nsIFrame
** aParent
= nullptr);
1722 struct PresShellState
{
1723 PresShell
* mPresShell
;
1725 Maybe
<nsAutoLayoutPhase
> mAutoLayoutPhase
;
1727 Maybe
<OutOfFlowDisplayData
> mFixedBackgroundDisplayData
;
1728 uint32_t mFirstFrameMarkedForDisplay
;
1729 uint32_t mFirstFrameWithOOFData
;
1730 bool mIsBackgroundOnly
;
1731 // This is a per-document flag turning off event handling for all content
1732 // in the document, and is set when we enter a subdocument for a pointer-
1733 // events:none frame.
1734 bool mInsidePointerEventsNoneDoc
;
1735 bool mTouchEventPrefEnabledDoc
;
1736 nsIFrame
* mPresShellIgnoreScrollFrame
;
1737 nsIFrame
* mCaretFrame
= nullptr;
1740 PresShellState
* CurrentPresShellState() {
1741 NS_ASSERTION(mPresShellStates
.Length() > 0,
1742 "Someone forgot to enter a presshell");
1743 return &mPresShellStates
[mPresShellStates
.Length() - 1];
1746 void AddSizeOfExcludingThis(nsWindowSizes
&) const;
1748 struct FrameWillChangeBudget
{
1749 FrameWillChangeBudget() : mPresContext(nullptr), mUsage(0) {}
1751 FrameWillChangeBudget(const nsPresContext
* aPresContext
, uint32_t aUsage
)
1752 : mPresContext(aPresContext
), mUsage(aUsage
) {}
1754 const nsPresContext
* mPresContext
;
1758 // will-change budget tracker
1759 typedef uint32_t DocumentWillChangeBudget
;
1761 nsIFrame
* const mReferenceFrame
;
1762 nsIFrame
* mIgnoreScrollFrame
;
1764 const ActiveScrolledRoot
* mCurrentActiveScrolledRoot
;
1765 const ActiveScrolledRoot
* mCurrentContainerASR
;
1766 // mCurrentFrame is the frame that we're currently calling (or about to call)
1767 // BuildDisplayList on.
1768 const nsIFrame
* mCurrentFrame
;
1769 // The reference frame for mCurrentFrame.
1770 const nsIFrame
* mCurrentReferenceFrame
;
1772 // A temporary list that we append scroll info items to while building
1773 // display items for the contents of frames with SVG effects.
1774 // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
1775 // This is a pointer and not a real nsDisplayList value because the
1776 // nsDisplayList class is defined below this class, so we can't use it here.
1777 nsDisplayList
* mScrollInfoItemsForHoisting
;
1778 nsTArray
<RefPtr
<ActiveScrolledRoot
>> mActiveScrolledRoots
;
1779 DisplayItemClipChain
* mFirstClipChainToDestroy
;
1780 nsTArray
<nsDisplayItem
*> mTemporaryItems
;
1781 nsDisplayTableBackgroundSet
* mTableBackgroundSet
;
1782 ViewID mCurrentScrollParentId
;
1783 ViewID mCurrentScrollbarTarget
;
1785 nsTArray
<nsIFrame
*> mSVGEffectsFrames
;
1786 // When we are inside a filter, the current ASR at the time we entered the
1787 // filter. Otherwise nullptr.
1788 const ActiveScrolledRoot
* mFilterASR
;
1789 nsCString mLinkSpec
; // Destination of link currently being emitted, if any.
1791 // Optimized versions for non-retained display list.
1792 LayoutDeviceIntRegion mWindowDraggingRegion
;
1793 LayoutDeviceIntRegion mWindowNoDraggingRegion
;
1794 nsRegion mWindowOpaqueRegion
;
1796 nsClassHashtable
<nsPtrHashKey
<nsDisplayItem
>,
1797 nsTArray
<nsIWidget::ThemeGeometry
>>
1799 DisplayListClipState mClipState
;
1800 nsTHashMap
<nsPtrHashKey
<const nsPresContext
>, DocumentWillChangeBudget
>
1801 mDocumentWillChangeBudgets
;
1803 // Any frame listed in this set is already counted in the budget
1804 // and thus is in-budget.
1805 nsTHashMap
<nsPtrHashKey
<const nsIFrame
>, FrameWillChangeBudget
>
1806 mFrameWillChangeBudgets
;
1808 nsTHashMap
<nsPtrHashKey
<dom::RemoteBrowser
>, dom::EffectsInfo
>
1811 nsTHashSet
<nsCString
> mDestinations
; // Destination names emitted.
1813 // Stores reusable items collected during display list preprocessing.
1814 nsTHashSet
<nsDisplayItem
*> mReuseableItems
;
1816 // Tracked carets used for retained display list.
1817 AutoTArray
<RefPtr
<nsCaret
>, 1> mPaintedCarets
;
1819 // Tracked regions used for retained display list.
1820 WeakFrameRegion mRetainedWindowDraggingRegion
;
1821 WeakFrameRegion mRetainedWindowNoDraggingRegion
;
1823 // Window opaque region is calculated during layer building.
1824 WeakFrameRegion mRetainedWindowOpaqueRegion
;
1826 std::unordered_set
<const DisplayItemClipChain
*, DisplayItemClipChainHasher
,
1827 DisplayItemClipChainEqualer
>
1829 std::unordered_set
<nsIScrollableFrame
*> mScrollFramesToNotify
;
1831 AutoTArray
<nsIFrame
*, 20> mFramesWithOOFData
;
1832 AutoTArray
<nsIFrame
*, 40> mFramesMarkedForDisplayIfVisible
;
1833 AutoTArray
<PresShellState
, 8> mPresShellStates
;
1835 using Arena
= nsPresArena
<32768, DisplayListArenaObjectId
,
1836 size_t(DisplayListArenaObjectId::COUNT
)>;
1839 AutoTArray
<nsIFrame
*, 400> mFramesMarkedForDisplay
;
1841 gfx::CompositorHitTestInfo mCompositorHitTestInfo
;
1843 // The offset from mCurrentFrame to mCurrentReferenceFrame.
1844 nsPoint mCurrentOffsetToReferenceFrame
;
1846 Maybe
<float> mVisibleThreshold
;
1848 Maybe
<nsPoint
> mAdditionalOffset
;
1850 // Relative to mCurrentFrame.
1851 nsRect mVisibleRect
;
1855 Preserves3DContext mPreserves3DCtx
;
1857 uint8_t mBuildingExtraPagesForPageNum
;
1859 nsDisplayListBuilderMode mMode
;
1860 static uint32_t sPaintSequenceNumber
;
1862 uint32_t mNumActiveScrollframesEncountered
= 0;
1864 bool mContainsBlendMode
;
1865 bool mIsBuildingScrollbar
;
1866 bool mCurrentScrollbarWillHaveLayer
;
1868 bool mRetainingDisplayList
;
1869 bool mPartialUpdate
;
1870 bool mIgnoreSuppression
;
1871 bool mIncludeAllOutOfFlows
;
1872 bool mDescendIntoSubdocuments
;
1873 bool mSelectedFramesOnly
;
1874 bool mAllowMergingAndFlattening
;
1875 // True when we're building a display list that's directly or indirectly
1876 // under an nsDisplayTransform
1880 bool mInPageSequence
;
1881 bool mIsInChromePresContext
;
1882 bool mSyncDecodeImages
;
1883 bool mIsPaintingToWindow
;
1884 bool mUseHighQualityScaling
;
1885 bool mIsPaintingForWebRender
;
1886 bool mIsCompositingCheap
;
1887 bool mAncestorHasApzAwareEventHandler
;
1888 // True when the first async-scrollable scroll frame for which we build a
1889 // display list has a display port. An async-scrollable scroll frame is one
1890 // which WantsAsyncScroll().
1891 bool mHaveScrollableDisplayPort
;
1892 bool mWindowDraggingAllowed
;
1893 bool mIsBuildingForPopup
;
1894 bool mForceLayerForScrollParent
;
1895 bool mContainsNonMinimalDisplayPort
;
1896 bool mAsyncPanZoomEnabled
;
1897 bool mBuildingInvisibleItems
;
1899 bool mInInvalidSubtree
;
1900 bool mBuildCompositorHitTestInfo
;
1901 bool mDisablePartialUpdates
;
1902 bool mPartialBuildFailed
;
1903 bool mIsInActiveDocShell
;
1904 bool mBuildAsyncZoomContainer
;
1905 bool mIsRelativeToLayoutViewport
;
1906 bool mUseOverlayScrollbars
;
1907 bool mAlwaysLayerizeScrollbars
;
1909 bool mIsReusingStackingContextItems
;
1911 Maybe
<layers::ScrollDirection
> mCurrentScrollbarDirection
;
1914 // All types are defined in nsDisplayItemTypes.h
1915 #define NS_DISPLAY_DECL_NAME(n, e) \
1916 const char* Name() const override { return n; } \
1917 constexpr static DisplayItemType ItemType() { return DisplayItemType::e; } \
1920 void* operator new(size_t aSize, nsDisplayListBuilder* aBuilder) { \
1921 return aBuilder->Allocate(aSize, DisplayItemType::e); \
1924 template <typename T, typename F, typename... Args> \
1925 friend T* mozilla::MakeDisplayItemWithIndex( \
1926 nsDisplayListBuilder* aBuilder, F* aFrame, const uint16_t aIndex, \
1931 #define NS_DISPLAY_ALLOW_CLONING() \
1932 template <typename T> \
1933 friend T* mozilla::MakeClone(nsDisplayListBuilder* aBuilder, \
1936 nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override { \
1937 return MakeClone(aBuilder, this); \
1940 template <typename T
>
1941 MOZ_ALWAYS_INLINE T
* MakeClone(nsDisplayListBuilder
* aBuilder
, const T
* aItem
) {
1942 static_assert(std::is_base_of
<nsDisplayWrapList
, T
>::value
,
1943 "Display item type should be derived from nsDisplayWrapList");
1944 T
* item
= new (aBuilder
) T(aBuilder
, *aItem
);
1945 item
->SetType(T::ItemType());
1949 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1950 void AssertUniqueItem(nsDisplayItem
* aItem
);
1954 * Returns true, if a display item of given |aType| needs to be built within
1955 * opacity:0 container.
1957 bool ShouldBuildItemForEvents(const DisplayItemType aType
);
1960 * Initializes the hit test information of |aItem| if the item type supports it.
1962 void InitializeHitTestInfo(nsDisplayListBuilder
* aBuilder
,
1963 nsPaintedDisplayItem
* aItem
,
1964 const DisplayItemType aType
);
1966 template <typename T
, typename F
, typename
... Args
>
1967 MOZ_ALWAYS_INLINE T
* MakeDisplayItemWithIndex(nsDisplayListBuilder
* aBuilder
,
1968 F
* aFrame
, const uint16_t aIndex
,
1970 static_assert(std::is_base_of
<nsDisplayItem
, T
>::value
,
1971 "Display item type should be derived from nsDisplayItem");
1972 static_assert(std::is_base_of
<nsIFrame
, F
>::value
,
1973 "Frame type should be derived from nsIFrame");
1975 const DisplayItemType type
= T::ItemType();
1976 if (aBuilder
->InEventsOnly() && !ShouldBuildItemForEvents(type
)) {
1977 // This item is not needed for events.
1981 T
* item
= new (aBuilder
) T(aBuilder
, aFrame
, std::forward
<Args
>(aArgs
)...);
1983 if (type
!= DisplayItemType::TYPE_GENERIC
) {
1984 item
->SetType(type
);
1987 item
->SetPerFrameIndex(aIndex
);
1988 item
->SetExtraPageForPageNum(aBuilder
->GetBuildingExtraPagesForPageNum());
1990 nsPaintedDisplayItem
* paintedItem
= item
->AsPaintedDisplayItem();
1992 InitializeHitTestInfo(aBuilder
, paintedItem
, type
);
1995 if (aBuilder
->InInvalidSubtree() ||
1996 item
->FrameForInvalidation()->IsFrameModified()) {
1997 item
->SetModifiedFrame(true);
2000 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2001 if (aBuilder
->IsRetainingDisplayList() && aBuilder
->IsBuilding()) {
2002 AssertUniqueItem(item
);
2005 // Verify that InInvalidSubtree matches invalidation frame's modified state.
2006 if (aBuilder
->InInvalidSubtree()) {
2007 MOZ_DIAGNOSTIC_ASSERT(
2008 AnyContentAncestorModified(item
->FrameForInvalidation()));
2011 DebugOnly
<bool> isContainerType
=
2012 (GetDisplayItemFlagsForType(type
) & TYPE_IS_CONTAINER
);
2014 MOZ_ASSERT(item
->HasChildren() == isContainerType
,
2015 "Container items must have container display item flag set.");
2018 DL_LOGV("Created display item %p (%s) (frame: %p)", item
, item
->Name(),
2024 template <typename T
, typename F
, typename
... Args
>
2025 MOZ_ALWAYS_INLINE T
* MakeDisplayItem(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
2027 return MakeDisplayItemWithIndex
<T
>(aBuilder
, aFrame
, 0,
2028 std::forward
<Args
>(aArgs
)...);
2032 * nsDisplayItemBase is a base-class for all display items. It is mainly
2033 * responsible for handling the frame-display item 1:n relationship, as well as
2034 * storing the state needed for display list merging.
2036 * Display items are arena-allocated during display list construction.
2038 * Display items can be containers --- i.e., they can perform hit testing
2039 * and painting by recursively traversing a list of child items.
2041 * Display items belong to a list at all times (except temporarily as they
2042 * move from one list to another).
2044 class nsDisplayItem
{
2046 using LayerManager
= layers::LayerManager
;
2047 using WebRenderLayerManager
= layers::WebRenderLayerManager
;
2048 using StackingContextHelper
= layers::StackingContextHelper
;
2049 using ViewID
= layers::ScrollableLayerGuid::ViewID
;
2052 * Downcasts this item to nsPaintedDisplayItem, if possible.
2054 virtual nsPaintedDisplayItem
* AsPaintedDisplayItem() { return nullptr; }
2055 virtual const nsPaintedDisplayItem
* AsPaintedDisplayItem() const {
2060 * Downcasts this item to nsDisplayWrapList, if possible.
2062 virtual nsDisplayWrapList
* AsDisplayWrapList() { return nullptr; }
2063 virtual const nsDisplayWrapList
* AsDisplayWrapList() const { return nullptr; }
2066 * Create a clone of this item.
2068 virtual nsDisplayWrapList
* Clone(nsDisplayListBuilder
* aBuilder
) const {
2073 * Checks if the given display item can be merged with this item.
2074 * @return true if the merging is possible, otherwise false.
2076 virtual bool CanMerge(const nsDisplayItem
* aItem
) const { return false; }
2079 * Frees the memory allocated for this display item.
2080 * The given display list builder must have allocated this display item.
2082 virtual void Destroy(nsDisplayListBuilder
* aBuilder
) {
2083 const DisplayItemType type
= GetType();
2084 DL_LOGV("Destroying display item %p (%s)", this, Name());
2086 if (IsReusedItem()) {
2087 aBuilder
->RemoveReusedDisplayItem(this);
2090 this->~nsDisplayItem();
2091 aBuilder
->Destroy(type
, this);
2095 * Returns the frame that this display item was created for.
2096 * Never returns null.
2098 inline nsIFrame
* Frame() const {
2099 MOZ_ASSERT(mFrame
, "Trying to use display item after frame deletion!");
2104 * Called when the display item is prepared for deletion. The display item
2105 * should not be used after calling this function.
2107 virtual void RemoveFrame(nsIFrame
* aFrame
) {
2110 if (mFrame
&& aFrame
== mFrame
) {
2117 * A display item can depend on multiple different frames for invalidation.
2119 virtual nsIFrame
* GetDependentFrame() { return nullptr; }
2122 * Returns the frame that provides the style data, and should
2123 * be checked when deciding if this display item can be reused.
2125 virtual nsIFrame
* FrameForInvalidation() const { return Frame(); }
2128 * Display items can override this to communicate that they won't
2129 * contribute any visual information (for example fully transparent).
2131 virtual bool IsInvisible() const { return false; }
2134 * Returns the printable name of this display item.
2136 virtual const char* Name() const = 0;
2139 * Some consecutive items should be rendered together as a unit, e.g.,
2140 * outlines for the same element. For this, we need a way for items to
2141 * identify their type. We use the type for other purposes too.
2143 DisplayItemType
GetType() const {
2144 MOZ_ASSERT(mType
!= DisplayItemType::TYPE_ZERO
,
2145 "Display item should have a valid type!");
2150 * Pairing this with the Frame() pointer gives a key that
2151 * uniquely identifies this display item in the display item tree.
2153 uint32_t GetPerFrameKey() const {
2154 // The top 8 bits are the page index
2155 // The middle 16 bits of the per frame key uniquely identify the display
2156 // item when there are more than one item of the same type for a frame.
2157 // The low 8 bits are the display item type.
2158 return (static_cast<uint32_t>(mExtraPageForPageNum
)
2159 << (TYPE_BITS
+ (sizeof(mPerFrameIndex
) * 8))) |
2160 (static_cast<uint32_t>(mPerFrameIndex
) << TYPE_BITS
) |
2161 static_cast<uint32_t>(mType
);
2165 * Returns true if this item was reused during display list merging.
2167 bool IsReused() const { return mItemFlags
.contains(ItemFlag::ReusedItem
); }
2169 void SetReused(bool aReused
) { SetItemFlag(ItemFlag::ReusedItem
, aReused
); }
2172 * Returns true if this item can be reused during display list merging.
2174 bool CanBeReused() const {
2175 return !mItemFlags
.contains(ItemFlag::CantBeReused
);
2178 void SetCantBeReused() { mItemFlags
+= ItemFlag::CantBeReused
; }
2180 bool CanBeCached() const {
2181 return !mItemFlags
.contains(ItemFlag::CantBeCached
);
2184 void SetCantBeCached() { mItemFlags
+= ItemFlag::CantBeCached
; }
2186 bool IsOldItem() const { return !!mOldList
; }
2189 * Returns true if the frame of this display item is in a modified subtree.
2191 bool HasModifiedFrame() const {
2192 return mItemFlags
.contains(ItemFlag::ModifiedFrame
);
2195 void SetModifiedFrame(bool aModified
) {
2196 SetItemFlag(ItemFlag::ModifiedFrame
, aModified
);
2199 bool HasDeletedFrame() const;
2202 * Set the nsDisplayList that this item belongs to, and what index it is
2204 * Temporary state for merging used by RetainedDisplayListBuilder.
2206 void SetOldListIndex(nsDisplayList
* aList
, OldListIndex aIndex
,
2207 uint32_t aListKey
, uint32_t aNestingDepth
) {
2208 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2209 mOldListKey
= aListKey
;
2210 mOldNestingDepth
= aNestingDepth
;
2212 mOldList
= reinterpret_cast<uintptr_t>(aList
);
2213 mOldListIndex
= aIndex
;
2216 bool GetOldListIndex(nsDisplayList
* aList
, uint32_t aListKey
,
2217 OldListIndex
* aOutIndex
) {
2218 if (mOldList
!= reinterpret_cast<uintptr_t>(aList
)) {
2219 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2220 MOZ_CRASH_UNSAFE_PRINTF(
2221 "Item found was in the wrong list! type %d "
2222 "(outer type was %d at depth %d, now is %d)",
2223 GetPerFrameKey(), mOldListKey
, mOldNestingDepth
, aListKey
);
2227 *aOutIndex
= mOldListIndex
;
2232 * Returns the display list containing the children of this display item.
2233 * The children may be in a different coordinate system than this item.
2235 virtual RetainedDisplayList
* GetChildren() const { return nullptr; }
2236 bool HasChildren() const { return GetChildren(); }
2239 * Display items with children may return true here. This causes the
2240 * display list iterator to descend into the child display list.
2242 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) {
2246 virtual bool CreatesStackingContextHelper() { return false; }
2249 * Returns true if this item can be moved asynchronously on the compositor,
2250 * see RetainedDisplayListBuilder.cpp comments.
2252 virtual bool CanMoveAsync() { return false; }
2255 // This is never instantiated directly (it has pure virtual methods), so no
2256 // need to count constructors and destructors.
2257 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
2258 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
2259 const ActiveScrolledRoot
* aActiveScrolledRoot
);
2262 * The custom copy-constructor is implemented to prevent copying the saved
2263 * state of the item.
2264 * This is currently only used when creating temporary items for merging.
2266 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, const nsDisplayItem
& aOther
)
2267 : mFrame(aOther
.mFrame
),
2268 mItemFlags(aOther
.mItemFlags
),
2269 mType(aOther
.mType
),
2270 mExtraPageForPageNum(aOther
.mExtraPageForPageNum
),
2271 mPerFrameIndex(aOther
.mPerFrameIndex
),
2272 mBuildingRect(aOther
.mBuildingRect
),
2273 mToReferenceFrame(aOther
.mToReferenceFrame
),
2274 mActiveScrolledRoot(aOther
.mActiveScrolledRoot
),
2275 mClipChain(aOther
.mClipChain
) {
2276 MOZ_COUNT_CTOR(nsDisplayItem
);
2277 // TODO: It might be better to remove the flags that aren't copied.
2278 if (aOther
.ForceNotVisible()) {
2279 mItemFlags
+= ItemFlag::ForceNotVisible
;
2281 if (mFrame
->In3DContextAndBackfaceIsHidden()) {
2282 mItemFlags
+= ItemFlag::BackfaceHidden
;
2284 if (aOther
.Combines3DTransformWithAncestors()) {
2285 mItemFlags
+= ItemFlag::Combines3DTransformWithAncestors
;
2289 virtual ~nsDisplayItem() {
2290 MOZ_COUNT_DTOR(nsDisplayItem
);
2292 mFrame
->RemoveDisplayItem(this);
2296 void SetType(const DisplayItemType aType
) { mType
= aType
; }
2298 void SetPerFrameIndex(const uint16_t aIndex
) { mPerFrameIndex
= aIndex
; }
2300 // Display list building for printing can build duplicate
2301 // container display items when they contain a mixture of
2302 // OOF and normal content that is spread across multiple
2303 // pages. We include the page number for the duplicates
2304 // to make our GetPerFrameKey unique.
2305 void SetExtraPageForPageNum(const uint8_t aPageNum
) {
2306 mExtraPageForPageNum
= aPageNum
;
2309 void SetDeletedFrame();
2312 nsDisplayItem() = delete;
2313 nsDisplayItem(const nsDisplayItem
&) = delete;
2316 * Invalidate cached information that depends on this node's contents, after
2317 * a mutation of those contents.
2319 * Specifically, if you mutate an |nsDisplayItem| in a way that would change
2320 * the WebRender display list items generated for it, you should call this
2323 * If a |RestoreState| method exists to restore some piece of state, that's a
2324 * good indication that modifications to said state should be accompanied by a
2325 * call to this method. Opacity flattening's effects on
2326 * |nsDisplayBackgroundColor| items are one example.
2328 virtual void InvalidateItemCacheEntry() {}
2330 struct HitTestState
{
2331 explicit HitTestState() = default;
2334 NS_ASSERTION(mItemBuffer
.Length() == 0,
2335 "mItemBuffer should have been cleared");
2338 // Handling transform items for preserve 3D frames.
2339 bool mInPreserves3D
= false;
2340 // When hit-testing for visibility, we may hit an fully opaque item in a
2341 // nested display list. We want to stop at that point, without looking
2342 // further on other items.
2343 bool mHitOccludingItem
= false;
2345 float mCurrentOpacity
= 1.0f
;
2347 AutoTArray
<nsDisplayItem
*, 100> mItemBuffer
;
2350 uint8_t GetFlags() const { return GetDisplayItemFlagsForType(GetType()); }
2352 virtual bool IsContentful() const { return GetFlags() & TYPE_IS_CONTENTFUL
; }
2355 * This is called after we've constructed a display list for event handling.
2356 * When this is called, we've already ensured that aRect intersects the
2357 * item's bounds and that clipping has been taking into account.
2359 * @param aRect the point or rect being tested, relative to the reference
2360 * frame. If the width and height are both 1 app unit, it indicates we're
2361 * hit testing a point, not a rect.
2362 * @param aState must point to a HitTestState. If you don't have one,
2363 * just create one with the default constructor and pass it in.
2364 * @param aOutFrames each item appends the frame(s) in this display item that
2365 * the rect is considered over (if any) to aOutFrames.
2367 virtual void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
2368 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) {}
2370 virtual nsIFrame
* StyleFrame() const { return mFrame
; }
2373 * Compute the used z-index of our frame; returns zero for elements to which
2374 * z-index does not apply, and for z-index:auto.
2375 * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
2377 virtual int32_t ZIndex() const;
2379 * The default bounds is the frame border rect.
2380 * @param aSnap *aSnap is set to true if the returned rect will be
2381 * snapped to nearest device pixel edges during actual drawing.
2382 * It might be set to false and snap anyway, so code computing the set of
2383 * pixels affected by this display item needs to round outwards to pixel
2384 * boundaries when *aSnap is set to false.
2385 * This does not take the item's clipping into account.
2386 * @return a rectangle relative to aBuilder->ReferenceFrame() that
2387 * contains the area drawn by this display item
2389 virtual nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const {
2391 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2395 * Returns the untransformed bounds of this display item.
2397 virtual nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
2398 bool* aSnap
) const {
2399 return GetBounds(aBuilder
, aSnap
);
2402 virtual nsRegion
GetTightBounds(nsDisplayListBuilder
* aBuilder
,
2403 bool* aSnap
) const {
2409 * Returns true if nothing will be rendered inside aRect, false if uncertain.
2410 * aRect is assumed to be contained in this item's bounds.
2412 virtual bool IsInvisibleInRect(const nsRect
& aRect
) const { return false; }
2415 * Returns the result of GetBounds intersected with the item's clip.
2416 * The intersection is approximate since rounded corners are not taking into
2419 nsRect
GetClippedBounds(nsDisplayListBuilder
* aBuilder
) const;
2421 nsRect
GetBorderRect() const {
2422 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2425 nsRect
GetPaddingRect() const {
2426 return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
2429 nsRect
GetContentRect() const {
2430 return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
2434 * Checks if the frame(s) owning this display item have been marked as
2435 * invalid, and needing repainting.
2437 virtual bool IsInvalid(nsRect
& aRect
) const {
2438 bool result
= mFrame
? mFrame
->IsInvalid(aRect
) : false;
2439 aRect
+= ToReferenceFrame();
2444 * Creates and initializes an nsDisplayItemGeometry object that retains the
2445 * current areas covered by this display item. These need to retain enough
2446 * information such that they can be compared against a future nsDisplayItem
2447 * of the same type, and determine if repainting needs to happen.
2449 * Subclasses wishing to store more information need to override both this
2450 * and ComputeInvalidationRegion, as well as implementing an
2451 * nsDisplayItemGeometry subclass.
2453 * The default implementation tracks both the display item bounds, and the
2454 * frame's border rect.
2456 virtual nsDisplayItemGeometry
* AllocateGeometry(
2457 nsDisplayListBuilder
* aBuilder
) {
2458 return new nsDisplayItemGenericGeometry(this, aBuilder
);
2462 * Compares an nsDisplayItemGeometry object from a previous paint against the
2463 * current item. Computes if the geometry of the item has changed, and the
2464 * invalidation area required for correct repainting.
2466 * The existing geometry will have been created from a display item with a
2467 * matching GetPerFrameKey()/mFrame pair to the current item.
2469 * The default implementation compares the display item bounds, and the
2470 * frame's border rect, and invalidates the entire bounds if either rect
2473 * @param aGeometry The geometry of the matching display item from the
2475 * @param aInvalidRegion Output param, the region to invalidate, or
2476 * unchanged if none.
2478 virtual void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
2479 const nsDisplayItemGeometry
* aGeometry
,
2480 nsRegion
* aInvalidRegion
) const {
2481 const nsDisplayItemGenericGeometry
* geometry
=
2482 static_cast<const nsDisplayItemGenericGeometry
*>(aGeometry
);
2484 if (!geometry
->mBounds
.IsEqualInterior(GetBounds(aBuilder
, &snap
)) ||
2485 !geometry
->mBorderRect
.IsEqualInterior(GetBorderRect())) {
2486 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
2491 * An alternative default implementation of ComputeInvalidationRegion,
2492 * that instead invalidates only the changed area between the two items.
2494 void ComputeInvalidationRegionDifference(
2495 nsDisplayListBuilder
* aBuilder
,
2496 const nsDisplayItemBoundsGeometry
* aGeometry
,
2497 nsRegion
* aInvalidRegion
) const {
2499 nsRect bounds
= GetBounds(aBuilder
, &snap
);
2501 if (!aGeometry
->mBounds
.IsEqualInterior(bounds
)) {
2503 if (aGeometry
->mHasRoundedCorners
|| Frame()->GetBorderRadii(radii
)) {
2504 aInvalidRegion
->Or(aGeometry
->mBounds
, bounds
);
2506 aInvalidRegion
->Xor(aGeometry
->mBounds
, bounds
);
2512 * This function is called when an item's list of children has been modified
2513 * by RetainedDisplayListBuilder.
2515 virtual void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) {}
2517 virtual void AddSizeOfExcludingThis(nsWindowSizes
&) const {}
2520 * @param aSnap set to true if the edges of the rectangles of the opaque
2521 * region would be snapped to device pixels when drawing
2522 * @return a region of the item that is opaque --- that is, every pixel
2523 * that is visible is painted with an opaque
2524 * color. This is useful for determining when one piece
2525 * of content completely obscures another so that we can do occlusion
2527 * This does not take clipping into account.
2528 * This must return a simple region (1 rect) for painting display lists.
2529 * It is only allowed to be a complex region for hit testing.
2531 virtual nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
2532 bool* aSnap
) const {
2537 * @return Some(nscolor) if the item is guaranteed to paint every pixel in its
2538 * bounds with the same (possibly translucent) color
2540 virtual Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const {
2545 * @return true if the contents of this item are rendered fixed relative
2546 * to the nearest viewport.
2548 virtual bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const {
2553 * Returns true if all layers that can be active should be forced to be
2554 * active. Requires setting the pref layers.force-active=true.
2556 static bool ForceActiveLayers();
2558 #ifdef MOZ_DUMP_PAINTING
2560 * Mark this display item as being painted via
2561 * FrameLayerBuilder::DrawPaintedLayer.
2563 bool Painted() const { return mItemFlags
.contains(ItemFlag::Painted
); }
2566 * Check if this display item has been painted.
2568 void SetPainted() { mItemFlags
+= ItemFlag::Painted
; }
2572 * Function to create the WebRenderCommands.
2573 * We should check if the layer state is
2574 * active first and have an early return if the layer state is
2577 * @return true if successfully creating webrender commands.
2579 virtual bool CreateWebRenderCommands(
2580 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
2581 const StackingContextHelper
& aSc
,
2582 layers::RenderRootStateManager
* aManager
,
2583 nsDisplayListBuilder
* aDisplayListBuilder
) {
2588 * Updates the provided aLayerData with any APZ-relevant scroll data
2589 * that is specific to this display item. This is stuff that would normally
2590 * be put on the layer during BuildLayer, but this is only called in
2591 * layers-free webrender mode, where we don't have layers.
2593 * This function returns true if and only if it has APZ-relevant scroll data
2594 * to provide. Note that the arguments passed in may be nullptr, in which case
2595 * the function should still return true if and only if it has APZ-relevant
2596 * scroll data, but obviously in this case it can't actually put the
2597 * data onto aLayerData, because there isn't one.
2599 * This function assumes that aData and aLayerData will either both be null,
2600 * or will both be non-null. The caller is responsible for enforcing this.
2602 virtual bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
2603 layers::WebRenderLayerScrollData
* aLayerData
) {
2608 * Returns true if this item needs to have its geometry updated, despite
2609 * returning empty invalidation region.
2611 virtual bool NeedsGeometryUpdates() const { return false; }
2614 * When this item is rendered using fallback rendering, whether it should use
2615 * blob rendering (i.e. a recording DrawTarget), as opposed to a pixel-backed
2617 * Some items, such as those calling into the native themed widget machinery,
2618 * are more efficiently painted without blob recording. Those should return
2621 virtual bool ShouldUseBlobRenderingForFallback() const { return true; }
2624 * If this has a child list where the children are in the same coordinate
2625 * system as this item (i.e., they have the same reference frame),
2628 virtual RetainedDisplayList
* GetSameCoordinateSystemChildren() const {
2632 virtual void UpdateBounds(nsDisplayListBuilder
* aBuilder
) {}
2634 * Do UpdateBounds() for items with frames establishing or extending
2635 * 3D rendering context.
2637 * This function is called by UpdateBoundsFor3D() of
2638 * nsDisplayTransform(), and it is called by
2639 * BuildDisplayListForStackingContext() on transform items
2640 * establishing 3D rendering context.
2642 * The bounds of a transform item with the frame establishing 3D
2643 * rendering context should be computed by calling
2644 * DoUpdateBoundsPreserves3D() on all descendants that participate
2645 * the same 3d rendering context.
2647 virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) {}
2650 * Returns the building rectangle used by nsDisplayListBuilder when
2651 * this item was constructed.
2653 const nsRect
& GetBuildingRect() const { return mBuildingRect
; }
2655 void SetBuildingRect(const nsRect
& aBuildingRect
) {
2656 mBuildingRect
= aBuildingRect
;
2660 * Returns the building rect for the children, relative to their
2661 * reference frame. Can be different from mBuildingRect for
2662 * nsDisplayTransform, since the reference frame for the children is different
2663 * from the reference frame for the item itself.
2665 virtual const nsRect
& GetBuildingRectForChildren() const {
2666 return mBuildingRect
;
2669 virtual void WriteDebugInfo(std::stringstream
& aStream
) {}
2672 * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
2674 const nsPoint
& ToReferenceFrame() const {
2675 NS_ASSERTION(mFrame
, "No frame?");
2676 return mToReferenceFrame
;
2680 * Returns the reference frame for display item children of this item.
2682 virtual const nsIFrame
* ReferenceFrameForChildren() const { return nullptr; }
2685 * Checks if this display item (or any children) contains content that might
2686 * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
2687 * bounds of the area that needs component alpha, or an empty rect if nothing
2690 virtual nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const {
2695 * Check if we can add async animations to the layer for this display item.
2697 virtual bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) {
2701 virtual bool SupportsOptimizingToImage() const { return false; }
2703 virtual const DisplayItemClip
& GetClip() const;
2704 void IntersectClip(nsDisplayListBuilder
* aBuilder
,
2705 const DisplayItemClipChain
* aOther
, bool aStore
);
2707 virtual void SetActiveScrolledRoot(
2708 const ActiveScrolledRoot
* aActiveScrolledRoot
) {
2709 mActiveScrolledRoot
= aActiveScrolledRoot
;
2711 const ActiveScrolledRoot
* GetActiveScrolledRoot() const {
2712 return mActiveScrolledRoot
;
2715 virtual void SetClipChain(const DisplayItemClipChain
* aClipChain
,
2717 const DisplayItemClipChain
* GetClipChain() const { return mClipChain
; }
2719 bool BackfaceIsHidden() const {
2720 return mItemFlags
.contains(ItemFlag::BackfaceHidden
);
2723 bool Combines3DTransformWithAncestors() const {
2724 return mItemFlags
.contains(ItemFlag::Combines3DTransformWithAncestors
);
2727 bool ForceNotVisible() const {
2728 return mItemFlags
.contains(ItemFlag::ForceNotVisible
);
2731 bool In3DContextAndBackfaceIsHidden() const {
2732 return mItemFlags
.contains(ItemFlag::BackfaceHidden
) &&
2733 mItemFlags
.contains(ItemFlag::Combines3DTransformWithAncestors
);
2736 bool HasDifferentFrame(const nsDisplayItem
* aOther
) const {
2737 return mFrame
!= aOther
->mFrame
;
2740 bool HasHitTestInfo() const {
2741 return mItemFlags
.contains(ItemFlag::HasHitTestInfo
);
2744 bool HasSameTypeAndClip(const nsDisplayItem
* aOther
) const {
2745 return GetPerFrameKey() == aOther
->GetPerFrameKey() &&
2746 GetClipChain() == aOther
->GetClipChain();
2749 bool HasSameContent(const nsDisplayItem
* aOther
) const {
2750 return mFrame
->GetContent() == aOther
->Frame()->GetContent();
2753 virtual void NotifyUsed(nsDisplayListBuilder
* aBuilder
) {}
2755 virtual Maybe
<nsRect
> GetClipWithRespectToASR(
2756 nsDisplayListBuilder
* aBuilder
, const ActiveScrolledRoot
* aASR
) const;
2758 virtual const nsRect
& GetUntransformedPaintRect() const {
2759 return GetBuildingRect();
2762 nsRect
GetPaintRect(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
);
2764 virtual const HitTestInfo
& GetHitTestInfo() { return HitTestInfo::Empty(); }
2766 enum class ReuseState
: uint8_t {
2768 // Set during display list building.
2770 // Set during display list preprocessing.
2772 // Set during partial display list build.
2776 void SetReusable() {
2777 MOZ_ASSERT(mReuseState
== ReuseState::None
||
2778 mReuseState
== ReuseState::Reused
);
2779 mReuseState
= ReuseState::Reusable
;
2782 bool IsReusable() const { return mReuseState
== ReuseState::Reusable
; }
2784 void SetPreProcessed() {
2785 MOZ_ASSERT(mReuseState
== ReuseState::Reusable
);
2786 mReuseState
= ReuseState::PreProcessed
;
2789 bool IsPreProcessed() const {
2790 return mReuseState
== ReuseState::PreProcessed
;
2793 void SetReusedItem() {
2794 MOZ_ASSERT(mReuseState
== ReuseState::PreProcessed
);
2795 mReuseState
= ReuseState::Reused
;
2798 bool IsReusedItem() const { return mReuseState
== ReuseState::Reused
; }
2800 void ResetReuseState() { mReuseState
= ReuseState::None
; }
2802 ReuseState
GetReuseState() const { return mReuseState
; }
2804 nsIFrame
* mFrame
; // 8
2807 enum class ItemFlag
: uint16_t {
2813 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2818 Combines3DTransformWithAncestors
,
2821 #ifdef MOZ_DUMP_PAINTING
2822 // True if this frame has been painted.
2827 EnumSet
<ItemFlag
, uint16_t> mItemFlags
; // 2
2828 DisplayItemType mType
= DisplayItemType::TYPE_ZERO
; // 1
2829 uint8_t mExtraPageForPageNum
= 0; // 1
2830 uint16_t mPerFrameIndex
= 0; // 2
2831 ReuseState mReuseState
= ReuseState::None
;
2832 OldListIndex mOldListIndex
; // 4
2833 uintptr_t mOldList
= 0; // 8
2835 // This is the rectangle that nsDisplayListBuilder was using as the visible
2836 // rect to decide which items to construct.
2837 nsRect mBuildingRect
;
2840 void SetItemFlag(ItemFlag aFlag
, const bool aValue
) {
2842 mItemFlags
+= aFlag
;
2844 mItemFlags
-= aFlag
;
2848 void SetHasHitTestInfo() { mItemFlags
+= ItemFlag::HasHitTestInfo
; }
2850 // Result of ToReferenceFrame(mFrame), if mFrame is non-null
2851 nsPoint mToReferenceFrame
;
2853 RefPtr
<const ActiveScrolledRoot
> mActiveScrolledRoot
;
2854 RefPtr
<const DisplayItemClipChain
> mClipChain
;
2856 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2858 bool IsMergedItem() const {
2859 return mItemFlags
.contains(ItemFlag::MergedItem
);
2862 bool IsPreProcessedItem() const {
2863 return mItemFlags
.contains(ItemFlag::PreProcessedItem
);
2866 void SetMergedPreProcessed(bool aMerged
, bool aPreProcessed
) {
2867 SetItemFlag(ItemFlag::MergedItem
, aMerged
);
2868 SetItemFlag(ItemFlag::PreProcessedItem
, aPreProcessed
);
2871 uint32_t mOldListKey
= 0;
2872 uint32_t mOldNestingDepth
= 0;
2876 class nsPaintedDisplayItem
: public nsDisplayItem
{
2878 nsPaintedDisplayItem
* AsPaintedDisplayItem() final
{ return this; }
2879 const nsPaintedDisplayItem
* AsPaintedDisplayItem() const final
{
2884 * Returns true if this display item would return true from ApplyOpacity
2885 * without actually applying the opacity. Otherwise returns false.
2887 virtual bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
2888 nsDisplayListBuilder
* aBuilder
) const {
2893 * Returns true if this item supports PaintWithClip, where the clipping
2894 * is used directly as the primitive geometry instead of needing an explicit
2897 virtual bool CanPaintWithClip(const DisplayItemClip
& aClip
) { return false; }
2900 * Same as |Paint()|, except provides a clip to use the geometry to draw with.
2901 * Must not be called unless |CanPaintWithClip()| returned true.
2903 virtual void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
2904 const DisplayItemClip
& aClip
) {
2905 MOZ_ASSERT_UNREACHABLE("PaintWithClip() is not implemented!");
2909 * Paint this item to some rendering context.
2911 virtual void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) = 0;
2914 * External storage used by |DisplayItemCache| to avoid hashmap lookups.
2915 * If an item is reused and has the cache index set, it means that
2916 * |DisplayItemCache| has assigned a cache slot for the item.
2918 Maybe
<uint16_t>& CacheIndex() { return mCacheIndex
; }
2920 void InvalidateItemCacheEntry() override
{
2921 // |nsPaintedDisplayItem|s may have |DisplayItemCache| entries
2922 // that no longer match after a mutation. The cache will notice
2923 // on its own that the entry is no longer in use, and free it.
2924 mCacheIndex
= Nothing();
2927 const HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
2928 void InitializeHitTestInfo(nsDisplayListBuilder
* aBuilder
) {
2929 mHitTestInfo
.Initialize(aBuilder
, Frame());
2930 SetHasHitTestInfo();
2934 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
2935 : nsPaintedDisplayItem(aBuilder
, aFrame
,
2936 aBuilder
->CurrentActiveScrolledRoot()) {}
2938 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
2939 const ActiveScrolledRoot
* aActiveScrolledRoot
)
2940 : nsDisplayItem(aBuilder
, aFrame
, aActiveScrolledRoot
) {}
2942 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
,
2943 const nsPaintedDisplayItem
& aOther
)
2944 : nsDisplayItem(aBuilder
, aOther
), mHitTestInfo(aOther
.mHitTestInfo
) {}
2947 HitTestInfo mHitTestInfo
;
2948 Maybe
<uint16_t> mCacheIndex
;
2951 template <typename T
>
2952 struct MOZ_HEAP_CLASS LinkedListNode
{
2953 explicit LinkedListNode(T aValue
) : mNext(nullptr), mValue(aValue
) {}
2954 LinkedListNode
* mNext
;
2958 template <typename T
>
2959 struct LinkedListIterator
{
2960 using iterator_category
= std::forward_iterator_tag
;
2961 using difference_type
= std::ptrdiff_t;
2962 using value_type
= T
;
2964 using reference
= T
&;
2965 using Node
= LinkedListNode
<T
>;
2967 explicit LinkedListIterator(Node
* aNode
= nullptr) : mNode(aNode
) {}
2969 bool HasNext() const { return mNode
!= nullptr; }
2971 LinkedListIterator
<T
>& operator++() {
2973 mNode
= mNode
->mNext
;
2977 bool operator==(const LinkedListIterator
<T
>& aOther
) const {
2978 return mNode
== aOther
.mNode
;
2981 bool operator!=(const LinkedListIterator
<T
>& aOther
) const {
2982 return mNode
!= aOther
.mNode
;
2985 const T
operator*() const {
2987 return mNode
->mValue
;
2992 return mNode
->mValue
;
2999 * Manages a singly-linked list of display list items.
3001 * Stepping upward through this list is very fast. Stepping downward is very
3002 * slow so we don't support it. The methods that need to step downward
3003 * (HitTest()) internally build a temporary array of all
3004 * the items while they do the downward traversal, so overall they're still
3005 * linear time. We have optimized for efficient AppendToTop() of both
3006 * items and lists, with minimal codesize.
3008 * Internal linked list nodes are allocated using arena allocator.
3010 class nsDisplayList
{
3012 using Node
= LinkedListNode
<nsDisplayItem
*>;
3013 using iterator
= LinkedListIterator
<nsDisplayItem
*>;
3014 using const_iterator
= iterator
;
3016 iterator
begin() { return iterator(mBottom
); }
3017 iterator
end() { return iterator(nullptr); }
3018 const_iterator
begin() const { return iterator(mBottom
); }
3019 const_iterator
end() const { return iterator(nullptr); }
3021 explicit nsDisplayList(nsDisplayListBuilder
* aBuilder
) : mBuilder(aBuilder
) {}
3023 nsDisplayList() = delete;
3024 nsDisplayList(const nsDisplayList
&) = delete;
3025 nsDisplayList
& operator=(const nsDisplayList
&) = delete;
3027 virtual ~nsDisplayList() {
3028 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3029 if (!mAllowNonEmptyDestruction
) {
3030 MOZ_RELEASE_ASSERT(IsEmpty(), "Nonempty list left over?");
3037 nsDisplayList(nsDisplayList
&& aOther
)
3038 : mBottom(aOther
.mBottom
),
3040 mLength(aOther
.mLength
),
3041 mBuilder(aOther
.mBuilder
) {
3045 nsDisplayList
& operator=(nsDisplayList
&& aOther
) {
3046 MOZ_RELEASE_ASSERT(mBuilder
== aOther
.mBuilder
);
3048 if (this != &aOther
) {
3049 MOZ_RELEASE_ASSERT(IsEmpty());
3050 mBottom
= std::move(aOther
.mBottom
);
3051 mTop
= std::move(aOther
.mTop
);
3052 mLength
= std::move(aOther
.mLength
);
3059 * Append an item to the top of the list.
3061 void AppendToTop(nsDisplayItem
* aItem
) {
3066 auto* next
= Allocate(aItem
);
3079 MOZ_ASSERT(mBottom
&& mTop
);
3080 MOZ_ASSERT(mTop
->mNext
== nullptr);
3083 template <typename T
, typename F
, typename
... Args
>
3084 void AppendNewToTop(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3086 AppendNewToTopWithIndex
<T
>(aBuilder
, aFrame
, 0,
3087 std::forward
<Args
>(aArgs
)...);
3090 template <typename T
, typename F
, typename
... Args
>
3091 void AppendNewToTopWithIndex(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3092 const uint16_t aIndex
, Args
&&... aArgs
) {
3093 nsDisplayItem
* item
= MakeDisplayItemWithIndex
<T
>(
3094 aBuilder
, aFrame
, aIndex
, std::forward
<Args
>(aArgs
)...);
3099 * Removes all items from aList and appends them to the top of this list.
3101 void AppendToTop(nsDisplayList
* aList
) {
3102 MOZ_ASSERT(aList
!= this);
3103 MOZ_RELEASE_ASSERT(mBuilder
== aList
->mBuilder
);
3105 if (aList
->IsEmpty()) {
3110 std::swap(mBottom
, aList
->mBottom
);
3111 std::swap(mTop
, aList
->mTop
);
3112 std::swap(mLength
, aList
->mLength
);
3114 MOZ_ASSERT(mTop
&& mTop
->mNext
== nullptr);
3115 mTop
->mNext
= aList
->mBottom
;
3117 mLength
+= aList
->mLength
;
3124 * Clears the display list.
3132 * Creates a shallow copy of this display list to |aDestination|.
3134 void CopyTo(nsDisplayList
* aDestination
) const {
3135 for (auto* item
: *this) {
3136 aDestination
->AppendToTop(item
);
3141 * Calls the function |aFn| for each display item in the display list.
3143 void ForEach(const std::function
<void(nsDisplayItem
*)>& aFn
) {
3144 for (auto* item
: *this) {
3149 * Remove all items from the list and call their destructors.
3151 virtual void DeleteAll(nsDisplayListBuilder
* aBuilder
);
3154 * @return the item at the bottom of the list, or null if the list is empty
3156 nsDisplayItem
* GetBottom() const {
3157 return mBottom
? mBottom
->mValue
: nullptr;
3161 * @return the item at the top of the list, or null if the list is empty
3163 nsDisplayItem
* GetTop() const { return mTop
? mTop
->mValue
: nullptr; }
3165 bool IsEmpty() const { return mBottom
== nullptr; }
3168 * @return the number of items in the list
3170 size_t Length() const { return mLength
; }
3173 * Stable sort the list by the z-order of Frame() on
3174 * each item. 'auto' is counted as zero.
3175 * It is assumed that the list is already in content document order.
3177 void SortByZOrder();
3180 * Stable sort the list by the tree order of the content of
3181 * Frame() on each item. z-index is ignored.
3182 * @param aCommonAncestor a common ancestor of all the content elements
3183 * associated with the display items, for speeding up tree order
3184 * checks, or nullptr if not known; it's only a hint, if it is not an
3185 * ancestor of some elements, then we lose performance but not correctness
3187 void SortByContentOrder(nsIContent
* aCommonAncestor
);
3190 * Sort the display list using a stable sort.
3191 * aComparator(Item item1, Item item2) should return true if item1 should go
3193 * We sort the items into increasing order.
3195 template <typename Item
, typename Comparator
>
3196 void Sort(const Comparator
& aComparator
) {
3198 // Only sort lists with more than one item.
3202 // Some casual local browsing testing suggests that a local preallocated
3203 // array of 20 items should be able to avoid a lot of dynamic allocations
3205 AutoTArray
<Item
, 20> items
;
3206 // Ensure we need just one alloc otherwise, no-op if enough.
3207 items
.SetCapacity(Length());
3209 for (nsDisplayItem
* item
: TakeItems()) {
3210 items
.AppendElement(Item(item
));
3212 items
.StableSort(aComparator
);
3214 for (Item
& item
: items
) {
3219 nsDisplayList
TakeItems() {
3220 // This std::move makes this a defined empty list, see assignment operator.
3221 nsDisplayList list
= std::move(*this);
3222 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3223 list
.mAllowNonEmptyDestruction
= true;
3228 nsDisplayItem
* RemoveBottom() {
3233 nsDisplayItem
* bottom
= mBottom
->mValue
;
3235 auto next
= mBottom
->mNext
;
3236 Deallocate(mBottom
);
3240 // No bottom item means no items at all.
3244 MOZ_ASSERT(mLength
> 0);
3251 * Paint the list to the rendering context. We assume that (0,0) in aCtx
3252 * corresponds to the origin of the reference frame. For best results,
3253 * aCtx's current transform should make (0,0) pixel-aligned. The
3254 * rectangle in aDirtyRect is painted, which *must* be contained in the
3255 * dirty rect used to construct the display list.
3257 * If aFlags contains PAINT_USE_WIDGET_LAYERS and
3258 * ShouldUseWidgetLayerManager() is set, then we will paint using
3259 * the reference frame's widget's layer manager (and ctx may be null),
3260 * otherwise we will use a temporary BasicLayerManager and ctx must
3263 * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
3264 * layer manager has already had BeginTransaction() called on it and
3265 * we should not call it again.
3267 * This must only be called on the root display list of the display list
3270 * We return the layer manager used for painting --- mainly so that
3271 * callers can dump its layer tree if necessary.
3275 PAINT_USE_WIDGET_LAYERS
= 0x01,
3276 PAINT_EXISTING_TRANSACTION
= 0x04,
3277 PAINT_IDENTICAL_DISPLAY_LIST
= 0x08
3279 void PaintRoot(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
3280 uint32_t aFlags
, Maybe
<double> aDisplayListBuildTime
);
3282 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
3283 int32_t aAppUnitsPerDevPixel
);
3286 * Get the bounds. Takes the union of the bounds of all children.
3287 * The result is not cached.
3289 nsRect
GetClippedBounds(nsDisplayListBuilder
* aBuilder
) const;
3292 * Get this list's bounds, respecting clips relative to aASR. The result is
3293 * the union of each item's clipped bounds with respect to aASR. That means
3294 * that if an item can move asynchronously with an ASR that is a descendant
3295 * of aASR, then the clipped bounds with respect to aASR will be the clip of
3296 * that item for aASR, because the item can move anywhere inside that clip.
3297 * If there is an item in this list which is not bounded with respect to
3298 * aASR (i.e. which does not have "finite bounds" with respect to aASR),
3299 * then this method trigger an assertion failure.
3300 * The optional aBuildingRect out argument can be set to non-null if the
3301 * caller is also interested to know the building rect. This can be used
3302 * to get the visible rect efficiently without traversing the display list
3305 nsRect
GetClippedBoundsWithRespectToASR(
3306 nsDisplayListBuilder
* aBuilder
, const ActiveScrolledRoot
* aASR
,
3307 nsRect
* aBuildingRect
= nullptr) const;
3310 * Returns the opaque region of this display list.
3312 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
) {
3315 for (nsDisplayItem
* item
: *this) {
3316 result
.OrWith(item
->GetOpaqueRegion(aBuilder
, &snap
));
3322 * Returns the bounds of the area that needs component alpha.
3324 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const {
3326 for (nsDisplayItem
* item
: *this) {
3327 bounds
.UnionRect(bounds
, item
->GetComponentAlphaBounds(aBuilder
));
3333 * Find the topmost display item that returns a non-null frame, and return
3336 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
3337 nsDisplayItem::HitTestState
* aState
,
3338 nsTArray
<nsIFrame
*>* aOutFrames
) const;
3340 * Compute the union of the visible rects of the items in the list. The
3341 * result is not cached.
3343 nsRect
GetBuildingRect() const;
3346 inline Node
* Allocate(nsDisplayItem
* aItem
) {
3348 mBuilder
->Allocate(sizeof(Node
), DisplayListArenaObjectId::LISTNODE
);
3349 return new (ptr
) Node(aItem
);
3352 inline void Deallocate(Node
* aNode
) {
3354 mBuilder
->Destroy(DisplayListArenaObjectId::LISTNODE
, aNode
);
3357 void DeallocateNodes() {
3358 Node
* current
= mBottom
;
3359 Node
* next
= nullptr;
3362 next
= current
->mNext
;
3363 Deallocate(current
);
3368 inline void SetEmpty() {
3374 Node
* mBottom
= nullptr;
3375 Node
* mTop
= nullptr;
3377 nsDisplayListBuilder
* mBuilder
= nullptr;
3379 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3380 // This checks that the invariant of display lists owning their items is held.
3381 bool mAllowNonEmptyDestruction
= false;
3386 * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
3387 * will put any generated items onto the appropriate list given here. It's
3388 * basically just a collection with one list for each separate stacking layer.
3389 * The lists themselves are external to this object and thus can be shared
3390 * with others. Some of the list pointers may even refer to the same list.
3392 class nsDisplayListSet
{
3395 * @return a list where one should place the border and/or background for
3396 * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
3398 nsDisplayList
* BorderBackground() const { return mLists
[0]; }
3400 * @return a list where one should place the borders and/or backgrounds for
3401 * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
3403 nsDisplayList
* BlockBorderBackgrounds() const { return mLists
[1]; }
3405 * @return a list where one should place descendant floats (step 5 of
3406 * CSS 2.1 appendix E)
3408 nsDisplayList
* Floats() const { return mLists
[2]; }
3410 * @return a list where one should place the (pseudo) stacking contexts
3411 * for descendants of this frame (everything from steps 3, 7 and 8
3412 * of CSS 2.1 appendix E)
3414 nsDisplayList
* PositionedDescendants() const { return mLists
[3]; }
3416 * @return a list where one should place the outlines
3417 * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
3419 nsDisplayList
* Outlines() const { return mLists
[4]; }
3421 * @return a list where one should place all other content
3423 nsDisplayList
* Content() const { return mLists
[5]; }
3425 const std::array
<nsDisplayList
*, 6>& Lists() const { return mLists
; }
3428 * Clears all the display lists in the set.
3431 for (auto* list
: mLists
) {
3438 * Deletes all the display items in the set.
3440 void DeleteAll(nsDisplayListBuilder
* aBuilder
) {
3441 for (auto* list
: mLists
) {
3442 list
->DeleteAll(aBuilder
);
3446 nsDisplayListSet(nsDisplayList
* aBorderBackground
,
3447 nsDisplayList
* aBlockBorderBackgrounds
,
3448 nsDisplayList
* aFloats
, nsDisplayList
* aContent
,
3449 nsDisplayList
* aPositionedDescendants
,
3450 nsDisplayList
* aOutlines
)
3451 : mLists
{aBorderBackground
, aBlockBorderBackgrounds
, aFloats
,
3452 aContent
, aPositionedDescendants
, aOutlines
} {}
3455 * A copy constructor that lets the caller override the BorderBackground
3458 nsDisplayListSet(const nsDisplayListSet
& aLists
,
3459 nsDisplayList
* aBorderBackground
)
3460 : mLists(aLists
.mLists
) {
3461 mLists
[0] = aBorderBackground
;
3465 * Returns true if all the display lists in the display list set are empty.
3467 bool IsEmpty() const {
3468 for (auto* list
: mLists
) {
3469 if (!list
->IsEmpty()) {
3478 * Calls the function |aFn| for each display item in the display list set.
3480 void ForEach(const std::function
<void(nsDisplayItem
*)>& aFn
) const {
3481 for (auto* list
: mLists
) {
3487 * Creates a shallow copy of this display list set to |aDestination|.
3489 void CopyTo(const nsDisplayListSet
& aDestination
) const;
3492 * Move all display items in our lists to top of the corresponding lists in
3495 void MoveTo(const nsDisplayListSet
& aDestination
) const;
3498 // This class is only used on stack, so we don't have to worry about leaking
3499 // it. Don't let us be heap-allocated!
3500 void* operator new(size_t sz
) noexcept(true);
3502 std::array
<nsDisplayList
*, 6> mLists
;
3506 * A specialization of nsDisplayListSet where the lists are actually internal
3507 * to the object, and all distinct.
3509 struct nsDisplayListCollection
: public nsDisplayListSet
{
3510 explicit nsDisplayListCollection(nsDisplayListBuilder
* aBuilder
)
3511 : nsDisplayListSet(&mLists
[0], &mLists
[1], &mLists
[2], &mLists
[3],
3512 &mLists
[4], &mLists
[5]),
3513 mLists
{nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
},
3514 nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
},
3515 nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
}} {}
3518 * Sort all lists by content order.
3520 void SortAllByContentOrder(nsIContent
* aCommonAncestor
) {
3521 for (auto& mList
: mLists
) {
3522 mList
.SortByContentOrder(aCommonAncestor
);
3527 * Serialize this display list collection into a display list with the items
3528 * in the correct Z order.
3529 * @param aOutList the result display list
3530 * @param aContent the content element to use for content ordering
3532 void SerializeWithCorrectZOrder(nsDisplayList
* aOutResultList
,
3533 nsIContent
* aContent
);
3536 // This class is only used on stack, so we don't have to worry about leaking
3537 // it. Don't let us be heap-allocated!
3538 void* operator new(size_t sz
) noexcept(true);
3540 nsDisplayList mLists
[6];
3544 * A display list that also retains the partial build
3545 * information (in the form of a DAG) used to create it.
3547 * Display lists built from a partial list aren't necessarily
3548 * in the same order as a full build, and the DAG retains
3549 * the information needing to interpret the current
3552 class RetainedDisplayList
: public nsDisplayList
{
3554 explicit RetainedDisplayList(nsDisplayListBuilder
* aBuilder
)
3555 : nsDisplayList(aBuilder
) {}
3557 RetainedDisplayList(RetainedDisplayList
&& aOther
)
3558 : nsDisplayList(std::move(aOther
)), mDAG(std::move(aOther
.mDAG
)) {}
3560 RetainedDisplayList(const RetainedDisplayList
&) = delete;
3561 RetainedDisplayList
& operator=(const RetainedDisplayList
&) = delete;
3563 ~RetainedDisplayList() override
{
3564 MOZ_ASSERT(mOldItems
.IsEmpty(), "Must empty list before destroying");
3567 RetainedDisplayList
& operator=(RetainedDisplayList
&& aOther
) {
3568 MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
3569 MOZ_ASSERT(mOldItems
.IsEmpty(), "Can only move into an empty list!");
3571 nsDisplayList::operator=(std::move(aOther
));
3572 mDAG
= std::move(aOther
.mDAG
);
3573 mOldItems
= std::move(aOther
.mOldItems
);
3577 RetainedDisplayList
& operator=(nsDisplayList
&& aOther
) {
3578 MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
3579 MOZ_ASSERT(mOldItems
.IsEmpty(), "Can only move into an empty list!");
3580 nsDisplayList::operator=(std::move(aOther
));
3584 void DeleteAll(nsDisplayListBuilder
* aBuilder
) override
{
3585 for (OldItemInfo
& i
: mOldItems
) {
3586 if (i
.mItem
&& i
.mOwnsItem
) {
3587 i
.mItem
->Destroy(aBuilder
);
3588 MOZ_ASSERT(!GetBottom() || aBuilder
->PartialBuildFailed(),
3589 "mOldItems should not be owning items if we also have items "
3590 "in the normal list");
3595 nsDisplayList::DeleteAll(aBuilder
);
3598 void AddSizeOfExcludingThis(nsWindowSizes
&) const;
3600 DirectedAcyclicGraph
<MergedListUnits
> mDAG
;
3602 // Temporary state initialized during the preprocess pass
3603 // of RetainedDisplayListBuilder and then used during merging.
3604 nsTArray
<OldItemInfo
> mOldItems
;
3607 class nsDisplayContainer final
: public nsDisplayItem
{
3609 nsDisplayContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3610 const ActiveScrolledRoot
* aActiveScrolledRoot
,
3611 nsDisplayList
* aList
);
3613 ~nsDisplayContainer() override
{ MOZ_COUNT_DTOR(nsDisplayContainer
); }
3615 NS_DISPLAY_DECL_NAME("nsDisplayContainer", TYPE_CONTAINER
)
3617 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
3618 mChildren
.DeleteAll(aBuilder
);
3619 nsDisplayItem::Destroy(aBuilder
);
3622 bool CreateWebRenderCommands(
3623 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3624 const StackingContextHelper
& aSc
,
3625 layers::RenderRootStateManager
* aManager
,
3626 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3628 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3630 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
3632 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
3633 bool* aSnap
) const override
;
3635 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
{
3639 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
3640 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
3641 return GetChildren();
3644 Maybe
<nsRect
> GetClipWithRespectToASR(
3645 nsDisplayListBuilder
* aBuilder
,
3646 const ActiveScrolledRoot
* aASR
) const override
;
3648 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
3649 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
3651 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
3655 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
3656 bool aStore
) override
{
3657 MOZ_ASSERT_UNREACHABLE("nsDisplayContainer does not support clipping");
3660 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
3663 mutable RetainedDisplayList mChildren
;
3668 * Use this class to implement not-very-frequently-used display items
3669 * that are not opaque, do not receive events, and are bounded by a frame's
3672 * This should not be used for display items which are created frequently,
3673 * because each item is one or two pointers bigger than an item from a
3674 * custom display item class could be, and fractionally slower. However it does
3675 * save code size. We use this for infrequently-used item types.
3677 class nsDisplayGeneric
: public nsPaintedDisplayItem
{
3679 typedef void (*PaintCallback
)(nsIFrame
* aFrame
, gfx::DrawTarget
* aDrawTarget
,
3680 const nsRect
& aDirtyRect
, nsPoint aFramePt
);
3682 // XXX: should be removed eventually
3683 typedef void (*OldPaintCallback
)(nsIFrame
* aFrame
, gfxContext
* aCtx
,
3684 const nsRect
& aDirtyRect
, nsPoint aFramePt
);
3686 nsDisplayGeneric(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3687 PaintCallback aPaint
, const char* aName
,
3688 DisplayItemType aType
)
3689 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3693 MOZ_COUNT_CTOR(nsDisplayGeneric
);
3697 // XXX: should be removed eventually
3698 nsDisplayGeneric(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3699 OldPaintCallback aOldPaint
, const char* aName
,
3700 DisplayItemType aType
)
3701 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3703 mOldPaint(aOldPaint
),
3705 MOZ_COUNT_CTOR(nsDisplayGeneric
);
3709 constexpr static DisplayItemType
ItemType() {
3710 return DisplayItemType::TYPE_GENERIC
;
3713 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayGeneric
)
3715 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
3716 MOZ_ASSERT(!!mPaint
!= !!mOldPaint
);
3718 mPaint(mFrame
, aCtx
->GetDrawTarget(), GetPaintRect(aBuilder
, aCtx
),
3719 ToReferenceFrame());
3721 mOldPaint(mFrame
, aCtx
, GetPaintRect(aBuilder
, aCtx
), ToReferenceFrame());
3725 const char* Name() const override
{ return mName
; }
3727 // This override is needed because GetType() for nsDisplayGeneric subclasses
3728 // does not match TYPE_GENERIC that was used to allocate the object.
3729 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
3730 this->~nsDisplayGeneric();
3731 aBuilder
->Destroy(DisplayItemType::TYPE_GENERIC
, this);
3735 void* operator new(size_t aSize
, nsDisplayListBuilder
* aBuilder
) {
3736 return aBuilder
->Allocate(aSize
, DisplayItemType::TYPE_GENERIC
);
3739 template <typename T
, typename F
, typename
... Args
>
3740 friend T
* MakeDisplayItemWithIndex(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3741 const uint16_t aIndex
, Args
&&... aArgs
);
3743 PaintCallback mPaint
;
3744 OldPaintCallback mOldPaint
; // XXX: should be removed eventually
3748 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
3750 * This class implements painting of reflow counts. Ideally, we would simply
3751 * make all the frame names be those returned by nsIFrame::GetFrameName
3752 * (except that tosses in the content tag name!) and support only one color
3753 * and eliminate this class altogether in favor of nsDisplayGeneric, but for
3754 * the time being we can't pass args to a PaintCallback, so just have a
3755 * separate class to do the right thing. Sadly, this alsmo means we need to
3756 * hack all leaf frame classes to handle this.
3758 * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
3759 * here... I could switch it all to nscolor, but why bother?
3761 class nsDisplayReflowCount
: public nsPaintedDisplayItem
{
3763 nsDisplayReflowCount(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3764 const char* aFrameName
, uint32_t aColor
= 0)
3765 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3766 mFrameName(aFrameName
),
3768 MOZ_COUNT_CTOR(nsDisplayReflowCount
);
3771 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayReflowCount
)
3773 NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT
)
3775 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3778 const char* mFrameName
;
3782 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
3784 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3785 PresShell()->IsPaintingFrameCounts()) { \
3786 aLists.Outlines()->AppendNewToTop<mozilla::nsDisplayReflowCount>( \
3787 aBuilder, this, _name); \
3791 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
3793 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3794 PresShell()->IsPaintingFrameCounts()) { \
3795 aLists.Outlines()->AppendNewToTop<mozilla::nsDisplayReflowCount>( \
3796 aBuilder, this, _name, _color); \
3801 Macro to be used for classes that don't actually implement BuildDisplayList
3803 # define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
3804 void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
3805 const nsRect& aDirtyRect, \
3806 const nsDisplayListSet& aLists) { \
3807 DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
3808 _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
3811 #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3813 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
3814 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
3815 # define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
3817 #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3819 class nsDisplayCaret
: public nsPaintedDisplayItem
{
3821 nsDisplayCaret(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aCaretFrame
);
3823 #ifdef NS_BUILD_REFCNT_LOGGING
3824 ~nsDisplayCaret() override
;
3827 NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET
)
3829 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3830 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3831 bool CreateWebRenderCommands(
3832 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3833 const StackingContextHelper
& aSc
,
3834 layers::RenderRootStateManager
* aManager
,
3835 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3838 RefPtr
<nsCaret
> mCaret
;
3843 * The standard display item to paint the CSS borders of a frame.
3845 class nsDisplayBorder
: public nsPaintedDisplayItem
{
3847 nsDisplayBorder(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
3849 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBorder
)
3851 NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER
)
3853 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
3854 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3855 bool CreateWebRenderCommands(
3856 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3857 const StackingContextHelper
& aSc
,
3858 layers::RenderRootStateManager
* aManager
,
3859 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3860 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3861 nsDisplayItemGeometry
* AllocateGeometry(
3862 nsDisplayListBuilder
* aBuilder
) override
;
3863 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
3864 const nsDisplayItemGeometry
* aGeometry
,
3865 nsRegion
* aInvalidRegion
) const override
;
3867 nsRegion
GetTightBounds(nsDisplayListBuilder
* aBuilder
,
3868 bool* aSnap
) const override
{
3870 return CalculateBounds
<nsRegion
>(*mFrame
->StyleBorder());
3874 template <typename T
>
3875 T
CalculateBounds(const nsStyleBorder
& aStyleBorder
) const {
3876 nsRect
borderBounds(ToReferenceFrame(), mFrame
->GetSize());
3877 if (aStyleBorder
.IsBorderImageSizeAvailable()) {
3878 borderBounds
.Inflate(aStyleBorder
.GetImageOutset());
3879 return borderBounds
;
3882 nsMargin border
= aStyleBorder
.GetComputedBorder();
3884 if (border
.top
> 0) {
3885 result
= nsRect(borderBounds
.X(), borderBounds
.Y(), borderBounds
.Width(),
3888 if (border
.right
> 0) {
3889 result
.OrWith(nsRect(borderBounds
.XMost() - border
.right
,
3890 borderBounds
.Y(), border
.right
,
3891 borderBounds
.Height()));
3893 if (border
.bottom
> 0) {
3894 result
.OrWith(nsRect(borderBounds
.X(),
3895 borderBounds
.YMost() - border
.bottom
,
3896 borderBounds
.Width(), border
.bottom
));
3898 if (border
.left
> 0) {
3899 result
.OrWith(nsRect(borderBounds
.X(), borderBounds
.Y(), border
.left
,
3900 borderBounds
.Height()));
3904 if (mFrame
->GetBorderRadii(radii
)) {
3905 if (border
.left
> 0 || border
.top
> 0) {
3906 nsSize
cornerSize(radii
[eCornerTopLeftX
], radii
[eCornerTopLeftY
]);
3907 result
.OrWith(nsRect(borderBounds
.TopLeft(), cornerSize
));
3909 if (border
.top
> 0 || border
.right
> 0) {
3910 nsSize
cornerSize(radii
[eCornerTopRightX
], radii
[eCornerTopRightY
]);
3912 nsRect(borderBounds
.TopRight() - nsPoint(cornerSize
.width
, 0),
3915 if (border
.right
> 0 || border
.bottom
> 0) {
3916 nsSize
cornerSize(radii
[eCornerBottomRightX
],
3917 radii
[eCornerBottomRightY
]);
3918 result
.OrWith(nsRect(borderBounds
.BottomRight() -
3919 nsPoint(cornerSize
.width
, cornerSize
.height
),
3922 if (border
.bottom
> 0 || border
.left
> 0) {
3923 nsSize
cornerSize(radii
[eCornerBottomLeftX
], radii
[eCornerBottomLeftY
]);
3925 nsRect(borderBounds
.BottomLeft() - nsPoint(0, cornerSize
.height
),
3936 * A simple display item that just renders a solid color across the
3937 * specified bounds. For canvas frames (in the CSS sense) we split off the
3938 * drawing of the background color into this class (from nsDisplayBackground
3939 * via nsDisplayCanvasBackground). This is done so that we can always draw a
3940 * background color to avoid ugly flashes of white when we can't draw a full
3941 * frame tree (ie when a page is loading). The bounds can differ from the
3942 * frame's bounds -- this is needed when a frame/iframe is loading and there
3943 * is not yet a frame tree to go in the frame/iframe so we use the subdoc
3944 * frame of the parent document as a standin.
3946 class nsDisplaySolidColorBase
: public nsPaintedDisplayItem
{
3948 nsDisplaySolidColorBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3950 : nsPaintedDisplayItem(aBuilder
, aFrame
), mColor(aColor
) {}
3952 nsDisplayItemGeometry
* AllocateGeometry(
3953 nsDisplayListBuilder
* aBuilder
) override
{
3954 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
);
3957 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
3958 const nsDisplayItemGeometry
* aGeometry
,
3959 nsRegion
* aInvalidRegion
) const override
{
3960 const nsDisplaySolidColorGeometry
* geometry
=
3961 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
3962 if (mColor
!= geometry
->mColor
) {
3964 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
3967 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
3970 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
3971 bool* aSnap
) const override
{
3974 if (NS_GET_A(mColor
) == 255) {
3975 result
= GetBounds(aBuilder
, aSnap
);
3980 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
{
3981 return Some(mColor
);
3988 class nsDisplaySolidColor
: public nsDisplaySolidColorBase
{
3990 nsDisplaySolidColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3991 const nsRect
& aBounds
, nscolor aColor
,
3992 bool aCanBeReused
= true)
3993 : nsDisplaySolidColorBase(aBuilder
, aFrame
, aColor
),
3995 mIsCheckerboardBackground(false) {
3996 NS_ASSERTION(NS_GET_A(aColor
) > 0,
3997 "Don't create invisible nsDisplaySolidColors!");
3998 MOZ_COUNT_CTOR(nsDisplaySolidColor
);
3999 if (!aCanBeReused
) {
4004 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColor
)
4006 NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR
)
4008 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4009 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4010 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4011 void SetIsCheckerboardBackground() { mIsCheckerboardBackground
= true; }
4012 bool CreateWebRenderCommands(
4013 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4014 const StackingContextHelper
& aSc
,
4015 layers::RenderRootStateManager
* aManager
,
4016 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4018 int32_t ZIndex() const override
{
4019 if (mOverrideZIndex
) {
4020 return mOverrideZIndex
.value();
4022 return nsDisplaySolidColorBase::ZIndex();
4025 void SetOverrideZIndex(int32_t aZIndex
) { mOverrideZIndex
= Some(aZIndex
); }
4029 bool mIsCheckerboardBackground
;
4030 Maybe
<int32_t> mOverrideZIndex
;
4034 * A display item that renders a solid color over a region. This is not
4035 * exposed through CSS, its only purpose is efficient invalidation of
4036 * the find bar highlighter dimmer.
4038 class nsDisplaySolidColorRegion
: public nsPaintedDisplayItem
{
4040 nsDisplaySolidColorRegion(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4041 const nsRegion
& aRegion
, nscolor aColor
)
4042 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4044 mColor(gfx::sRGBColor::FromABGR(aColor
)) {
4045 NS_ASSERTION(NS_GET_A(aColor
) > 0,
4046 "Don't create invisible nsDisplaySolidColorRegions!");
4047 MOZ_COUNT_CTOR(nsDisplaySolidColorRegion
);
4050 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColorRegion
)
4052 NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION
)
4054 nsDisplayItemGeometry
* AllocateGeometry(
4055 nsDisplayListBuilder
* aBuilder
) override
{
4056 return new nsDisplaySolidColorRegionGeometry(this, aBuilder
, mRegion
,
4060 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4061 const nsDisplayItemGeometry
* aGeometry
,
4062 nsRegion
* aInvalidRegion
) const override
{
4063 const nsDisplaySolidColorRegionGeometry
* geometry
=
4064 static_cast<const nsDisplaySolidColorRegionGeometry
*>(aGeometry
);
4065 if (mColor
== geometry
->mColor
) {
4066 aInvalidRegion
->Xor(geometry
->mRegion
, mRegion
);
4068 aInvalidRegion
->Or(geometry
->mRegion
.GetBounds(), mRegion
.GetBounds());
4072 bool CreateWebRenderCommands(
4073 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4074 const StackingContextHelper
& aSc
,
4075 layers::RenderRootStateManager
* aManager
,
4076 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4079 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4080 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4081 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4085 gfx::sRGBColor mColor
;
4088 enum class AppendedBackgroundType
: uint8_t {
4095 * A display item to paint one background-image for a frame. Each background
4096 * image layer gets its own nsDisplayBackgroundImage.
4098 class nsDisplayBackgroundImage
: public nsPaintedDisplayItem
{
4101 nsDisplayListBuilder
* builder
;
4102 const ComputedStyle
* backgroundStyle
;
4103 nsCOMPtr
<imgIContainer
> image
;
4104 nsRect backgroundRect
;
4109 bool shouldFixToViewport
;
4113 * aLayer signifies which background layer this item represents.
4114 * aIsThemed should be the value of aFrame->IsThemed.
4115 * aBackgroundStyle should be the result of
4116 * nsCSSRendering::FindBackground, or null if FindBackground returned false.
4117 * aBackgroundRect is relative to aFrame.
4119 static InitData
GetInitData(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4120 uint16_t aLayer
, const nsRect
& aBackgroundRect
,
4121 const ComputedStyle
* aBackgroundStyle
);
4123 explicit nsDisplayBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4124 nsIFrame
* aFrame
, const InitData
& aInitData
,
4125 nsIFrame
* aFrameForBounds
= nullptr);
4126 ~nsDisplayBackgroundImage() override
;
4128 NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND
)
4131 * This will create and append new items for all the layers of the
4132 * background. Returns the type of background that was appended.
4133 * aAllowWillPaintBorderOptimization should usually be left at true, unless
4134 * aFrame has special border drawing that causes opaque borders to not
4135 * actually be opaque.
4137 static AppendedBackgroundType
AppendBackgroundItemsToTop(
4138 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4139 const nsRect
& aBackgroundRect
, nsDisplayList
* aList
,
4140 bool aAllowWillPaintBorderOptimization
= true,
4141 const nsRect
& aBackgroundOriginRect
= nsRect(),
4142 nsIFrame
* aSecondaryReferenceFrame
= nullptr,
4143 Maybe
<nsDisplayListBuilder::AutoBuildingDisplayList
>*
4144 aAutoBuildingDisplayList
= nullptr);
4146 bool CreateWebRenderCommands(
4147 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4148 const StackingContextHelper
& aSc
,
4149 layers::RenderRootStateManager
* aManager
,
4150 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4151 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4152 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4153 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4154 bool* aSnap
) const override
;
4155 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4157 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4158 nsDisplayListBuilder
* aBuilder
) const override
;
4161 * GetBounds() returns the background painting area.
4163 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4165 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4168 * Return the background positioning area.
4169 * (GetBounds() returns the background painting area.)
4170 * Can be called only when mBackgroundStyle is non-null.
4172 nsRect
GetPositioningArea() const;
4175 * Returns true if existing rendered pixels of this display item may need
4176 * to be redrawn if the positioning area size changes but its position does
4178 * If false, only the changed painting area needs to be redrawn when the
4179 * positioning area size changes but its position does not.
4181 bool RenderingMightDependOnPositioningAreaSizeChange() const;
4183 nsDisplayItemGeometry
* AllocateGeometry(
4184 nsDisplayListBuilder
* aBuilder
) override
{
4185 return new nsDisplayBackgroundGeometry(this, aBuilder
);
4188 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4189 const nsDisplayItemGeometry
* aGeometry
,
4190 nsRegion
* aInvalidRegion
) const override
;
4191 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
4192 return mShouldFixToViewport
;
4195 nsRect
GetDestRect() const { return mDestRect
; }
4197 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4199 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4200 if (!aBuilder
->IsRetainingDisplayList() || mDependentFrame
== aFrame
) {
4203 mDependentFrame
= aFrame
;
4205 mDependentFrame
->AddDisplayItem(this);
4209 void RemoveFrame(nsIFrame
* aFrame
) override
{
4210 if (aFrame
== mDependentFrame
) {
4211 mDependentFrame
= nullptr;
4213 nsPaintedDisplayItem::RemoveFrame(aFrame
);
4216 // Match https://w3c.github.io/paint-timing/#contentful-image
4217 bool IsContentful() const override
{
4218 const auto& styleImage
=
4219 mBackgroundStyle
->StyleBackground()->mImage
.mLayers
[mLayer
].mImage
;
4221 return styleImage
.IsSizeAvailable() && styleImage
.FinalImage().IsUrl();
4225 bool CanBuildWebRenderDisplayItems(layers::WebRenderLayerManager
* aManager
,
4226 nsDisplayListBuilder
* aBuilder
) const;
4227 nsRect
GetBoundsInternal(nsDisplayListBuilder
* aBuilder
,
4228 nsIFrame
* aFrameForBounds
= nullptr);
4230 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4231 const nsRect
& aBounds
, nsRect
* aClipRect
);
4233 // Cache the result of nsCSSRendering::FindBackground. Always null if
4234 // mIsThemed is true or if FindBackground returned false.
4235 RefPtr
<const ComputedStyle
> mBackgroundStyle
;
4236 nsCOMPtr
<imgIContainer
> mImage
;
4237 nsIFrame
* mDependentFrame
;
4238 nsRect mBackgroundRect
; // relative to the reference frame
4241 /* Bounds of this display item */
4244 bool mIsRasterImage
;
4245 /* Whether the image should be treated as fixed to the viewport. */
4246 bool mShouldFixToViewport
;
4250 * A display item to paint background image for table. For table parts, such
4251 * as row, row group, col, col group, when drawing its background, we'll
4252 * create separate background image display item for its containning cell.
4253 * Those background image display items will reference to same DisplayItemData
4254 * if we keep the mFrame point to cell's ancestor frame. We don't want to this
4255 * happened bacause share same DisplatItemData will cause many bugs. So that
4256 * we let mFrame point to cell frame and store the table type of the ancestor
4257 * frame. And use mFrame and table type as key to generate DisplayItemData to
4258 * avoid sharing DisplayItemData.
4260 * Also store ancestor frame as mStyleFrame for all rendering informations.
4262 class nsDisplayTableBackgroundImage
: public nsDisplayBackgroundImage
{
4264 nsDisplayTableBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4265 nsIFrame
* aFrame
, const InitData
& aData
,
4266 nsIFrame
* aCellFrame
);
4267 ~nsDisplayTableBackgroundImage() override
;
4269 NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE
)
4271 bool IsInvalid(nsRect
& aRect
) const override
;
4273 nsIFrame
* FrameForInvalidation() const override
{ return mStyleFrame
; }
4275 void RemoveFrame(nsIFrame
* aFrame
) override
{
4276 if (aFrame
== mStyleFrame
) {
4277 mStyleFrame
= nullptr;
4280 nsDisplayBackgroundImage::RemoveFrame(aFrame
);
4284 nsIFrame
* StyleFrame() const override
{ return mStyleFrame
; }
4285 nsIFrame
* mStyleFrame
;
4289 * A display item to paint the native theme background for a frame.
4291 class nsDisplayThemedBackground
: public nsPaintedDisplayItem
{
4293 nsDisplayThemedBackground(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4294 const nsRect
& aBackgroundRect
);
4296 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayThemedBackground
)
4298 NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND
)
4300 void Init(nsDisplayListBuilder
* aBuilder
);
4302 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4303 aBuilder
->UnregisterThemeGeometry(this);
4304 nsPaintedDisplayItem::Destroy(aBuilder
);
4307 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4308 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4309 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4310 bool* aSnap
) const override
;
4311 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4312 bool CreateWebRenderCommands(
4313 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4314 const StackingContextHelper
& aSc
,
4315 layers::RenderRootStateManager
* aManager
,
4316 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4318 bool ShouldUseBlobRenderingForFallback() const override
{
4319 return !XRE_IsParentProcess();
4323 * GetBounds() returns the background painting area.
4325 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4327 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4330 * Return the background positioning area.
4331 * (GetBounds() returns the background painting area.)
4332 * Can be called only when mBackgroundStyle is non-null.
4334 nsRect
GetPositioningArea() const;
4337 * Return whether our frame's document does not have the state
4338 * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
4340 bool IsWindowActive() const;
4342 nsDisplayItemGeometry
* AllocateGeometry(
4343 nsDisplayListBuilder
* aBuilder
) override
{
4344 return new nsDisplayThemedBackgroundGeometry(this, aBuilder
);
4347 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4348 const nsDisplayItemGeometry
* aGeometry
,
4349 nsRegion
* aInvalidRegion
) const override
;
4351 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4354 nsRect
GetBoundsInternal();
4356 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4357 const nsRect
& aBounds
, nsRect
* aClipRect
);
4359 nsRect mBackgroundRect
;
4361 nsITheme::Transparency mThemeTransparency
;
4362 StyleAppearance mAppearance
;
4365 class nsDisplayTableThemedBackground
: public nsDisplayThemedBackground
{
4367 nsDisplayTableThemedBackground(nsDisplayListBuilder
* aBuilder
,
4369 const nsRect
& aBackgroundRect
,
4370 nsIFrame
* aAncestorFrame
)
4371 : nsDisplayThemedBackground(aBuilder
, aFrame
, aBackgroundRect
),
4372 mAncestorFrame(aAncestorFrame
) {
4373 if (aBuilder
->IsRetainingDisplayList()) {
4374 mAncestorFrame
->AddDisplayItem(this);
4378 ~nsDisplayTableThemedBackground() override
{
4379 if (mAncestorFrame
) {
4380 mAncestorFrame
->RemoveDisplayItem(this);
4384 NS_DISPLAY_DECL_NAME("TableThemedBackground",
4385 TYPE_TABLE_THEMED_BACKGROUND_IMAGE
)
4387 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4389 void RemoveFrame(nsIFrame
* aFrame
) override
{
4390 if (aFrame
== mAncestorFrame
) {
4391 mAncestorFrame
= nullptr;
4394 nsDisplayThemedBackground::RemoveFrame(aFrame
);
4398 nsIFrame
* StyleFrame() const override
{ return mAncestorFrame
; }
4399 nsIFrame
* mAncestorFrame
;
4402 class nsDisplayBackgroundColor
: public nsPaintedDisplayItem
{
4404 nsDisplayBackgroundColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4405 const nsRect
& aBackgroundRect
,
4406 const ComputedStyle
* aBackgroundStyle
,
4407 const nscolor
& aColor
)
4408 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4409 mBackgroundRect(aBackgroundRect
),
4410 mHasStyle(aBackgroundStyle
),
4411 mDependentFrame(nullptr),
4412 mColor(gfx::sRGBColor::FromABGR(aColor
)) {
4415 aBackgroundStyle
->StyleBackground()->BottomLayer().mClip
;
4417 MOZ_ASSERT(aBuilder
->IsForEventDelivery());
4421 ~nsDisplayBackgroundColor() override
{
4422 if (mDependentFrame
) {
4423 mDependentFrame
->RemoveDisplayItem(this);
4427 NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR
)
4429 bool HasBackgroundClipText() const {
4430 MOZ_ASSERT(mHasStyle
);
4431 return mBottomLayerClip
== StyleGeometryBox::Text
;
4434 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4435 void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4436 const DisplayItemClip
& aClip
) override
;
4437 bool CreateWebRenderCommands(
4438 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4439 const StackingContextHelper
& aSc
,
4440 layers::RenderRootStateManager
* aManager
,
4441 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4442 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4443 bool* aSnap
) const override
;
4444 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4445 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4446 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4447 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4448 nsDisplayListBuilder
* aBuilder
) const override
;
4450 float GetOpacity() const { return mColor
.a
; }
4452 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
4454 return mBackgroundRect
;
4457 bool CanPaintWithClip(const DisplayItemClip
& aClip
) override
{
4458 if (HasBackgroundClipText()) {
4462 if (aClip
.GetRoundedRectCount() > 1) {
4469 nsDisplayItemGeometry
* AllocateGeometry(
4470 nsDisplayListBuilder
* aBuilder
) override
{
4471 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
.ToABGR());
4474 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4475 const nsDisplayItemGeometry
* aGeometry
,
4476 nsRegion
* aInvalidRegion
) const override
{
4477 const nsDisplaySolidColorGeometry
* geometry
=
4478 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
4480 if (mColor
.ToABGR() != geometry
->mColor
) {
4482 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
4485 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
4488 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4490 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4491 if (!aBuilder
->IsRetainingDisplayList() || mDependentFrame
== aFrame
) {
4494 mDependentFrame
= aFrame
;
4496 mDependentFrame
->AddDisplayItem(this);
4500 void RemoveFrame(nsIFrame
* aFrame
) override
{
4501 if (aFrame
== mDependentFrame
) {
4502 mDependentFrame
= nullptr;
4505 nsPaintedDisplayItem::RemoveFrame(aFrame
);
4508 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4510 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
4513 const nsRect mBackgroundRect
;
4514 const bool mHasStyle
;
4515 StyleGeometryBox mBottomLayerClip
;
4516 nsIFrame
* mDependentFrame
;
4517 gfx::sRGBColor mColor
;
4520 class nsDisplayTableBackgroundColor
: public nsDisplayBackgroundColor
{
4522 nsDisplayTableBackgroundColor(nsDisplayListBuilder
* aBuilder
,
4523 nsIFrame
* aFrame
, const nsRect
& aBackgroundRect
,
4524 const ComputedStyle
* aBackgroundStyle
,
4525 const nscolor
& aColor
, nsIFrame
* aAncestorFrame
)
4526 : nsDisplayBackgroundColor(aBuilder
, aFrame
, aBackgroundRect
,
4527 aBackgroundStyle
, aColor
),
4528 mAncestorFrame(aAncestorFrame
) {
4529 if (aBuilder
->IsRetainingDisplayList()) {
4530 mAncestorFrame
->AddDisplayItem(this);
4534 ~nsDisplayTableBackgroundColor() override
{
4535 if (mAncestorFrame
) {
4536 mAncestorFrame
->RemoveDisplayItem(this);
4540 NS_DISPLAY_DECL_NAME("TableBackgroundColor", TYPE_TABLE_BACKGROUND_COLOR
)
4542 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4544 void RemoveFrame(nsIFrame
* aFrame
) override
{
4545 if (aFrame
== mAncestorFrame
) {
4546 mAncestorFrame
= nullptr;
4549 nsDisplayBackgroundColor::RemoveFrame(aFrame
);
4552 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
{
4557 nsIFrame
* mAncestorFrame
;
4561 * The standard display item to paint the outer CSS box-shadows of a frame.
4563 class nsDisplayBoxShadowOuter final
: public nsPaintedDisplayItem
{
4565 nsDisplayBoxShadowOuter(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4566 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4567 MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter
);
4568 mBounds
= GetBoundsInternal();
4571 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowOuter
)
4573 NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER
)
4575 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4576 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4577 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
4578 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4579 const nsDisplayItemGeometry
* aGeometry
,
4580 nsRegion
* aInvalidRegion
) const override
;
4582 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4583 nsDisplayListBuilder
* aBuilder
) const override
{
4584 return CanBuildWebRenderDisplayItems();
4587 bool CanBuildWebRenderDisplayItems() const;
4588 bool CreateWebRenderCommands(
4589 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4590 const StackingContextHelper
& aSc
,
4591 layers::RenderRootStateManager
* aManager
,
4592 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4593 nsRect
GetBoundsInternal();
4600 * The standard display item to paint the inner CSS box-shadows of a frame.
4602 class nsDisplayBoxShadowInner
: public nsPaintedDisplayItem
{
4604 nsDisplayBoxShadowInner(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4605 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4606 MOZ_COUNT_CTOR(nsDisplayBoxShadowInner
);
4609 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowInner
)
4611 NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER
)
4613 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4615 nsDisplayItemGeometry
* AllocateGeometry(
4616 nsDisplayListBuilder
* aBuilder
) override
{
4617 return new nsDisplayBoxShadowInnerGeometry(this, aBuilder
);
4620 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4621 const nsDisplayItemGeometry
* aGeometry
,
4622 nsRegion
* aInvalidRegion
) const override
{
4623 const nsDisplayBoxShadowInnerGeometry
* geometry
=
4624 static_cast<const nsDisplayBoxShadowInnerGeometry
*>(aGeometry
);
4625 if (!geometry
->mPaddingRect
.IsEqualInterior(GetPaddingRect())) {
4626 // nsDisplayBoxShadowInner is based around the padding rect, but it can
4627 // touch pixels outside of this. We should invalidate the entire bounds.
4629 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &snap
));
4633 static bool CanCreateWebRenderCommands(nsDisplayListBuilder
* aBuilder
,
4635 const nsPoint
& aReferenceOffset
);
4636 static void CreateInsetBoxShadowWebRenderCommands(
4637 wr::DisplayListBuilder
& aBuilder
, const StackingContextHelper
& aSc
,
4638 nsRect
& aVisibleRect
, nsIFrame
* aFrame
, const nsRect
& aBorderRect
);
4639 bool CreateWebRenderCommands(
4640 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4641 const StackingContextHelper
& aSc
,
4642 layers::RenderRootStateManager
* aManager
,
4643 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4647 * The standard display item to paint the CSS outline of a frame.
4649 class nsDisplayOutline final
: public nsPaintedDisplayItem
{
4651 nsDisplayOutline(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4652 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4653 MOZ_COUNT_CTOR(nsDisplayOutline
);
4656 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOutline
)
4658 NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE
)
4660 bool ShouldUseBlobRenderingForFallback() const override
{
4661 MOZ_ASSERT(IsThemedOutline(),
4662 "The only fallback path we have is for themed outlines");
4663 return !XRE_IsParentProcess();
4666 bool CreateWebRenderCommands(
4667 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4668 const StackingContextHelper
& aSc
,
4669 layers::RenderRootStateManager
* aManager
,
4670 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4671 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
4672 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4673 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4676 nsRect
GetInnerRect() const;
4677 bool IsThemedOutline() const;
4678 bool HasRadius() const;
4682 * A class that lets you receive events within the frame bounds but never
4685 class nsDisplayEventReceiver final
: public nsDisplayItem
{
4687 nsDisplayEventReceiver(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4688 : nsDisplayItem(aBuilder
, aFrame
) {
4689 MOZ_COUNT_CTOR(nsDisplayEventReceiver
);
4692 MOZ_COUNTED_DTOR_FINAL(nsDisplayEventReceiver
)
4694 NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER
)
4696 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4697 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
;
4701 * Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
4702 * this gets built when we're doing widget painting and we need to send the
4703 * compositor some hit-test info for a frame. This is effectively a dummy item
4704 * whose sole purpose is to carry the hit-test info to the compositor.
4706 class nsDisplayCompositorHitTestInfo final
: public nsDisplayItem
{
4708 nsDisplayCompositorHitTestInfo(nsDisplayListBuilder
* aBuilder
,
4710 : nsDisplayItem(aBuilder
, aFrame
) {
4711 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
4712 mHitTestInfo
.Initialize(aBuilder
, aFrame
);
4713 SetHasHitTestInfo();
4716 nsDisplayCompositorHitTestInfo(
4717 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, const nsRect
& aArea
,
4718 const gfx::CompositorHitTestInfo
& aHitTestFlags
)
4719 : nsDisplayItem(aBuilder
, aFrame
) {
4720 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
4721 mHitTestInfo
.SetAreaAndInfo(aArea
, aHitTestFlags
);
4722 mHitTestInfo
.InitializeScrollTarget(aBuilder
);
4723 SetHasHitTestInfo();
4726 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo
)
4728 NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO
)
4730 bool CreateWebRenderCommands(
4731 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4732 const StackingContextHelper
& aSc
,
4733 layers::RenderRootStateManager
* aManager
,
4734 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4736 bool isInvisible() const { return true; }
4738 int32_t ZIndex() const override
;
4739 void SetOverrideZIndex(int32_t aZIndex
);
4741 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
4746 const HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
4749 HitTestInfo mHitTestInfo
;
4750 Maybe
<int32_t> mOverrideZIndex
;
4753 class nsDisplayWrapper
;
4756 * A class that lets you wrap a display list as a display item.
4758 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
4759 * list has many items, it's not clear which one has the 'underlying frame'.
4760 * Thus we force the creator to specify what the underlying frame is. The
4761 * underlying frame should be the root of a stacking context, because sorting
4762 * a list containing this item will not get at the children.
4764 * In some cases (e.g., clipping) we want to wrap a list but we don't have a
4765 * particular underlying frame that is a stacking context root. In that case
4766 * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
4767 * detect and handle this case.
4769 class nsDisplayWrapList
: public nsPaintedDisplayItem
{
4772 * Takes all the items from aList and puts them in our list.
4774 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4775 nsDisplayList
* aList
);
4777 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4778 nsDisplayItem
* aItem
);
4780 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4781 nsDisplayList
* aList
,
4782 const ActiveScrolledRoot
* aActiveScrolledRoot
,
4783 bool aClearClipChain
= false);
4785 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4786 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4788 mFrameActiveScrolledRoot(aBuilder
->CurrentActiveScrolledRoot()),
4790 mHasZIndexOverride(false) {
4791 MOZ_COUNT_CTOR(nsDisplayWrapList
);
4792 mBaseBuildingRect
= GetBuildingRect();
4794 mOriginalClipChain
= mClipChain
;
4797 nsDisplayWrapList() = delete;
4800 * A custom copy-constructor that does not copy mList, as this would mutate
4803 nsDisplayWrapList(const nsDisplayWrapList
& aOther
) = delete;
4804 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
,
4805 const nsDisplayWrapList
& aOther
)
4806 : nsPaintedDisplayItem(aBuilder
, aOther
),
4809 mFrameActiveScrolledRoot(aOther
.mFrameActiveScrolledRoot
),
4810 mMergedFrames(aOther
.mMergedFrames
.Clone()),
4811 mBounds(aOther
.mBounds
),
4812 mBaseBuildingRect(aOther
.mBaseBuildingRect
),
4813 mOriginalClipChain(aOther
.mClipChain
),
4814 mOverrideZIndex(aOther
.mOverrideZIndex
),
4815 mHasZIndexOverride(aOther
.mHasZIndexOverride
),
4816 mClearingClipChain(aOther
.mClearingClipChain
) {
4817 MOZ_COUNT_CTOR(nsDisplayWrapList
);
4820 ~nsDisplayWrapList() override
;
4822 const nsDisplayWrapList
* AsDisplayWrapList() const final
{ return this; }
4823 nsDisplayWrapList
* AsDisplayWrapList() final
{ return this; }
4825 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4826 mList
.DeleteAll(aBuilder
);
4827 nsPaintedDisplayItem::Destroy(aBuilder
);
4831 * Creates a new nsDisplayWrapper that holds a pointer to the display list
4832 * owned by the given nsDisplayItem.
4834 nsDisplayWrapper
* CreateShallowCopy(nsDisplayListBuilder
* aBuilder
);
4837 * Call this if the wrapped list is changed.
4839 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
{
4840 // Clear the clip chain up to the asr, but don't store it, so that we'll
4841 // recover it when we reuse the item.
4842 if (mClearingClipChain
) {
4843 const DisplayItemClipChain
* clip
= mOriginalClipChain
;
4844 while (clip
&& ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(),
4846 clip
= clip
->mParent
;
4848 SetClipChain(clip
, false);
4851 nsRect buildingRect
;
4852 mBounds
= mListPtr
->GetClippedBoundsWithRespectToASR(
4853 aBuilder
, mActiveScrolledRoot
, &buildingRect
);
4854 // The display list may contain content that's visible outside the visible
4855 // rect (i.e. the current dirty rect) passed in when the item was created.
4856 // This happens when the dirty rect has been restricted to the visual
4857 // overflow rect of a frame for some reason (e.g. when setting up dirty
4858 // rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
4859 // frame contains placeholders for out-of-flows that aren't descendants of
4861 buildingRect
.UnionRect(mBaseBuildingRect
, buildingRect
);
4862 SetBuildingRect(buildingRect
);
4865 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
4866 bool aStore
) override
{
4867 nsDisplayItem::SetClipChain(aClipChain
, aStore
);
4870 mOriginalClipChain
= mClipChain
;
4874 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4875 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4876 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4877 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4878 bool* aSnap
) const override
;
4879 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4882 * Try to merge with the other item (which is below us in the display
4883 * list). This gets used by nsDisplayClip to coalesce clipping operations
4884 * (optimization), by nsDisplayOpacity to merge rendering for the same
4885 * content element into a single opacity group (correctness), and will be
4886 * used by nsDisplayOutline to merge multiple outlines for the same element
4887 * (also for correctness).
4889 virtual void Merge(const nsDisplayItem
* aItem
) {
4890 MOZ_ASSERT(CanMerge(aItem
));
4891 MOZ_ASSERT(Frame() != aItem
->Frame());
4892 MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList
*>(aItem
));
4896 * Returns the underlying frames of all display items that have been
4897 * merged into this one (excluding this item's own underlying frame)
4900 const nsTArray
<nsIFrame
*>& GetMergedFrames() const { return mMergedFrames
; }
4902 bool HasMergedFrames() const { return !mMergedFrames
.IsEmpty(); }
4904 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
4908 bool IsInvalid(nsRect
& aRect
) const override
{
4909 if (mFrame
->IsInvalid(aRect
) && aRect
.IsEmpty()) {
4913 for (uint32_t i
= 0; i
< mMergedFrames
.Length(); i
++) {
4914 if (mMergedFrames
[i
]->IsInvalid(temp
) && temp
.IsEmpty()) {
4918 aRect
= aRect
.Union(temp
);
4920 aRect
+= ToReferenceFrame();
4921 return !aRect
.IsEmpty();
4924 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
4926 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
4930 RetainedDisplayList
* GetChildren() const override
{ return mListPtr
; }
4932 int32_t ZIndex() const override
{
4933 return (mHasZIndexOverride
) ? mOverrideZIndex
4934 : nsPaintedDisplayItem::ZIndex();
4937 void SetOverrideZIndex(int32_t aZIndex
) {
4938 mHasZIndexOverride
= true;
4939 mOverrideZIndex
= aZIndex
;
4943 * This creates a copy of this item, but wrapping aItem instead of
4944 * our existing list. Only gets called if this item returned nullptr
4945 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
4946 * GetUnderlyingFrame().
4948 nsDisplayWrapList
* WrapWithClone(nsDisplayListBuilder
* aBuilder
,
4949 nsDisplayItem
* aItem
) {
4950 MOZ_ASSERT_UNREACHABLE("We never returned nullptr for GetUnderlyingFrame!");
4954 bool CreateWebRenderCommands(
4955 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4956 const StackingContextHelper
& aSc
,
4957 layers::RenderRootStateManager
* aManager
,
4958 nsDisplayListBuilder
* aDisplayListBuilder
) override
{
4959 return CreateWebRenderCommandsNewClipListOption(
4960 aBuilder
, aResources
, aSc
, aManager
, aDisplayListBuilder
, true);
4963 // Same as the above but with the option to pass the aNewClipList argument to
4964 // WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList.
4965 bool CreateWebRenderCommandsNewClipListOption(
4966 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4967 const StackingContextHelper
& aSc
,
4968 layers::RenderRootStateManager
* aManager
,
4969 nsDisplayListBuilder
* aDisplayListBuilder
, bool aNewClipList
);
4971 const ActiveScrolledRoot
* GetFrameActiveScrolledRoot() {
4972 return mFrameActiveScrolledRoot
;
4976 void MergeFromTrackingMergedFrames(const nsDisplayWrapList
* aOther
) {
4977 mBounds
.UnionRect(mBounds
, aOther
->mBounds
);
4978 nsRect buildingRect
;
4979 buildingRect
.UnionRect(GetBuildingRect(), aOther
->GetBuildingRect());
4980 SetBuildingRect(buildingRect
);
4981 mMergedFrames
.AppendElement(aOther
->mFrame
);
4982 mMergedFrames
.AppendElements(aOther
->mMergedFrames
.Clone());
4985 RetainedDisplayList mList
;
4986 RetainedDisplayList
* mListPtr
;
4987 // The active scrolled root for the frame that created this
4989 RefPtr
<const ActiveScrolledRoot
> mFrameActiveScrolledRoot
;
4990 // The frames from items that have been merged into this item, excluding
4991 // this item's own frame.
4992 nsTArray
<nsIFrame
*> mMergedFrames
;
4994 // Displaylist building rect contributed by this display item itself.
4995 // Our mBuildingRect may include the visible areas of children.
4996 nsRect mBaseBuildingRect
;
4997 RefPtr
<const DisplayItemClipChain
> mOriginalClipChain
;
4998 int32_t mOverrideZIndex
;
4999 bool mHasZIndexOverride
;
5000 bool mClearingClipChain
= false;
5003 class nsDisplayWrapper
: public nsDisplayWrapList
{
5005 NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST
)
5007 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5008 nsDisplayList
* aList
,
5009 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5010 bool aClearClipChain
= false)
5011 : nsDisplayWrapList(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5014 nsDisplayWrapper(const nsDisplayWrapper
& aOther
) = delete;
5015 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
,
5016 const nsDisplayWrapList
& aOther
)
5017 : nsDisplayWrapList(aBuilder
, aOther
) {}
5019 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5022 NS_DISPLAY_ALLOW_CLONING()
5023 friend class nsDisplayListBuilder
;
5024 friend class nsDisplayWrapList
;
5028 * We call WrapDisplayList on the in-flow lists: BorderBackground(),
5029 * BlockBorderBackgrounds() and Content().
5030 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
5031 * and Floats(). This is done to support special wrapping processing for frames
5032 * that may not be in-flow descendants of the current frame.
5034 class nsDisplayItemWrapper
{
5036 // This is never instantiated directly (it has pure virtual methods), so no
5037 // need to count constructors and destructors.
5039 bool WrapBorderBackground() { return true; }
5040 virtual nsDisplayItem
* WrapList(nsDisplayListBuilder
* aBuilder
,
5041 nsIFrame
* aFrame
, nsDisplayList
* aList
) = 0;
5042 virtual nsDisplayItem
* WrapItem(nsDisplayListBuilder
* aBuilder
,
5043 nsDisplayItem
* aItem
) = 0;
5045 nsresult
WrapLists(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5046 const nsDisplayListSet
& aIn
, const nsDisplayListSet
& aOut
);
5047 nsresult
WrapListsInPlace(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5048 const nsDisplayListSet
& aLists
);
5051 nsDisplayItemWrapper() = default;
5055 * The standard display item to paint a stacking context with translucency
5056 * set by the stacking context root frame's 'opacity' style.
5058 class nsDisplayOpacity
: public nsDisplayWrapList
{
5060 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5061 nsDisplayList
* aList
,
5062 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5063 bool aForEventsOnly
, bool aNeedsActiveLayer
,
5064 bool aWrapsBackdropFilter
);
5066 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
,
5067 const nsDisplayOpacity
& aOther
)
5068 : nsDisplayWrapList(aBuilder
, aOther
),
5069 mOpacity(aOther
.mOpacity
),
5070 mForEventsOnly(aOther
.mForEventsOnly
),
5071 mNeedsActiveLayer(aOther
.mNeedsActiveLayer
),
5072 mChildOpacityState(ChildOpacityState::Unknown
),
5073 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
5074 MOZ_COUNT_CTOR(nsDisplayOpacity
);
5075 // We should not try to merge flattened opacities.
5076 MOZ_ASSERT(aOther
.mChildOpacityState
!= ChildOpacityState::Applied
);
5079 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5080 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5082 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOpacity
)
5084 NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY
)
5086 void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) override
{
5087 mChildOpacityState
= ChildOpacityState::Unknown
;
5090 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5091 bool* aSnap
) const override
;
5092 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5094 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5095 // items for the same content element should be merged into a single
5096 // compositing group
5097 // aItem->GetUnderlyingFrame() returns non-null because it's
5099 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5100 HasSameContent(aItem
);
5103 nsDisplayItemGeometry
* AllocateGeometry(
5104 nsDisplayListBuilder
* aBuilder
) override
{
5105 return new nsDisplayOpacityGeometry(this, aBuilder
, mOpacity
);
5108 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5109 const nsDisplayItemGeometry
* aGeometry
,
5110 nsRegion
* aInvalidRegion
) const override
;
5112 bool IsInvalid(nsRect
& aRect
) const override
{
5113 if (mForEventsOnly
) {
5116 return nsDisplayWrapList::IsInvalid(aRect
);
5118 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
5119 nsDisplayListBuilder
* aBuilder
) const override
;
5120 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5124 bool CanApplyOpacityToChildren(WebRenderLayerManager
* aManager
,
5125 nsDisplayListBuilder
* aBuilder
,
5126 float aInheritedOpacity
);
5128 bool NeedsGeometryUpdates() const override
{
5129 // For flattened nsDisplayOpacity items, ComputeInvalidationRegion() only
5130 // handles invalidation for changed |mOpacity|. In order to keep track of
5131 // the current bounds of the item for invalidation, nsDisplayOpacityGeometry
5132 // for the corresponding DisplayItemData needs to be updated, even if the
5133 // reported invalidation region is empty.
5134 return mChildOpacityState
== ChildOpacityState::Deferred
;
5138 * Returns true if ShouldFlattenAway() applied opacity to children.
5140 bool OpacityAppliedToChildren() const {
5141 return mChildOpacityState
== ChildOpacityState::Applied
;
5144 static bool NeedsActiveLayer(nsDisplayListBuilder
* aBuilder
,
5146 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5147 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
5148 bool CreateWebRenderCommands(
5149 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5150 const StackingContextHelper
& aSc
,
5151 layers::RenderRootStateManager
* aManager
,
5152 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5154 float GetOpacity() const { return mOpacity
; }
5156 bool CreatesStackingContextHelper() override
{ return true; }
5159 NS_DISPLAY_ALLOW_CLONING()
5161 bool CanApplyToChildren(WebRenderLayerManager
* aManager
,
5162 nsDisplayListBuilder
* aBuilder
);
5166 bool mForEventsOnly
: 1;
5167 enum class ChildOpacityState
: uint8_t {
5168 // Our child list has changed since the last time ApplyToChildren was
5171 // Our children defer opacity handling to us.
5173 // Opacity is applied to our children.
5176 bool mNeedsActiveLayer
: 1;
5178 ChildOpacityState mChildOpacityState
: 2;
5180 ChildOpacityState mChildOpacityState
;
5182 bool mWrapsBackdropFilter
;
5185 class nsDisplayBlendMode
: public nsDisplayWrapList
{
5187 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5188 nsDisplayList
* aList
, StyleBlend aBlendMode
,
5189 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5190 const bool aIsForBackground
);
5191 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
,
5192 const nsDisplayBlendMode
& aOther
)
5193 : nsDisplayWrapList(aBuilder
, aOther
),
5194 mBlendMode(aOther
.mBlendMode
),
5195 mIsForBackground(aOther
.mIsForBackground
) {
5196 MOZ_COUNT_CTOR(nsDisplayBlendMode
);
5199 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendMode
)
5201 NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE
)
5203 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5204 bool* aSnap
) const override
;
5205 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5206 const nsDisplayItemGeometry
* aGeometry
,
5207 nsRegion
* aInvalidRegion
) const override
{
5208 // We don't need to compute an invalidation region since we have
5209 // LayerTreeInvalidation
5212 bool CreateWebRenderCommands(
5213 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5214 const StackingContextHelper
& aSc
,
5215 layers::RenderRootStateManager
* aManager
,
5216 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5217 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5219 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
5221 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5225 gfx::CompositionOp
BlendMode();
5227 bool CreatesStackingContextHelper() override
{ return true; }
5230 StyleBlend mBlendMode
;
5231 bool mIsForBackground
;
5234 NS_DISPLAY_ALLOW_CLONING()
5237 class nsDisplayTableBlendMode
: public nsDisplayBlendMode
{
5239 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5240 nsDisplayList
* aList
, StyleBlend aBlendMode
,
5241 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5242 nsIFrame
* aAncestorFrame
, const bool aIsForBackground
)
5243 : nsDisplayBlendMode(aBuilder
, aFrame
, aList
, aBlendMode
,
5244 aActiveScrolledRoot
, aIsForBackground
),
5245 mAncestorFrame(aAncestorFrame
) {
5246 if (aBuilder
->IsRetainingDisplayList()) {
5247 mAncestorFrame
->AddDisplayItem(this);
5251 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
,
5252 const nsDisplayTableBlendMode
& aOther
)
5253 : nsDisplayBlendMode(aBuilder
, aOther
),
5254 mAncestorFrame(aOther
.mAncestorFrame
) {
5255 if (aBuilder
->IsRetainingDisplayList()) {
5256 mAncestorFrame
->AddDisplayItem(this);
5260 ~nsDisplayTableBlendMode() override
{
5261 if (mAncestorFrame
) {
5262 mAncestorFrame
->RemoveDisplayItem(this);
5266 NS_DISPLAY_DECL_NAME("TableBlendMode", TYPE_TABLE_BLEND_MODE
)
5268 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5270 void RemoveFrame(nsIFrame
* aFrame
) override
{
5271 if (aFrame
== mAncestorFrame
) {
5272 mAncestorFrame
= nullptr;
5275 nsDisplayBlendMode::RemoveFrame(aFrame
);
5279 nsIFrame
* mAncestorFrame
;
5282 NS_DISPLAY_ALLOW_CLONING()
5285 class nsDisplayBlendContainer
: public nsDisplayWrapList
{
5287 static nsDisplayBlendContainer
* CreateForMixBlendMode(
5288 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5289 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5291 static nsDisplayBlendContainer
* CreateForBackgroundBlendMode(
5292 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5293 nsIFrame
* aSecondaryFrame
, nsDisplayList
* aList
,
5294 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5296 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendContainer
)
5298 NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER
)
5300 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5301 bool CreateWebRenderCommands(
5302 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5303 const StackingContextHelper
& aSc
,
5304 layers::RenderRootStateManager
* aManager
,
5305 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5307 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5308 // Items for the same content element should be merged into a single
5309 // compositing group.
5310 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5311 HasSameContent(aItem
) &&
5313 static_cast<const nsDisplayBlendContainer
*>(aItem
)
5317 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5321 bool CreatesStackingContextHelper() override
{ return true; }
5324 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5325 nsDisplayList
* aList
,
5326 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5327 bool aIsForBackground
);
5328 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
,
5329 const nsDisplayBlendContainer
& aOther
)
5330 : nsDisplayWrapList(aBuilder
, aOther
),
5331 mIsForBackground(aOther
.mIsForBackground
) {
5332 MOZ_COUNT_CTOR(nsDisplayBlendContainer
);
5335 // Used to distinguish containers created at building stacking
5336 // context or appending background.
5337 bool mIsForBackground
;
5340 NS_DISPLAY_ALLOW_CLONING()
5343 class nsDisplayTableBlendContainer
: public nsDisplayBlendContainer
{
5345 NS_DISPLAY_DECL_NAME("TableBlendContainer", TYPE_TABLE_BLEND_CONTAINER
)
5347 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5349 void RemoveFrame(nsIFrame
* aFrame
) override
{
5350 if (aFrame
== mAncestorFrame
) {
5351 mAncestorFrame
= nullptr;
5354 nsDisplayBlendContainer::RemoveFrame(aFrame
);
5358 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5359 nsDisplayList
* aList
,
5360 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5361 bool aIsForBackground
, nsIFrame
* aAncestorFrame
)
5362 : nsDisplayBlendContainer(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5364 mAncestorFrame(aAncestorFrame
) {
5365 if (aBuilder
->IsRetainingDisplayList()) {
5366 mAncestorFrame
->AddDisplayItem(this);
5370 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
,
5371 const nsDisplayTableBlendContainer
& aOther
)
5372 : nsDisplayBlendContainer(aBuilder
, aOther
),
5373 mAncestorFrame(aOther
.mAncestorFrame
) {}
5375 ~nsDisplayTableBlendContainer() override
{
5376 if (mAncestorFrame
) {
5377 mAncestorFrame
->RemoveDisplayItem(this);
5381 nsIFrame
* mAncestorFrame
;
5384 NS_DISPLAY_ALLOW_CLONING()
5388 * nsDisplayOwnLayer constructor flags. If we nest this class inside
5389 * nsDisplayOwnLayer then we can't forward-declare it up at the top of this
5390 * file and that makes it hard to use in all the places that we need to use it.
5392 enum class nsDisplayOwnLayerFlags
{
5394 GenerateSubdocInvalidations
= 1 << 0,
5395 GenerateScrollableLayer
= 1 << 1,
5398 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags
)
5401 * A display item that has no purpose but to ensure its contents get
5404 class nsDisplayOwnLayer
: public nsDisplayWrapList
{
5407 OwnLayerForTransformWithRoundedClip
,
5408 OwnLayerForStackingContext
,
5409 OwnLayerForScrollbar
,
5410 OwnLayerForScrollThumb
,
5416 * @param aFlags eGenerateSubdocInvalidations :
5417 * Add UserData to the created ContainerLayer, so that invalidations
5418 * for this layer are send to our nsPresContext.
5419 * eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and
5420 * subclasses), indicates this layer is to be a scrollable layer, so call
5421 * ComputeFrameMetrics, etc.
5422 * @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar
5423 * is set in the flags, this parameter should be the ViewID of the
5424 * scrollable content this scrollbar is for.
5427 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5428 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5429 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
,
5430 const layers::ScrollbarData
& aScrollbarData
= layers::ScrollbarData
{},
5431 bool aForceActive
= true, bool aClearClipChain
= false);
5433 nsDisplayOwnLayer(nsDisplayListBuilder
* aBuilder
,
5434 const nsDisplayOwnLayer
& aOther
)
5435 : nsDisplayWrapList(aBuilder
, aOther
),
5436 mFlags(aOther
.mFlags
),
5437 mScrollbarData(aOther
.mScrollbarData
),
5438 mForceActive(aOther
.mForceActive
),
5439 mWrAnimationId(aOther
.mWrAnimationId
) {
5440 MOZ_COUNT_CTOR(nsDisplayOwnLayer
);
5443 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOwnLayer
)
5445 NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER
)
5447 bool CreateWebRenderCommands(
5448 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5449 const StackingContextHelper
& aSc
,
5450 layers::RenderRootStateManager
* aManager
,
5451 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5452 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5453 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5454 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5455 GetChildren()->Paint(aBuilder
, aCtx
,
5456 mFrame
->PresContext()->AppUnitsPerDevPixel());
5459 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5460 // Don't allow merging, each sublist must have its own layer
5464 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5468 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5469 nsDisplayOwnLayerFlags
GetFlags() { return mFlags
; }
5470 bool IsScrollThumbLayer() const;
5471 bool IsScrollbarContainer() const;
5472 bool IsRootScrollbarContainer() const;
5473 bool IsScrollbarLayerForRoot() const;
5474 bool IsZoomingLayer() const;
5475 bool IsFixedPositionLayer() const;
5476 bool IsStickyPositionLayer() const;
5477 bool HasDynamicToolbar() const;
5478 virtual bool ShouldGetFixedOrStickyAnimationId() { return false; }
5480 bool CreatesStackingContextHelper() override
{ return true; }
5483 nsDisplayOwnLayerFlags mFlags
;
5486 * If this nsDisplayOwnLayer represents a scroll thumb layer or a
5487 * scrollbar container layer, mScrollbarData stores information
5488 * about the scrollbar. Otherwise, mScrollbarData will be
5489 * default-constructed (in particular with mDirection == Nothing())
5490 * and can be ignored.
5492 layers::ScrollbarData mScrollbarData
;
5494 uint64_t mWrAnimationId
;
5498 * A display item for subdocuments. This is more or less the same as
5499 * nsDisplayOwnLayer, except that it always populates the FrameMetrics instance
5500 * on the ContainerLayer it builds.
5502 class nsDisplaySubDocument
: public nsDisplayOwnLayer
{
5504 nsDisplaySubDocument(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5505 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
5506 nsDisplayOwnLayerFlags aFlags
);
5507 ~nsDisplaySubDocument() override
;
5509 NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT
)
5511 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5513 virtual nsSubDocumentFrame
* SubDocumentFrame() { return mSubDocFrame
; }
5515 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5516 return mShouldFlatten
;
5519 void SetShouldFlattenAway(bool aShouldFlatten
) {
5520 mShouldFlatten
= aShouldFlatten
;
5523 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5524 bool* aSnap
) const override
;
5526 nsIFrame
* FrameForInvalidation() const override
;
5527 void RemoveFrame(nsIFrame
* aFrame
) override
;
5530 ViewID mScrollParentId
;
5531 bool mForceDispatchToContentRegion
{};
5532 bool mShouldFlatten
;
5533 nsSubDocumentFrame
* mSubDocFrame
;
5537 * A display item used to represent sticky position elements. The contents
5538 * gets its own layer and creates a stacking context, and the layer will have
5539 * position-related metadata set on it.
5541 class nsDisplayStickyPosition
: public nsDisplayOwnLayer
{
5543 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5544 nsDisplayList
* aList
,
5545 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5546 const ActiveScrolledRoot
* aContainerASR
,
5547 bool aClippedToDisplayPort
);
5548 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
,
5549 const nsDisplayStickyPosition
& aOther
)
5550 : nsDisplayOwnLayer(aBuilder
, aOther
),
5551 mContainerASR(aOther
.mContainerASR
),
5552 mClippedToDisplayPort(aOther
.mClippedToDisplayPort
),
5553 mShouldFlatten(false) {
5554 MOZ_COUNT_CTOR(nsDisplayStickyPosition
);
5557 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayStickyPosition
)
5559 const DisplayItemClip
& GetClip() const override
{
5560 return DisplayItemClip::NoClip();
5562 bool IsClippedToDisplayPort() const { return mClippedToDisplayPort
; }
5564 NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION
)
5565 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5566 GetChildren()->Paint(aBuilder
, aCtx
,
5567 mFrame
->PresContext()->AppUnitsPerDevPixel());
5570 bool CreateWebRenderCommands(
5571 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5572 const StackingContextHelper
& aSc
,
5573 layers::RenderRootStateManager
* aManager
,
5574 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5576 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5577 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5578 bool ShouldGetFixedOrStickyAnimationId() override
;
5580 const ActiveScrolledRoot
* GetContainerASR() const { return mContainerASR
; }
5582 bool CreatesStackingContextHelper() override
{ return true; }
5584 bool CanMoveAsync() override
{ return true; }
5586 void SetShouldFlatten(bool aShouldFlatten
) {
5587 mShouldFlatten
= aShouldFlatten
;
5590 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) final
{
5591 return mShouldFlatten
;
5595 NS_DISPLAY_ALLOW_CLONING()
5597 void CalculateLayerScrollRanges(StickyScrollContainer
* aStickyScrollContainer
,
5598 float aAppUnitsPerDevPixel
, float aScaleX
,
5600 LayerRectAbsolute
& aStickyOuter
,
5601 LayerRectAbsolute
& aStickyInner
);
5603 StickyScrollContainer
* GetStickyScrollContainer();
5605 // This stores the ASR that this sticky container item would have assuming it
5606 // has no fixed descendants. This may be the same as the ASR returned by
5607 // GetActiveScrolledRoot(), or it may be a descendant of that.
5608 RefPtr
<const ActiveScrolledRoot
> mContainerASR
;
5609 // This flag tracks if this sticky item is just clipped to the enclosing
5610 // scrollframe's displayport, or if there are additional clips in play. In
5611 // the former case, we can skip setting the displayport clip as the scrolled-
5612 // clip of the corresponding layer. This allows sticky items to remain
5613 // unclipped when the enclosing scrollframe is scrolled past the displayport.
5614 // i.e. when the rest of the scrollframe checkerboards, the sticky item will
5615 // not. This makes sense to do because the sticky item has abnormal scrolling
5616 // behavior and may still be visible even if the rest of the scrollframe is
5617 // checkerboarded. Note that the sticky item will still be subject to the
5619 bool mClippedToDisplayPort
;
5621 // True if this item should be flattened away.
5622 bool mShouldFlatten
;
5625 class nsDisplayFixedPosition
: public nsDisplayOwnLayer
{
5627 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5628 nsDisplayList
* aList
,
5629 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5630 const ActiveScrolledRoot
* aScrollTargetASR
);
5631 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
,
5632 const nsDisplayFixedPosition
& aOther
)
5633 : nsDisplayOwnLayer(aBuilder
, aOther
),
5634 mScrollTargetASR(aOther
.mScrollTargetASR
),
5635 mIsFixedBackground(aOther
.mIsFixedBackground
) {
5636 MOZ_COUNT_CTOR(nsDisplayFixedPosition
);
5639 static nsDisplayFixedPosition
* CreateForFixedBackground(
5640 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5641 nsIFrame
* aSecondaryFrame
, nsDisplayBackgroundImage
* aImage
,
5642 const uint16_t aIndex
, const ActiveScrolledRoot
* aScrollTargetASR
);
5644 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFixedPosition
)
5646 NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION
)
5648 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5649 GetChildren()->Paint(aBuilder
, aCtx
,
5650 mFrame
->PresContext()->AppUnitsPerDevPixel());
5653 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
5654 return mIsFixedBackground
;
5657 bool CreateWebRenderCommands(
5658 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5659 const StackingContextHelper
& aSc
,
5660 layers::RenderRootStateManager
* aManager
,
5661 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5662 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5663 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5664 bool ShouldGetFixedOrStickyAnimationId() override
;
5665 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5668 // For background-attachment:fixed
5669 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5670 nsDisplayList
* aList
,
5671 const ActiveScrolledRoot
* aScrollTargetASR
);
5672 ViewID
GetScrollTargetId() const;
5674 RefPtr
<const ActiveScrolledRoot
> mScrollTargetASR
;
5675 bool mIsFixedBackground
;
5678 NS_DISPLAY_ALLOW_CLONING()
5681 class nsDisplayTableFixedPosition
: public nsDisplayFixedPosition
{
5683 NS_DISPLAY_DECL_NAME("TableFixedPosition", TYPE_TABLE_FIXED_POSITION
)
5685 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5687 void RemoveFrame(nsIFrame
* aFrame
) override
{
5688 if (aFrame
== mAncestorFrame
) {
5689 mAncestorFrame
= nullptr;
5692 nsDisplayFixedPosition::RemoveFrame(aFrame
);
5696 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5697 nsDisplayList
* aList
, nsIFrame
* aAncestorFrame
,
5698 const ActiveScrolledRoot
* aScrollTargetASR
);
5700 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
,
5701 const nsDisplayTableFixedPosition
& aOther
)
5702 : nsDisplayFixedPosition(aBuilder
, aOther
),
5703 mAncestorFrame(aOther
.mAncestorFrame
) {}
5705 ~nsDisplayTableFixedPosition() override
{
5706 if (mAncestorFrame
) {
5707 mAncestorFrame
->RemoveDisplayItem(this);
5711 nsIFrame
* mAncestorFrame
;
5714 NS_DISPLAY_ALLOW_CLONING()
5718 * This creates an empty scrollable layer. It has no child layers.
5719 * It is used to record the existence of a scrollable frame in the layer
5722 class nsDisplayScrollInfoLayer
: public nsDisplayWrapList
{
5724 nsDisplayScrollInfoLayer(nsDisplayListBuilder
* aBuilder
,
5725 nsIFrame
* aScrolledFrame
, nsIFrame
* aScrollFrame
,
5726 const gfx::CompositorHitTestInfo
& aHitInfo
,
5727 const nsRect
& aHitArea
);
5729 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayScrollInfoLayer
)
5731 NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER
)
5733 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5734 bool* aSnap
) const override
{
5739 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5743 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5747 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5748 UniquePtr
<layers::ScrollMetadata
> ComputeScrollMetadata(
5749 nsDisplayListBuilder
* aBuilder
,
5750 layers::WebRenderLayerManager
* aLayerManager
);
5751 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5752 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5753 bool CreateWebRenderCommands(
5754 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5755 const StackingContextHelper
& aSc
,
5756 layers::RenderRootStateManager
* aManager
,
5757 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5760 nsIFrame
* mScrollFrame
;
5761 nsIFrame
* mScrolledFrame
;
5762 ViewID mScrollParentId
;
5763 gfx::CompositorHitTestInfo mHitInfo
;
5768 * nsDisplayZoom is used for subdocuments that have a different full zoom than
5769 * their parent documents. This item creates a container layer.
5771 class nsDisplayZoom
: public nsDisplaySubDocument
{
5774 * @param aFrame is the root frame of the subdocument.
5775 * @param aList contains the display items for the subdocument.
5776 * @param aAPD is the app units per dev pixel ratio of the subdocument.
5777 * @param aParentAPD is the app units per dev pixel ratio of the parent
5779 * @param aFlags eGenerateSubdocInvalidations :
5780 * Add UserData to the created ContainerLayer, so that invalidations
5781 * for this layer are send to our nsPresContext.
5783 nsDisplayZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5784 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
5785 int32_t aAPD
, int32_t aParentAPD
,
5786 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
);
5788 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayZoom
)
5790 NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM
)
5792 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5793 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5794 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5795 // Get the app units per dev pixel ratio of the child document.
5796 int32_t GetChildAppUnitsPerDevPixel() { return mAPD
; }
5797 // Get the app units per dev pixel ratio of the parent document.
5798 int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD
; }
5801 int32_t mAPD
, mParentAPD
;
5805 * nsDisplayAsyncZoom is used for APZ zooming. It wraps the contents of the
5806 * root content document's scroll frame, including fixed position content. It
5807 * does not contain the scroll frame's scrollbars. It is clipped to the scroll
5808 * frame's scroll port clip. It is not scrolled; only its non-fixed contents
5809 * are scrolled. This item creates a container layer.
5811 class nsDisplayAsyncZoom
: public nsDisplayOwnLayer
{
5813 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5814 nsDisplayList
* aList
,
5815 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5816 layers::FrameMetrics::ViewID aViewID
);
5817 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
,
5818 const nsDisplayAsyncZoom
& aOther
)
5819 : nsDisplayOwnLayer(aBuilder
, aOther
), mViewID(aOther
.mViewID
) {
5820 MOZ_COUNT_CTOR(nsDisplayAsyncZoom
);
5823 #ifdef NS_BUILD_REFCNT_LOGGING
5824 virtual ~nsDisplayAsyncZoom();
5827 NS_DISPLAY_DECL_NAME("AsyncZoom", TYPE_ASYNC_ZOOM
)
5829 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5830 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5831 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5832 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5835 layers::FrameMetrics::ViewID mViewID
;
5839 * A base class for different effects types.
5841 class nsDisplayEffectsBase
: public nsDisplayWrapList
{
5843 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5844 nsDisplayList
* aList
,
5845 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5846 bool aClearClipChain
= false);
5847 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5848 nsDisplayList
* aList
);
5850 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
,
5851 const nsDisplayEffectsBase
& aOther
)
5852 : nsDisplayWrapList(aBuilder
, aOther
),
5853 mEffectsBounds(aOther
.mEffectsBounds
) {
5854 MOZ_COUNT_CTOR(nsDisplayEffectsBase
);
5857 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayEffectsBase
)
5859 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5860 bool* aSnap
) const override
;
5861 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5862 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5864 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5868 gfxRect
BBoxInUserSpace() const;
5869 gfxPoint
UserSpaceOffset() const;
5871 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5872 const nsDisplayItemGeometry
* aGeometry
,
5873 nsRegion
* aInvalidRegion
) const override
;
5876 bool ValidateSVGFrame();
5878 // relative to mFrame
5879 nsRect mEffectsBounds
;
5883 * A display item to paint a stacking context with 'mask' and 'clip-path'
5884 * effects set by the stacking context root frame's style. The 'mask' and
5885 * 'clip-path' properties may both contain multiple masks and clip paths,
5888 * Note that 'mask' and 'clip-path' may just contain CSS simple-images and CSS
5889 * basic shapes, respectively. That is, they don't necessarily reference
5890 * resources such as SVG 'mask' and 'clipPath' elements.
5892 class nsDisplayMasksAndClipPaths
: public nsDisplayEffectsBase
{
5894 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5895 nsDisplayList
* aList
,
5896 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5897 bool aWrapsBackdropFilter
);
5898 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
,
5899 const nsDisplayMasksAndClipPaths
& aOther
)
5900 : nsDisplayEffectsBase(aBuilder
, aOther
),
5901 mDestRects(aOther
.mDestRects
.Clone()),
5902 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
5903 MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths
);
5906 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayMasksAndClipPaths
)
5908 NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK
)
5910 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
5912 void Merge(const nsDisplayItem
* aItem
) override
{
5913 nsDisplayWrapList::Merge(aItem
);
5915 const nsDisplayMasksAndClipPaths
* other
=
5916 static_cast<const nsDisplayMasksAndClipPaths
*>(aItem
);
5917 mEffectsBounds
.UnionRect(
5919 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
5922 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5924 nsDisplayItemGeometry
* AllocateGeometry(
5925 nsDisplayListBuilder
* aBuilder
) override
{
5926 return new nsDisplayMasksAndClipPathsGeometry(this, aBuilder
);
5929 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5930 const nsDisplayItemGeometry
* aGeometry
,
5931 nsRegion
* aInvalidRegion
) const override
;
5932 #ifdef MOZ_DUMP_PAINTING
5933 void PrintEffects(nsACString
& aTo
);
5938 void PaintWithContentsPaintCallback(
5939 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
5940 const std::function
<void()>& aPaintChildren
);
5943 * Paint mask onto aMaskContext in mFrame's coordinate space and
5944 * return whether the mask layer was painted successfully.
5946 bool PaintMask(nsDisplayListBuilder
* aBuilder
, gfxContext
* aMaskContext
,
5947 bool aHandleOpacity
, bool* aMaskPainted
= nullptr);
5949 const nsTArray
<nsRect
>& GetDestRects() { return mDestRects
; }
5951 bool CreateWebRenderCommands(
5952 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5953 const StackingContextHelper
& aSc
,
5954 layers::RenderRootStateManager
* aManager
,
5955 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5957 Maybe
<nsRect
> GetClipWithRespectToASR(
5958 nsDisplayListBuilder
* aBuilder
,
5959 const ActiveScrolledRoot
* aASR
) const override
;
5961 bool CreatesStackingContextHelper() override
{ return true; }
5964 NS_DISPLAY_ALLOW_CLONING()
5966 nsTArray
<nsRect
> mDestRects
;
5967 bool mWrapsBackdropFilter
;
5970 class nsDisplayBackdropFilters
: public nsDisplayWrapList
{
5972 nsDisplayBackdropFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5973 nsDisplayList
* aList
, const nsRect
& aBackdropRect
,
5974 nsIFrame
* aStyleFrame
)
5975 : nsDisplayWrapList(aBuilder
, aFrame
, aList
),
5976 mStyle(aFrame
== aStyleFrame
? nullptr : aStyleFrame
->Style()),
5977 mBackdropRect(aBackdropRect
) {
5978 MOZ_COUNT_CTOR(nsDisplayBackdropFilters
);
5981 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropFilters
)
5983 NS_DISPLAY_DECL_NAME("BackdropFilter", TYPE_BACKDROP_FILTER
)
5985 bool CreateWebRenderCommands(
5986 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5987 const StackingContextHelper
& aSc
,
5988 layers::RenderRootStateManager
* aManager
,
5989 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5990 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5992 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5993 return !aBuilder
->IsPaintingForWebRender();
5996 bool CreatesStackingContextHelper() override
{ return true; }
5998 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6001 RefPtr
<ComputedStyle
> mStyle
;
6002 nsRect mBackdropRect
;
6006 * A display item to paint a stacking context with filter effects set by the
6007 * stacking context root frame's style.
6009 * Note that the filters may just be simple CSS filter functions. That is,
6010 * they won't necessarily be references to SVG 'filter' elements.
6012 class nsDisplayFilters
: public nsDisplayEffectsBase
{
6014 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6015 nsDisplayList
* aList
, nsIFrame
* aStyleFrame
,
6016 bool aWrapsBackdropFilter
);
6018 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
,
6019 const nsDisplayFilters
& aOther
)
6020 : nsDisplayEffectsBase(aBuilder
, aOther
),
6021 mStyle(aOther
.mStyle
),
6022 mEffectsBounds(aOther
.mEffectsBounds
),
6023 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
6024 MOZ_COUNT_CTOR(nsDisplayFilters
);
6027 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFilters
)
6029 NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER
)
6031 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
6032 // Items for the same content element should be merged into a single
6033 // compositing group.
6034 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
6035 HasSameContent(aItem
);
6038 void Merge(const nsDisplayItem
* aItem
) override
{
6039 nsDisplayWrapList::Merge(aItem
);
6041 const nsDisplayFilters
* other
= static_cast<const nsDisplayFilters
*>(aItem
);
6042 mEffectsBounds
.UnionRect(
6044 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
6047 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6049 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
6051 return mEffectsBounds
+ ToReferenceFrame();
6054 nsDisplayItemGeometry
* AllocateGeometry(
6055 nsDisplayListBuilder
* aBuilder
) override
{
6056 return new nsDisplaySVGEffectGeometry(this, aBuilder
);
6059 #ifdef MOZ_DUMP_PAINTING
6060 void PrintEffects(nsACString
& aTo
);
6063 void PaintWithContentsPaintCallback(
6064 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6065 const std::function
<void(gfxContext
* aContext
)>& aPaintChildren
);
6067 bool CreateWebRenderCommands(
6068 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6069 const StackingContextHelper
& aSc
,
6070 layers::RenderRootStateManager
* aManager
,
6071 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6072 bool CanCreateWebRenderCommands() const;
6074 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
6075 nsDisplayListBuilder
* aBuilder
) const override
{
6076 return CanCreateWebRenderCommands();
6079 bool CreatesStackingContextHelper() override
{ return true; }
6082 NS_DISPLAY_ALLOW_CLONING()
6084 RefPtr
<ComputedStyle
> mStyle
;
6085 // relative to mFrame
6086 nsRect mEffectsBounds
;
6087 nsRect mVisibleRect
;
6088 bool mWrapsBackdropFilter
;
6091 /* A display item that applies a transformation to all of its descendant
6092 * elements. This wrapper should only be used if there is a transform applied
6093 * to the root element.
6095 * The reason that a "bounds" rect is involved in transform calculations is
6096 * because CSS-transforms allow percentage values for the x and y components
6097 * of <translation-value>s, where percentages are percentages of the element's
6100 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
6102 * INVARIANT: The wrapped frame is non-null.
6104 class nsDisplayTransform
: public nsPaintedDisplayItem
{
6105 using Matrix4x4
= gfx::Matrix4x4
;
6106 using Matrix4x4Flagged
= gfx::Matrix4x4Flagged
;
6107 using TransformReferenceBox
= nsStyleTransformMatrix::TransformReferenceBox
;
6110 enum class PrerenderDecision
: uint8_t { No
, Full
, Partial
};
6113 WithTransformGetter
,
6116 /* Constructor accepts a display list, empties it, and wraps it up. It also
6117 * ferries the underlying frame to the nsDisplayItem constructor.
6119 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6120 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
);
6122 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6123 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6124 PrerenderDecision aPrerenderDecision
);
6126 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6127 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6128 decltype(WithTransformGetter
));
6130 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayTransform
)
6132 NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM
)
6134 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
6137 * This function updates bounds for items with a frame establishing
6138 * 3D rendering context.
6140 void UpdateBoundsFor3D(nsDisplayListBuilder
* aBuilder
);
6142 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
;
6144 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
6145 GetChildren()->DeleteAll(aBuilder
);
6146 nsPaintedDisplayItem::Destroy(aBuilder
);
6149 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
6151 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
6153 nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
6154 bool* aSnap
) const override
{
6156 return mChildBounds
;
6159 const nsRect
& GetUntransformedPaintRect() const override
{
6160 return mChildrenBuildingRect
;
6163 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6165 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6166 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6167 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6168 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6169 bool* aSnap
) const override
;
6170 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6171 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6172 const Maybe
<gfx::Polygon
>& aPolygon
);
6173 bool CreateWebRenderCommands(
6174 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6175 const StackingContextHelper
& aSc
,
6176 layers::RenderRootStateManager
* aManager
,
6177 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6178 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
6179 layers::WebRenderLayerScrollData
* aLayerData
) override
;
6181 nsDisplayItemGeometry
* AllocateGeometry(
6182 nsDisplayListBuilder
* aBuilder
) override
{
6183 return new nsDisplayTransformGeometry(
6184 this, aBuilder
, GetTransformForRendering(),
6185 mFrame
->PresContext()->AppUnitsPerDevPixel());
6188 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6189 const nsDisplayItemGeometry
* aGeometry
,
6190 nsRegion
* aInvalidRegion
) const override
{
6191 const nsDisplayTransformGeometry
* geometry
=
6192 static_cast<const nsDisplayTransformGeometry
*>(aGeometry
);
6194 // This code is only called for flattened, inactive transform items.
6195 // Only check if the transform has changed. The bounds invalidation should
6196 // be handled by the children themselves.
6197 if (!geometry
->mTransform
.FuzzyEqual(GetTransformForRendering())) {
6199 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
6203 const nsIFrame
* ReferenceFrameForChildren() const override
{
6204 // If we were created using a transform-getter, then we don't
6205 // belong to a transformed frame, and aren't a reference frame
6206 // for our children.
6207 if (!mHasTransformGetter
) {
6210 return nsPaintedDisplayItem::ReferenceFrameForChildren();
6213 const nsRect
& GetBuildingRectForChildren() const override
{
6214 return mChildrenBuildingRect
;
6217 enum { INDEX_MAX
= UINT32_MAX
>> TYPE_BITS
};
6220 * We include the perspective matrix from our containing block for the
6221 * purposes of visibility calculations, but we exclude it from the transform
6222 * we set on the layer (for rendering), since there will be an
6223 * nsDisplayPerspective created for that.
6225 const Matrix4x4Flagged
& GetTransform() const;
6226 const Matrix4x4Flagged
& GetInverseTransform() const;
6228 bool ShouldSkipTransform(nsDisplayListBuilder
* aBuilder
) const;
6229 Matrix4x4
GetTransformForRendering(
6230 LayoutDevicePoint
* aOutOrigin
= nullptr) const;
6233 * Return the transform that is aggregation of all transform on the
6234 * preserves3d chain.
6236 const Matrix4x4
& GetAccumulatedPreserved3DTransform(
6237 nsDisplayListBuilder
* aBuilder
);
6239 float GetHitDepthAtPoint(nsDisplayListBuilder
* aBuilder
,
6240 const nsPoint
& aPoint
);
6242 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
6243 * space) and returns the smallest rectangle (in aFrame's coordinate space)
6244 * containing the transformed image of that rectangle. That is, it takes
6245 * the four corners of the rectangle, transforms them according to the
6246 * matrix associated with the specified frame, then returns the smallest
6247 * rectangle containing the four transformed points.
6249 * @param untransformedBounds The rectangle (in app units) to transform.
6250 * @param aFrame The frame whose transformation should be applied. This
6251 * function raises an assertion if aFrame is null or doesn't have a
6252 * transform applied to it.
6253 * @param aRefBox the reference box to use, which would usually be just
6254 * TransformReferemceBox(aFrame), but callers may override it if
6257 static nsRect
TransformRect(const nsRect
& aUntransformedBounds
,
6258 const nsIFrame
* aFrame
,
6259 TransformReferenceBox
& aRefBox
);
6261 /* UntransformRect is like TransformRect, except that it inverts the
6264 static bool UntransformRect(const nsRect
& aTransformedBounds
,
6265 const nsRect
& aChildBounds
,
6266 const nsIFrame
* aFrame
, nsRect
* aOutRect
);
6267 static bool UntransformRect(const nsRect
& aTransformedBounds
,
6268 const nsRect
& aChildBounds
,
6269 const Matrix4x4
& aMatrix
, float aAppUnitsPerPixel
,
6272 bool UntransformRect(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6273 nsRect
* aOutRect
) const;
6275 bool UntransformBuildingRect(nsDisplayListBuilder
* aBuilder
,
6276 nsRect
* aOutRect
) const {
6277 return UntransformRect(aBuilder
, GetBuildingRect(), aOutRect
);
6280 static gfx::Point3D
GetDeltaToTransformOrigin(const nsIFrame
* aFrame
,
6281 TransformReferenceBox
&,
6282 float aAppUnitsPerPixel
);
6285 * Returns true if aFrame has perspective applied from its containing
6287 * Returns the matrix to append to apply the persective (taking
6288 * perspective-origin into account), relative to aFrames coordinate
6290 * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
6293 static bool ComputePerspectiveMatrix(const nsIFrame
* aFrame
,
6294 float aAppUnitsPerPixel
,
6295 Matrix4x4
& aOutMatrix
);
6297 struct MOZ_STACK_CLASS FrameTransformProperties
{
6298 FrameTransformProperties(const nsIFrame
* aFrame
,
6299 TransformReferenceBox
& aRefBox
,
6300 float aAppUnitsPerPixel
);
6301 FrameTransformProperties(const StyleTranslate
& aTranslate
,
6302 const StyleRotate
& aRotate
,
6303 const StyleScale
& aScale
,
6304 const StyleTransform
& aTransform
,
6305 const Maybe
<ResolvedMotionPathData
>& aMotion
,
6306 const gfx::Point3D
& aToTransformOrigin
)
6308 mTranslate(aTranslate
),
6311 mTransform(aTransform
),
6313 mToTransformOrigin(aToTransformOrigin
) {}
6315 bool HasTransform() const {
6316 return !mTranslate
.IsNone() || !mRotate
.IsNone() || !mScale
.IsNone() ||
6317 !mTransform
.IsNone() || mMotion
.isSome();
6320 const nsIFrame
* mFrame
;
6321 const StyleTranslate
& mTranslate
;
6322 const StyleRotate
& mRotate
;
6323 const StyleScale
& mScale
;
6324 const StyleTransform
& mTransform
;
6325 const Maybe
<ResolvedMotionPathData
> mMotion
;
6326 const gfx::Point3D mToTransformOrigin
;
6330 * Given a frame with the transform property or an SVG transform,
6331 * returns the transformation matrix for that frame.
6333 * @param aFrame The frame to get the matrix from.
6334 * @param aOrigin Relative to which point this transform should be applied.
6335 * @param aAppUnitsPerPixel The number of app units per graphics unit.
6336 * @param aBoundsOverride [optional] If this is nullptr (the default), the
6337 * computation will use the value of TransformReferenceBox(aFrame).
6338 * Otherwise, it will use the value of aBoundsOverride. This is
6339 * mostly for internal use and in most cases you will not need to
6341 * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
6342 * by aOrigin. This translation is applied *before* the CSS transform.
6343 * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
6344 * include the transform of any ancestors participating in the same
6345 * 3d rendering context.
6346 * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
6347 * perspective transform from the containing block if applicable.
6350 OFFSET_BY_ORIGIN
= 1 << 0,
6351 INCLUDE_PRESERVE3D_ANCESTORS
= 1 << 1,
6352 INCLUDE_PERSPECTIVE
= 1 << 2,
6354 static constexpr uint32_t kTransformRectFlags
=
6355 INCLUDE_PERSPECTIVE
| OFFSET_BY_ORIGIN
| INCLUDE_PRESERVE3D_ANCESTORS
;
6356 static Matrix4x4
GetResultingTransformMatrix(const nsIFrame
* aFrame
,
6357 const nsPoint
& aOrigin
,
6358 float aAppUnitsPerPixel
,
6360 static Matrix4x4
GetResultingTransformMatrix(
6361 const FrameTransformProperties
& aProperties
, TransformReferenceBox
&,
6362 float aAppUnitsPerPixel
);
6364 struct PrerenderInfo
{
6365 bool CanUseAsyncAnimations() const {
6366 return mDecision
!= PrerenderDecision::No
&& mHasAnimations
;
6368 PrerenderDecision mDecision
= PrerenderDecision::No
;
6369 bool mHasAnimations
= true;
6372 * Decide whether we should prerender some or all of the contents of the
6373 * transformed frame even when it's not completely visible (yet).
6374 * Return PrerenderDecision::Full if the entire contents should be
6375 * prerendered, PrerenderDecision::Partial if some but not all of the
6376 * contents should be prerendered, or PrerenderDecision::No if only the
6377 * visible area should be rendered.
6378 * |mNoAffectDecisionInPreserve3D| is set if the prerender decision should not
6379 * affect the decision on other frames in the preserve 3d tree.
6380 * |aDirtyRect| is updated to the area that should be prerendered.
6382 static PrerenderInfo
ShouldPrerenderTransformedContent(
6383 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsRect
* aDirtyRect
);
6385 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
6387 bool MayBeAnimated(nsDisplayListBuilder
* aBuilder
) const;
6389 void WriteDebugInfo(std::stringstream
& aStream
) override
;
6391 bool CanMoveAsync() override
{
6392 return EffectCompositor::HasAnimationsForCompositor(
6393 mFrame
, DisplayItemType::TYPE_TRANSFORM
);
6397 * This item is an additional item as the boundary between parent
6398 * and child 3D rendering context.
6399 * \see nsIFrame::BuildDisplayListForStackingContext().
6401 bool IsTransformSeparator() const { return mIsTransformSeparator
; }
6403 * This item is the boundary between parent and child 3D rendering
6406 bool IsLeafOf3DContext() const {
6407 return (IsTransformSeparator() ||
6408 (!mFrame
->Extend3DContext() && Combines3DTransformWithAncestors()));
6411 * The backing frame of this item participates a 3D rendering
6414 bool IsParticipating3DContext() const {
6415 return mFrame
->Extend3DContext() || Combines3DTransformWithAncestors();
6418 bool IsPartialPrerender() const {
6419 return mPrerenderDecision
== PrerenderDecision::Partial
;
6423 * Mark this item as created together with `nsDisplayPerspective`.
6424 * \see nsIFrame::BuildDisplayListForStackingContext().
6426 void MarkWithAssociatedPerspective() { mHasAssociatedPerspective
= true; }
6428 void AddSizeOfExcludingThis(nsWindowSizes
&) const override
;
6430 bool CreatesStackingContextHelper() override
{ return true; }
6432 void SetContainsASRs(bool aContainsASRs
) { mContainsASRs
= aContainsASRs
; }
6433 bool GetContainsASRs() const { return mContainsASRs
; }
6434 bool ShouldDeferTransform() const {
6435 return !mFrame
->ChildrenHavePerspective() && !mContainsASRs
;
6439 void ComputeBounds(nsDisplayListBuilder
* aBuilder
);
6440 nsRect
TransformUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
6441 const Matrix4x4Flagged
& aMatrix
) const;
6442 void UpdateUntransformedBounds(nsDisplayListBuilder
* aBuilder
);
6444 void SetReferenceFrameToAncestor(nsDisplayListBuilder
* aBuilder
);
6445 void Init(nsDisplayListBuilder
* aBuilder
, nsDisplayList
* aChildren
);
6447 static Matrix4x4
GetResultingTransformMatrixInternal(
6448 const FrameTransformProperties
& aProperties
,
6449 TransformReferenceBox
& aRefBox
, const nsPoint
& aOrigin
,
6450 float aAppUnitsPerPixel
, uint32_t aFlags
);
6452 void Collect3DTransformLeaves(nsDisplayListBuilder
* aBuilder
,
6453 nsTArray
<nsDisplayTransform
*>& aLeaves
);
6454 using TransformPolygon
= layers::BSPPolygon
<nsDisplayTransform
>;
6455 void CollectSorted3DTransformLeaves(nsDisplayListBuilder
* aBuilder
,
6456 nsTArray
<TransformPolygon
>& aLeaves
);
6458 mutable RetainedDisplayList mChildren
;
6459 mutable Maybe
<Matrix4x4Flagged
> mTransform
;
6460 mutable Maybe
<Matrix4x4Flagged
> mInverseTransform
;
6461 // Accumulated transform of ancestors on the preserves-3d chain.
6462 UniquePtr
<Matrix4x4
> mTransformPreserves3D
;
6463 nsRect mChildrenBuildingRect
;
6465 // The untransformed bounds of |mChildren|.
6466 nsRect mChildBounds
;
6467 // The transformed bounds of this display item.
6469 PrerenderDecision mPrerenderDecision
: 8;
6470 // This item is a separator between 3D rendering contexts, and
6471 // mTransform have been presetted by the constructor.
6472 // This also forces us not to extend the 3D context. Since we don't create a
6473 // transform item, a container layer, for every frame in a preserves3d
6474 // context, the transform items of a child preserves3d context may extend the
6475 // parent context unintendedly if the root of the child preserves3d context
6476 // doesn't create a transform item.
6477 bool mIsTransformSeparator
: 1;
6478 // True if we have a transform getter.
6479 bool mHasTransformGetter
: 1;
6480 // True if this item is created together with `nsDisplayPerspective`
6481 // from the same CSS stacking context.
6482 bool mHasAssociatedPerspective
: 1;
6483 bool mContainsASRs
: 1;
6486 /* A display item that applies a perspective transformation to a single
6487 * nsDisplayTransform child item. We keep this as a separate item since the
6488 * perspective-origin is relative to an ancestor of the transformed frame, and
6489 * APZ can scroll the child separately.
6491 class nsDisplayPerspective
: public nsPaintedDisplayItem
{
6493 nsDisplayPerspective(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6494 nsDisplayList
* aList
);
6495 ~nsDisplayPerspective() override
= default;
6497 NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE
)
6499 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
6500 mList
.DeleteAll(aBuilder
);
6501 nsPaintedDisplayItem::Destroy(aBuilder
);
6504 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6505 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
{
6506 return GetChildren()->HitTest(aBuilder
, aRect
, aState
, aOutFrames
);
6509 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
6511 return GetChildren()->GetClippedBoundsWithRespectToASR(aBuilder
,
6512 mActiveScrolledRoot
);
6515 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6516 const nsDisplayItemGeometry
* aGeometry
,
6517 nsRegion
* aInvalidRegion
) const override
{}
6519 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6520 bool* aSnap
) const override
;
6522 bool CreateWebRenderCommands(
6523 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6524 const StackingContextHelper
& aSc
,
6525 layers::RenderRootStateManager
* aManager
,
6526 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6528 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6530 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
6534 RetainedDisplayList
* GetChildren() const override
{ return &mList
; }
6536 nsRect
GetComponentAlphaBounds(
6537 nsDisplayListBuilder
* aBuilder
) const override
{
6538 return GetChildren()->GetComponentAlphaBounds(aBuilder
);
6541 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
{
6542 if (GetChildren()->GetTop()) {
6543 static_cast<nsDisplayTransform
*>(GetChildren()->GetTop())
6544 ->DoUpdateBoundsPreserves3D(aBuilder
);
6548 bool CreatesStackingContextHelper() override
{ return true; }
6551 mutable RetainedDisplayList mList
;
6554 class nsDisplayTextGeometry
;
6557 * This class adds basic support for limiting the rendering (in the inline axis
6558 * of the writing mode) to the part inside the specified edges.
6559 * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
6560 * of the frame's scrollable overflow rectangle and are the amount to suppress
6563 * Setting none, both or only one edge is allowed.
6564 * The values must be non-negative.
6565 * The default value for both edges is zero, which means everything is painted.
6567 class nsDisplayText final
: public nsPaintedDisplayItem
{
6569 nsDisplayText(nsDisplayListBuilder
* aBuilder
, nsTextFrame
* aFrame
);
6570 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayText
)
6572 NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT
)
6574 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const final
{
6579 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6580 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
{
6581 if (nsRect(ToReferenceFrame(), mFrame
->GetSize()).Intersects(aRect
)) {
6582 aOutFrames
->AppendElement(mFrame
);
6586 bool CreateWebRenderCommands(wr::DisplayListBuilder
& aBuilder
,
6587 wr::IpcResourceUpdateQueue
& aResources
,
6588 const StackingContextHelper
& aSc
,
6589 layers::RenderRootStateManager
* aManager
,
6590 nsDisplayListBuilder
* aDisplayListBuilder
) final
;
6591 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) final
;
6593 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const final
{
6594 if (gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()) {
6595 // On OS X, web authors can turn off subpixel text rendering using the
6596 // CSS property -moz-osx-font-smoothing. If they do that, we don't need
6597 // to use component alpha layers for the affected text.
6598 if (mFrame
->StyleFont()->mFont
.smoothing
== NS_FONT_SMOOTHING_GRAYSCALE
) {
6603 return GetBounds(aBuilder
, &snap
);
6606 nsDisplayItemGeometry
* AllocateGeometry(nsDisplayListBuilder
* aBuilder
) final
;
6608 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6609 const nsDisplayItemGeometry
* aGeometry
,
6610 nsRegion
* aInvalidRegion
) const final
;
6612 void RenderToContext(gfxContext
* aCtx
, nsDisplayListBuilder
* aBuilder
,
6613 const nsRect
& aVisibleRect
, float aOpacity
= 1.0f
,
6614 bool aIsRecording
= false);
6616 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
6617 nsDisplayListBuilder
* aBuilder
) const final
;
6619 void WriteDebugInfo(std::stringstream
& aStream
) final
;
6621 static nsDisplayText
* CheckCast(nsDisplayItem
* aItem
) {
6622 return (aItem
->GetType() == DisplayItemType::TYPE_TEXT
)
6623 ? static_cast<nsDisplayText
*>(aItem
)
6627 nscoord
& VisIStartEdge() { return mVisIStartEdge
; }
6628 nscoord
& VisIEndEdge() { return mVisIEndEdge
; }
6632 nsRect mVisibleRect
;
6634 // Lengths measured from the visual inline start and end sides
6635 // (i.e. left and right respectively in horizontal writing modes,
6636 // regardless of bidi directionality; top and bottom in vertical modes).
6637 nscoord mVisIStartEdge
;
6638 nscoord mVisIEndEdge
;
6642 * A display item that for webrender to handle SVG
6644 class nsDisplaySVGWrapper
: public nsDisplayWrapList
{
6646 nsDisplaySVGWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6647 nsDisplayList
* aList
);
6649 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySVGWrapper
)
6651 NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER
)
6653 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6654 GetChildren()->Paint(aBuilder
, aCtx
,
6655 mFrame
->PresContext()->AppUnitsPerDevPixel());
6657 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6658 bool CreateWebRenderCommands(
6659 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6660 const StackingContextHelper
& aSc
,
6661 layers::RenderRootStateManager
* aManager
,
6662 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6666 * A display item for webrender to handle SVG foreign object
6668 class nsDisplayForeignObject
: public nsDisplayWrapList
{
6670 nsDisplayForeignObject(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6671 nsDisplayList
* aList
);
6672 #ifdef NS_BUILD_REFCNT_LOGGING
6673 virtual ~nsDisplayForeignObject();
6676 NS_DISPLAY_DECL_NAME("ForeignObject", TYPE_FOREIGN_OBJECT
)
6678 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6679 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6680 GetChildren()->Paint(aBuilder
, aCtx
,
6681 mFrame
->PresContext()->AppUnitsPerDevPixel());
6684 bool CreateWebRenderCommands(
6685 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6686 const StackingContextHelper
& aSc
,
6687 layers::RenderRootStateManager
* aManager
,
6688 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6692 * A display item to represent a hyperlink.
6694 class nsDisplayLink
: public nsPaintedDisplayItem
{
6696 nsDisplayLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6697 const char* aLinkSpec
, const nsRect
& aRect
)
6698 : nsPaintedDisplayItem(aBuilder
, aFrame
),
6699 mLinkSpec(aLinkSpec
),
6702 NS_DISPLAY_DECL_NAME("Link", TYPE_LINK
)
6704 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6707 nsCString mLinkSpec
;
6712 * A display item to represent a destination within the document.
6714 class nsDisplayDestination
: public nsPaintedDisplayItem
{
6716 nsDisplayDestination(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6717 const char* aDestinationName
, const nsPoint
& aPosition
)
6718 : nsPaintedDisplayItem(aBuilder
, aFrame
),
6719 mDestinationName(aDestinationName
),
6720 mPosition(aPosition
) {}
6722 NS_DISPLAY_DECL_NAME("Destination", TYPE_DESTINATION
)
6724 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6727 nsCString mDestinationName
;
6731 class MOZ_STACK_CLASS FlattenedDisplayListIterator
{
6733 FlattenedDisplayListIterator(nsDisplayListBuilder
* aBuilder
,
6734 nsDisplayList
* aList
)
6735 : mBuilder(aBuilder
), mStart(aList
->begin()), mEnd(aList
->end()) {
6736 ResolveFlattening();
6739 bool HasNext() const { return !AtEndOfCurrentList(); }
6741 nsDisplayItem
* GetNextItem() {
6742 MOZ_ASSERT(HasNext());
6744 nsDisplayItem
* current
= NextItem();
6747 if (!AtEndOfCurrentList() && current
->CanMerge(NextItem())) {
6748 // Since we can merge at least two display items, create an array and
6749 // collect mergeable display items there.
6750 AutoTArray
<nsDisplayItem
*, 2> willMerge
{current
};
6753 while (it
!= mEnd
) {
6754 nsDisplayItem
* next
= *it
;
6755 if (current
->CanMerge(next
)) {
6756 willMerge
.AppendElement(next
);
6764 current
= mBuilder
->MergeItems(willMerge
);
6767 ResolveFlattening();
6772 void Advance() { ++mStart
; }
6774 bool AtEndOfNestedList() const {
6775 return AtEndOfCurrentList() && mStack
.Length() > 0;
6778 bool AtEndOfCurrentList() const { return mStart
== mEnd
; }
6780 nsDisplayItem
* NextItem() {
6781 MOZ_ASSERT(HasNext());
6785 bool ShouldFlattenNextItem() {
6786 return HasNext() && NextItem()->ShouldFlattenAway(mBuilder
);
6789 void ResolveFlattening() {
6790 // Handle the case where we reach the end of a nested list, or the current
6791 // item should start a new nested list. Repeat this until we find an actual
6792 // item, or the very end of the outer list.
6793 while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
6794 if (AtEndOfNestedList()) {
6795 // We reached the end of the list, pop the next list from the stack.
6796 std::tie(mStart
, mEnd
) = mStack
.PopLastElement();
6798 // The next item wants to be flattened. This means that we will skip the
6799 // flattened item and directly iterate over its sublist.
6800 MOZ_ASSERT(ShouldFlattenNextItem());
6802 nsDisplayList
* sublist
= NextItem()->GetChildren();
6803 MOZ_ASSERT(sublist
);
6805 // Skip the flattened item.
6808 // Store the current position on the stack.
6809 if (!AtEndOfCurrentList()) {
6810 mStack
.AppendElement(std::make_pair(mStart
, mEnd
));
6813 // Iterate over the sublist.
6814 mStart
= sublist
->begin();
6815 mEnd
= sublist
->end();
6821 nsDisplayListBuilder
* mBuilder
;
6822 nsDisplayList::iterator mStart
;
6823 nsDisplayList::iterator mEnd
;
6824 AutoTArray
<std::pair
<nsDisplayList::iterator
, nsDisplayList::iterator
>, 3>
6828 class PaintTelemetry
{
6830 class AutoRecordPaint
{
6840 static uint32_t sPaintLevel
;
6843 } // namespace mozilla
6845 #endif /*NSDISPLAYLIST_H_*/