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 : mAccumulatedTransform(),
315 mAccumulatedRectLevels(0),
316 mVisibleRect(aOther
.mVisibleRect
),
317 mAllowAsyncAnimation(aOther
.mAllowAsyncAnimation
) {}
319 // Accmulate transforms of ancestors on the preserves-3d chain.
320 gfx::Matrix4x4 mAccumulatedTransform
;
321 // Accmulate visible rect of descendants in the preserves-3d context.
322 nsRect mAccumulatedRect
;
323 // How far this frame is from the root of the current 3d context.
324 int mAccumulatedRectLevels
;
326 // Allow async animation for this 3D context.
327 bool mAllowAsyncAnimation
;
331 using ViewID
= layers::ScrollableLayerGuid::ViewID
;
334 * @param aReferenceFrame the frame at the root of the subtree; its origin
335 * is the origin of the reference coordinate system for this display list
336 * @param aMode encodes what the builder is being used for.
337 * @param aBuildCaret whether or not we should include the caret in any
338 * display lists that we make.
340 nsDisplayListBuilder(nsIFrame
* aReferenceFrame
,
341 nsDisplayListBuilderMode aMode
, bool aBuildCaret
,
342 bool aRetainingDisplayList
= false);
343 ~nsDisplayListBuilder();
348 void AddTemporaryItem(nsDisplayItem
* aItem
) {
349 mTemporaryItems
.AppendElement(aItem
);
352 WindowRenderer
* GetWidgetWindowRenderer(nsView
** aView
= nullptr);
353 layers::WebRenderLayerManager
* GetWidgetLayerManager(
354 nsView
** aView
= nullptr);
357 * @return true if the display is being built in order to determine which
358 * frame is under the mouse position.
360 bool IsForEventDelivery() const {
361 return mMode
== nsDisplayListBuilderMode::EventDelivery
;
365 * @return true if the display list is being built for painting. This
366 * includes both painting to a window or other buffer and painting to
367 * a print/pdf destination.
369 bool IsForPainting() const {
370 return mMode
== nsDisplayListBuilderMode::Painting
||
371 mMode
== nsDisplayListBuilderMode::PaintForPrinting
;
375 * @return true if the display list is being built specifically for printing.
377 bool IsForPrinting() const {
378 return mMode
== nsDisplayListBuilderMode::PaintForPrinting
;
382 * @return true if the display list is being built for determining frame
385 bool IsForFrameVisibility() const {
386 return mMode
== nsDisplayListBuilderMode::FrameVisibility
;
390 * @return true if the display list is being built for creating the glyph
391 * mask from text items.
393 bool IsForGenerateGlyphMask() const {
394 return mMode
== nsDisplayListBuilderMode::GenerateGlyph
;
397 bool BuildCompositorHitTestInfo() const {
398 return mBuildCompositorHitTestInfo
;
402 * @return true if "painting is suppressed" during page load and we
403 * should paint only the background of the document.
405 bool IsBackgroundOnly() {
406 NS_ASSERTION(mPresShellStates
.Length() > 0,
407 "don't call this if we're not in a presshell");
408 return CurrentPresShellState()->mIsBackgroundOnly
;
412 * @return the root of given frame's (sub)tree, whose origin
413 * establishes the coordinate system for the child display items.
415 const nsIFrame
* FindReferenceFrameFor(const nsIFrame
* aFrame
,
416 nsPoint
* aOffset
= nullptr) const;
418 const Maybe
<nsPoint
>& AdditionalOffset() const { return mAdditionalOffset
; }
421 * @return the root of the display list's frame (sub)tree, whose origin
422 * establishes the coordinate system for the display list
424 nsIFrame
* RootReferenceFrame() const { return mReferenceFrame
; }
427 * @return a point pt such that adding pt to a coordinate relative to aFrame
428 * makes it relative to ReferenceFrame(), i.e., returns
429 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
430 * the appunits of aFrame.
432 const nsPoint
ToReferenceFrame(const nsIFrame
* aFrame
) const {
434 FindReferenceFrameFor(aFrame
, &result
);
438 * When building the display list, the scrollframe aFrame will be "ignored"
439 * for the purposes of clipping, and its scrollbars will be hidden. We use
440 * this to allow RenderOffscreen to render a whole document without beign
441 * clipped by the viewport or drawing the viewport scrollbars.
443 void SetIgnoreScrollFrame(nsIFrame
* aFrame
) { mIgnoreScrollFrame
= aFrame
; }
445 * Get the scrollframe to ignore, if any.
447 nsIFrame
* GetIgnoreScrollFrame() { return mIgnoreScrollFrame
; }
448 void SetIsRelativeToLayoutViewport();
449 bool IsRelativeToLayoutViewport() const {
450 return mIsRelativeToLayoutViewport
;
453 * Get the ViewID of the nearest scrolling ancestor frame.
455 ViewID
GetCurrentScrollParentId() const { return mCurrentScrollParentId
; }
457 * Get and set the flag that indicates if scroll parents should have layers
458 * forcibly created. This flag is set when a deeply nested scrollframe has
459 * a displayport, and for scroll handoff to work properly the ancestor
460 * scrollframes should also get their own scrollable layers.
462 void ForceLayerForScrollParent() { mForceLayerForScrollParent
= true; }
464 * Set the flag that indicates there is a non-minimal display port in the
465 * current subtree. This is used to determine display port expiry.
467 void SetContainsNonMinimalDisplayPort() {
468 mContainsNonMinimalDisplayPort
= true;
471 * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
472 * which we are building display items at the moment.
474 ViewID
GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget
; }
475 Maybe
<layers::ScrollDirection
> GetCurrentScrollbarDirection() const {
476 return mCurrentScrollbarDirection
;
479 * Returns true if building a scrollbar, and the scrollbar will not be
482 bool IsBuildingNonLayerizedScrollbar() const {
483 return mIsBuildingScrollbar
&& !mCurrentScrollbarWillHaveLayer
;
486 * Calling this setter makes us include all out-of-flow descendant
487 * frames in the display list, wherever they may be positioned (even
488 * outside the dirty rects).
490 void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows
= true; }
491 bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows
; }
493 * Calling this setter makes us exclude all leaf frames that aren't
496 void SetSelectedFramesOnly() { mSelectedFramesOnly
= true; }
497 bool GetSelectedFramesOnly() { return mSelectedFramesOnly
; }
499 * @return Returns true if we should include the caret in any display lists
502 bool IsBuildingCaret() const { return mBuildCaret
; }
504 bool IsRetainingDisplayList() const { return mRetainingDisplayList
; }
506 bool IsPartialUpdate() const { return mPartialUpdate
; }
507 void SetPartialUpdate(bool aPartial
) { mPartialUpdate
= aPartial
; }
509 bool IsBuilding() const { return mIsBuilding
; }
510 void SetIsBuilding(bool aIsBuilding
) { mIsBuilding
= aIsBuilding
; }
512 bool InInvalidSubtree() const { return mInInvalidSubtree
; }
515 * Allows callers to selectively override the regular paint suppression
516 * checks, so that methods like GetFrameForPoint work when painting is
519 void IgnorePaintSuppression() { mIgnoreSuppression
= true; }
521 * @return Returns if this builder will ignore paint suppression.
523 bool IsIgnoringPaintSuppression() { return mIgnoreSuppression
; }
525 * Call this if we're doing normal painting to the window.
527 void SetPaintingToWindow(bool aToWindow
) { mIsPaintingToWindow
= aToWindow
; }
528 bool IsPaintingToWindow() const { return mIsPaintingToWindow
; }
530 * Call this if we're using high quality scaling for image decoding.
531 * It is also implied by IsPaintingToWindow.
533 void SetUseHighQualityScaling(bool aUseHighQualityScaling
) {
534 mUseHighQualityScaling
= aUseHighQualityScaling
;
536 bool UseHighQualityScaling() const {
537 return mIsPaintingToWindow
|| mUseHighQualityScaling
;
540 * Call this if we're doing painting for WebRender
542 void SetPaintingForWebRender(bool aForWebRender
) {
543 mIsPaintingForWebRender
= true;
545 bool IsPaintingForWebRender() const { return mIsPaintingForWebRender
; }
547 * Call this to prevent descending into subdocuments.
549 void SetDescendIntoSubdocuments(bool aDescend
) {
550 mDescendIntoSubdocuments
= aDescend
;
553 bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments
; }
556 * Get dirty rect relative to current frame (the frame that we're calling
557 * BuildDisplayList on right now).
559 const nsRect
& GetVisibleRect() { return mVisibleRect
; }
560 const nsRect
& GetDirtyRect() { return mDirtyRect
; }
562 void SetVisibleRect(const nsRect
& aVisibleRect
) {
563 mVisibleRect
= aVisibleRect
;
566 void IntersectVisibleRect(const nsRect
& aVisibleRect
) {
567 mVisibleRect
.IntersectRect(mVisibleRect
, aVisibleRect
);
570 void SetDirtyRect(const nsRect
& aDirtyRect
) { mDirtyRect
= aDirtyRect
; }
572 void IntersectDirtyRect(const nsRect
& aDirtyRect
) {
573 mDirtyRect
.IntersectRect(mDirtyRect
, aDirtyRect
);
576 const nsIFrame
* GetCurrentFrame() { return mCurrentFrame
; }
577 const nsIFrame
* GetCurrentReferenceFrame() { return mCurrentReferenceFrame
; }
579 const nsPoint
& GetCurrentFrameOffsetToReferenceFrame() const {
580 return mCurrentOffsetToReferenceFrame
;
583 void Check() { mPool
.Check(); }
586 * Get the paint sequence number of the current paint.
588 static uint32_t GetPaintSequenceNumber() { return sPaintSequenceNumber
; }
591 * Increment the paint sequence number.
593 static void IncrementPaintSequenceNumber() { ++sPaintSequenceNumber
; }
596 * Returns true if merging and flattening of display lists should be
597 * performed while computing visibility.
599 bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening
; }
600 void SetAllowMergingAndFlattening(bool aAllow
) {
601 mAllowMergingAndFlattening
= aAllow
;
604 void SetCompositorHitTestInfo(const gfx::CompositorHitTestInfo
& aInfo
) {
605 mCompositorHitTestInfo
= aInfo
;
608 const gfx::CompositorHitTestInfo
& GetCompositorHitTestInfo() const {
609 return mCompositorHitTestInfo
;
613 * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
614 * needed, and adds it to the top of |aList|.
616 void BuildCompositorHitTestInfoIfNeeded(nsIFrame
* aFrame
,
617 nsDisplayList
* aList
);
619 bool IsInsidePointerEventsNoneDoc() {
620 return CurrentPresShellState()->mInsidePointerEventsNoneDoc
;
623 bool IsTouchEventPrefEnabledDoc() {
624 return CurrentPresShellState()->mTouchEventPrefEnabledDoc
;
627 bool GetAncestorHasApzAwareEventHandler() const {
628 return mAncestorHasApzAwareEventHandler
;
631 void SetAncestorHasApzAwareEventHandler(bool aValue
) {
632 mAncestorHasApzAwareEventHandler
= aValue
;
635 bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort
; }
636 void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort
= true; }
637 void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort
= false; }
639 bool SetIsCompositingCheap(bool aCompositingCheap
) {
640 bool temp
= mIsCompositingCheap
;
641 mIsCompositingCheap
= aCompositingCheap
;
645 bool IsCompositingCheap() const { return mIsCompositingCheap
; }
647 * Display the caret if needed.
649 bool DisplayCaret(nsIFrame
* aFrame
, nsDisplayList
* aList
) {
650 nsIFrame
* frame
= GetCaretFrame();
651 if (aFrame
== frame
&& !IsBackgroundOnly()) {
652 frame
->DisplayCaret(this, aList
);
658 * Get the frame that the caret is supposed to draw in.
659 * If the caret is currently invisible, this will be null.
661 nsIFrame
* GetCaretFrame() { return mCaretFrame
; }
663 * Get the rectangle we're supposed to draw the caret into.
665 const nsRect
& GetCaretRect() { return mCaretRect
; }
667 * Get the caret associated with the current presshell.
672 * Returns the root scroll frame for the current PresShell, if the PresShell
673 * is ignoring viewport scrolling.
675 nsIFrame
* GetPresShellIgnoreScrollFrame() {
676 return CurrentPresShellState()->mPresShellIgnoreScrollFrame
;
680 * Notify the display list builder that we're entering a presshell.
681 * aReferenceFrame should be a frame in the new presshell.
682 * aPointerEventsNoneDoc should be set to true if the frame generating this
683 * document is pointer-events:none.
685 void EnterPresShell(const nsIFrame
* aReferenceFrame
,
686 bool aPointerEventsNoneDoc
= false);
688 * For print-preview documents, we sometimes need to build display items for
689 * the same frames multiple times in the same presentation, with different
690 * clipping. Between each such batch of items, call
691 * ResetMarkedFramesForDisplayList to make sure that the results of
692 * MarkFramesForDisplayList do not carry over between batches.
694 void ResetMarkedFramesForDisplayList(const nsIFrame
* aReferenceFrame
);
696 * Notify the display list builder that we're leaving a presshell.
698 void LeavePresShell(const nsIFrame
* aReferenceFrame
,
699 nsDisplayList
* aPaintedContents
);
701 void IncrementPresShellPaintCount(PresShell
* aPresShell
);
704 * Returns true if we're currently building a display list that's
705 * directly or indirectly under an nsDisplayTransform.
707 bool IsInTransform() const { return mInTransform
; }
709 bool InEventsOnly() const { return mInEventsOnly
; }
711 * Indicate whether or not we're directly or indirectly under and
712 * nsDisplayTransform or SVG foreignObject.
714 void SetInTransform(bool aInTransform
) { mInTransform
= aInTransform
; }
717 * Returns true if we're currently building a display list that's
718 * under an nsDisplayFilters.
720 bool IsInFilter() const { return mInFilter
; }
723 * Return true if we're currently building a display list for a
726 bool IsInSubdocument() const { return mPresShellStates
.Length() > 1; }
728 void SetDisablePartialUpdates(bool aDisable
) {
729 mDisablePartialUpdates
= aDisable
;
731 bool DisablePartialUpdates() const { return mDisablePartialUpdates
; }
733 void SetPartialBuildFailed(bool aFailed
) { mPartialBuildFailed
= aFailed
; }
734 bool PartialBuildFailed() const { return mPartialBuildFailed
; }
736 bool IsInActiveDocShell() const { return mIsInActiveDocShell
; }
737 void SetInActiveDocShell(bool aActive
) { mIsInActiveDocShell
= aActive
; }
740 * Return true if we're currently building a display list for the presshell
741 * of a chrome document, or if we're building the display list for a popup.
743 bool IsInChromeDocumentOrPopup() const {
744 return mIsInChromePresContext
|| mIsBuildingForPopup
;
748 * @return true if images have been set to decode synchronously.
750 bool ShouldSyncDecodeImages() const { return mSyncDecodeImages
; }
753 * Indicates whether we should synchronously decode images. If true, we decode
754 * and draw whatever image data has been loaded. If false, we just draw
755 * whatever has already been decoded.
757 void SetSyncDecodeImages(bool aSyncDecodeImages
) {
758 mSyncDecodeImages
= aSyncDecodeImages
;
761 nsDisplayTableBackgroundSet
* SetTableBackgroundSet(
762 nsDisplayTableBackgroundSet
* aTableSet
) {
763 nsDisplayTableBackgroundSet
* old
= mTableBackgroundSet
;
764 mTableBackgroundSet
= aTableSet
;
767 nsDisplayTableBackgroundSet
* GetTableBackgroundSet() const {
768 return mTableBackgroundSet
;
771 void FreeClipChains();
774 * Frees the temporary display items created during merging.
776 void FreeTemporaryItems();
779 * Helper method to generate background painting flags based on the
780 * information available in the display list builder.
782 uint32_t GetBackgroundPaintFlags();
785 * Helper method to generate nsImageRenderer flags based on the information
786 * available in the display list builder.
788 uint32_t GetImageRendererFlags() const;
791 * Helper method to generate image decoding flags based on the
792 * information available in the display list builder.
794 uint32_t GetImageDecodeFlags() const;
797 * Subtracts aRegion from *aVisibleRegion. We avoid letting
798 * aVisibleRegion become overcomplex by simplifying it if necessary.
800 void SubtractFromVisibleRegion(nsRegion
* aVisibleRegion
,
801 const nsRegion
& aRegion
);
804 * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
805 * (which is relative to aDirtyFrame). If the frames have placeholders
806 * that might not be displayed, we mark the placeholders and their ancestors
807 * to ensure that display list construction descends into them
808 * anyway. nsDisplayListBuilder will take care of unmarking them when it is
811 void MarkFramesForDisplayList(nsIFrame
* aDirtyFrame
,
812 const nsFrameList
& aFrames
);
813 void MarkFrameForDisplay(nsIFrame
* aFrame
, const nsIFrame
* aStopAtFrame
);
814 void MarkFrameForDisplayIfVisible(nsIFrame
* aFrame
,
815 const nsIFrame
* aStopAtFrame
);
816 void AddFrameMarkedForDisplayIfVisible(nsIFrame
* aFrame
);
818 void ClearFixedBackgroundDisplayData();
820 * Mark all child frames that Preserve3D() as needing display.
821 * Because these frames include transforms set on their parent, dirty rects
822 * for intermediate frames may be empty, yet child frames could still be
825 void MarkPreserve3DFramesForDisplayList(nsIFrame
* aDirtyFrame
);
828 * Returns true if we need to descend into this frame when building
829 * the display list, even though it doesn't intersect the dirty
830 * rect, because it may have out-of-flows that do so.
832 bool ShouldDescendIntoFrame(nsIFrame
* aFrame
, bool aVisible
) const {
833 return aFrame
->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO
) ||
834 (aVisible
&& aFrame
->ForceDescendIntoIfVisible()) ||
835 GetIncludeAllOutOfFlows();
839 * Returns the list of registered theme geometries.
841 nsTArray
<nsIWidget::ThemeGeometry
> GetThemeGeometries() const {
842 nsTArray
<nsIWidget::ThemeGeometry
> geometries
;
844 for (const auto& data
: mThemeGeometries
.Values()) {
845 geometries
.AppendElements(*data
);
852 * Notifies the builder that a particular themed widget exists
853 * at the given rectangle within the currently built display list.
854 * For certain appearance values (currently only StyleAppearance::Toolbar and
855 * StyleAppearance::WindowTitlebar) this gets called during every display list
856 * construction, for every themed widget of the right type within the
857 * display list, except for themed widgets which are transformed or have
858 * effects applied to them (e.g. CSS opacity or filters).
860 * @param aWidgetType the -moz-appearance value for the themed widget
861 * @param aItem the item associated with the theme geometry
862 * @param aRect the device-pixel rect relative to the widget's displayRoot
863 * for the themed widget
865 void RegisterThemeGeometry(uint8_t aWidgetType
, nsDisplayItem
* aItem
,
866 const LayoutDeviceIntRect
& aRect
) {
867 if (!mIsPaintingToWindow
) {
871 nsTArray
<nsIWidget::ThemeGeometry
>* geometries
=
872 mThemeGeometries
.GetOrInsertNew(aItem
);
873 geometries
->AppendElement(nsIWidget::ThemeGeometry(aWidgetType
, aRect
));
877 * Removes theme geometries associated with the given display item |aItem|.
879 void UnregisterThemeGeometry(nsDisplayItem
* aItem
) {
880 mThemeGeometries
.Remove(aItem
);
884 * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
885 * -moz-window-dragging value is |drag|, its border box is added to the
886 * collected dragging region; if the value is |no-drag|, the border box is
887 * subtracted from the region; if the value is |default|, that frame does
888 * not influence the window dragging region.
890 void AdjustWindowDraggingRegion(nsIFrame
* aFrame
);
892 LayoutDeviceIntRegion
GetWindowDraggingRegion() const;
894 void RemoveModifiedWindowRegions();
895 void ClearRetainedWindowRegions();
897 const nsTHashMap
<nsPtrHashKey
<dom::RemoteBrowser
>, dom::EffectsInfo
>&
898 GetEffectUpdates() const {
899 return mEffectsUpdates
;
902 void AddEffectUpdate(dom::RemoteBrowser
* aBrowser
,
903 const dom::EffectsInfo
& aUpdate
);
906 * Allocate memory in our arena. It will only be freed when this display list
907 * builder is destroyed. This memory holds nsDisplayItems and
908 * DisplayItemClipChain objects.
910 * Destructors are called as soon as the item is no longer used.
912 void* Allocate(size_t aSize
, DisplayListArenaObjectId aId
) {
913 return mPool
.Allocate(aId
, aSize
);
915 void* Allocate(size_t aSize
, DisplayItemType aType
) {
916 #define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) \
917 static_assert(size_t(DisplayItemType::TYPE_##name_) == \
918 size_t(DisplayListArenaObjectId::name_), \
920 #include "nsDisplayItemTypesList.h"
921 static_assert(size_t(DisplayItemType::TYPE_MAX
) ==
922 size_t(DisplayListArenaObjectId::CLIPCHAIN
),
924 static_assert(size_t(DisplayItemType::TYPE_MAX
) + 1 ==
925 size_t(DisplayListArenaObjectId::LISTNODE
),
927 #undef DECLARE_DISPLAY_ITEM_TYPE
928 return Allocate(aSize
, DisplayListArenaObjectId(size_t(aType
)));
931 void Destroy(DisplayListArenaObjectId aId
, void* aPtr
) {
932 return mPool
.Free(aId
, aPtr
);
934 void Destroy(DisplayItemType aType
, void* aPtr
) {
935 return Destroy(DisplayListArenaObjectId(size_t(aType
)), aPtr
);
939 * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
940 * automatically when the arena goes away.
942 ActiveScrolledRoot
* AllocateActiveScrolledRoot(
943 const ActiveScrolledRoot
* aParent
, nsIScrollableFrame
* aScrollableFrame
);
946 * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
947 * up automatically when the arena goes away.
949 const DisplayItemClipChain
* AllocateDisplayItemClipChain(
950 const DisplayItemClip
& aClip
, const ActiveScrolledRoot
* aASR
,
951 const DisplayItemClipChain
* aParent
);
954 * Intersect two clip chains, allocating the new clip chain items in this
955 * builder's arena. The result is parented to aAncestor, and no intersections
956 * happen past aAncestor's ASR.
957 * That means aAncestor has to be living in this builder's arena already.
958 * aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
959 * their values are copied into the newly-allocated intersected clip chain
960 * and this function does not hold on to any pointers to them.
962 const DisplayItemClipChain
* CreateClipChainIntersection(
963 const DisplayItemClipChain
* aAncestor
,
964 const DisplayItemClipChain
* aLeafClip1
,
965 const DisplayItemClipChain
* aLeafClip2
);
968 * Same as above, except aAncestor is computed as the nearest common
969 * ancestor of the two provided clips.
971 const DisplayItemClipChain
* CreateClipChainIntersection(
972 const DisplayItemClipChain
* aLeafClip1
,
973 const DisplayItemClipChain
* aLeafClip2
);
976 * Clone the supplied clip chain's chain items into this builder's arena.
978 const DisplayItemClipChain
* CopyWholeChain(
979 const DisplayItemClipChain
* aClipChain
);
981 const ActiveScrolledRoot
* GetFilterASR() const { return mFilterASR
; }
984 * Merges the display items in |aMergedItems| and returns a new temporary
986 * The display items in |aMergedItems| have to be mergeable with each other.
988 nsDisplayWrapList
* MergeItems(nsTArray
<nsDisplayItem
*>& aItems
);
991 * A helper class used to temporarily set nsDisplayListBuilder properties for
992 * building display items.
993 * aVisibleRect and aDirtyRect are relative to aForChild.
995 class AutoBuildingDisplayList
{
997 AutoBuildingDisplayList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aForChild
,
998 const nsRect
& aVisibleRect
,
999 const nsRect
& aDirtyRect
)
1000 : AutoBuildingDisplayList(aBuilder
, aForChild
, aVisibleRect
, aDirtyRect
,
1001 aForChild
->IsTransformed()) {}
1003 AutoBuildingDisplayList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aForChild
,
1004 const nsRect
& aVisibleRect
,
1005 const nsRect
& aDirtyRect
,
1006 const bool aIsTransformed
);
1008 void SetReferenceFrameAndCurrentOffset(const nsIFrame
* aFrame
,
1009 const nsPoint
& aOffset
) {
1010 mBuilder
->mCurrentReferenceFrame
= aFrame
;
1011 mBuilder
->mCurrentOffsetToReferenceFrame
= aOffset
;
1014 void SetAdditionalOffset(const nsPoint
& aOffset
) {
1015 MOZ_ASSERT(!mBuilder
->mAdditionalOffset
);
1016 mBuilder
->mAdditionalOffset
= Some(aOffset
);
1018 mBuilder
->mCurrentOffsetToReferenceFrame
+= aOffset
;
1021 void RestoreBuildingInvisibleItemsValue() {
1022 mBuilder
->mBuildingInvisibleItems
= mPrevBuildingInvisibleItems
;
1025 ~AutoBuildingDisplayList() {
1026 mBuilder
->mCurrentFrame
= mPrevFrame
;
1027 mBuilder
->mCurrentReferenceFrame
= mPrevReferenceFrame
;
1028 mBuilder
->mCurrentOffsetToReferenceFrame
= mPrevOffset
;
1029 mBuilder
->mVisibleRect
= mPrevVisibleRect
;
1030 mBuilder
->mDirtyRect
= mPrevDirtyRect
;
1031 mBuilder
->mAncestorHasApzAwareEventHandler
=
1032 mPrevAncestorHasApzAwareEventHandler
;
1033 mBuilder
->mBuildingInvisibleItems
= mPrevBuildingInvisibleItems
;
1034 mBuilder
->mInInvalidSubtree
= mPrevInInvalidSubtree
;
1035 mBuilder
->mAdditionalOffset
= mPrevAdditionalOffset
;
1036 mBuilder
->mCompositorHitTestInfo
= mPrevCompositorHitTestInfo
;
1040 nsDisplayListBuilder
* mBuilder
;
1041 const nsIFrame
* mPrevFrame
;
1042 const nsIFrame
* mPrevReferenceFrame
;
1043 nsPoint mPrevOffset
;
1044 Maybe
<nsPoint
> mPrevAdditionalOffset
;
1045 nsRect mPrevVisibleRect
;
1046 nsRect mPrevDirtyRect
;
1047 gfx::CompositorHitTestInfo mPrevCompositorHitTestInfo
;
1048 bool mPrevAncestorHasApzAwareEventHandler
;
1049 bool mPrevBuildingInvisibleItems
;
1050 bool mPrevInInvalidSubtree
;
1054 * A helper class to temporarily set the value of mInTransform.
1056 class AutoInTransformSetter
{
1058 AutoInTransformSetter(nsDisplayListBuilder
* aBuilder
, bool aInTransform
)
1059 : mBuilder(aBuilder
), mOldValue(aBuilder
->mInTransform
) {
1060 aBuilder
->mInTransform
= aInTransform
;
1063 ~AutoInTransformSetter() { mBuilder
->mInTransform
= mOldValue
; }
1066 nsDisplayListBuilder
* mBuilder
;
1070 class AutoInEventsOnly
{
1072 AutoInEventsOnly(nsDisplayListBuilder
* aBuilder
, bool aInEventsOnly
)
1073 : mBuilder(aBuilder
), mOldValue(aBuilder
->mInEventsOnly
) {
1074 aBuilder
->mInEventsOnly
|= aInEventsOnly
;
1077 ~AutoInEventsOnly() { mBuilder
->mInEventsOnly
= mOldValue
; }
1080 nsDisplayListBuilder
* mBuilder
;
1085 * A helper class to temporarily set the value of mFilterASR and
1088 class AutoEnterFilter
{
1090 AutoEnterFilter(nsDisplayListBuilder
* aBuilder
, bool aUsingFilter
)
1091 : mBuilder(aBuilder
),
1092 mOldValue(aBuilder
->mFilterASR
),
1093 mOldInFilter(aBuilder
->mInFilter
) {
1094 if (!aBuilder
->mFilterASR
&& aUsingFilter
) {
1095 aBuilder
->mFilterASR
= aBuilder
->CurrentActiveScrolledRoot();
1096 aBuilder
->mInFilter
= true;
1100 ~AutoEnterFilter() {
1101 mBuilder
->mFilterASR
= mOldValue
;
1102 mBuilder
->mInFilter
= mOldInFilter
;
1106 nsDisplayListBuilder
* mBuilder
;
1107 const ActiveScrolledRoot
* mOldValue
;
1112 * Used to update the current active scrolled root on the display list
1113 * builder, and to create new active scrolled roots.
1115 class AutoCurrentActiveScrolledRootSetter
{
1117 explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder
* aBuilder
)
1118 : mBuilder(aBuilder
),
1119 mSavedActiveScrolledRoot(aBuilder
->mCurrentActiveScrolledRoot
),
1120 mContentClipASR(aBuilder
->ClipState().GetContentClipASR()),
1121 mDescendantsStartIndex(aBuilder
->mActiveScrolledRoots
.Length()),
1123 mOldScrollParentId(aBuilder
->mCurrentScrollParentId
),
1124 mOldForceLayer(aBuilder
->mForceLayerForScrollParent
),
1125 mOldContainsNonMinimalDisplayPort(
1126 mBuilder
->mContainsNonMinimalDisplayPort
),
1127 mCanBeScrollParent(false) {}
1129 void SetCurrentScrollParentId(ViewID aScrollId
) {
1130 // Update the old scroll parent id.
1131 mOldScrollParentId
= mBuilder
->mCurrentScrollParentId
;
1132 // If this AutoCurrentActiveScrolledRootSetter has the same aScrollId as
1133 // the previous one on the stack, then that means the scrollframe that
1134 // created this isn't actually scrollable and cannot participate in
1135 // scroll handoff. We set mCanBeScrollParent to false to indicate this.
1136 mCanBeScrollParent
= (mOldScrollParentId
!= aScrollId
);
1137 mBuilder
->mCurrentScrollParentId
= aScrollId
;
1138 mBuilder
->mForceLayerForScrollParent
= false;
1139 mBuilder
->mContainsNonMinimalDisplayPort
= false;
1142 bool ShouldForceLayerForScrollParent() const {
1143 // Only scrollframes participating in scroll handoff can be forced to
1145 return mCanBeScrollParent
&& mBuilder
->mForceLayerForScrollParent
;
1148 bool GetContainsNonMinimalDisplayPort() const {
1149 // Only for scrollframes participating in scroll handoff can we return
1151 return mCanBeScrollParent
&& mBuilder
->mContainsNonMinimalDisplayPort
;
1154 ~AutoCurrentActiveScrolledRootSetter() {
1155 mBuilder
->mCurrentActiveScrolledRoot
= mSavedActiveScrolledRoot
;
1156 mBuilder
->mCurrentScrollParentId
= mOldScrollParentId
;
1157 if (mCanBeScrollParent
) {
1158 // If this flag is set, caller code is responsible for having dealt
1159 // with the current value of mBuilder->mForceLayerForScrollParent, so
1160 // we can just restore the old value.
1161 mBuilder
->mForceLayerForScrollParent
= mOldForceLayer
;
1163 // Otherwise we need to keep propagating the force-layerization flag
1164 // upwards to the next ancestor scrollframe that does participate in
1166 mBuilder
->mForceLayerForScrollParent
|= mOldForceLayer
;
1168 mBuilder
->mContainsNonMinimalDisplayPort
|=
1169 mOldContainsNonMinimalDisplayPort
;
1172 void SetCurrentActiveScrolledRoot(
1173 const ActiveScrolledRoot
* aActiveScrolledRoot
);
1175 void EnterScrollFrame(nsIScrollableFrame
* aScrollableFrame
) {
1177 ActiveScrolledRoot
* asr
= mBuilder
->AllocateActiveScrolledRoot(
1178 mBuilder
->mCurrentActiveScrolledRoot
, aScrollableFrame
);
1179 mBuilder
->mCurrentActiveScrolledRoot
= asr
;
1183 void InsertScrollFrame(nsIScrollableFrame
* aScrollableFrame
);
1186 nsDisplayListBuilder
* mBuilder
;
1188 * The builder's mCurrentActiveScrolledRoot at construction time which
1189 * needs to be restored at destruction time.
1191 const ActiveScrolledRoot
* mSavedActiveScrolledRoot
;
1193 * If there's a content clip on the builder at construction time, then
1194 * mContentClipASR is that content clip's ASR, otherwise null. The
1195 * assumption is that the content clip doesn't get relaxed while this
1196 * object is on the stack.
1198 const ActiveScrolledRoot
* mContentClipASR
;
1200 * InsertScrollFrame needs to mutate existing ASRs (those that were
1201 * created while this object was on the stack), and mDescendantsStartIndex
1202 * makes it easier to skip ASRs that were created in the past.
1204 size_t mDescendantsStartIndex
;
1206 * Flag to make sure that only one of SetCurrentActiveScrolledRoot /
1207 * EnterScrollFrame / InsertScrollFrame is called per instance of this
1211 ViewID mOldScrollParentId
;
1212 bool mOldForceLayer
;
1213 bool mOldContainsNonMinimalDisplayPort
;
1214 bool mCanBeScrollParent
;
1218 * Keeps track of the innermost ASR that can be used as the ASR for a
1219 * container item that wraps all items that were created while this
1220 * object was on the stack.
1221 * The rule is: all child items of the container item need to have
1222 * clipped bounds with respect to the container ASR.
1224 class AutoContainerASRTracker
{
1226 explicit AutoContainerASRTracker(nsDisplayListBuilder
* aBuilder
);
1228 const ActiveScrolledRoot
* GetContainerASR() {
1229 return mBuilder
->mCurrentContainerASR
;
1232 ~AutoContainerASRTracker() {
1233 mBuilder
->mCurrentContainerASR
= ActiveScrolledRoot::PickAncestor(
1234 mBuilder
->mCurrentContainerASR
, mSavedContainerASR
);
1238 nsDisplayListBuilder
* mBuilder
;
1239 const ActiveScrolledRoot
* mSavedContainerASR
;
1243 * A helper class to temporarily set the value of mCurrentScrollbarTarget
1244 * and mCurrentScrollbarFlags.
1246 class AutoCurrentScrollbarInfoSetter
{
1248 AutoCurrentScrollbarInfoSetter(
1249 nsDisplayListBuilder
* aBuilder
, ViewID aScrollTargetID
,
1250 const Maybe
<layers::ScrollDirection
>& aScrollbarDirection
,
1251 bool aWillHaveLayer
)
1252 : mBuilder(aBuilder
) {
1253 aBuilder
->mIsBuildingScrollbar
= true;
1254 aBuilder
->mCurrentScrollbarTarget
= aScrollTargetID
;
1255 aBuilder
->mCurrentScrollbarDirection
= aScrollbarDirection
;
1256 aBuilder
->mCurrentScrollbarWillHaveLayer
= aWillHaveLayer
;
1259 ~AutoCurrentScrollbarInfoSetter() {
1260 // No need to restore old values because scrollbars cannot be nested.
1261 mBuilder
->mIsBuildingScrollbar
= false;
1262 mBuilder
->mCurrentScrollbarTarget
=
1263 layers::ScrollableLayerGuid::NULL_SCROLL_ID
;
1264 mBuilder
->mCurrentScrollbarDirection
.reset();
1265 mBuilder
->mCurrentScrollbarWillHaveLayer
= false;
1269 nsDisplayListBuilder
* mBuilder
;
1273 * A helper class to temporarily set mBuildingExtraPagesForPageNum.
1275 class MOZ_RAII AutoPageNumberSetter
{
1277 AutoPageNumberSetter(nsDisplayListBuilder
* aBuilder
, const uint8_t aPageNum
)
1278 : mBuilder(aBuilder
),
1279 mOldPageNum(aBuilder
->GetBuildingExtraPagesForPageNum()) {
1280 mBuilder
->SetBuildingExtraPagesForPageNum(aPageNum
);
1282 ~AutoPageNumberSetter() {
1283 mBuilder
->SetBuildingExtraPagesForPageNum(mOldPageNum
);
1287 nsDisplayListBuilder
* mBuilder
;
1288 uint8_t mOldPageNum
;
1292 * A helper class to track current effective transform for items.
1294 * For frames that is Combines3DTransformWithAncestors(), we need to
1295 * apply all transforms of ancestors on the same preserves3D chain
1296 * on the bounds of current frame to the coordination of the 3D
1297 * context root. The 3D context root computes it's bounds from
1298 * these transformed bounds.
1300 class AutoAccumulateTransform
{
1302 explicit AutoAccumulateTransform(nsDisplayListBuilder
* aBuilder
)
1303 : mBuilder(aBuilder
),
1304 mSavedTransform(aBuilder
->mPreserves3DCtx
.mAccumulatedTransform
) {}
1306 ~AutoAccumulateTransform() {
1307 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
= mSavedTransform
;
1310 void Accumulate(const gfx::Matrix4x4
& aTransform
) {
1311 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
=
1312 aTransform
* mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
;
1315 const gfx::Matrix4x4
& GetCurrentTransform() {
1316 return mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
;
1320 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
= gfx::Matrix4x4();
1324 nsDisplayListBuilder
* mBuilder
;
1325 gfx::Matrix4x4 mSavedTransform
;
1329 * A helper class to collect bounds rects of descendants.
1331 * For a 3D context root, it's bounds is computed from the bounds of
1332 * descendants. If we transform bounds frame by frame applying
1333 * transforms, the bounds may turn to empty for any singular
1334 * transform on the path, but it is not empty for the accumulated
1337 class AutoAccumulateRect
{
1339 explicit AutoAccumulateRect(nsDisplayListBuilder
* aBuilder
)
1340 : mBuilder(aBuilder
),
1341 mSavedRect(aBuilder
->mPreserves3DCtx
.mAccumulatedRect
) {
1342 aBuilder
->mPreserves3DCtx
.mAccumulatedRect
= nsRect();
1343 aBuilder
->mPreserves3DCtx
.mAccumulatedRectLevels
++;
1346 ~AutoAccumulateRect() {
1347 mBuilder
->mPreserves3DCtx
.mAccumulatedRect
= mSavedRect
;
1348 mBuilder
->mPreserves3DCtx
.mAccumulatedRectLevels
--;
1352 nsDisplayListBuilder
* mBuilder
;
1356 void AccumulateRect(const nsRect
& aRect
) {
1357 mPreserves3DCtx
.mAccumulatedRect
.UnionRect(mPreserves3DCtx
.mAccumulatedRect
,
1361 const nsRect
& GetAccumulatedRect() {
1362 return mPreserves3DCtx
.mAccumulatedRect
;
1366 * The level is increased by one for items establishing 3D rendering
1367 * context and starting a new accumulation.
1369 int GetAccumulatedRectLevels() {
1370 return mPreserves3DCtx
.mAccumulatedRectLevels
;
1373 struct OutOfFlowDisplayData
{
1374 OutOfFlowDisplayData(
1375 const DisplayItemClipChain
* aContainingBlockClipChain
,
1376 const DisplayItemClipChain
* aCombinedClipChain
,
1377 const ActiveScrolledRoot
* aContainingBlockActiveScrolledRoot
,
1378 const ViewID
& aScrollParentId
, const nsRect
& aVisibleRect
,
1379 const nsRect
& aDirtyRect
)
1380 : mContainingBlockClipChain(aContainingBlockClipChain
),
1381 mCombinedClipChain(aCombinedClipChain
),
1382 mContainingBlockActiveScrolledRoot(
1383 aContainingBlockActiveScrolledRoot
),
1384 mVisibleRect(aVisibleRect
),
1385 mDirtyRect(aDirtyRect
),
1386 mScrollParentId(aScrollParentId
) {}
1387 const DisplayItemClipChain
* mContainingBlockClipChain
;
1388 const DisplayItemClipChain
*
1389 mCombinedClipChain
; // only necessary for the special case of top layer
1390 const ActiveScrolledRoot
* mContainingBlockActiveScrolledRoot
;
1392 // If this OutOfFlowDisplayData is associated with the ViewportFrame
1393 // of a document that has a resolution (creating separate visual and
1394 // layout viewports with their own coordinate spaces), these rects
1395 // are in layout coordinates. Similarly, GetVisibleRectForFrame() in
1396 // such a case returns a quantity in layout coordinates.
1397 nsRect mVisibleRect
;
1399 ViewID mScrollParentId
;
1401 static nsRect
ComputeVisibleRectForFrame(nsDisplayListBuilder
* aBuilder
,
1403 const nsRect
& aVisibleRect
,
1404 const nsRect
& aDirtyRect
,
1405 nsRect
* aOutDirtyRect
);
1407 nsRect
GetVisibleRectForFrame(nsDisplayListBuilder
* aBuilder
,
1408 nsIFrame
* aFrame
, nsRect
* aDirtyRect
) {
1409 return ComputeVisibleRectForFrame(aBuilder
, aFrame
, mVisibleRect
,
1410 mDirtyRect
, aDirtyRect
);
1414 NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty
,
1415 OutOfFlowDisplayData
)
1417 struct DisplayListBuildingData
{
1418 nsIFrame
* mModifiedAGR
= nullptr;
1421 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect
,
1422 DisplayListBuildingData
)
1424 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect
,
1427 static OutOfFlowDisplayData
* GetOutOfFlowData(nsIFrame
* aFrame
) {
1428 if (!aFrame
->GetParent()) {
1431 return aFrame
->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
1434 nsPresContext
* CurrentPresContext();
1436 OutOfFlowDisplayData
* GetCurrentFixedBackgroundDisplayData() {
1437 auto& displayData
= CurrentPresShellState()->mFixedBackgroundDisplayData
;
1438 return displayData
? displayData
.ptr() : nullptr;
1442 * Accumulates opaque stuff into the window opaque region.
1444 void AddWindowOpaqueRegion(nsIFrame
* aFrame
, const nsRect
& aBounds
) {
1445 if (IsRetainingDisplayList()) {
1446 mRetainedWindowOpaqueRegion
.Add(aFrame
, aBounds
);
1449 mWindowOpaqueRegion
.Or(mWindowOpaqueRegion
, aBounds
);
1452 * Returns the window opaque region built so far. This may be incomplete
1453 * since the opaque region is built during layer construction.
1455 const nsRegion
GetWindowOpaqueRegion() {
1456 return IsRetainingDisplayList() ? mRetainedWindowOpaqueRegion
.ToRegion()
1457 : mWindowOpaqueRegion
;
1461 * mContainsBlendMode is true if we processed a display item that
1462 * has a blend mode attached. We do this so we can insert a
1463 * nsDisplayBlendContainer in the parent stacking context.
1465 void SetContainsBlendMode(bool aContainsBlendMode
) {
1466 mContainsBlendMode
= aContainsBlendMode
;
1468 bool ContainsBlendMode() const { return mContainsBlendMode
; }
1470 DisplayListClipState
& ClipState() { return mClipState
; }
1471 const ActiveScrolledRoot
* CurrentActiveScrolledRoot() {
1472 return mCurrentActiveScrolledRoot
;
1474 const ActiveScrolledRoot
* CurrentAncestorASRStackingContextContents() {
1475 return mCurrentContainerASR
;
1479 * Add the current frame to the will-change budget if possible and
1480 * remeber the outcome. Subsequent calls to IsInWillChangeBudget
1481 * will return the same value as return here.
1483 bool AddToWillChangeBudget(nsIFrame
* aFrame
, const nsSize
& aSize
);
1486 * This will add the current frame to the will-change budget the first
1487 * time it is seen. On subsequent calls this will return the same
1488 * answer. This effectively implements a first-come, first-served
1489 * allocation of the will-change budget.
1491 bool IsInWillChangeBudget(nsIFrame
* aFrame
, const nsSize
& aSize
);
1494 * Clears the will-change budget status for the given |aFrame|.
1495 * This will also remove the frame from will-change budgets.
1497 void ClearWillChangeBudgetStatus(nsIFrame
* aFrame
);
1500 * Removes the given |aFrame| from will-change budgets.
1502 void RemoveFromWillChangeBudgets(const nsIFrame
* aFrame
);
1505 * Clears the will-change budgets.
1507 void ClearWillChangeBudgets();
1509 void EnterSVGEffectsContents(nsIFrame
* aEffectsFrame
,
1510 nsDisplayList
* aHoistedItemsStorage
);
1511 void ExitSVGEffectsContents();
1513 bool ShouldBuildScrollInfoItemsForHoisting() const;
1515 void AppendNewScrollInfoItemForHoisting(
1516 nsDisplayScrollInfoLayer
* aScrollInfoItem
);
1519 * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
1521 * mPreserves3DCtx is used by class AutoAccumulateTransform &
1522 * AutoAccumulateRect to passing data between frames in the 3D
1523 * context. If a frame create a new 3D context, it should restore
1524 * the value of mPreserves3DCtx before returning back to the parent.
1525 * This class do it for the users.
1527 class AutoPreserves3DContext
{
1529 explicit AutoPreserves3DContext(nsDisplayListBuilder
* aBuilder
)
1530 : mBuilder(aBuilder
), mSavedCtx(aBuilder
->mPreserves3DCtx
) {}
1532 ~AutoPreserves3DContext() { mBuilder
->mPreserves3DCtx
= mSavedCtx
; }
1535 nsDisplayListBuilder
* mBuilder
;
1536 Preserves3DContext mSavedCtx
;
1539 const nsRect
GetPreserves3DRect() const {
1540 return mPreserves3DCtx
.mVisibleRect
;
1543 void SavePreserves3DRect() { mPreserves3DCtx
.mVisibleRect
= mVisibleRect
; }
1545 void SavePreserves3DAllowAsyncAnimation(bool aValue
) {
1546 mPreserves3DCtx
.mAllowAsyncAnimation
= aValue
;
1549 bool GetPreserves3DAllowAsyncAnimation() const {
1550 return mPreserves3DCtx
.mAllowAsyncAnimation
;
1553 bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems
; }
1555 void SetBuildingInvisibleItems(bool aBuildingInvisibleItems
) {
1556 mBuildingInvisibleItems
= aBuildingInvisibleItems
;
1559 void SetBuildingExtraPagesForPageNum(uint8_t aPageNum
) {
1560 mBuildingExtraPagesForPageNum
= aPageNum
;
1562 uint8_t GetBuildingExtraPagesForPageNum() const {
1563 return mBuildingExtraPagesForPageNum
;
1566 bool HitTestIsForVisibility() const { return mVisibleThreshold
.isSome(); }
1568 float VisibilityThreshold() const {
1569 MOZ_DIAGNOSTIC_ASSERT(HitTestIsForVisibility());
1570 return mVisibleThreshold
.valueOr(1.0f
);
1573 void SetHitTestIsForVisibility(float aVisibleThreshold
) {
1574 mVisibleThreshold
= Some(aVisibleThreshold
);
1577 bool ShouldBuildAsyncZoomContainer() const {
1578 return mBuildAsyncZoomContainer
;
1580 void UpdateShouldBuildAsyncZoomContainer();
1582 void UpdateShouldBuildBackdropRootContainer();
1584 bool ShouldRebuildDisplayListDueToPrefChange();
1587 * Represents a region composed of frame/rect pairs.
1588 * WeakFrames are used to track whether a rect still belongs to the region.
1589 * Modified frames and rects are removed and re-added to the region if needed.
1591 struct WeakFrameRegion
{
1593 * A wrapper to store WeakFrame and the pointer to the underlying frame.
1594 * This is needed because WeakFrame does not store the frame pointer after
1595 * the frame has been deleted.
1597 struct WeakFrameWrapper
{
1598 explicit WeakFrameWrapper(nsIFrame
* aFrame
)
1599 : mWeakFrame(new WeakFrame(aFrame
)), mFrame(aFrame
) {}
1601 UniquePtr
<WeakFrame
> mWeakFrame
;
1605 nsTHashSet
<void*> mFrameSet
;
1606 nsTArray
<WeakFrameWrapper
> mFrames
;
1607 nsTArray
<pixman_box32_t
> mRects
;
1609 template <typename RectType
>
1610 void Add(nsIFrame
* aFrame
, const RectType
& aRect
) {
1611 if (mFrameSet
.Contains(aFrame
)) {
1615 mFrameSet
.Insert(aFrame
);
1616 mFrames
.AppendElement(WeakFrameWrapper(aFrame
));
1617 mRects
.AppendElement(nsRegion::RectToBox(aRect
));
1626 void RemoveModifiedFramesAndRects();
1628 size_t SizeOfExcludingThis(MallocSizeOf
) const;
1630 typedef gfx::ArrayView
<pixman_box32_t
> BoxArrayView
;
1632 nsRegion
ToRegion() const { return nsRegion(BoxArrayView(mRects
)); }
1634 LayoutDeviceIntRegion
ToLayoutDeviceIntRegion() const {
1635 return LayoutDeviceIntRegion(BoxArrayView(mRects
));
1639 void AddScrollFrameToNotify(nsIScrollableFrame
* aScrollFrame
);
1640 void NotifyAndClearScrollFrames();
1642 // Helper class to find what link spec (if any) to associate with a frame,
1643 // recording it in the builder, and generate the corresponding DisplayItem.
1644 // This also takes care of generating a named destination for internal links
1645 // if the element has an id or name attribute.
1648 Linkifier(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
1649 nsDisplayList
* aList
);
1652 if (mBuilderToReset
) {
1653 mBuilderToReset
->mLinkSpec
.Truncate(0);
1657 void MaybeAppendLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
1660 nsDisplayListBuilder
* mBuilderToReset
= nullptr;
1661 nsDisplayList
* mList
;
1665 * Returns the nearest ancestor frame to aFrame that is considered to have
1666 * (or will have) animated geometry. This can return aFrame.
1668 nsIFrame
* FindAnimatedGeometryRootFrameFor(nsIFrame
* aFrame
);
1671 * Returns true if this is a retained builder and reuse stacking contexts
1672 * mode is enabled by pref.
1674 bool IsReusingStackingContextItems() const {
1675 return mIsReusingStackingContextItems
;
1679 * Adds display item |aItem| to the reuseable display items set.
1681 void AddReusableDisplayItem(nsDisplayItem
* aItem
);
1684 * Removes display item |aItem| from the reuseable display items set.
1685 * This is needed because display items are sometimes deleted during
1686 * display list building.
1687 * Called by |nsDisplayItem::Destroy()| when the item has been reused.
1689 void RemoveReusedDisplayItem(nsDisplayItem
* aItem
);
1692 * Clears the reuseable display items set.
1694 void ClearReuseableDisplayItems();
1697 * Marks the given display item |aItem| as reused, and updates the necessary
1698 * display list builder state.
1700 void ReuseDisplayItem(nsDisplayItem
* aItem
);
1703 bool MarkOutOfFlowFrameForDisplay(nsIFrame
* aDirtyFrame
, nsIFrame
* aFrame
,
1704 const nsRect
& aVisibleRect
,
1705 const nsRect
& aDirtyRect
);
1707 friend class nsDisplayBackgroundImage
;
1708 friend class RetainedDisplayListBuilder
;
1711 * Returns whether a frame acts as an animated geometry root, optionally
1712 * returning the next ancestor to check.
1714 bool IsAnimatedGeometryRoot(nsIFrame
* aFrame
, nsIFrame
** aParent
= nullptr);
1716 struct PresShellState
{
1717 PresShell
* mPresShell
;
1719 Maybe
<nsAutoLayoutPhase
> mAutoLayoutPhase
;
1721 Maybe
<OutOfFlowDisplayData
> mFixedBackgroundDisplayData
;
1722 uint32_t mFirstFrameMarkedForDisplay
;
1723 uint32_t mFirstFrameWithOOFData
;
1724 bool mIsBackgroundOnly
;
1725 // This is a per-document flag turning off event handling for all content
1726 // in the document, and is set when we enter a subdocument for a pointer-
1727 // events:none frame.
1728 bool mInsidePointerEventsNoneDoc
;
1729 bool mTouchEventPrefEnabledDoc
;
1730 nsIFrame
* mPresShellIgnoreScrollFrame
;
1733 PresShellState
* CurrentPresShellState() {
1734 NS_ASSERTION(mPresShellStates
.Length() > 0,
1735 "Someone forgot to enter a presshell");
1736 return &mPresShellStates
[mPresShellStates
.Length() - 1];
1739 void AddSizeOfExcludingThis(nsWindowSizes
&) const;
1741 struct FrameWillChangeBudget
{
1742 FrameWillChangeBudget() : mPresContext(nullptr), mUsage(0) {}
1744 FrameWillChangeBudget(const nsPresContext
* aPresContext
, uint32_t aUsage
)
1745 : mPresContext(aPresContext
), mUsage(aUsage
) {}
1747 const nsPresContext
* mPresContext
;
1751 // will-change budget tracker
1752 typedef uint32_t DocumentWillChangeBudget
;
1754 nsIFrame
* const mReferenceFrame
;
1755 nsIFrame
* mIgnoreScrollFrame
;
1757 const ActiveScrolledRoot
* mCurrentActiveScrolledRoot
;
1758 const ActiveScrolledRoot
* mCurrentContainerASR
;
1759 // mCurrentFrame is the frame that we're currently calling (or about to call)
1760 // BuildDisplayList on.
1761 const nsIFrame
* mCurrentFrame
;
1762 // The reference frame for mCurrentFrame.
1763 const nsIFrame
* mCurrentReferenceFrame
;
1765 nsIFrame
* mCaretFrame
;
1766 // A temporary list that we append scroll info items to while building
1767 // display items for the contents of frames with SVG effects.
1768 // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
1769 // This is a pointer and not a real nsDisplayList value because the
1770 // nsDisplayList class is defined below this class, so we can't use it here.
1771 nsDisplayList
* mScrollInfoItemsForHoisting
;
1772 nsTArray
<RefPtr
<ActiveScrolledRoot
>> mActiveScrolledRoots
;
1773 DisplayItemClipChain
* mFirstClipChainToDestroy
;
1774 nsTArray
<nsDisplayItem
*> mTemporaryItems
;
1775 nsDisplayTableBackgroundSet
* mTableBackgroundSet
;
1776 ViewID mCurrentScrollParentId
;
1777 ViewID mCurrentScrollbarTarget
;
1779 nsTArray
<nsIFrame
*> mSVGEffectsFrames
;
1780 // When we are inside a filter, the current ASR at the time we entered the
1781 // filter. Otherwise nullptr.
1782 const ActiveScrolledRoot
* mFilterASR
;
1783 nsCString mLinkSpec
; // Destination of link currently being emitted, if any.
1785 // Optimized versions for non-retained display list.
1786 LayoutDeviceIntRegion mWindowDraggingRegion
;
1787 LayoutDeviceIntRegion mWindowNoDraggingRegion
;
1788 nsRegion mWindowOpaqueRegion
;
1790 nsClassHashtable
<nsPtrHashKey
<nsDisplayItem
>,
1791 nsTArray
<nsIWidget::ThemeGeometry
>>
1793 DisplayListClipState mClipState
;
1794 nsTHashMap
<nsPtrHashKey
<const nsPresContext
>, DocumentWillChangeBudget
>
1795 mDocumentWillChangeBudgets
;
1797 // Any frame listed in this set is already counted in the budget
1798 // and thus is in-budget.
1799 nsTHashMap
<nsPtrHashKey
<const nsIFrame
>, FrameWillChangeBudget
>
1800 mFrameWillChangeBudgets
;
1802 nsTHashMap
<nsPtrHashKey
<dom::RemoteBrowser
>, dom::EffectsInfo
>
1805 nsTHashSet
<nsCString
> mDestinations
; // Destination names emitted.
1807 // Stores reusable items collected during display list preprocessing.
1808 nsTHashSet
<nsDisplayItem
*> mReuseableItems
;
1810 // Tracked regions used for retained display list.
1811 WeakFrameRegion mRetainedWindowDraggingRegion
;
1812 WeakFrameRegion mRetainedWindowNoDraggingRegion
;
1814 // Window opaque region is calculated during layer building.
1815 WeakFrameRegion mRetainedWindowOpaqueRegion
;
1817 std::unordered_set
<const DisplayItemClipChain
*, DisplayItemClipChainHasher
,
1818 DisplayItemClipChainEqualer
>
1820 std::unordered_set
<nsIScrollableFrame
*> mScrollFramesToNotify
;
1822 AutoTArray
<nsIFrame
*, 20> mFramesWithOOFData
;
1823 AutoTArray
<nsIFrame
*, 40> mFramesMarkedForDisplayIfVisible
;
1824 AutoTArray
<PresShellState
, 8> mPresShellStates
;
1826 using Arena
= nsPresArena
<32768, DisplayListArenaObjectId
,
1827 size_t(DisplayListArenaObjectId::COUNT
)>;
1830 AutoTArray
<nsIFrame
*, 400> mFramesMarkedForDisplay
;
1832 gfx::CompositorHitTestInfo mCompositorHitTestInfo
;
1834 // The offset from mCurrentFrame to mCurrentReferenceFrame.
1835 nsPoint mCurrentOffsetToReferenceFrame
;
1837 Maybe
<float> mVisibleThreshold
;
1839 Maybe
<nsPoint
> mAdditionalOffset
;
1841 // Relative to mCurrentFrame.
1842 nsRect mVisibleRect
;
1846 Preserves3DContext mPreserves3DCtx
;
1848 uint8_t mBuildingExtraPagesForPageNum
;
1850 nsDisplayListBuilderMode mMode
;
1851 static uint32_t sPaintSequenceNumber
;
1853 bool mContainsBlendMode
;
1854 bool mIsBuildingScrollbar
;
1855 bool mCurrentScrollbarWillHaveLayer
;
1857 bool mRetainingDisplayList
;
1858 bool mPartialUpdate
;
1859 bool mIgnoreSuppression
;
1860 bool mIncludeAllOutOfFlows
;
1861 bool mDescendIntoSubdocuments
;
1862 bool mSelectedFramesOnly
;
1863 bool mAllowMergingAndFlattening
;
1864 // True when we're building a display list that's directly or indirectly
1865 // under an nsDisplayTransform
1869 bool mInPageSequence
;
1870 bool mIsInChromePresContext
;
1871 bool mSyncDecodeImages
;
1872 bool mIsPaintingToWindow
;
1873 bool mUseHighQualityScaling
;
1874 bool mIsPaintingForWebRender
;
1875 bool mIsCompositingCheap
;
1876 bool mAncestorHasApzAwareEventHandler
;
1877 // True when the first async-scrollable scroll frame for which we build a
1878 // display list has a display port. An async-scrollable scroll frame is one
1879 // which WantsAsyncScroll().
1880 bool mHaveScrollableDisplayPort
;
1881 bool mWindowDraggingAllowed
;
1882 bool mIsBuildingForPopup
;
1883 bool mForceLayerForScrollParent
;
1884 bool mContainsNonMinimalDisplayPort
;
1885 bool mAsyncPanZoomEnabled
;
1886 bool mBuildingInvisibleItems
;
1888 bool mInInvalidSubtree
;
1889 bool mBuildCompositorHitTestInfo
;
1890 bool mDisablePartialUpdates
;
1891 bool mPartialBuildFailed
;
1892 bool mIsInActiveDocShell
;
1893 bool mBuildAsyncZoomContainer
;
1894 bool mIsRelativeToLayoutViewport
;
1895 bool mUseOverlayScrollbars
;
1896 bool mAlwaysLayerizeScrollbars
;
1898 bool mIsReusingStackingContextItems
;
1900 Maybe
<layers::ScrollDirection
> mCurrentScrollbarDirection
;
1903 // All types are defined in nsDisplayItemTypes.h
1904 #define NS_DISPLAY_DECL_NAME(n, e) \
1905 const char* Name() const override { return n; } \
1906 constexpr static DisplayItemType ItemType() { return DisplayItemType::e; } \
1909 void* operator new(size_t aSize, nsDisplayListBuilder* aBuilder) { \
1910 return aBuilder->Allocate(aSize, DisplayItemType::e); \
1913 template <typename T, typename F, typename... Args> \
1914 friend T* mozilla::MakeDisplayItemWithIndex( \
1915 nsDisplayListBuilder* aBuilder, F* aFrame, const uint16_t aIndex, \
1920 #define NS_DISPLAY_ALLOW_CLONING() \
1921 template <typename T> \
1922 friend T* mozilla::MakeClone(nsDisplayListBuilder* aBuilder, \
1925 nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override { \
1926 return MakeClone(aBuilder, this); \
1929 template <typename T
>
1930 MOZ_ALWAYS_INLINE T
* MakeClone(nsDisplayListBuilder
* aBuilder
, const T
* aItem
) {
1931 static_assert(std::is_base_of
<nsDisplayWrapList
, T
>::value
,
1932 "Display item type should be derived from nsDisplayWrapList");
1933 T
* item
= new (aBuilder
) T(aBuilder
, *aItem
);
1934 item
->SetType(T::ItemType());
1938 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1939 void AssertUniqueItem(nsDisplayItem
* aItem
);
1943 * Returns true, if a display item of given |aType| needs to be built within
1944 * opacity:0 container.
1946 bool ShouldBuildItemForEvents(const DisplayItemType aType
);
1949 * Initializes the hit test information of |aItem| if the item type supports it.
1951 void InitializeHitTestInfo(nsDisplayListBuilder
* aBuilder
,
1952 nsPaintedDisplayItem
* aItem
,
1953 const DisplayItemType aType
);
1955 template <typename T
, typename F
, typename
... Args
>
1956 MOZ_ALWAYS_INLINE T
* MakeDisplayItemWithIndex(nsDisplayListBuilder
* aBuilder
,
1957 F
* aFrame
, const uint16_t aIndex
,
1959 static_assert(std::is_base_of
<nsDisplayItem
, T
>::value
,
1960 "Display item type should be derived from nsDisplayItem");
1961 static_assert(std::is_base_of
<nsIFrame
, F
>::value
,
1962 "Frame type should be derived from nsIFrame");
1964 const DisplayItemType type
= T::ItemType();
1965 if (aBuilder
->InEventsOnly() && !ShouldBuildItemForEvents(type
)) {
1966 // This item is not needed for events.
1970 T
* item
= new (aBuilder
) T(aBuilder
, aFrame
, std::forward
<Args
>(aArgs
)...);
1972 if (type
!= DisplayItemType::TYPE_GENERIC
) {
1973 item
->SetType(type
);
1976 item
->SetPerFrameIndex(aIndex
);
1977 item
->SetExtraPageForPageNum(aBuilder
->GetBuildingExtraPagesForPageNum());
1979 nsPaintedDisplayItem
* paintedItem
= item
->AsPaintedDisplayItem();
1981 InitializeHitTestInfo(aBuilder
, paintedItem
, type
);
1984 if (aBuilder
->InInvalidSubtree() ||
1985 item
->FrameForInvalidation()->IsFrameModified()) {
1986 item
->SetModifiedFrame(true);
1989 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1990 if (aBuilder
->IsRetainingDisplayList() && aBuilder
->IsBuilding()) {
1991 AssertUniqueItem(item
);
1994 // Verify that InInvalidSubtree matches invalidation frame's modified state.
1995 if (aBuilder
->InInvalidSubtree()) {
1996 MOZ_DIAGNOSTIC_ASSERT(
1997 AnyContentAncestorModified(item
->FrameForInvalidation()));
2000 DebugOnly
<bool> isContainerType
=
2001 (GetDisplayItemFlagsForType(type
) & TYPE_IS_CONTAINER
);
2003 MOZ_ASSERT(item
->HasChildren() == isContainerType
,
2004 "Container items must have container display item flag set.");
2007 DL_LOGV("Created display item %p (%s) (frame: %p)", item
, item
->Name(),
2013 template <typename T
, typename F
, typename
... Args
>
2014 MOZ_ALWAYS_INLINE T
* MakeDisplayItem(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
2016 return MakeDisplayItemWithIndex
<T
>(aBuilder
, aFrame
, 0,
2017 std::forward
<Args
>(aArgs
)...);
2021 * nsDisplayItemBase is a base-class for all display items. It is mainly
2022 * responsible for handling the frame-display item 1:n relationship, as well as
2023 * storing the state needed for display list merging.
2025 * Display items are arena-allocated during display list construction.
2027 * Display items can be containers --- i.e., they can perform hit testing
2028 * and painting by recursively traversing a list of child items.
2030 * Display items belong to a list at all times (except temporarily as they
2031 * move from one list to another).
2033 class nsDisplayItem
{
2035 using LayerManager
= layers::LayerManager
;
2036 using WebRenderLayerManager
= layers::WebRenderLayerManager
;
2037 using StackingContextHelper
= layers::StackingContextHelper
;
2038 using ViewID
= layers::ScrollableLayerGuid::ViewID
;
2041 * Downcasts this item to nsPaintedDisplayItem, if possible.
2043 virtual nsPaintedDisplayItem
* AsPaintedDisplayItem() { return nullptr; }
2044 virtual const nsPaintedDisplayItem
* AsPaintedDisplayItem() const {
2049 * Downcasts this item to nsDisplayWrapList, if possible.
2051 virtual nsDisplayWrapList
* AsDisplayWrapList() { return nullptr; }
2052 virtual const nsDisplayWrapList
* AsDisplayWrapList() const { return nullptr; }
2055 * Create a clone of this item.
2057 virtual nsDisplayWrapList
* Clone(nsDisplayListBuilder
* aBuilder
) const {
2062 * Checks if the given display item can be merged with this item.
2063 * @return true if the merging is possible, otherwise false.
2065 virtual bool CanMerge(const nsDisplayItem
* aItem
) const { return false; }
2068 * Frees the memory allocated for this display item.
2069 * The given display list builder must have allocated this display item.
2071 virtual void Destroy(nsDisplayListBuilder
* aBuilder
) {
2072 const DisplayItemType type
= GetType();
2073 DL_LOGV("Destroying display item %p (%s)", this, Name());
2075 if (IsReusedItem()) {
2076 aBuilder
->RemoveReusedDisplayItem(this);
2079 this->~nsDisplayItem();
2080 aBuilder
->Destroy(type
, this);
2084 * Returns the frame that this display item was created for.
2085 * Never returns null.
2087 inline nsIFrame
* Frame() const {
2088 MOZ_ASSERT(mFrame
, "Trying to use display item after frame deletion!");
2093 * Called when the display item is prepared for deletion. The display item
2094 * should not be used after calling this function.
2096 virtual void RemoveFrame(nsIFrame
* aFrame
) {
2099 if (mFrame
&& aFrame
== mFrame
) {
2106 * A display item can depend on multiple different frames for invalidation.
2108 virtual nsIFrame
* GetDependentFrame() { return nullptr; }
2111 * Returns the frame that provides the style data, and should
2112 * be checked when deciding if this display item can be reused.
2114 virtual nsIFrame
* FrameForInvalidation() const { return Frame(); }
2117 * Display items can override this to communicate that they won't
2118 * contribute any visual information (for example fully transparent).
2120 virtual bool IsInvisible() const { return false; }
2123 * Returns the printable name of this display item.
2125 virtual const char* Name() const = 0;
2128 * Some consecutive items should be rendered together as a unit, e.g.,
2129 * outlines for the same element. For this, we need a way for items to
2130 * identify their type. We use the type for other purposes too.
2132 DisplayItemType
GetType() const {
2133 MOZ_ASSERT(mType
!= DisplayItemType::TYPE_ZERO
,
2134 "Display item should have a valid type!");
2139 * Pairing this with the Frame() pointer gives a key that
2140 * uniquely identifies this display item in the display item tree.
2142 uint32_t GetPerFrameKey() const {
2143 // The top 8 bits are the page index
2144 // The middle 16 bits of the per frame key uniquely identify the display
2145 // item when there are more than one item of the same type for a frame.
2146 // The low 8 bits are the display item type.
2147 return (static_cast<uint32_t>(mExtraPageForPageNum
)
2148 << (TYPE_BITS
+ (sizeof(mPerFrameIndex
) * 8))) |
2149 (static_cast<uint32_t>(mPerFrameIndex
) << TYPE_BITS
) |
2150 static_cast<uint32_t>(mType
);
2154 * Returns true if this item was reused during display list merging.
2156 bool IsReused() const { return mItemFlags
.contains(ItemFlag::ReusedItem
); }
2158 void SetReused(bool aReused
) { SetItemFlag(ItemFlag::ReusedItem
, aReused
); }
2161 * Returns true if this item can be reused during display list merging.
2163 bool CanBeReused() const {
2164 return !mItemFlags
.contains(ItemFlag::CantBeReused
);
2167 void SetCantBeReused() { mItemFlags
+= ItemFlag::CantBeReused
; }
2169 bool CanBeCached() const {
2170 return !mItemFlags
.contains(ItemFlag::CantBeCached
);
2173 void SetCantBeCached() { mItemFlags
+= ItemFlag::CantBeCached
; }
2175 bool IsOldItem() const { return !!mOldList
; }
2178 * Returns true if the frame of this display item is in a modified subtree.
2180 bool HasModifiedFrame() const {
2181 return mItemFlags
.contains(ItemFlag::ModifiedFrame
);
2184 void SetModifiedFrame(bool aModified
) {
2185 SetItemFlag(ItemFlag::ModifiedFrame
, aModified
);
2188 bool HasDeletedFrame() const;
2191 * Set the nsDisplayList that this item belongs to, and what index it is
2193 * Temporary state for merging used by RetainedDisplayListBuilder.
2195 void SetOldListIndex(nsDisplayList
* aList
, OldListIndex aIndex
,
2196 uint32_t aListKey
, uint32_t aNestingDepth
) {
2197 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2198 mOldListKey
= aListKey
;
2199 mOldNestingDepth
= aNestingDepth
;
2201 mOldList
= reinterpret_cast<uintptr_t>(aList
);
2202 mOldListIndex
= aIndex
;
2205 bool GetOldListIndex(nsDisplayList
* aList
, uint32_t aListKey
,
2206 OldListIndex
* aOutIndex
) {
2207 if (mOldList
!= reinterpret_cast<uintptr_t>(aList
)) {
2208 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2209 MOZ_CRASH_UNSAFE_PRINTF(
2210 "Item found was in the wrong list! type %d "
2211 "(outer type was %d at depth %d, now is %d)",
2212 GetPerFrameKey(), mOldListKey
, mOldNestingDepth
, aListKey
);
2216 *aOutIndex
= mOldListIndex
;
2221 * Returns the display list containing the children of this display item.
2222 * The children may be in a different coordinate system than this item.
2224 virtual RetainedDisplayList
* GetChildren() const { return nullptr; }
2225 bool HasChildren() const { return GetChildren(); }
2228 * Display items with children may return true here. This causes the
2229 * display list iterator to descend into the child display list.
2231 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) {
2235 virtual bool CreatesStackingContextHelper() { return false; }
2238 * Returns true if this item can be moved asynchronously on the compositor,
2239 * see RetainedDisplayListBuilder.cpp comments.
2241 virtual bool CanMoveAsync() { return false; }
2244 // This is never instantiated directly (it has pure virtual methods), so no
2245 // need to count constructors and destructors.
2246 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
2247 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
2248 const ActiveScrolledRoot
* aActiveScrolledRoot
);
2251 * The custom copy-constructor is implemented to prevent copying the saved
2252 * state of the item.
2253 * This is currently only used when creating temporary items for merging.
2255 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, const nsDisplayItem
& aOther
)
2256 : mFrame(aOther
.mFrame
),
2257 mItemFlags(aOther
.mItemFlags
),
2258 mType(aOther
.mType
),
2259 mExtraPageForPageNum(aOther
.mExtraPageForPageNum
),
2260 mPerFrameIndex(aOther
.mPerFrameIndex
),
2261 mBuildingRect(aOther
.mBuildingRect
),
2262 mToReferenceFrame(aOther
.mToReferenceFrame
),
2263 mActiveScrolledRoot(aOther
.mActiveScrolledRoot
),
2264 mClipChain(aOther
.mClipChain
) {
2265 MOZ_COUNT_CTOR(nsDisplayItem
);
2266 // TODO: It might be better to remove the flags that aren't copied.
2267 if (aOther
.ForceNotVisible()) {
2268 mItemFlags
+= ItemFlag::ForceNotVisible
;
2270 if (mFrame
->In3DContextAndBackfaceIsHidden()) {
2271 mItemFlags
+= ItemFlag::BackfaceHidden
;
2273 if (aOther
.Combines3DTransformWithAncestors()) {
2274 mItemFlags
+= ItemFlag::Combines3DTransformWithAncestors
;
2278 virtual ~nsDisplayItem() {
2279 MOZ_COUNT_DTOR(nsDisplayItem
);
2281 mFrame
->RemoveDisplayItem(this);
2285 void SetType(const DisplayItemType aType
) { mType
= aType
; }
2287 void SetPerFrameIndex(const uint16_t aIndex
) { mPerFrameIndex
= aIndex
; }
2289 // Display list building for printing can build duplicate
2290 // container display items when they contain a mixture of
2291 // OOF and normal content that is spread across multiple
2292 // pages. We include the page number for the duplicates
2293 // to make our GetPerFrameKey unique.
2294 void SetExtraPageForPageNum(const uint8_t aPageNum
) {
2295 mExtraPageForPageNum
= aPageNum
;
2298 void SetDeletedFrame();
2301 nsDisplayItem() = delete;
2302 nsDisplayItem(const nsDisplayItem
&) = delete;
2305 * Invalidate cached information that depends on this node's contents, after
2306 * a mutation of those contents.
2308 * Specifically, if you mutate an |nsDisplayItem| in a way that would change
2309 * the WebRender display list items generated for it, you should call this
2312 * If a |RestoreState| method exists to restore some piece of state, that's a
2313 * good indication that modifications to said state should be accompanied by a
2314 * call to this method. Opacity flattening's effects on
2315 * |nsDisplayBackgroundColor| items are one example.
2317 virtual void InvalidateItemCacheEntry() {}
2319 struct HitTestState
{
2320 explicit HitTestState() = default;
2323 NS_ASSERTION(mItemBuffer
.Length() == 0,
2324 "mItemBuffer should have been cleared");
2327 // Handling transform items for preserve 3D frames.
2328 bool mInPreserves3D
= false;
2329 // When hit-testing for visibility, we may hit an fully opaque item in a
2330 // nested display list. We want to stop at that point, without looking
2331 // further on other items.
2332 bool mHitOccludingItem
= false;
2334 float mCurrentOpacity
= 1.0f
;
2336 AutoTArray
<nsDisplayItem
*, 100> mItemBuffer
;
2339 uint8_t GetFlags() const { return GetDisplayItemFlagsForType(GetType()); }
2341 virtual bool IsContentful() const { return GetFlags() & TYPE_IS_CONTENTFUL
; }
2344 * This is called after we've constructed a display list for event handling.
2345 * When this is called, we've already ensured that aRect intersects the
2346 * item's bounds and that clipping has been taking into account.
2348 * @param aRect the point or rect being tested, relative to the reference
2349 * frame. If the width and height are both 1 app unit, it indicates we're
2350 * hit testing a point, not a rect.
2351 * @param aState must point to a HitTestState. If you don't have one,
2352 * just create one with the default constructor and pass it in.
2353 * @param aOutFrames each item appends the frame(s) in this display item that
2354 * the rect is considered over (if any) to aOutFrames.
2356 virtual void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
2357 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) {}
2359 virtual nsIFrame
* StyleFrame() const { return mFrame
; }
2362 * Compute the used z-index of our frame; returns zero for elements to which
2363 * z-index does not apply, and for z-index:auto.
2364 * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
2366 virtual int32_t ZIndex() const;
2368 * The default bounds is the frame border rect.
2369 * @param aSnap *aSnap is set to true if the returned rect will be
2370 * snapped to nearest device pixel edges during actual drawing.
2371 * It might be set to false and snap anyway, so code computing the set of
2372 * pixels affected by this display item needs to round outwards to pixel
2373 * boundaries when *aSnap is set to false.
2374 * This does not take the item's clipping into account.
2375 * @return a rectangle relative to aBuilder->ReferenceFrame() that
2376 * contains the area drawn by this display item
2378 virtual nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const {
2380 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2384 * Returns the untransformed bounds of this display item.
2386 virtual nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
2387 bool* aSnap
) const {
2388 return GetBounds(aBuilder
, aSnap
);
2391 virtual nsRegion
GetTightBounds(nsDisplayListBuilder
* aBuilder
,
2392 bool* aSnap
) const {
2398 * Returns true if nothing will be rendered inside aRect, false if uncertain.
2399 * aRect is assumed to be contained in this item's bounds.
2401 virtual bool IsInvisibleInRect(const nsRect
& aRect
) const { return false; }
2404 * Returns the result of GetBounds intersected with the item's clip.
2405 * The intersection is approximate since rounded corners are not taking into
2408 nsRect
GetClippedBounds(nsDisplayListBuilder
* aBuilder
) const;
2410 nsRect
GetBorderRect() const {
2411 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2414 nsRect
GetPaddingRect() const {
2415 return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
2418 nsRect
GetContentRect() const {
2419 return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
2423 * Checks if the frame(s) owning this display item have been marked as
2424 * invalid, and needing repainting.
2426 virtual bool IsInvalid(nsRect
& aRect
) const {
2427 bool result
= mFrame
? mFrame
->IsInvalid(aRect
) : false;
2428 aRect
+= ToReferenceFrame();
2433 * Creates and initializes an nsDisplayItemGeometry object that retains the
2434 * current areas covered by this display item. These need to retain enough
2435 * information such that they can be compared against a future nsDisplayItem
2436 * of the same type, and determine if repainting needs to happen.
2438 * Subclasses wishing to store more information need to override both this
2439 * and ComputeInvalidationRegion, as well as implementing an
2440 * nsDisplayItemGeometry subclass.
2442 * The default implementation tracks both the display item bounds, and the
2443 * frame's border rect.
2445 virtual nsDisplayItemGeometry
* AllocateGeometry(
2446 nsDisplayListBuilder
* aBuilder
) {
2447 return new nsDisplayItemGenericGeometry(this, aBuilder
);
2451 * Compares an nsDisplayItemGeometry object from a previous paint against the
2452 * current item. Computes if the geometry of the item has changed, and the
2453 * invalidation area required for correct repainting.
2455 * The existing geometry will have been created from a display item with a
2456 * matching GetPerFrameKey()/mFrame pair to the current item.
2458 * The default implementation compares the display item bounds, and the
2459 * frame's border rect, and invalidates the entire bounds if either rect
2462 * @param aGeometry The geometry of the matching display item from the
2464 * @param aInvalidRegion Output param, the region to invalidate, or
2465 * unchanged if none.
2467 virtual void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
2468 const nsDisplayItemGeometry
* aGeometry
,
2469 nsRegion
* aInvalidRegion
) const {
2470 const nsDisplayItemGenericGeometry
* geometry
=
2471 static_cast<const nsDisplayItemGenericGeometry
*>(aGeometry
);
2473 if (!geometry
->mBounds
.IsEqualInterior(GetBounds(aBuilder
, &snap
)) ||
2474 !geometry
->mBorderRect
.IsEqualInterior(GetBorderRect())) {
2475 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
2480 * An alternative default implementation of ComputeInvalidationRegion,
2481 * that instead invalidates only the changed area between the two items.
2483 void ComputeInvalidationRegionDifference(
2484 nsDisplayListBuilder
* aBuilder
,
2485 const nsDisplayItemBoundsGeometry
* aGeometry
,
2486 nsRegion
* aInvalidRegion
) const {
2488 nsRect bounds
= GetBounds(aBuilder
, &snap
);
2490 if (!aGeometry
->mBounds
.IsEqualInterior(bounds
)) {
2492 if (aGeometry
->mHasRoundedCorners
|| Frame()->GetBorderRadii(radii
)) {
2493 aInvalidRegion
->Or(aGeometry
->mBounds
, bounds
);
2495 aInvalidRegion
->Xor(aGeometry
->mBounds
, bounds
);
2501 * This function is called when an item's list of children has been modified
2502 * by RetainedDisplayListBuilder.
2504 virtual void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) {}
2506 virtual void AddSizeOfExcludingThis(nsWindowSizes
&) const {}
2509 * @param aSnap set to true if the edges of the rectangles of the opaque
2510 * region would be snapped to device pixels when drawing
2511 * @return a region of the item that is opaque --- that is, every pixel
2512 * that is visible is painted with an opaque
2513 * color. This is useful for determining when one piece
2514 * of content completely obscures another so that we can do occlusion
2516 * This does not take clipping into account.
2517 * This must return a simple region (1 rect) for painting display lists.
2518 * It is only allowed to be a complex region for hit testing.
2520 virtual nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
2521 bool* aSnap
) const {
2526 * @return Some(nscolor) if the item is guaranteed to paint every pixel in its
2527 * bounds with the same (possibly translucent) color
2529 virtual Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const {
2534 * @return true if the contents of this item are rendered fixed relative
2535 * to the nearest viewport.
2537 virtual bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const {
2542 * Returns true if all layers that can be active should be forced to be
2543 * active. Requires setting the pref layers.force-active=true.
2545 static bool ForceActiveLayers();
2547 #ifdef MOZ_DUMP_PAINTING
2549 * Mark this display item as being painted via
2550 * FrameLayerBuilder::DrawPaintedLayer.
2552 bool Painted() const { return mItemFlags
.contains(ItemFlag::Painted
); }
2555 * Check if this display item has been painted.
2557 void SetPainted() { mItemFlags
+= ItemFlag::Painted
; }
2561 * Function to create the WebRenderCommands.
2562 * We should check if the layer state is
2563 * active first and have an early return if the layer state is
2566 * @return true if successfully creating webrender commands.
2568 virtual bool CreateWebRenderCommands(
2569 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
2570 const StackingContextHelper
& aSc
,
2571 layers::RenderRootStateManager
* aManager
,
2572 nsDisplayListBuilder
* aDisplayListBuilder
) {
2577 * Updates the provided aLayerData with any APZ-relevant scroll data
2578 * that is specific to this display item. This is stuff that would normally
2579 * be put on the layer during BuildLayer, but this is only called in
2580 * layers-free webrender mode, where we don't have layers.
2582 * This function returns true if and only if it has APZ-relevant scroll data
2583 * to provide. Note that the arguments passed in may be nullptr, in which case
2584 * the function should still return true if and only if it has APZ-relevant
2585 * scroll data, but obviously in this case it can't actually put the
2586 * data onto aLayerData, because there isn't one.
2588 * This function assumes that aData and aLayerData will either both be null,
2589 * or will both be non-null. The caller is responsible for enforcing this.
2591 virtual bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
2592 layers::WebRenderLayerScrollData
* aLayerData
) {
2597 * Returns true if this item needs to have its geometry updated, despite
2598 * returning empty invalidation region.
2600 virtual bool NeedsGeometryUpdates() const { return false; }
2603 * When this item is rendered using fallback rendering, whether it should use
2604 * blob rendering (i.e. a recording DrawTarget), as opposed to a pixel-backed
2606 * Some items, such as those calling into the native themed widget machinery,
2607 * are more efficiently painted without blob recording. Those should return
2610 virtual bool ShouldUseBlobRenderingForFallback() const { return true; }
2613 * If this has a child list where the children are in the same coordinate
2614 * system as this item (i.e., they have the same reference frame),
2617 virtual RetainedDisplayList
* GetSameCoordinateSystemChildren() const {
2621 virtual void UpdateBounds(nsDisplayListBuilder
* aBuilder
) {}
2623 * Do UpdateBounds() for items with frames establishing or extending
2624 * 3D rendering context.
2626 * This function is called by UpdateBoundsFor3D() of
2627 * nsDisplayTransform(), and it is called by
2628 * BuildDisplayListForStackingContext() on transform items
2629 * establishing 3D rendering context.
2631 * The bounds of a transform item with the frame establishing 3D
2632 * rendering context should be computed by calling
2633 * DoUpdateBoundsPreserves3D() on all descendants that participate
2634 * the same 3d rendering context.
2636 virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) {}
2639 * Returns the building rectangle used by nsDisplayListBuilder when
2640 * this item was constructed.
2642 const nsRect
& GetBuildingRect() const { return mBuildingRect
; }
2644 void SetBuildingRect(const nsRect
& aBuildingRect
) {
2645 mBuildingRect
= aBuildingRect
;
2649 * Returns the building rect for the children, relative to their
2650 * reference frame. Can be different from mBuildingRect for
2651 * nsDisplayTransform, since the reference frame for the children is different
2652 * from the reference frame for the item itself.
2654 virtual const nsRect
& GetBuildingRectForChildren() const {
2655 return mBuildingRect
;
2658 virtual void WriteDebugInfo(std::stringstream
& aStream
) {}
2661 * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
2663 const nsPoint
& ToReferenceFrame() const {
2664 NS_ASSERTION(mFrame
, "No frame?");
2665 return mToReferenceFrame
;
2669 * Returns the reference frame for display item children of this item.
2671 virtual const nsIFrame
* ReferenceFrameForChildren() const { return nullptr; }
2674 * Checks if this display item (or any children) contains content that might
2675 * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
2676 * bounds of the area that needs component alpha, or an empty rect if nothing
2679 virtual nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const {
2684 * Check if we can add async animations to the layer for this display item.
2686 virtual bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) {
2690 virtual bool SupportsOptimizingToImage() const { return false; }
2692 virtual const DisplayItemClip
& GetClip() const;
2693 void IntersectClip(nsDisplayListBuilder
* aBuilder
,
2694 const DisplayItemClipChain
* aOther
, bool aStore
);
2696 virtual void SetActiveScrolledRoot(
2697 const ActiveScrolledRoot
* aActiveScrolledRoot
) {
2698 mActiveScrolledRoot
= aActiveScrolledRoot
;
2700 const ActiveScrolledRoot
* GetActiveScrolledRoot() const {
2701 return mActiveScrolledRoot
;
2704 virtual void SetClipChain(const DisplayItemClipChain
* aClipChain
,
2706 const DisplayItemClipChain
* GetClipChain() const { return mClipChain
; }
2708 bool BackfaceIsHidden() const {
2709 return mItemFlags
.contains(ItemFlag::BackfaceHidden
);
2712 bool Combines3DTransformWithAncestors() const {
2713 return mItemFlags
.contains(ItemFlag::Combines3DTransformWithAncestors
);
2716 bool ForceNotVisible() const {
2717 return mItemFlags
.contains(ItemFlag::ForceNotVisible
);
2720 bool In3DContextAndBackfaceIsHidden() const {
2721 return mItemFlags
.contains(ItemFlag::BackfaceHidden
) &&
2722 mItemFlags
.contains(ItemFlag::Combines3DTransformWithAncestors
);
2725 bool HasDifferentFrame(const nsDisplayItem
* aOther
) const {
2726 return mFrame
!= aOther
->mFrame
;
2729 bool HasHitTestInfo() const {
2730 return mItemFlags
.contains(ItemFlag::HasHitTestInfo
);
2733 bool HasSameTypeAndClip(const nsDisplayItem
* aOther
) const {
2734 return GetPerFrameKey() == aOther
->GetPerFrameKey() &&
2735 GetClipChain() == aOther
->GetClipChain();
2738 bool HasSameContent(const nsDisplayItem
* aOther
) const {
2739 return mFrame
->GetContent() == aOther
->Frame()->GetContent();
2742 virtual void NotifyUsed(nsDisplayListBuilder
* aBuilder
) {}
2744 virtual Maybe
<nsRect
> GetClipWithRespectToASR(
2745 nsDisplayListBuilder
* aBuilder
, const ActiveScrolledRoot
* aASR
) const;
2747 virtual const nsRect
& GetUntransformedPaintRect() const {
2748 return GetBuildingRect();
2751 nsRect
GetPaintRect(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
);
2753 virtual const HitTestInfo
& GetHitTestInfo() { return HitTestInfo::Empty(); }
2755 enum class ReuseState
: uint8_t {
2757 // Set during display list building.
2759 // Set during display list preprocessing.
2761 // Set during partial display list build.
2765 void SetReusable() {
2766 MOZ_ASSERT(mReuseState
== ReuseState::None
||
2767 mReuseState
== ReuseState::Reused
);
2768 mReuseState
= ReuseState::Reusable
;
2771 bool IsReusable() const { return mReuseState
== ReuseState::Reusable
; }
2773 void SetPreProcessed() {
2774 MOZ_ASSERT(mReuseState
== ReuseState::Reusable
);
2775 mReuseState
= ReuseState::PreProcessed
;
2778 bool IsPreProcessed() const {
2779 return mReuseState
== ReuseState::PreProcessed
;
2782 void SetReusedItem() {
2783 MOZ_ASSERT(mReuseState
== ReuseState::PreProcessed
);
2784 mReuseState
= ReuseState::Reused
;
2787 bool IsReusedItem() const { return mReuseState
== ReuseState::Reused
; }
2789 void ResetReuseState() { mReuseState
= ReuseState::None
; }
2791 ReuseState
GetReuseState() const { return mReuseState
; }
2793 nsIFrame
* mFrame
; // 8
2796 enum class ItemFlag
: uint16_t {
2802 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2807 Combines3DTransformWithAncestors
,
2810 #ifdef MOZ_DUMP_PAINTING
2811 // True if this frame has been painted.
2816 EnumSet
<ItemFlag
, uint16_t> mItemFlags
; // 2
2817 DisplayItemType mType
= DisplayItemType::TYPE_ZERO
; // 1
2818 uint8_t mExtraPageForPageNum
= 0; // 1
2819 uint16_t mPerFrameIndex
= 0; // 2
2820 ReuseState mReuseState
= ReuseState::None
;
2821 OldListIndex mOldListIndex
; // 4
2822 uintptr_t mOldList
= 0; // 8
2824 // This is the rectangle that nsDisplayListBuilder was using as the visible
2825 // rect to decide which items to construct.
2826 nsRect mBuildingRect
;
2829 void SetItemFlag(ItemFlag aFlag
, const bool aValue
) {
2831 mItemFlags
+= aFlag
;
2833 mItemFlags
-= aFlag
;
2837 void SetHasHitTestInfo() { mItemFlags
+= ItemFlag::HasHitTestInfo
; }
2839 // Result of ToReferenceFrame(mFrame), if mFrame is non-null
2840 nsPoint mToReferenceFrame
;
2842 RefPtr
<const ActiveScrolledRoot
> mActiveScrolledRoot
;
2843 RefPtr
<const DisplayItemClipChain
> mClipChain
;
2845 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2847 bool IsMergedItem() const {
2848 return mItemFlags
.contains(ItemFlag::MergedItem
);
2851 bool IsPreProcessedItem() const {
2852 return mItemFlags
.contains(ItemFlag::PreProcessedItem
);
2855 void SetMergedPreProcessed(bool aMerged
, bool aPreProcessed
) {
2856 SetItemFlag(ItemFlag::MergedItem
, aMerged
);
2857 SetItemFlag(ItemFlag::PreProcessedItem
, aPreProcessed
);
2860 uint32_t mOldListKey
= 0;
2861 uint32_t mOldNestingDepth
= 0;
2865 class nsPaintedDisplayItem
: public nsDisplayItem
{
2867 nsPaintedDisplayItem
* AsPaintedDisplayItem() final
{ return this; }
2868 const nsPaintedDisplayItem
* AsPaintedDisplayItem() const final
{
2873 * Returns true if this display item would return true from ApplyOpacity
2874 * without actually applying the opacity. Otherwise returns false.
2876 virtual bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
2877 nsDisplayListBuilder
* aBuilder
) const {
2882 * Returns true if this item supports PaintWithClip, where the clipping
2883 * is used directly as the primitive geometry instead of needing an explicit
2886 virtual bool CanPaintWithClip(const DisplayItemClip
& aClip
) { return false; }
2889 * Same as |Paint()|, except provides a clip to use the geometry to draw with.
2890 * Must not be called unless |CanPaintWithClip()| returned true.
2892 virtual void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
2893 const DisplayItemClip
& aClip
) {
2894 MOZ_ASSERT_UNREACHABLE("PaintWithClip() is not implemented!");
2898 * Paint this item to some rendering context.
2900 virtual void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) = 0;
2903 * External storage used by |DisplayItemCache| to avoid hashmap lookups.
2904 * If an item is reused and has the cache index set, it means that
2905 * |DisplayItemCache| has assigned a cache slot for the item.
2907 Maybe
<uint16_t>& CacheIndex() { return mCacheIndex
; }
2909 void InvalidateItemCacheEntry() override
{
2910 // |nsPaintedDisplayItem|s may have |DisplayItemCache| entries
2911 // that no longer match after a mutation. The cache will notice
2912 // on its own that the entry is no longer in use, and free it.
2913 mCacheIndex
= Nothing();
2916 const HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
2917 void InitializeHitTestInfo(nsDisplayListBuilder
* aBuilder
) {
2918 mHitTestInfo
.Initialize(aBuilder
, Frame());
2919 SetHasHitTestInfo();
2923 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
2924 : nsPaintedDisplayItem(aBuilder
, aFrame
,
2925 aBuilder
->CurrentActiveScrolledRoot()) {}
2927 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
2928 const ActiveScrolledRoot
* aActiveScrolledRoot
)
2929 : nsDisplayItem(aBuilder
, aFrame
, aActiveScrolledRoot
) {}
2931 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
,
2932 const nsPaintedDisplayItem
& aOther
)
2933 : nsDisplayItem(aBuilder
, aOther
), mHitTestInfo(aOther
.mHitTestInfo
) {}
2936 HitTestInfo mHitTestInfo
;
2937 Maybe
<uint16_t> mCacheIndex
;
2940 template <typename T
>
2941 struct MOZ_HEAP_CLASS LinkedListNode
{
2942 explicit LinkedListNode(T aValue
) : mNext(nullptr), mValue(aValue
) {}
2943 LinkedListNode
* mNext
;
2947 template <typename T
>
2948 struct LinkedListIterator
{
2949 using iterator_category
= std::forward_iterator_tag
;
2950 using difference_type
= std::ptrdiff_t;
2951 using value_type
= T
;
2953 using reference
= T
&;
2954 using Node
= LinkedListNode
<T
>;
2956 explicit LinkedListIterator(Node
* aNode
= nullptr) : mNode(aNode
) {}
2958 bool HasNext() const { return mNode
!= nullptr; }
2960 LinkedListIterator
<T
>& operator++() {
2962 mNode
= mNode
->mNext
;
2966 bool operator==(const LinkedListIterator
<T
>& aOther
) const {
2967 return mNode
== aOther
.mNode
;
2970 bool operator!=(const LinkedListIterator
<T
>& aOther
) const {
2971 return mNode
!= aOther
.mNode
;
2974 const T
operator*() const {
2976 return mNode
->mValue
;
2981 return mNode
->mValue
;
2988 * Manages a singly-linked list of display list items.
2990 * Stepping upward through this list is very fast. Stepping downward is very
2991 * slow so we don't support it. The methods that need to step downward
2992 * (HitTest()) internally build a temporary array of all
2993 * the items while they do the downward traversal, so overall they're still
2994 * linear time. We have optimized for efficient AppendToTop() of both
2995 * items and lists, with minimal codesize.
2997 * Internal linked list nodes are allocated using arena allocator.
2999 class nsDisplayList
{
3001 using Node
= LinkedListNode
<nsDisplayItem
*>;
3002 using iterator
= LinkedListIterator
<nsDisplayItem
*>;
3003 using const_iterator
= iterator
;
3005 iterator
begin() { return iterator(mBottom
); }
3006 iterator
end() { return iterator(nullptr); }
3007 const_iterator
begin() const { return iterator(mBottom
); }
3008 const_iterator
end() const { return iterator(nullptr); }
3010 explicit nsDisplayList(nsDisplayListBuilder
* aBuilder
) : mBuilder(aBuilder
) {}
3012 nsDisplayList() = delete;
3013 nsDisplayList(const nsDisplayList
&) = delete;
3014 nsDisplayList
& operator=(const nsDisplayList
&) = delete;
3016 virtual ~nsDisplayList() {
3017 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3018 if (!mAllowNonEmptyDestruction
) {
3019 MOZ_RELEASE_ASSERT(IsEmpty(), "Nonempty list left over?");
3026 nsDisplayList(nsDisplayList
&& aOther
)
3027 : mBottom(aOther
.mBottom
),
3029 mLength(aOther
.mLength
),
3030 mBuilder(aOther
.mBuilder
) {
3034 nsDisplayList
& operator=(nsDisplayList
&& aOther
) {
3035 MOZ_RELEASE_ASSERT(mBuilder
== aOther
.mBuilder
);
3037 if (this != &aOther
) {
3038 MOZ_RELEASE_ASSERT(IsEmpty());
3039 mBottom
= std::move(aOther
.mBottom
);
3040 mTop
= std::move(aOther
.mTop
);
3041 mLength
= std::move(aOther
.mLength
);
3048 * Append an item to the top of the list.
3050 void AppendToTop(nsDisplayItem
* aItem
) {
3055 auto* next
= Allocate(aItem
);
3068 MOZ_ASSERT(mBottom
&& mTop
);
3069 MOZ_ASSERT(mTop
->mNext
== nullptr);
3072 template <typename T
, typename F
, typename
... Args
>
3073 void AppendNewToTop(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3075 AppendNewToTopWithIndex
<T
>(aBuilder
, aFrame
, 0,
3076 std::forward
<Args
>(aArgs
)...);
3079 template <typename T
, typename F
, typename
... Args
>
3080 void AppendNewToTopWithIndex(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3081 const uint16_t aIndex
, Args
&&... aArgs
) {
3082 nsDisplayItem
* item
= MakeDisplayItemWithIndex
<T
>(
3083 aBuilder
, aFrame
, aIndex
, std::forward
<Args
>(aArgs
)...);
3088 * Removes all items from aList and appends them to the top of this list.
3090 void AppendToTop(nsDisplayList
* aList
) {
3091 MOZ_ASSERT(aList
!= this);
3092 MOZ_RELEASE_ASSERT(mBuilder
== aList
->mBuilder
);
3094 if (aList
->IsEmpty()) {
3099 std::swap(mBottom
, aList
->mBottom
);
3100 std::swap(mTop
, aList
->mTop
);
3101 std::swap(mLength
, aList
->mLength
);
3103 MOZ_ASSERT(mTop
&& mTop
->mNext
== nullptr);
3104 mTop
->mNext
= aList
->mBottom
;
3106 mLength
+= aList
->mLength
;
3113 * Clears the display list.
3121 * Creates a shallow copy of this display list to |aDestination|.
3123 void CopyTo(nsDisplayList
* aDestination
) const {
3124 for (auto* item
: *this) {
3125 aDestination
->AppendToTop(item
);
3130 * Calls the function |aFn| for each display item in the display list.
3132 void ForEach(const std::function
<void(nsDisplayItem
*)>& aFn
) {
3133 for (auto* item
: *this) {
3138 * Remove all items from the list and call their destructors.
3140 virtual void DeleteAll(nsDisplayListBuilder
* aBuilder
);
3143 * @return the item at the bottom of the list, or null if the list is empty
3145 nsDisplayItem
* GetBottom() const {
3146 return mBottom
? mBottom
->mValue
: nullptr;
3150 * @return the item at the top of the list, or null if the list is empty
3152 nsDisplayItem
* GetTop() const { return mTop
? mTop
->mValue
: nullptr; }
3154 bool IsEmpty() const { return mBottom
== nullptr; }
3157 * @return the number of items in the list
3159 size_t Length() const { return mLength
; }
3162 * Stable sort the list by the z-order of Frame() on
3163 * each item. 'auto' is counted as zero.
3164 * It is assumed that the list is already in content document order.
3166 void SortByZOrder();
3169 * Stable sort the list by the tree order of the content of
3170 * Frame() on each item. z-index is ignored.
3171 * @param aCommonAncestor a common ancestor of all the content elements
3172 * associated with the display items, for speeding up tree order
3173 * checks, or nullptr if not known; it's only a hint, if it is not an
3174 * ancestor of some elements, then we lose performance but not correctness
3176 void SortByContentOrder(nsIContent
* aCommonAncestor
);
3179 * Sort the display list using a stable sort.
3180 * aComparator(Item item1, Item item2) should return true if item1 should go
3182 * We sort the items into increasing order.
3184 template <typename Item
, typename Comparator
>
3185 void Sort(const Comparator
& aComparator
) {
3187 // Only sort lists with more than one item.
3191 // Some casual local browsing testing suggests that a local preallocated
3192 // array of 20 items should be able to avoid a lot of dynamic allocations
3194 AutoTArray
<Item
, 20> items
;
3196 for (nsDisplayItem
* item
: TakeItems()) {
3197 items
.AppendElement(Item(item
));
3200 std::stable_sort(items
.begin(), items
.end(), aComparator
);
3202 for (Item
& item
: items
) {
3207 nsDisplayList
TakeItems() {
3208 nsDisplayList list
= std::move(*this);
3209 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3210 list
.mAllowNonEmptyDestruction
= true;
3215 nsDisplayItem
* RemoveBottom() {
3220 nsDisplayItem
* bottom
= mBottom
->mValue
;
3222 auto next
= mBottom
->mNext
;
3223 Deallocate(mBottom
);
3227 // No bottom item means no items at all.
3231 MOZ_ASSERT(mLength
> 0);
3238 * Paint the list to the rendering context. We assume that (0,0) in aCtx
3239 * corresponds to the origin of the reference frame. For best results,
3240 * aCtx's current transform should make (0,0) pixel-aligned. The
3241 * rectangle in aDirtyRect is painted, which *must* be contained in the
3242 * dirty rect used to construct the display list.
3244 * If aFlags contains PAINT_USE_WIDGET_LAYERS and
3245 * ShouldUseWidgetLayerManager() is set, then we will paint using
3246 * the reference frame's widget's layer manager (and ctx may be null),
3247 * otherwise we will use a temporary BasicLayerManager and ctx must
3250 * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
3251 * layer manager has already had BeginTransaction() called on it and
3252 * we should not call it again.
3254 * This must only be called on the root display list of the display list
3257 * We return the layer manager used for painting --- mainly so that
3258 * callers can dump its layer tree if necessary.
3262 PAINT_USE_WIDGET_LAYERS
= 0x01,
3263 PAINT_EXISTING_TRANSACTION
= 0x04,
3264 PAINT_IDENTICAL_DISPLAY_LIST
= 0x08
3266 void PaintRoot(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
3267 uint32_t aFlags
, Maybe
<double> aDisplayListBuildTime
);
3269 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
3270 int32_t aAppUnitsPerDevPixel
);
3273 * Get the bounds. Takes the union of the bounds of all children.
3274 * The result is not cached.
3276 nsRect
GetClippedBounds(nsDisplayListBuilder
* aBuilder
) const;
3279 * Get this list's bounds, respecting clips relative to aASR. The result is
3280 * the union of each item's clipped bounds with respect to aASR. That means
3281 * that if an item can move asynchronously with an ASR that is a descendant
3282 * of aASR, then the clipped bounds with respect to aASR will be the clip of
3283 * that item for aASR, because the item can move anywhere inside that clip.
3284 * If there is an item in this list which is not bounded with respect to
3285 * aASR (i.e. which does not have "finite bounds" with respect to aASR),
3286 * then this method trigger an assertion failure.
3287 * The optional aBuildingRect out argument can be set to non-null if the
3288 * caller is also interested to know the building rect. This can be used
3289 * to get the visible rect efficiently without traversing the display list
3292 nsRect
GetClippedBoundsWithRespectToASR(
3293 nsDisplayListBuilder
* aBuilder
, const ActiveScrolledRoot
* aASR
,
3294 nsRect
* aBuildingRect
= nullptr) const;
3297 * Returns the opaque region of this display list.
3299 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
) {
3302 for (nsDisplayItem
* item
: *this) {
3303 result
.OrWith(item
->GetOpaqueRegion(aBuilder
, &snap
));
3309 * Returns the bounds of the area that needs component alpha.
3311 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const {
3313 for (nsDisplayItem
* item
: *this) {
3314 bounds
.UnionRect(bounds
, item
->GetComponentAlphaBounds(aBuilder
));
3320 * Find the topmost display item that returns a non-null frame, and return
3323 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
3324 nsDisplayItem::HitTestState
* aState
,
3325 nsTArray
<nsIFrame
*>* aOutFrames
) const;
3327 * Compute the union of the visible rects of the items in the list. The
3328 * result is not cached.
3330 nsRect
GetBuildingRect() const;
3333 inline Node
* Allocate(nsDisplayItem
* aItem
) {
3335 mBuilder
->Allocate(sizeof(Node
), DisplayListArenaObjectId::LISTNODE
);
3336 return new (ptr
) Node(aItem
);
3339 inline void Deallocate(Node
* aNode
) {
3341 mBuilder
->Destroy(DisplayListArenaObjectId::LISTNODE
, aNode
);
3344 void DeallocateNodes() {
3345 Node
* current
= mBottom
;
3346 Node
* next
= nullptr;
3349 next
= current
->mNext
;
3350 Deallocate(current
);
3355 inline void SetEmpty() {
3361 Node
* mBottom
= nullptr;
3362 Node
* mTop
= nullptr;
3364 nsDisplayListBuilder
* mBuilder
= nullptr;
3366 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3367 // This checks that the invariant of display lists owning their items is held.
3368 bool mAllowNonEmptyDestruction
= false;
3373 * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
3374 * will put any generated items onto the appropriate list given here. It's
3375 * basically just a collection with one list for each separate stacking layer.
3376 * The lists themselves are external to this object and thus can be shared
3377 * with others. Some of the list pointers may even refer to the same list.
3379 class nsDisplayListSet
{
3382 * @return a list where one should place the border and/or background for
3383 * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
3385 nsDisplayList
* BorderBackground() const { return mLists
[0]; }
3387 * @return a list where one should place the borders and/or backgrounds for
3388 * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
3390 nsDisplayList
* BlockBorderBackgrounds() const { return mLists
[1]; }
3392 * @return a list where one should place descendant floats (step 5 of
3393 * CSS 2.1 appendix E)
3395 nsDisplayList
* Floats() const { return mLists
[2]; }
3397 * @return a list where one should place the (pseudo) stacking contexts
3398 * for descendants of this frame (everything from steps 3, 7 and 8
3399 * of CSS 2.1 appendix E)
3401 nsDisplayList
* PositionedDescendants() const { return mLists
[3]; }
3403 * @return a list where one should place the outlines
3404 * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
3406 nsDisplayList
* Outlines() const { return mLists
[4]; }
3408 * @return a list where one should place all other content
3410 nsDisplayList
* Content() const { return mLists
[5]; }
3412 const std::array
<nsDisplayList
*, 6>& Lists() const { return mLists
; }
3415 * Clears all the display lists in the set.
3418 for (auto* list
: mLists
) {
3425 * Deletes all the display items in the set.
3427 void DeleteAll(nsDisplayListBuilder
* aBuilder
) {
3428 for (auto* list
: mLists
) {
3429 list
->DeleteAll(aBuilder
);
3433 nsDisplayListSet(nsDisplayList
* aBorderBackground
,
3434 nsDisplayList
* aBlockBorderBackgrounds
,
3435 nsDisplayList
* aFloats
, nsDisplayList
* aContent
,
3436 nsDisplayList
* aPositionedDescendants
,
3437 nsDisplayList
* aOutlines
)
3438 : mLists
{aBorderBackground
, aBlockBorderBackgrounds
, aFloats
,
3439 aContent
, aPositionedDescendants
, aOutlines
} {}
3442 * A copy constructor that lets the caller override the BorderBackground
3445 nsDisplayListSet(const nsDisplayListSet
& aLists
,
3446 nsDisplayList
* aBorderBackground
)
3447 : mLists(aLists
.mLists
) {
3448 mLists
[0] = aBorderBackground
;
3452 * Returns true if all the display lists in the display list set are empty.
3454 bool IsEmpty() const {
3455 for (auto* list
: mLists
) {
3456 if (!list
->IsEmpty()) {
3465 * Calls the function |aFn| for each display item in the display list set.
3467 void ForEach(const std::function
<void(nsDisplayItem
*)>& aFn
) const {
3468 for (auto* list
: mLists
) {
3474 * Creates a shallow copy of this display list set to |aDestination|.
3476 void CopyTo(const nsDisplayListSet
& aDestination
) const;
3479 * Move all display items in our lists to top of the corresponding lists in
3482 void MoveTo(const nsDisplayListSet
& aDestination
) const;
3485 // This class is only used on stack, so we don't have to worry about leaking
3486 // it. Don't let us be heap-allocated!
3487 void* operator new(size_t sz
) noexcept(true);
3489 std::array
<nsDisplayList
*, 6> mLists
;
3493 * A specialization of nsDisplayListSet where the lists are actually internal
3494 * to the object, and all distinct.
3496 struct nsDisplayListCollection
: public nsDisplayListSet
{
3497 explicit nsDisplayListCollection(nsDisplayListBuilder
* aBuilder
)
3498 : nsDisplayListSet(&mLists
[0], &mLists
[1], &mLists
[2], &mLists
[3],
3499 &mLists
[4], &mLists
[5]),
3500 mLists
{nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
},
3501 nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
},
3502 nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
}} {}
3505 * Sort all lists by content order.
3507 void SortAllByContentOrder(nsIContent
* aCommonAncestor
) {
3508 for (auto& mList
: mLists
) {
3509 mList
.SortByContentOrder(aCommonAncestor
);
3514 * Serialize this display list collection into a display list with the items
3515 * in the correct Z order.
3516 * @param aOutList the result display list
3517 * @param aContent the content element to use for content ordering
3519 void SerializeWithCorrectZOrder(nsDisplayList
* aOutResultList
,
3520 nsIContent
* aContent
);
3523 // This class is only used on stack, so we don't have to worry about leaking
3524 // it. Don't let us be heap-allocated!
3525 void* operator new(size_t sz
) noexcept(true);
3527 nsDisplayList mLists
[6];
3531 * A display list that also retains the partial build
3532 * information (in the form of a DAG) used to create it.
3534 * Display lists built from a partial list aren't necessarily
3535 * in the same order as a full build, and the DAG retains
3536 * the information needing to interpret the current
3539 class RetainedDisplayList
: public nsDisplayList
{
3541 explicit RetainedDisplayList(nsDisplayListBuilder
* aBuilder
)
3542 : nsDisplayList(aBuilder
) {}
3544 RetainedDisplayList(RetainedDisplayList
&& aOther
)
3545 : nsDisplayList(std::move(aOther
)), mDAG(std::move(aOther
.mDAG
)) {}
3547 RetainedDisplayList(const RetainedDisplayList
&) = delete;
3548 RetainedDisplayList
& operator=(const RetainedDisplayList
&) = delete;
3550 ~RetainedDisplayList() override
{
3551 MOZ_ASSERT(mOldItems
.IsEmpty(), "Must empty list before destroying");
3554 RetainedDisplayList
& operator=(RetainedDisplayList
&& aOther
) {
3555 MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
3556 MOZ_ASSERT(mOldItems
.IsEmpty(), "Can only move into an empty list!");
3558 nsDisplayList::operator=(std::move(aOther
));
3559 mDAG
= std::move(aOther
.mDAG
);
3560 mOldItems
= std::move(aOther
.mOldItems
);
3564 RetainedDisplayList
& operator=(nsDisplayList
&& aOther
) {
3565 MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
3566 MOZ_ASSERT(mOldItems
.IsEmpty(), "Can only move into an empty list!");
3567 nsDisplayList::operator=(std::move(aOther
));
3571 void DeleteAll(nsDisplayListBuilder
* aBuilder
) override
{
3572 for (OldItemInfo
& i
: mOldItems
) {
3573 if (i
.mItem
&& i
.mOwnsItem
) {
3574 i
.mItem
->Destroy(aBuilder
);
3575 MOZ_ASSERT(!GetBottom(),
3576 "mOldItems should not be owning items if we also have items "
3577 "in the normal list");
3582 nsDisplayList::DeleteAll(aBuilder
);
3585 void AddSizeOfExcludingThis(nsWindowSizes
&) const;
3587 DirectedAcyclicGraph
<MergedListUnits
> mDAG
;
3589 // Temporary state initialized during the preprocess pass
3590 // of RetainedDisplayListBuilder and then used during merging.
3591 nsTArray
<OldItemInfo
> mOldItems
;
3594 class nsDisplayContainer final
: public nsDisplayItem
{
3596 nsDisplayContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3597 const ActiveScrolledRoot
* aActiveScrolledRoot
,
3598 nsDisplayList
* aList
);
3600 ~nsDisplayContainer() override
{ MOZ_COUNT_DTOR(nsDisplayContainer
); }
3602 NS_DISPLAY_DECL_NAME("nsDisplayContainer", TYPE_CONTAINER
)
3604 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
3605 mChildren
.DeleteAll(aBuilder
);
3606 nsDisplayItem::Destroy(aBuilder
);
3609 bool CreateWebRenderCommands(
3610 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3611 const StackingContextHelper
& aSc
,
3612 layers::RenderRootStateManager
* aManager
,
3613 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3615 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3617 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
3619 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
3620 bool* aSnap
) const override
;
3622 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
{
3626 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
3627 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
3628 return GetChildren();
3631 Maybe
<nsRect
> GetClipWithRespectToASR(
3632 nsDisplayListBuilder
* aBuilder
,
3633 const ActiveScrolledRoot
* aASR
) const override
;
3635 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
3636 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
3638 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
3642 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
3643 bool aStore
) override
{
3644 MOZ_ASSERT_UNREACHABLE("nsDisplayContainer does not support clipping");
3647 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
3650 mutable RetainedDisplayList mChildren
;
3655 * Use this class to implement not-very-frequently-used display items
3656 * that are not opaque, do not receive events, and are bounded by a frame's
3659 * This should not be used for display items which are created frequently,
3660 * because each item is one or two pointers bigger than an item from a
3661 * custom display item class could be, and fractionally slower. However it does
3662 * save code size. We use this for infrequently-used item types.
3664 class nsDisplayGeneric
: public nsPaintedDisplayItem
{
3666 typedef void (*PaintCallback
)(nsIFrame
* aFrame
, gfx::DrawTarget
* aDrawTarget
,
3667 const nsRect
& aDirtyRect
, nsPoint aFramePt
);
3669 // XXX: should be removed eventually
3670 typedef void (*OldPaintCallback
)(nsIFrame
* aFrame
, gfxContext
* aCtx
,
3671 const nsRect
& aDirtyRect
, nsPoint aFramePt
);
3673 nsDisplayGeneric(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3674 PaintCallback aPaint
, const char* aName
,
3675 DisplayItemType aType
)
3676 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3680 MOZ_COUNT_CTOR(nsDisplayGeneric
);
3684 // XXX: should be removed eventually
3685 nsDisplayGeneric(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3686 OldPaintCallback aOldPaint
, const char* aName
,
3687 DisplayItemType aType
)
3688 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3690 mOldPaint(aOldPaint
),
3692 MOZ_COUNT_CTOR(nsDisplayGeneric
);
3696 constexpr static DisplayItemType
ItemType() {
3697 return DisplayItemType::TYPE_GENERIC
;
3700 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayGeneric
)
3702 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
3703 MOZ_ASSERT(!!mPaint
!= !!mOldPaint
);
3705 mPaint(mFrame
, aCtx
->GetDrawTarget(), GetPaintRect(aBuilder
, aCtx
),
3706 ToReferenceFrame());
3708 mOldPaint(mFrame
, aCtx
, GetPaintRect(aBuilder
, aCtx
), ToReferenceFrame());
3712 const char* Name() const override
{ return mName
; }
3714 // This override is needed because GetType() for nsDisplayGeneric subclasses
3715 // does not match TYPE_GENERIC that was used to allocate the object.
3716 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
3717 this->~nsDisplayGeneric();
3718 aBuilder
->Destroy(DisplayItemType::TYPE_GENERIC
, this);
3722 void* operator new(size_t aSize
, nsDisplayListBuilder
* aBuilder
) {
3723 return aBuilder
->Allocate(aSize
, DisplayItemType::TYPE_GENERIC
);
3726 template <typename T
, typename F
, typename
... Args
>
3727 friend T
* MakeDisplayItemWithIndex(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3728 const uint16_t aIndex
, Args
&&... aArgs
);
3730 PaintCallback mPaint
;
3731 OldPaintCallback mOldPaint
; // XXX: should be removed eventually
3735 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
3737 * This class implements painting of reflow counts. Ideally, we would simply
3738 * make all the frame names be those returned by nsIFrame::GetFrameName
3739 * (except that tosses in the content tag name!) and support only one color
3740 * and eliminate this class altogether in favor of nsDisplayGeneric, but for
3741 * the time being we can't pass args to a PaintCallback, so just have a
3742 * separate class to do the right thing. Sadly, this alsmo means we need to
3743 * hack all leaf frame classes to handle this.
3745 * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
3746 * here... I could switch it all to nscolor, but why bother?
3748 class nsDisplayReflowCount
: public nsPaintedDisplayItem
{
3750 nsDisplayReflowCount(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3751 const char* aFrameName
, uint32_t aColor
= 0)
3752 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3753 mFrameName(aFrameName
),
3755 MOZ_COUNT_CTOR(nsDisplayReflowCount
);
3758 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayReflowCount
)
3760 NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT
)
3762 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3765 const char* mFrameName
;
3769 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
3771 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3772 PresShell()->IsPaintingFrameCounts()) { \
3773 aLists.Outlines()->AppendNewToTop<mozilla::nsDisplayReflowCount>( \
3774 aBuilder, this, _name); \
3778 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
3780 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3781 PresShell()->IsPaintingFrameCounts()) { \
3782 aLists.Outlines()->AppendNewToTop<mozilla::nsDisplayReflowCount>( \
3783 aBuilder, this, _name, _color); \
3788 Macro to be used for classes that don't actually implement BuildDisplayList
3790 # define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
3791 void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
3792 const nsRect& aDirtyRect, \
3793 const nsDisplayListSet& aLists) { \
3794 DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
3795 _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
3798 #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3800 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
3801 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
3802 # define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
3804 #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3806 class nsDisplayCaret
: public nsPaintedDisplayItem
{
3808 nsDisplayCaret(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aCaretFrame
);
3810 #ifdef NS_BUILD_REFCNT_LOGGING
3811 ~nsDisplayCaret() override
;
3814 NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET
)
3816 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3817 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3818 bool CreateWebRenderCommands(
3819 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3820 const StackingContextHelper
& aSc
,
3821 layers::RenderRootStateManager
* aManager
,
3822 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3825 RefPtr
<nsCaret
> mCaret
;
3830 * The standard display item to paint the CSS borders of a frame.
3832 class nsDisplayBorder
: public nsPaintedDisplayItem
{
3834 nsDisplayBorder(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
3836 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBorder
)
3838 NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER
)
3840 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
3841 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3842 bool CreateWebRenderCommands(
3843 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3844 const StackingContextHelper
& aSc
,
3845 layers::RenderRootStateManager
* aManager
,
3846 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3847 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3848 nsDisplayItemGeometry
* AllocateGeometry(
3849 nsDisplayListBuilder
* aBuilder
) override
;
3850 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
3851 const nsDisplayItemGeometry
* aGeometry
,
3852 nsRegion
* aInvalidRegion
) const override
;
3854 nsRegion
GetTightBounds(nsDisplayListBuilder
* aBuilder
,
3855 bool* aSnap
) const override
{
3857 return CalculateBounds
<nsRegion
>(*mFrame
->StyleBorder());
3861 template <typename T
>
3862 T
CalculateBounds(const nsStyleBorder
& aStyleBorder
) const {
3863 nsRect
borderBounds(ToReferenceFrame(), mFrame
->GetSize());
3864 if (aStyleBorder
.IsBorderImageSizeAvailable()) {
3865 borderBounds
.Inflate(aStyleBorder
.GetImageOutset());
3866 return borderBounds
;
3869 nsMargin border
= aStyleBorder
.GetComputedBorder();
3871 if (border
.top
> 0) {
3872 result
= nsRect(borderBounds
.X(), borderBounds
.Y(), borderBounds
.Width(),
3875 if (border
.right
> 0) {
3876 result
.OrWith(nsRect(borderBounds
.XMost() - border
.right
,
3877 borderBounds
.Y(), border
.right
,
3878 borderBounds
.Height()));
3880 if (border
.bottom
> 0) {
3881 result
.OrWith(nsRect(borderBounds
.X(),
3882 borderBounds
.YMost() - border
.bottom
,
3883 borderBounds
.Width(), border
.bottom
));
3885 if (border
.left
> 0) {
3886 result
.OrWith(nsRect(borderBounds
.X(), borderBounds
.Y(), border
.left
,
3887 borderBounds
.Height()));
3891 if (mFrame
->GetBorderRadii(radii
)) {
3892 if (border
.left
> 0 || border
.top
> 0) {
3893 nsSize
cornerSize(radii
[eCornerTopLeftX
], radii
[eCornerTopLeftY
]);
3894 result
.OrWith(nsRect(borderBounds
.TopLeft(), cornerSize
));
3896 if (border
.top
> 0 || border
.right
> 0) {
3897 nsSize
cornerSize(radii
[eCornerTopRightX
], radii
[eCornerTopRightY
]);
3899 nsRect(borderBounds
.TopRight() - nsPoint(cornerSize
.width
, 0),
3902 if (border
.right
> 0 || border
.bottom
> 0) {
3903 nsSize
cornerSize(radii
[eCornerBottomRightX
],
3904 radii
[eCornerBottomRightY
]);
3905 result
.OrWith(nsRect(borderBounds
.BottomRight() -
3906 nsPoint(cornerSize
.width
, cornerSize
.height
),
3909 if (border
.bottom
> 0 || border
.left
> 0) {
3910 nsSize
cornerSize(radii
[eCornerBottomLeftX
], radii
[eCornerBottomLeftY
]);
3912 nsRect(borderBounds
.BottomLeft() - nsPoint(0, cornerSize
.height
),
3923 * A simple display item that just renders a solid color across the
3924 * specified bounds. For canvas frames (in the CSS sense) we split off the
3925 * drawing of the background color into this class (from nsDisplayBackground
3926 * via nsDisplayCanvasBackground). This is done so that we can always draw a
3927 * background color to avoid ugly flashes of white when we can't draw a full
3928 * frame tree (ie when a page is loading). The bounds can differ from the
3929 * frame's bounds -- this is needed when a frame/iframe is loading and there
3930 * is not yet a frame tree to go in the frame/iframe so we use the subdoc
3931 * frame of the parent document as a standin.
3933 class nsDisplaySolidColorBase
: public nsPaintedDisplayItem
{
3935 nsDisplaySolidColorBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3937 : nsPaintedDisplayItem(aBuilder
, aFrame
), mColor(aColor
) {}
3939 nsDisplayItemGeometry
* AllocateGeometry(
3940 nsDisplayListBuilder
* aBuilder
) override
{
3941 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
);
3944 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
3945 const nsDisplayItemGeometry
* aGeometry
,
3946 nsRegion
* aInvalidRegion
) const override
{
3947 const nsDisplaySolidColorGeometry
* geometry
=
3948 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
3949 if (mColor
!= geometry
->mColor
) {
3951 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
3954 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
3957 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
3958 bool* aSnap
) const override
{
3961 if (NS_GET_A(mColor
) == 255) {
3962 result
= GetBounds(aBuilder
, aSnap
);
3967 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
{
3968 return Some(mColor
);
3975 class nsDisplaySolidColor
: public nsDisplaySolidColorBase
{
3977 nsDisplaySolidColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3978 const nsRect
& aBounds
, nscolor aColor
,
3979 bool aCanBeReused
= true)
3980 : nsDisplaySolidColorBase(aBuilder
, aFrame
, aColor
),
3982 mIsCheckerboardBackground(false) {
3983 NS_ASSERTION(NS_GET_A(aColor
) > 0,
3984 "Don't create invisible nsDisplaySolidColors!");
3985 MOZ_COUNT_CTOR(nsDisplaySolidColor
);
3986 if (!aCanBeReused
) {
3991 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColor
)
3993 NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR
)
3995 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3996 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3997 void WriteDebugInfo(std::stringstream
& aStream
) override
;
3998 void SetIsCheckerboardBackground() { mIsCheckerboardBackground
= true; }
3999 bool CreateWebRenderCommands(
4000 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4001 const StackingContextHelper
& aSc
,
4002 layers::RenderRootStateManager
* aManager
,
4003 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4005 int32_t ZIndex() const override
{
4006 if (mOverrideZIndex
) {
4007 return mOverrideZIndex
.value();
4009 return nsDisplaySolidColorBase::ZIndex();
4012 void SetOverrideZIndex(int32_t aZIndex
) { mOverrideZIndex
= Some(aZIndex
); }
4016 bool mIsCheckerboardBackground
;
4017 Maybe
<int32_t> mOverrideZIndex
;
4021 * A display item that renders a solid color over a region. This is not
4022 * exposed through CSS, its only purpose is efficient invalidation of
4023 * the find bar highlighter dimmer.
4025 class nsDisplaySolidColorRegion
: public nsPaintedDisplayItem
{
4027 nsDisplaySolidColorRegion(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4028 const nsRegion
& aRegion
, nscolor aColor
)
4029 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4031 mColor(gfx::sRGBColor::FromABGR(aColor
)) {
4032 NS_ASSERTION(NS_GET_A(aColor
) > 0,
4033 "Don't create invisible nsDisplaySolidColorRegions!");
4034 MOZ_COUNT_CTOR(nsDisplaySolidColorRegion
);
4037 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColorRegion
)
4039 NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION
)
4041 nsDisplayItemGeometry
* AllocateGeometry(
4042 nsDisplayListBuilder
* aBuilder
) override
{
4043 return new nsDisplaySolidColorRegionGeometry(this, aBuilder
, mRegion
,
4047 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4048 const nsDisplayItemGeometry
* aGeometry
,
4049 nsRegion
* aInvalidRegion
) const override
{
4050 const nsDisplaySolidColorRegionGeometry
* geometry
=
4051 static_cast<const nsDisplaySolidColorRegionGeometry
*>(aGeometry
);
4052 if (mColor
== geometry
->mColor
) {
4053 aInvalidRegion
->Xor(geometry
->mRegion
, mRegion
);
4055 aInvalidRegion
->Or(geometry
->mRegion
.GetBounds(), mRegion
.GetBounds());
4059 bool CreateWebRenderCommands(
4060 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4061 const StackingContextHelper
& aSc
,
4062 layers::RenderRootStateManager
* aManager
,
4063 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4066 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4067 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4068 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4072 gfx::sRGBColor mColor
;
4075 enum class AppendedBackgroundType
: uint8_t {
4082 * A display item to paint one background-image for a frame. Each background
4083 * image layer gets its own nsDisplayBackgroundImage.
4085 class nsDisplayBackgroundImage
: public nsPaintedDisplayItem
{
4088 nsDisplayListBuilder
* builder
;
4089 const ComputedStyle
* backgroundStyle
;
4090 nsCOMPtr
<imgIContainer
> image
;
4091 nsRect backgroundRect
;
4096 bool shouldFixToViewport
;
4100 * aLayer signifies which background layer this item represents.
4101 * aIsThemed should be the value of aFrame->IsThemed.
4102 * aBackgroundStyle should be the result of
4103 * nsCSSRendering::FindBackground, or null if FindBackground returned false.
4104 * aBackgroundRect is relative to aFrame.
4106 static InitData
GetInitData(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4107 uint16_t aLayer
, const nsRect
& aBackgroundRect
,
4108 const ComputedStyle
* aBackgroundStyle
);
4110 explicit nsDisplayBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4111 nsIFrame
* aFrame
, const InitData
& aInitData
,
4112 nsIFrame
* aFrameForBounds
= nullptr);
4113 ~nsDisplayBackgroundImage() override
;
4115 NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND
)
4118 * This will create and append new items for all the layers of the
4119 * background. Returns the type of background that was appended.
4120 * aAllowWillPaintBorderOptimization should usually be left at true, unless
4121 * aFrame has special border drawing that causes opaque borders to not
4122 * actually be opaque.
4124 static AppendedBackgroundType
AppendBackgroundItemsToTop(
4125 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4126 const nsRect
& aBackgroundRect
, nsDisplayList
* aList
,
4127 bool aAllowWillPaintBorderOptimization
= true,
4128 const nsRect
& aBackgroundOriginRect
= nsRect(),
4129 nsIFrame
* aSecondaryReferenceFrame
= nullptr,
4130 Maybe
<nsDisplayListBuilder::AutoBuildingDisplayList
>*
4131 aAutoBuildingDisplayList
= nullptr);
4133 bool CreateWebRenderCommands(
4134 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4135 const StackingContextHelper
& aSc
,
4136 layers::RenderRootStateManager
* aManager
,
4137 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4138 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4139 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4140 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4141 bool* aSnap
) const override
;
4142 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4144 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4145 nsDisplayListBuilder
* aBuilder
) const override
;
4148 * GetBounds() returns the background painting area.
4150 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4152 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4155 * Return the background positioning area.
4156 * (GetBounds() returns the background painting area.)
4157 * Can be called only when mBackgroundStyle is non-null.
4159 nsRect
GetPositioningArea() const;
4162 * Returns true if existing rendered pixels of this display item may need
4163 * to be redrawn if the positioning area size changes but its position does
4165 * If false, only the changed painting area needs to be redrawn when the
4166 * positioning area size changes but its position does not.
4168 bool RenderingMightDependOnPositioningAreaSizeChange() const;
4170 nsDisplayItemGeometry
* AllocateGeometry(
4171 nsDisplayListBuilder
* aBuilder
) override
{
4172 return new nsDisplayBackgroundGeometry(this, aBuilder
);
4175 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4176 const nsDisplayItemGeometry
* aGeometry
,
4177 nsRegion
* aInvalidRegion
) const override
;
4178 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
4179 return mShouldFixToViewport
;
4182 nsRect
GetDestRect() const { return mDestRect
; }
4184 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4186 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4187 if (!aBuilder
->IsRetainingDisplayList() || mDependentFrame
== aFrame
) {
4190 mDependentFrame
= aFrame
;
4192 mDependentFrame
->AddDisplayItem(this);
4196 void RemoveFrame(nsIFrame
* aFrame
) override
{
4197 if (aFrame
== mDependentFrame
) {
4198 mDependentFrame
= nullptr;
4200 nsPaintedDisplayItem::RemoveFrame(aFrame
);
4203 // Match https://w3c.github.io/paint-timing/#contentful-image
4204 bool IsContentful() const override
{
4205 const auto& styleImage
=
4206 mBackgroundStyle
->StyleBackground()->mImage
.mLayers
[mLayer
].mImage
;
4208 return styleImage
.IsSizeAvailable() && styleImage
.FinalImage().IsUrl();
4212 bool CanBuildWebRenderDisplayItems(layers::WebRenderLayerManager
* aManager
,
4213 nsDisplayListBuilder
* aBuilder
) const;
4214 nsRect
GetBoundsInternal(nsDisplayListBuilder
* aBuilder
,
4215 nsIFrame
* aFrameForBounds
= nullptr);
4217 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4218 const nsRect
& aBounds
, nsRect
* aClipRect
);
4220 // Cache the result of nsCSSRendering::FindBackground. Always null if
4221 // mIsThemed is true or if FindBackground returned false.
4222 RefPtr
<const ComputedStyle
> mBackgroundStyle
;
4223 nsCOMPtr
<imgIContainer
> mImage
;
4224 nsIFrame
* mDependentFrame
;
4225 nsRect mBackgroundRect
; // relative to the reference frame
4228 /* Bounds of this display item */
4231 bool mIsRasterImage
;
4232 /* Whether the image should be treated as fixed to the viewport. */
4233 bool mShouldFixToViewport
;
4237 * A display item to paint background image for table. For table parts, such
4238 * as row, row group, col, col group, when drawing its background, we'll
4239 * create separate background image display item for its containning cell.
4240 * Those background image display items will reference to same DisplayItemData
4241 * if we keep the mFrame point to cell's ancestor frame. We don't want to this
4242 * happened bacause share same DisplatItemData will cause many bugs. So that
4243 * we let mFrame point to cell frame and store the table type of the ancestor
4244 * frame. And use mFrame and table type as key to generate DisplayItemData to
4245 * avoid sharing DisplayItemData.
4247 * Also store ancestor frame as mStyleFrame for all rendering informations.
4249 class nsDisplayTableBackgroundImage
: public nsDisplayBackgroundImage
{
4251 nsDisplayTableBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4252 nsIFrame
* aFrame
, const InitData
& aData
,
4253 nsIFrame
* aCellFrame
);
4254 ~nsDisplayTableBackgroundImage() override
;
4256 NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE
)
4258 bool IsInvalid(nsRect
& aRect
) const override
;
4260 nsIFrame
* FrameForInvalidation() const override
{ return mStyleFrame
; }
4262 void RemoveFrame(nsIFrame
* aFrame
) override
{
4263 if (aFrame
== mStyleFrame
) {
4264 mStyleFrame
= nullptr;
4267 nsDisplayBackgroundImage::RemoveFrame(aFrame
);
4271 nsIFrame
* StyleFrame() const override
{ return mStyleFrame
; }
4272 nsIFrame
* mStyleFrame
;
4276 * A display item to paint the native theme background for a frame.
4278 class nsDisplayThemedBackground
: public nsPaintedDisplayItem
{
4280 nsDisplayThemedBackground(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4281 const nsRect
& aBackgroundRect
);
4283 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayThemedBackground
)
4285 NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND
)
4287 void Init(nsDisplayListBuilder
* aBuilder
);
4289 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4290 aBuilder
->UnregisterThemeGeometry(this);
4291 nsPaintedDisplayItem::Destroy(aBuilder
);
4294 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4295 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4296 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4297 bool* aSnap
) const override
;
4298 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4299 bool CreateWebRenderCommands(
4300 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4301 const StackingContextHelper
& aSc
,
4302 layers::RenderRootStateManager
* aManager
,
4303 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4305 bool ShouldUseBlobRenderingForFallback() const override
{
4306 return !XRE_IsParentProcess();
4310 * GetBounds() returns the background painting area.
4312 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4314 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4317 * Return the background positioning area.
4318 * (GetBounds() returns the background painting area.)
4319 * Can be called only when mBackgroundStyle is non-null.
4321 nsRect
GetPositioningArea() const;
4324 * Return whether our frame's document does not have the state
4325 * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
4327 bool IsWindowActive() const;
4329 nsDisplayItemGeometry
* AllocateGeometry(
4330 nsDisplayListBuilder
* aBuilder
) override
{
4331 return new nsDisplayThemedBackgroundGeometry(this, aBuilder
);
4334 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4335 const nsDisplayItemGeometry
* aGeometry
,
4336 nsRegion
* aInvalidRegion
) const override
;
4338 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4341 nsRect
GetBoundsInternal();
4343 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4344 const nsRect
& aBounds
, nsRect
* aClipRect
);
4346 nsRect mBackgroundRect
;
4348 nsITheme::Transparency mThemeTransparency
;
4349 StyleAppearance mAppearance
;
4352 class nsDisplayTableThemedBackground
: public nsDisplayThemedBackground
{
4354 nsDisplayTableThemedBackground(nsDisplayListBuilder
* aBuilder
,
4356 const nsRect
& aBackgroundRect
,
4357 nsIFrame
* aAncestorFrame
)
4358 : nsDisplayThemedBackground(aBuilder
, aFrame
, aBackgroundRect
),
4359 mAncestorFrame(aAncestorFrame
) {
4360 if (aBuilder
->IsRetainingDisplayList()) {
4361 mAncestorFrame
->AddDisplayItem(this);
4365 ~nsDisplayTableThemedBackground() override
{
4366 if (mAncestorFrame
) {
4367 mAncestorFrame
->RemoveDisplayItem(this);
4371 NS_DISPLAY_DECL_NAME("TableThemedBackground",
4372 TYPE_TABLE_THEMED_BACKGROUND_IMAGE
)
4374 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4376 void RemoveFrame(nsIFrame
* aFrame
) override
{
4377 if (aFrame
== mAncestorFrame
) {
4378 mAncestorFrame
= nullptr;
4381 nsDisplayThemedBackground::RemoveFrame(aFrame
);
4385 nsIFrame
* StyleFrame() const override
{ return mAncestorFrame
; }
4386 nsIFrame
* mAncestorFrame
;
4389 class nsDisplayBackgroundColor
: public nsPaintedDisplayItem
{
4391 nsDisplayBackgroundColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4392 const nsRect
& aBackgroundRect
,
4393 const ComputedStyle
* aBackgroundStyle
,
4394 const nscolor
& aColor
)
4395 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4396 mBackgroundRect(aBackgroundRect
),
4397 mHasStyle(aBackgroundStyle
),
4398 mDependentFrame(nullptr),
4399 mColor(gfx::sRGBColor::FromABGR(aColor
)) {
4402 aBackgroundStyle
->StyleBackground()->BottomLayer().mClip
;
4404 MOZ_ASSERT(aBuilder
->IsForEventDelivery());
4408 ~nsDisplayBackgroundColor() override
{
4409 if (mDependentFrame
) {
4410 mDependentFrame
->RemoveDisplayItem(this);
4414 NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR
)
4416 bool HasBackgroundClipText() const {
4417 MOZ_ASSERT(mHasStyle
);
4418 return mBottomLayerClip
== StyleGeometryBox::Text
;
4421 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4422 void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4423 const DisplayItemClip
& aClip
) override
;
4424 bool CreateWebRenderCommands(
4425 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4426 const StackingContextHelper
& aSc
,
4427 layers::RenderRootStateManager
* aManager
,
4428 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4429 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4430 bool* aSnap
) const override
;
4431 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4432 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4433 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4434 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4435 nsDisplayListBuilder
* aBuilder
) const override
;
4437 float GetOpacity() const { return mColor
.a
; }
4439 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
4441 return mBackgroundRect
;
4444 bool CanPaintWithClip(const DisplayItemClip
& aClip
) override
{
4445 if (HasBackgroundClipText()) {
4449 if (aClip
.GetRoundedRectCount() > 1) {
4456 nsDisplayItemGeometry
* AllocateGeometry(
4457 nsDisplayListBuilder
* aBuilder
) override
{
4458 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
.ToABGR());
4461 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4462 const nsDisplayItemGeometry
* aGeometry
,
4463 nsRegion
* aInvalidRegion
) const override
{
4464 const nsDisplaySolidColorGeometry
* geometry
=
4465 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
4467 if (mColor
.ToABGR() != geometry
->mColor
) {
4469 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
4472 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
4475 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4477 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4478 if (!aBuilder
->IsRetainingDisplayList() || mDependentFrame
== aFrame
) {
4481 mDependentFrame
= aFrame
;
4483 mDependentFrame
->AddDisplayItem(this);
4487 void RemoveFrame(nsIFrame
* aFrame
) override
{
4488 if (aFrame
== mDependentFrame
) {
4489 mDependentFrame
= nullptr;
4492 nsPaintedDisplayItem::RemoveFrame(aFrame
);
4495 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4497 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
4500 const nsRect mBackgroundRect
;
4501 const bool mHasStyle
;
4502 StyleGeometryBox mBottomLayerClip
;
4503 nsIFrame
* mDependentFrame
;
4504 gfx::sRGBColor mColor
;
4507 class nsDisplayTableBackgroundColor
: public nsDisplayBackgroundColor
{
4509 nsDisplayTableBackgroundColor(nsDisplayListBuilder
* aBuilder
,
4510 nsIFrame
* aFrame
, const nsRect
& aBackgroundRect
,
4511 const ComputedStyle
* aBackgroundStyle
,
4512 const nscolor
& aColor
, nsIFrame
* aAncestorFrame
)
4513 : nsDisplayBackgroundColor(aBuilder
, aFrame
, aBackgroundRect
,
4514 aBackgroundStyle
, aColor
),
4515 mAncestorFrame(aAncestorFrame
) {
4516 if (aBuilder
->IsRetainingDisplayList()) {
4517 mAncestorFrame
->AddDisplayItem(this);
4521 ~nsDisplayTableBackgroundColor() override
{
4522 if (mAncestorFrame
) {
4523 mAncestorFrame
->RemoveDisplayItem(this);
4527 NS_DISPLAY_DECL_NAME("TableBackgroundColor", TYPE_TABLE_BACKGROUND_COLOR
)
4529 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4531 void RemoveFrame(nsIFrame
* aFrame
) override
{
4532 if (aFrame
== mAncestorFrame
) {
4533 mAncestorFrame
= nullptr;
4536 nsDisplayBackgroundColor::RemoveFrame(aFrame
);
4539 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
{
4544 nsIFrame
* mAncestorFrame
;
4548 * The standard display item to paint the outer CSS box-shadows of a frame.
4550 class nsDisplayBoxShadowOuter final
: public nsPaintedDisplayItem
{
4552 nsDisplayBoxShadowOuter(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4553 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4554 MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter
);
4555 mBounds
= GetBoundsInternal();
4558 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowOuter
)
4560 NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER
)
4562 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4563 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4564 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
4565 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4566 const nsDisplayItemGeometry
* aGeometry
,
4567 nsRegion
* aInvalidRegion
) const override
;
4569 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4570 nsDisplayListBuilder
* aBuilder
) const override
{
4571 return CanBuildWebRenderDisplayItems();
4574 bool CanBuildWebRenderDisplayItems() const;
4575 bool CreateWebRenderCommands(
4576 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4577 const StackingContextHelper
& aSc
,
4578 layers::RenderRootStateManager
* aManager
,
4579 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4580 nsRect
GetBoundsInternal();
4587 * The standard display item to paint the inner CSS box-shadows of a frame.
4589 class nsDisplayBoxShadowInner
: public nsPaintedDisplayItem
{
4591 nsDisplayBoxShadowInner(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4592 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4593 MOZ_COUNT_CTOR(nsDisplayBoxShadowInner
);
4596 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowInner
)
4598 NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER
)
4600 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4602 nsDisplayItemGeometry
* AllocateGeometry(
4603 nsDisplayListBuilder
* aBuilder
) override
{
4604 return new nsDisplayBoxShadowInnerGeometry(this, aBuilder
);
4607 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4608 const nsDisplayItemGeometry
* aGeometry
,
4609 nsRegion
* aInvalidRegion
) const override
{
4610 const nsDisplayBoxShadowInnerGeometry
* geometry
=
4611 static_cast<const nsDisplayBoxShadowInnerGeometry
*>(aGeometry
);
4612 if (!geometry
->mPaddingRect
.IsEqualInterior(GetPaddingRect())) {
4613 // nsDisplayBoxShadowInner is based around the padding rect, but it can
4614 // touch pixels outside of this. We should invalidate the entire bounds.
4616 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &snap
));
4620 static bool CanCreateWebRenderCommands(nsDisplayListBuilder
* aBuilder
,
4622 const nsPoint
& aReferenceOffset
);
4623 static void CreateInsetBoxShadowWebRenderCommands(
4624 wr::DisplayListBuilder
& aBuilder
, const StackingContextHelper
& aSc
,
4625 nsRect
& aVisibleRect
, nsIFrame
* aFrame
, const nsRect
& aBorderRect
);
4626 bool CreateWebRenderCommands(
4627 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4628 const StackingContextHelper
& aSc
,
4629 layers::RenderRootStateManager
* aManager
,
4630 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4634 * The standard display item to paint the CSS outline of a frame.
4636 class nsDisplayOutline final
: public nsPaintedDisplayItem
{
4638 nsDisplayOutline(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4639 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4640 MOZ_COUNT_CTOR(nsDisplayOutline
);
4643 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOutline
)
4645 NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE
)
4647 bool ShouldUseBlobRenderingForFallback() const override
{
4648 MOZ_ASSERT(IsThemedOutline(),
4649 "The only fallback path we have is for themed outlines");
4650 return !XRE_IsParentProcess();
4653 bool CreateWebRenderCommands(
4654 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4655 const StackingContextHelper
& aSc
,
4656 layers::RenderRootStateManager
* aManager
,
4657 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4658 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
4659 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4660 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4663 nsRect
GetInnerRect() const;
4664 bool IsThemedOutline() const;
4665 bool HasRadius() const;
4669 * A class that lets you receive events within the frame bounds but never
4672 class nsDisplayEventReceiver final
: public nsDisplayItem
{
4674 nsDisplayEventReceiver(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4675 : nsDisplayItem(aBuilder
, aFrame
) {
4676 MOZ_COUNT_CTOR(nsDisplayEventReceiver
);
4679 MOZ_COUNTED_DTOR_FINAL(nsDisplayEventReceiver
)
4681 NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER
)
4683 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4684 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
;
4688 * Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
4689 * this gets built when we're doing widget painting and we need to send the
4690 * compositor some hit-test info for a frame. This is effectively a dummy item
4691 * whose sole purpose is to carry the hit-test info to the compositor.
4693 class nsDisplayCompositorHitTestInfo final
: public nsDisplayItem
{
4695 nsDisplayCompositorHitTestInfo(nsDisplayListBuilder
* aBuilder
,
4697 : nsDisplayItem(aBuilder
, aFrame
) {
4698 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
4699 mHitTestInfo
.Initialize(aBuilder
, aFrame
);
4700 SetHasHitTestInfo();
4703 nsDisplayCompositorHitTestInfo(
4704 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, const nsRect
& aArea
,
4705 const gfx::CompositorHitTestInfo
& aHitTestFlags
)
4706 : nsDisplayItem(aBuilder
, aFrame
) {
4707 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
4708 mHitTestInfo
.SetAreaAndInfo(aArea
, aHitTestFlags
);
4709 mHitTestInfo
.InitializeScrollTarget(aBuilder
);
4710 SetHasHitTestInfo();
4713 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo
)
4715 NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO
)
4717 bool CreateWebRenderCommands(
4718 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4719 const StackingContextHelper
& aSc
,
4720 layers::RenderRootStateManager
* aManager
,
4721 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4723 bool isInvisible() const { return true; }
4725 int32_t ZIndex() const override
;
4726 void SetOverrideZIndex(int32_t aZIndex
);
4728 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
4733 const HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
4736 HitTestInfo mHitTestInfo
;
4737 Maybe
<int32_t> mOverrideZIndex
;
4740 class nsDisplayWrapper
;
4743 * A class that lets you wrap a display list as a display item.
4745 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
4746 * list has many items, it's not clear which one has the 'underlying frame'.
4747 * Thus we force the creator to specify what the underlying frame is. The
4748 * underlying frame should be the root of a stacking context, because sorting
4749 * a list containing this item will not get at the children.
4751 * In some cases (e.g., clipping) we want to wrap a list but we don't have a
4752 * particular underlying frame that is a stacking context root. In that case
4753 * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
4754 * detect and handle this case.
4756 class nsDisplayWrapList
: public nsPaintedDisplayItem
{
4759 * Takes all the items from aList and puts them in our list.
4761 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4762 nsDisplayList
* aList
);
4764 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4765 nsDisplayItem
* aItem
);
4767 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4768 nsDisplayList
* aList
,
4769 const ActiveScrolledRoot
* aActiveScrolledRoot
,
4770 bool aClearClipChain
= false);
4772 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4773 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4775 mFrameActiveScrolledRoot(aBuilder
->CurrentActiveScrolledRoot()),
4777 mHasZIndexOverride(false) {
4778 MOZ_COUNT_CTOR(nsDisplayWrapList
);
4779 mBaseBuildingRect
= GetBuildingRect();
4781 mOriginalClipChain
= mClipChain
;
4784 nsDisplayWrapList() = delete;
4787 * A custom copy-constructor that does not copy mList, as this would mutate
4790 nsDisplayWrapList(const nsDisplayWrapList
& aOther
) = delete;
4791 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
,
4792 const nsDisplayWrapList
& aOther
)
4793 : nsPaintedDisplayItem(aBuilder
, aOther
),
4796 mFrameActiveScrolledRoot(aOther
.mFrameActiveScrolledRoot
),
4797 mMergedFrames(aOther
.mMergedFrames
.Clone()),
4798 mBounds(aOther
.mBounds
),
4799 mBaseBuildingRect(aOther
.mBaseBuildingRect
),
4800 mOriginalClipChain(aOther
.mClipChain
),
4801 mOverrideZIndex(aOther
.mOverrideZIndex
),
4802 mHasZIndexOverride(aOther
.mHasZIndexOverride
),
4803 mClearingClipChain(aOther
.mClearingClipChain
) {
4804 MOZ_COUNT_CTOR(nsDisplayWrapList
);
4807 ~nsDisplayWrapList() override
;
4809 const nsDisplayWrapList
* AsDisplayWrapList() const final
{ return this; }
4810 nsDisplayWrapList
* AsDisplayWrapList() final
{ return this; }
4812 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4813 mList
.DeleteAll(aBuilder
);
4814 nsPaintedDisplayItem::Destroy(aBuilder
);
4818 * Creates a new nsDisplayWrapper that holds a pointer to the display list
4819 * owned by the given nsDisplayItem.
4821 nsDisplayWrapper
* CreateShallowCopy(nsDisplayListBuilder
* aBuilder
);
4824 * Call this if the wrapped list is changed.
4826 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
{
4827 // Clear the clip chain up to the asr, but don't store it, so that we'll
4828 // recover it when we reuse the item.
4829 if (mClearingClipChain
) {
4830 const DisplayItemClipChain
* clip
= mOriginalClipChain
;
4831 while (clip
&& ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(),
4833 clip
= clip
->mParent
;
4835 SetClipChain(clip
, false);
4838 nsRect buildingRect
;
4839 mBounds
= mListPtr
->GetClippedBoundsWithRespectToASR(
4840 aBuilder
, mActiveScrolledRoot
, &buildingRect
);
4841 // The display list may contain content that's visible outside the visible
4842 // rect (i.e. the current dirty rect) passed in when the item was created.
4843 // This happens when the dirty rect has been restricted to the visual
4844 // overflow rect of a frame for some reason (e.g. when setting up dirty
4845 // rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
4846 // frame contains placeholders for out-of-flows that aren't descendants of
4848 buildingRect
.UnionRect(mBaseBuildingRect
, buildingRect
);
4849 SetBuildingRect(buildingRect
);
4852 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
4853 bool aStore
) override
{
4854 nsDisplayItem::SetClipChain(aClipChain
, aStore
);
4857 mOriginalClipChain
= mClipChain
;
4861 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4862 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4863 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4864 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4865 bool* aSnap
) const override
;
4866 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4869 * Try to merge with the other item (which is below us in the display
4870 * list). This gets used by nsDisplayClip to coalesce clipping operations
4871 * (optimization), by nsDisplayOpacity to merge rendering for the same
4872 * content element into a single opacity group (correctness), and will be
4873 * used by nsDisplayOutline to merge multiple outlines for the same element
4874 * (also for correctness).
4876 virtual void Merge(const nsDisplayItem
* aItem
) {
4877 MOZ_ASSERT(CanMerge(aItem
));
4878 MOZ_ASSERT(Frame() != aItem
->Frame());
4879 MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList
*>(aItem
));
4883 * Returns the underlying frames of all display items that have been
4884 * merged into this one (excluding this item's own underlying frame)
4887 const nsTArray
<nsIFrame
*>& GetMergedFrames() const { return mMergedFrames
; }
4889 bool HasMergedFrames() const { return !mMergedFrames
.IsEmpty(); }
4891 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
4895 bool IsInvalid(nsRect
& aRect
) const override
{
4896 if (mFrame
->IsInvalid(aRect
) && aRect
.IsEmpty()) {
4900 for (uint32_t i
= 0; i
< mMergedFrames
.Length(); i
++) {
4901 if (mMergedFrames
[i
]->IsInvalid(temp
) && temp
.IsEmpty()) {
4905 aRect
= aRect
.Union(temp
);
4907 aRect
+= ToReferenceFrame();
4908 return !aRect
.IsEmpty();
4911 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
4913 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
4917 RetainedDisplayList
* GetChildren() const override
{ return mListPtr
; }
4919 int32_t ZIndex() const override
{
4920 return (mHasZIndexOverride
) ? mOverrideZIndex
4921 : nsPaintedDisplayItem::ZIndex();
4924 void SetOverrideZIndex(int32_t aZIndex
) {
4925 mHasZIndexOverride
= true;
4926 mOverrideZIndex
= aZIndex
;
4930 * This creates a copy of this item, but wrapping aItem instead of
4931 * our existing list. Only gets called if this item returned nullptr
4932 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
4933 * GetUnderlyingFrame().
4935 nsDisplayWrapList
* WrapWithClone(nsDisplayListBuilder
* aBuilder
,
4936 nsDisplayItem
* aItem
) {
4937 MOZ_ASSERT_UNREACHABLE("We never returned nullptr for GetUnderlyingFrame!");
4941 bool CreateWebRenderCommands(
4942 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4943 const StackingContextHelper
& aSc
,
4944 layers::RenderRootStateManager
* aManager
,
4945 nsDisplayListBuilder
* aDisplayListBuilder
) override
{
4946 return CreateWebRenderCommandsNewClipListOption(
4947 aBuilder
, aResources
, aSc
, aManager
, aDisplayListBuilder
, true);
4950 // Same as the above but with the option to pass the aNewClipList argument to
4951 // WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList.
4952 bool CreateWebRenderCommandsNewClipListOption(
4953 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4954 const StackingContextHelper
& aSc
,
4955 layers::RenderRootStateManager
* aManager
,
4956 nsDisplayListBuilder
* aDisplayListBuilder
, bool aNewClipList
);
4958 const ActiveScrolledRoot
* GetFrameActiveScrolledRoot() {
4959 return mFrameActiveScrolledRoot
;
4963 void MergeFromTrackingMergedFrames(const nsDisplayWrapList
* aOther
) {
4964 mBounds
.UnionRect(mBounds
, aOther
->mBounds
);
4965 nsRect buildingRect
;
4966 buildingRect
.UnionRect(GetBuildingRect(), aOther
->GetBuildingRect());
4967 SetBuildingRect(buildingRect
);
4968 mMergedFrames
.AppendElement(aOther
->mFrame
);
4969 mMergedFrames
.AppendElements(aOther
->mMergedFrames
.Clone());
4972 RetainedDisplayList mList
;
4973 RetainedDisplayList
* mListPtr
;
4974 // The active scrolled root for the frame that created this
4976 RefPtr
<const ActiveScrolledRoot
> mFrameActiveScrolledRoot
;
4977 // The frames from items that have been merged into this item, excluding
4978 // this item's own frame.
4979 nsTArray
<nsIFrame
*> mMergedFrames
;
4981 // Displaylist building rect contributed by this display item itself.
4982 // Our mBuildingRect may include the visible areas of children.
4983 nsRect mBaseBuildingRect
;
4984 RefPtr
<const DisplayItemClipChain
> mOriginalClipChain
;
4985 int32_t mOverrideZIndex
;
4986 bool mHasZIndexOverride
;
4987 bool mClearingClipChain
= false;
4990 class nsDisplayWrapper
: public nsDisplayWrapList
{
4992 NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST
)
4994 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4995 nsDisplayList
* aList
,
4996 const ActiveScrolledRoot
* aActiveScrolledRoot
,
4997 bool aClearClipChain
= false)
4998 : nsDisplayWrapList(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5001 nsDisplayWrapper(const nsDisplayWrapper
& aOther
) = delete;
5002 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
,
5003 const nsDisplayWrapList
& aOther
)
5004 : nsDisplayWrapList(aBuilder
, aOther
) {}
5006 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5009 NS_DISPLAY_ALLOW_CLONING()
5010 friend class nsDisplayListBuilder
;
5011 friend class nsDisplayWrapList
;
5015 * We call WrapDisplayList on the in-flow lists: BorderBackground(),
5016 * BlockBorderBackgrounds() and Content().
5017 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
5018 * and Floats(). This is done to support special wrapping processing for frames
5019 * that may not be in-flow descendants of the current frame.
5021 class nsDisplayItemWrapper
{
5023 // This is never instantiated directly (it has pure virtual methods), so no
5024 // need to count constructors and destructors.
5026 bool WrapBorderBackground() { return true; }
5027 virtual nsDisplayItem
* WrapList(nsDisplayListBuilder
* aBuilder
,
5028 nsIFrame
* aFrame
, nsDisplayList
* aList
) = 0;
5029 virtual nsDisplayItem
* WrapItem(nsDisplayListBuilder
* aBuilder
,
5030 nsDisplayItem
* aItem
) = 0;
5032 nsresult
WrapLists(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5033 const nsDisplayListSet
& aIn
, const nsDisplayListSet
& aOut
);
5034 nsresult
WrapListsInPlace(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5035 const nsDisplayListSet
& aLists
);
5038 nsDisplayItemWrapper() = default;
5042 * The standard display item to paint a stacking context with translucency
5043 * set by the stacking context root frame's 'opacity' style.
5045 class nsDisplayOpacity
: public nsDisplayWrapList
{
5047 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5048 nsDisplayList
* aList
,
5049 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5050 bool aForEventsOnly
, bool aNeedsActiveLayer
,
5051 bool aWrapsBackdropFilter
);
5053 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
,
5054 const nsDisplayOpacity
& aOther
)
5055 : nsDisplayWrapList(aBuilder
, aOther
),
5056 mOpacity(aOther
.mOpacity
),
5057 mForEventsOnly(aOther
.mForEventsOnly
),
5058 mNeedsActiveLayer(aOther
.mNeedsActiveLayer
),
5059 mChildOpacityState(ChildOpacityState::Unknown
),
5060 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
5061 MOZ_COUNT_CTOR(nsDisplayOpacity
);
5062 // We should not try to merge flattened opacities.
5063 MOZ_ASSERT(aOther
.mChildOpacityState
!= ChildOpacityState::Applied
);
5066 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5067 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5069 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOpacity
)
5071 NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY
)
5073 void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) override
{
5074 mChildOpacityState
= ChildOpacityState::Unknown
;
5077 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5078 bool* aSnap
) const override
;
5079 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5081 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5082 // items for the same content element should be merged into a single
5083 // compositing group
5084 // aItem->GetUnderlyingFrame() returns non-null because it's
5086 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5087 HasSameContent(aItem
);
5090 nsDisplayItemGeometry
* AllocateGeometry(
5091 nsDisplayListBuilder
* aBuilder
) override
{
5092 return new nsDisplayOpacityGeometry(this, aBuilder
, mOpacity
);
5095 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5096 const nsDisplayItemGeometry
* aGeometry
,
5097 nsRegion
* aInvalidRegion
) const override
;
5099 bool IsInvalid(nsRect
& aRect
) const override
{
5100 if (mForEventsOnly
) {
5103 return nsDisplayWrapList::IsInvalid(aRect
);
5105 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
5106 nsDisplayListBuilder
* aBuilder
) const override
;
5107 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5111 bool CanApplyOpacityToChildren(WebRenderLayerManager
* aManager
,
5112 nsDisplayListBuilder
* aBuilder
,
5113 float aInheritedOpacity
);
5115 bool NeedsGeometryUpdates() const override
{
5116 // For flattened nsDisplayOpacity items, ComputeInvalidationRegion() only
5117 // handles invalidation for changed |mOpacity|. In order to keep track of
5118 // the current bounds of the item for invalidation, nsDisplayOpacityGeometry
5119 // for the corresponding DisplayItemData needs to be updated, even if the
5120 // reported invalidation region is empty.
5121 return mChildOpacityState
== ChildOpacityState::Deferred
;
5125 * Returns true if ShouldFlattenAway() applied opacity to children.
5127 bool OpacityAppliedToChildren() const {
5128 return mChildOpacityState
== ChildOpacityState::Applied
;
5131 static bool NeedsActiveLayer(nsDisplayListBuilder
* aBuilder
,
5133 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5134 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
5135 bool CreateWebRenderCommands(
5136 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5137 const StackingContextHelper
& aSc
,
5138 layers::RenderRootStateManager
* aManager
,
5139 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5141 float GetOpacity() const { return mOpacity
; }
5143 bool CreatesStackingContextHelper() override
{ return true; }
5146 NS_DISPLAY_ALLOW_CLONING()
5148 bool CanApplyToChildren(WebRenderLayerManager
* aManager
,
5149 nsDisplayListBuilder
* aBuilder
);
5153 bool mForEventsOnly
: 1;
5154 enum class ChildOpacityState
: uint8_t {
5155 // Our child list has changed since the last time ApplyToChildren was
5158 // Our children defer opacity handling to us.
5160 // Opacity is applied to our children.
5163 bool mNeedsActiveLayer
: 1;
5165 ChildOpacityState mChildOpacityState
: 2;
5167 ChildOpacityState mChildOpacityState
;
5169 bool mWrapsBackdropFilter
;
5172 class nsDisplayBlendMode
: public nsDisplayWrapList
{
5174 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5175 nsDisplayList
* aList
, StyleBlend aBlendMode
,
5176 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5177 const bool aIsForBackground
);
5178 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
,
5179 const nsDisplayBlendMode
& aOther
)
5180 : nsDisplayWrapList(aBuilder
, aOther
),
5181 mBlendMode(aOther
.mBlendMode
),
5182 mIsForBackground(aOther
.mIsForBackground
) {
5183 MOZ_COUNT_CTOR(nsDisplayBlendMode
);
5186 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendMode
)
5188 NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE
)
5190 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5191 bool* aSnap
) const override
;
5192 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5193 const nsDisplayItemGeometry
* aGeometry
,
5194 nsRegion
* aInvalidRegion
) const override
{
5195 // We don't need to compute an invalidation region since we have
5196 // LayerTreeInvalidation
5199 bool CreateWebRenderCommands(
5200 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5201 const StackingContextHelper
& aSc
,
5202 layers::RenderRootStateManager
* aManager
,
5203 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5204 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5206 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
5208 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5212 gfx::CompositionOp
BlendMode();
5214 bool CreatesStackingContextHelper() override
{ return true; }
5217 StyleBlend mBlendMode
;
5218 bool mIsForBackground
;
5221 NS_DISPLAY_ALLOW_CLONING()
5224 class nsDisplayTableBlendMode
: public nsDisplayBlendMode
{
5226 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5227 nsDisplayList
* aList
, StyleBlend aBlendMode
,
5228 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5229 nsIFrame
* aAncestorFrame
, const bool aIsForBackground
)
5230 : nsDisplayBlendMode(aBuilder
, aFrame
, aList
, aBlendMode
,
5231 aActiveScrolledRoot
, aIsForBackground
),
5232 mAncestorFrame(aAncestorFrame
) {
5233 if (aBuilder
->IsRetainingDisplayList()) {
5234 mAncestorFrame
->AddDisplayItem(this);
5238 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
,
5239 const nsDisplayTableBlendMode
& aOther
)
5240 : nsDisplayBlendMode(aBuilder
, aOther
),
5241 mAncestorFrame(aOther
.mAncestorFrame
) {
5242 if (aBuilder
->IsRetainingDisplayList()) {
5243 mAncestorFrame
->AddDisplayItem(this);
5247 ~nsDisplayTableBlendMode() override
{
5248 if (mAncestorFrame
) {
5249 mAncestorFrame
->RemoveDisplayItem(this);
5253 NS_DISPLAY_DECL_NAME("TableBlendMode", TYPE_TABLE_BLEND_MODE
)
5255 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5257 void RemoveFrame(nsIFrame
* aFrame
) override
{
5258 if (aFrame
== mAncestorFrame
) {
5259 mAncestorFrame
= nullptr;
5262 nsDisplayBlendMode::RemoveFrame(aFrame
);
5266 nsIFrame
* mAncestorFrame
;
5269 NS_DISPLAY_ALLOW_CLONING()
5272 class nsDisplayBlendContainer
: public nsDisplayWrapList
{
5274 static nsDisplayBlendContainer
* CreateForMixBlendMode(
5275 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5276 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5278 static nsDisplayBlendContainer
* CreateForBackgroundBlendMode(
5279 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5280 nsIFrame
* aSecondaryFrame
, nsDisplayList
* aList
,
5281 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5283 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendContainer
)
5285 NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER
)
5287 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5288 bool CreateWebRenderCommands(
5289 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5290 const StackingContextHelper
& aSc
,
5291 layers::RenderRootStateManager
* aManager
,
5292 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5294 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5295 // Items for the same content element should be merged into a single
5296 // compositing group.
5297 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5298 HasSameContent(aItem
) &&
5300 static_cast<const nsDisplayBlendContainer
*>(aItem
)
5304 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5308 bool CreatesStackingContextHelper() override
{ return true; }
5311 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5312 nsDisplayList
* aList
,
5313 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5314 bool aIsForBackground
);
5315 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
,
5316 const nsDisplayBlendContainer
& aOther
)
5317 : nsDisplayWrapList(aBuilder
, aOther
),
5318 mIsForBackground(aOther
.mIsForBackground
) {
5319 MOZ_COUNT_CTOR(nsDisplayBlendContainer
);
5322 // Used to distinguish containers created at building stacking
5323 // context or appending background.
5324 bool mIsForBackground
;
5327 NS_DISPLAY_ALLOW_CLONING()
5330 class nsDisplayTableBlendContainer
: public nsDisplayBlendContainer
{
5332 NS_DISPLAY_DECL_NAME("TableBlendContainer", TYPE_TABLE_BLEND_CONTAINER
)
5334 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5336 void RemoveFrame(nsIFrame
* aFrame
) override
{
5337 if (aFrame
== mAncestorFrame
) {
5338 mAncestorFrame
= nullptr;
5341 nsDisplayBlendContainer::RemoveFrame(aFrame
);
5345 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5346 nsDisplayList
* aList
,
5347 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5348 bool aIsForBackground
, nsIFrame
* aAncestorFrame
)
5349 : nsDisplayBlendContainer(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5351 mAncestorFrame(aAncestorFrame
) {
5352 if (aBuilder
->IsRetainingDisplayList()) {
5353 mAncestorFrame
->AddDisplayItem(this);
5357 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
,
5358 const nsDisplayTableBlendContainer
& aOther
)
5359 : nsDisplayBlendContainer(aBuilder
, aOther
),
5360 mAncestorFrame(aOther
.mAncestorFrame
) {}
5362 ~nsDisplayTableBlendContainer() override
{
5363 if (mAncestorFrame
) {
5364 mAncestorFrame
->RemoveDisplayItem(this);
5368 nsIFrame
* mAncestorFrame
;
5371 NS_DISPLAY_ALLOW_CLONING()
5375 * nsDisplayOwnLayer constructor flags. If we nest this class inside
5376 * nsDisplayOwnLayer then we can't forward-declare it up at the top of this
5377 * file and that makes it hard to use in all the places that we need to use it.
5379 enum class nsDisplayOwnLayerFlags
{
5381 GenerateSubdocInvalidations
= 1 << 0,
5382 GenerateScrollableLayer
= 1 << 1,
5385 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags
)
5388 * A display item that has no purpose but to ensure its contents get
5391 class nsDisplayOwnLayer
: public nsDisplayWrapList
{
5394 OwnLayerForTransformWithRoundedClip
,
5395 OwnLayerForStackingContext
,
5396 OwnLayerForScrollbar
,
5397 OwnLayerForScrollThumb
,
5403 * @param aFlags eGenerateSubdocInvalidations :
5404 * Add UserData to the created ContainerLayer, so that invalidations
5405 * for this layer are send to our nsPresContext.
5406 * eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and
5407 * subclasses), indicates this layer is to be a scrollable layer, so call
5408 * ComputeFrameMetrics, etc.
5409 * @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar
5410 * is set in the flags, this parameter should be the ViewID of the
5411 * scrollable content this scrollbar is for.
5414 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5415 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5416 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
,
5417 const layers::ScrollbarData
& aScrollbarData
= layers::ScrollbarData
{},
5418 bool aForceActive
= true, bool aClearClipChain
= false);
5420 nsDisplayOwnLayer(nsDisplayListBuilder
* aBuilder
,
5421 const nsDisplayOwnLayer
& aOther
)
5422 : nsDisplayWrapList(aBuilder
, aOther
),
5423 mFlags(aOther
.mFlags
),
5424 mScrollbarData(aOther
.mScrollbarData
),
5425 mForceActive(aOther
.mForceActive
),
5426 mWrAnimationId(aOther
.mWrAnimationId
) {
5427 MOZ_COUNT_CTOR(nsDisplayOwnLayer
);
5430 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOwnLayer
)
5432 NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER
)
5434 bool CreateWebRenderCommands(
5435 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5436 const StackingContextHelper
& aSc
,
5437 layers::RenderRootStateManager
* aManager
,
5438 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5439 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5440 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5441 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5442 GetChildren()->Paint(aBuilder
, aCtx
,
5443 mFrame
->PresContext()->AppUnitsPerDevPixel());
5446 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5447 // Don't allow merging, each sublist must have its own layer
5451 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5455 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5456 nsDisplayOwnLayerFlags
GetFlags() { return mFlags
; }
5457 bool IsScrollThumbLayer() const;
5458 bool IsScrollbarContainer() const;
5459 bool IsRootScrollbarContainer() const;
5460 bool IsScrollbarLayerForRoot() const;
5461 bool IsZoomingLayer() const;
5462 bool IsFixedPositionLayer() const;
5463 bool IsStickyPositionLayer() const;
5464 bool HasDynamicToolbar() const;
5465 bool ShouldFixedAndStickyContentGetAnimationIds() const;
5467 bool CreatesStackingContextHelper() override
{ return true; }
5470 nsDisplayOwnLayerFlags mFlags
;
5473 * If this nsDisplayOwnLayer represents a scroll thumb layer or a
5474 * scrollbar container layer, mScrollbarData stores information
5475 * about the scrollbar. Otherwise, mScrollbarData will be
5476 * default-constructed (in particular with mDirection == Nothing())
5477 * and can be ignored.
5479 layers::ScrollbarData mScrollbarData
;
5481 uint64_t mWrAnimationId
;
5485 * A display item for subdocuments. This is more or less the same as
5486 * nsDisplayOwnLayer, except that it always populates the FrameMetrics instance
5487 * on the ContainerLayer it builds.
5489 class nsDisplaySubDocument
: public nsDisplayOwnLayer
{
5491 nsDisplaySubDocument(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5492 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
5493 nsDisplayOwnLayerFlags aFlags
);
5494 ~nsDisplaySubDocument() override
;
5496 NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT
)
5498 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5500 virtual nsSubDocumentFrame
* SubDocumentFrame() { return mSubDocFrame
; }
5502 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5503 return mShouldFlatten
;
5506 void SetShouldFlattenAway(bool aShouldFlatten
) {
5507 mShouldFlatten
= aShouldFlatten
;
5510 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5511 bool* aSnap
) const override
;
5513 nsIFrame
* FrameForInvalidation() const override
;
5514 void RemoveFrame(nsIFrame
* aFrame
) override
;
5517 ViewID mScrollParentId
;
5518 bool mForceDispatchToContentRegion
{};
5519 bool mShouldFlatten
;
5520 nsSubDocumentFrame
* mSubDocFrame
;
5524 * A display item used to represent sticky position elements. The contents
5525 * gets its own layer and creates a stacking context, and the layer will have
5526 * position-related metadata set on it.
5528 class nsDisplayStickyPosition
: public nsDisplayOwnLayer
{
5530 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5531 nsDisplayList
* aList
,
5532 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5533 const ActiveScrolledRoot
* aContainerASR
,
5534 bool aClippedToDisplayPort
);
5535 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
,
5536 const nsDisplayStickyPosition
& aOther
)
5537 : nsDisplayOwnLayer(aBuilder
, aOther
),
5538 mContainerASR(aOther
.mContainerASR
),
5539 mClippedToDisplayPort(aOther
.mClippedToDisplayPort
),
5540 mShouldFlatten(false) {
5541 MOZ_COUNT_CTOR(nsDisplayStickyPosition
);
5544 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayStickyPosition
)
5546 const DisplayItemClip
& GetClip() const override
{
5547 return DisplayItemClip::NoClip();
5549 bool IsClippedToDisplayPort() const { return mClippedToDisplayPort
; }
5551 NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION
)
5552 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5553 GetChildren()->Paint(aBuilder
, aCtx
,
5554 mFrame
->PresContext()->AppUnitsPerDevPixel());
5557 bool CreateWebRenderCommands(
5558 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5559 const StackingContextHelper
& aSc
,
5560 layers::RenderRootStateManager
* aManager
,
5561 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5563 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5564 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5566 const ActiveScrolledRoot
* GetContainerASR() const { return mContainerASR
; }
5568 bool CreatesStackingContextHelper() override
{ return true; }
5570 bool CanMoveAsync() override
{ return true; }
5572 void SetShouldFlatten(bool aShouldFlatten
) {
5573 mShouldFlatten
= aShouldFlatten
;
5576 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) final
{
5577 return mShouldFlatten
;
5581 NS_DISPLAY_ALLOW_CLONING()
5583 void CalculateLayerScrollRanges(StickyScrollContainer
* aStickyScrollContainer
,
5584 float aAppUnitsPerDevPixel
, float aScaleX
,
5586 LayerRectAbsolute
& aStickyOuter
,
5587 LayerRectAbsolute
& aStickyInner
);
5589 StickyScrollContainer
* GetStickyScrollContainer();
5591 // This stores the ASR that this sticky container item would have assuming it
5592 // has no fixed descendants. This may be the same as the ASR returned by
5593 // GetActiveScrolledRoot(), or it may be a descendant of that.
5594 RefPtr
<const ActiveScrolledRoot
> mContainerASR
;
5595 // This flag tracks if this sticky item is just clipped to the enclosing
5596 // scrollframe's displayport, or if there are additional clips in play. In
5597 // the former case, we can skip setting the displayport clip as the scrolled-
5598 // clip of the corresponding layer. This allows sticky items to remain
5599 // unclipped when the enclosing scrollframe is scrolled past the displayport.
5600 // i.e. when the rest of the scrollframe checkerboards, the sticky item will
5601 // not. This makes sense to do because the sticky item has abnormal scrolling
5602 // behavior and may still be visible even if the rest of the scrollframe is
5603 // checkerboarded. Note that the sticky item will still be subject to the
5605 bool mClippedToDisplayPort
;
5607 // True if this item should be flattened away.
5608 bool mShouldFlatten
;
5611 class nsDisplayFixedPosition
: public nsDisplayOwnLayer
{
5613 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5614 nsDisplayList
* aList
,
5615 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5616 const ActiveScrolledRoot
* aScrollTargetASR
);
5617 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
,
5618 const nsDisplayFixedPosition
& aOther
)
5619 : nsDisplayOwnLayer(aBuilder
, aOther
),
5620 mScrollTargetASR(aOther
.mScrollTargetASR
),
5621 mIsFixedBackground(aOther
.mIsFixedBackground
) {
5622 MOZ_COUNT_CTOR(nsDisplayFixedPosition
);
5625 static nsDisplayFixedPosition
* CreateForFixedBackground(
5626 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5627 nsIFrame
* aSecondaryFrame
, nsDisplayBackgroundImage
* aImage
,
5628 const uint16_t aIndex
, const ActiveScrolledRoot
* aScrollTargetASR
);
5630 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFixedPosition
)
5632 NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION
)
5634 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5635 GetChildren()->Paint(aBuilder
, aCtx
,
5636 mFrame
->PresContext()->AppUnitsPerDevPixel());
5639 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
5640 return mIsFixedBackground
;
5643 bool CreateWebRenderCommands(
5644 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5645 const StackingContextHelper
& aSc
,
5646 layers::RenderRootStateManager
* aManager
,
5647 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5648 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5649 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5650 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5653 // For background-attachment:fixed
5654 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5655 nsDisplayList
* aList
,
5656 const ActiveScrolledRoot
* aScrollTargetASR
);
5657 ViewID
GetScrollTargetId();
5659 RefPtr
<const ActiveScrolledRoot
> mScrollTargetASR
;
5660 bool mIsFixedBackground
;
5663 NS_DISPLAY_ALLOW_CLONING()
5666 class nsDisplayTableFixedPosition
: public nsDisplayFixedPosition
{
5668 NS_DISPLAY_DECL_NAME("TableFixedPosition", TYPE_TABLE_FIXED_POSITION
)
5670 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5672 void RemoveFrame(nsIFrame
* aFrame
) override
{
5673 if (aFrame
== mAncestorFrame
) {
5674 mAncestorFrame
= nullptr;
5677 nsDisplayFixedPosition::RemoveFrame(aFrame
);
5681 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5682 nsDisplayList
* aList
, nsIFrame
* aAncestorFrame
,
5683 const ActiveScrolledRoot
* aScrollTargetASR
);
5685 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
,
5686 const nsDisplayTableFixedPosition
& aOther
)
5687 : nsDisplayFixedPosition(aBuilder
, aOther
),
5688 mAncestorFrame(aOther
.mAncestorFrame
) {}
5690 ~nsDisplayTableFixedPosition() override
{
5691 if (mAncestorFrame
) {
5692 mAncestorFrame
->RemoveDisplayItem(this);
5696 nsIFrame
* mAncestorFrame
;
5699 NS_DISPLAY_ALLOW_CLONING()
5703 * This creates an empty scrollable layer. It has no child layers.
5704 * It is used to record the existence of a scrollable frame in the layer
5707 class nsDisplayScrollInfoLayer
: public nsDisplayWrapList
{
5709 nsDisplayScrollInfoLayer(nsDisplayListBuilder
* aBuilder
,
5710 nsIFrame
* aScrolledFrame
, nsIFrame
* aScrollFrame
,
5711 const gfx::CompositorHitTestInfo
& aHitInfo
,
5712 const nsRect
& aHitArea
);
5714 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayScrollInfoLayer
)
5716 NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER
)
5718 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5719 bool* aSnap
) const override
{
5724 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5728 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5732 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5733 UniquePtr
<layers::ScrollMetadata
> ComputeScrollMetadata(
5734 nsDisplayListBuilder
* aBuilder
,
5735 layers::WebRenderLayerManager
* aLayerManager
);
5736 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5737 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5738 bool CreateWebRenderCommands(
5739 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5740 const StackingContextHelper
& aSc
,
5741 layers::RenderRootStateManager
* aManager
,
5742 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5745 nsIFrame
* mScrollFrame
;
5746 nsIFrame
* mScrolledFrame
;
5747 ViewID mScrollParentId
;
5748 gfx::CompositorHitTestInfo mHitInfo
;
5753 * nsDisplayZoom is used for subdocuments that have a different full zoom than
5754 * their parent documents. This item creates a container layer.
5756 class nsDisplayZoom
: public nsDisplaySubDocument
{
5759 * @param aFrame is the root frame of the subdocument.
5760 * @param aList contains the display items for the subdocument.
5761 * @param aAPD is the app units per dev pixel ratio of the subdocument.
5762 * @param aParentAPD is the app units per dev pixel ratio of the parent
5764 * @param aFlags eGenerateSubdocInvalidations :
5765 * Add UserData to the created ContainerLayer, so that invalidations
5766 * for this layer are send to our nsPresContext.
5768 nsDisplayZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5769 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
5770 int32_t aAPD
, int32_t aParentAPD
,
5771 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
);
5773 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayZoom
)
5775 NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM
)
5777 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5778 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5779 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5780 // Get the app units per dev pixel ratio of the child document.
5781 int32_t GetChildAppUnitsPerDevPixel() { return mAPD
; }
5782 // Get the app units per dev pixel ratio of the parent document.
5783 int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD
; }
5786 int32_t mAPD
, mParentAPD
;
5790 * nsDisplayAsyncZoom is used for APZ zooming. It wraps the contents of the
5791 * root content document's scroll frame, including fixed position content. It
5792 * does not contain the scroll frame's scrollbars. It is clipped to the scroll
5793 * frame's scroll port clip. It is not scrolled; only its non-fixed contents
5794 * are scrolled. This item creates a container layer.
5796 class nsDisplayAsyncZoom
: public nsDisplayOwnLayer
{
5798 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5799 nsDisplayList
* aList
,
5800 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5801 layers::FrameMetrics::ViewID aViewID
);
5802 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
,
5803 const nsDisplayAsyncZoom
& aOther
)
5804 : nsDisplayOwnLayer(aBuilder
, aOther
), mViewID(aOther
.mViewID
) {
5805 MOZ_COUNT_CTOR(nsDisplayAsyncZoom
);
5808 #ifdef NS_BUILD_REFCNT_LOGGING
5809 virtual ~nsDisplayAsyncZoom();
5812 NS_DISPLAY_DECL_NAME("AsyncZoom", TYPE_ASYNC_ZOOM
)
5814 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5815 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5816 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5817 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5820 layers::FrameMetrics::ViewID mViewID
;
5824 * A base class for different effects types.
5826 class nsDisplayEffectsBase
: public nsDisplayWrapList
{
5828 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5829 nsDisplayList
* aList
,
5830 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5831 bool aClearClipChain
= false);
5832 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5833 nsDisplayList
* aList
);
5835 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
,
5836 const nsDisplayEffectsBase
& aOther
)
5837 : nsDisplayWrapList(aBuilder
, aOther
),
5838 mEffectsBounds(aOther
.mEffectsBounds
) {
5839 MOZ_COUNT_CTOR(nsDisplayEffectsBase
);
5842 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayEffectsBase
)
5844 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5845 bool* aSnap
) const override
;
5846 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5847 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5849 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5853 gfxRect
BBoxInUserSpace() const;
5854 gfxPoint
UserSpaceOffset() const;
5856 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5857 const nsDisplayItemGeometry
* aGeometry
,
5858 nsRegion
* aInvalidRegion
) const override
;
5861 bool ValidateSVGFrame();
5863 // relative to mFrame
5864 nsRect mEffectsBounds
;
5868 * A display item to paint a stacking context with 'mask' and 'clip-path'
5869 * effects set by the stacking context root frame's style. The 'mask' and
5870 * 'clip-path' properties may both contain multiple masks and clip paths,
5873 * Note that 'mask' and 'clip-path' may just contain CSS simple-images and CSS
5874 * basic shapes, respectively. That is, they don't necessarily reference
5875 * resources such as SVG 'mask' and 'clipPath' elements.
5877 class nsDisplayMasksAndClipPaths
: public nsDisplayEffectsBase
{
5879 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5880 nsDisplayList
* aList
,
5881 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5882 bool aWrapsBackdropFilter
);
5883 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
,
5884 const nsDisplayMasksAndClipPaths
& aOther
)
5885 : nsDisplayEffectsBase(aBuilder
, aOther
),
5886 mDestRects(aOther
.mDestRects
.Clone()),
5887 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
5888 MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths
);
5891 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayMasksAndClipPaths
)
5893 NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK
)
5895 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
5897 void Merge(const nsDisplayItem
* aItem
) override
{
5898 nsDisplayWrapList::Merge(aItem
);
5900 const nsDisplayMasksAndClipPaths
* other
=
5901 static_cast<const nsDisplayMasksAndClipPaths
*>(aItem
);
5902 mEffectsBounds
.UnionRect(
5904 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
5907 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5909 nsDisplayItemGeometry
* AllocateGeometry(
5910 nsDisplayListBuilder
* aBuilder
) override
{
5911 return new nsDisplayMasksAndClipPathsGeometry(this, aBuilder
);
5914 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5915 const nsDisplayItemGeometry
* aGeometry
,
5916 nsRegion
* aInvalidRegion
) const override
;
5917 #ifdef MOZ_DUMP_PAINTING
5918 void PrintEffects(nsACString
& aTo
);
5923 void PaintWithContentsPaintCallback(
5924 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
5925 const std::function
<void()>& aPaintChildren
);
5928 * Paint mask onto aMaskContext in mFrame's coordinate space and
5929 * return whether the mask layer was painted successfully.
5931 bool PaintMask(nsDisplayListBuilder
* aBuilder
, gfxContext
* aMaskContext
,
5932 bool aHandleOpacity
, bool* aMaskPainted
= nullptr);
5934 const nsTArray
<nsRect
>& GetDestRects() { return mDestRects
; }
5936 bool CreateWebRenderCommands(
5937 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5938 const StackingContextHelper
& aSc
,
5939 layers::RenderRootStateManager
* aManager
,
5940 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5942 Maybe
<nsRect
> GetClipWithRespectToASR(
5943 nsDisplayListBuilder
* aBuilder
,
5944 const ActiveScrolledRoot
* aASR
) const override
;
5946 bool CreatesStackingContextHelper() override
{ return true; }
5949 NS_DISPLAY_ALLOW_CLONING()
5951 nsTArray
<nsRect
> mDestRects
;
5952 bool mWrapsBackdropFilter
;
5955 class nsDisplayBackdropFilters
: public nsDisplayWrapList
{
5957 nsDisplayBackdropFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5958 nsDisplayList
* aList
, const nsRect
& aBackdropRect
,
5959 nsIFrame
* aStyleFrame
)
5960 : nsDisplayWrapList(aBuilder
, aFrame
, aList
),
5961 mStyle(aFrame
== aStyleFrame
? nullptr : aStyleFrame
->Style()),
5962 mBackdropRect(aBackdropRect
) {
5963 MOZ_COUNT_CTOR(nsDisplayBackdropFilters
);
5966 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropFilters
)
5968 NS_DISPLAY_DECL_NAME("BackdropFilter", TYPE_BACKDROP_FILTER
)
5970 bool CreateWebRenderCommands(
5971 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5972 const StackingContextHelper
& aSc
,
5973 layers::RenderRootStateManager
* aManager
,
5974 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5975 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5977 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5978 return !aBuilder
->IsPaintingForWebRender();
5981 bool CreatesStackingContextHelper() override
{ return true; }
5983 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5986 RefPtr
<ComputedStyle
> mStyle
;
5987 nsRect mBackdropRect
;
5991 * A display item to paint a stacking context with filter effects set by the
5992 * stacking context root frame's style.
5994 * Note that the filters may just be simple CSS filter functions. That is,
5995 * they won't necessarily be references to SVG 'filter' elements.
5997 class nsDisplayFilters
: public nsDisplayEffectsBase
{
5999 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6000 nsDisplayList
* aList
, nsIFrame
* aStyleFrame
,
6001 bool aWrapsBackdropFilter
);
6003 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
,
6004 const nsDisplayFilters
& aOther
)
6005 : nsDisplayEffectsBase(aBuilder
, aOther
),
6006 mStyle(aOther
.mStyle
),
6007 mEffectsBounds(aOther
.mEffectsBounds
),
6008 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
6009 MOZ_COUNT_CTOR(nsDisplayFilters
);
6012 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFilters
)
6014 NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER
)
6016 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
6017 // Items for the same content element should be merged into a single
6018 // compositing group.
6019 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
6020 HasSameContent(aItem
);
6023 void Merge(const nsDisplayItem
* aItem
) override
{
6024 nsDisplayWrapList::Merge(aItem
);
6026 const nsDisplayFilters
* other
= static_cast<const nsDisplayFilters
*>(aItem
);
6027 mEffectsBounds
.UnionRect(
6029 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
6032 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6034 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
6036 return mEffectsBounds
+ ToReferenceFrame();
6039 nsDisplayItemGeometry
* AllocateGeometry(
6040 nsDisplayListBuilder
* aBuilder
) override
{
6041 return new nsDisplaySVGEffectGeometry(this, aBuilder
);
6044 #ifdef MOZ_DUMP_PAINTING
6045 void PrintEffects(nsACString
& aTo
);
6048 void PaintWithContentsPaintCallback(
6049 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6050 const std::function
<void(gfxContext
* aContext
)>& aPaintChildren
);
6052 bool CreateWebRenderCommands(
6053 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6054 const StackingContextHelper
& aSc
,
6055 layers::RenderRootStateManager
* aManager
,
6056 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6057 bool CanCreateWebRenderCommands() const;
6059 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
6060 nsDisplayListBuilder
* aBuilder
) const override
{
6061 return CanCreateWebRenderCommands();
6064 bool CreatesStackingContextHelper() override
{ return true; }
6067 NS_DISPLAY_ALLOW_CLONING()
6069 RefPtr
<ComputedStyle
> mStyle
;
6070 // relative to mFrame
6071 nsRect mEffectsBounds
;
6072 nsRect mVisibleRect
;
6073 bool mWrapsBackdropFilter
;
6076 /* A display item that applies a transformation to all of its descendant
6077 * elements. This wrapper should only be used if there is a transform applied
6078 * to the root element.
6080 * The reason that a "bounds" rect is involved in transform calculations is
6081 * because CSS-transforms allow percentage values for the x and y components
6082 * of <translation-value>s, where percentages are percentages of the element's
6085 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
6087 * INVARIANT: The wrapped frame is non-null.
6089 class nsDisplayTransform
: public nsPaintedDisplayItem
{
6090 using Matrix4x4
= gfx::Matrix4x4
;
6091 using Matrix4x4Flagged
= gfx::Matrix4x4Flagged
;
6092 using TransformReferenceBox
= nsStyleTransformMatrix::TransformReferenceBox
;
6095 enum class PrerenderDecision
: uint8_t { No
, Full
, Partial
};
6098 WithTransformGetter
,
6101 /* Constructor accepts a display list, empties it, and wraps it up. It also
6102 * ferries the underlying frame to the nsDisplayItem constructor.
6104 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6105 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
);
6107 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6108 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6109 PrerenderDecision aPrerenderDecision
);
6111 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6112 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6113 decltype(WithTransformGetter
));
6115 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayTransform
)
6117 NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM
)
6119 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
6122 * This function updates bounds for items with a frame establishing
6123 * 3D rendering context.
6125 void UpdateBoundsFor3D(nsDisplayListBuilder
* aBuilder
);
6127 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
;
6129 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
6130 GetChildren()->DeleteAll(aBuilder
);
6131 nsPaintedDisplayItem::Destroy(aBuilder
);
6134 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
6136 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
6138 nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
6139 bool* aSnap
) const override
{
6141 return mChildBounds
;
6144 const nsRect
& GetUntransformedPaintRect() const override
{
6145 return mChildrenBuildingRect
;
6148 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6150 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6151 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6152 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6153 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6154 bool* aSnap
) const override
;
6155 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6156 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6157 const Maybe
<gfx::Polygon
>& aPolygon
);
6158 bool CreateWebRenderCommands(
6159 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6160 const StackingContextHelper
& aSc
,
6161 layers::RenderRootStateManager
* aManager
,
6162 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6163 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
6164 layers::WebRenderLayerScrollData
* aLayerData
) override
;
6166 nsDisplayItemGeometry
* AllocateGeometry(
6167 nsDisplayListBuilder
* aBuilder
) override
{
6168 return new nsDisplayTransformGeometry(
6169 this, aBuilder
, GetTransformForRendering(),
6170 mFrame
->PresContext()->AppUnitsPerDevPixel());
6173 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6174 const nsDisplayItemGeometry
* aGeometry
,
6175 nsRegion
* aInvalidRegion
) const override
{
6176 const nsDisplayTransformGeometry
* geometry
=
6177 static_cast<const nsDisplayTransformGeometry
*>(aGeometry
);
6179 // This code is only called for flattened, inactive transform items.
6180 // Only check if the transform has changed. The bounds invalidation should
6181 // be handled by the children themselves.
6182 if (!geometry
->mTransform
.FuzzyEqual(GetTransformForRendering())) {
6184 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
6188 const nsIFrame
* ReferenceFrameForChildren() const override
{
6189 // If we were created using a transform-getter, then we don't
6190 // belong to a transformed frame, and aren't a reference frame
6191 // for our children.
6192 if (!mHasTransformGetter
) {
6195 return nsPaintedDisplayItem::ReferenceFrameForChildren();
6198 const nsRect
& GetBuildingRectForChildren() const override
{
6199 return mChildrenBuildingRect
;
6202 enum { INDEX_MAX
= UINT32_MAX
>> TYPE_BITS
};
6205 * We include the perspective matrix from our containing block for the
6206 * purposes of visibility calculations, but we exclude it from the transform
6207 * we set on the layer (for rendering), since there will be an
6208 * nsDisplayPerspective created for that.
6210 const Matrix4x4Flagged
& GetTransform() const;
6211 const Matrix4x4Flagged
& GetInverseTransform() const;
6213 bool ShouldSkipTransform(nsDisplayListBuilder
* aBuilder
) const;
6214 Matrix4x4
GetTransformForRendering(
6215 LayoutDevicePoint
* aOutOrigin
= nullptr) const;
6218 * Return the transform that is aggregation of all transform on the
6219 * preserves3d chain.
6221 const Matrix4x4
& GetAccumulatedPreserved3DTransform(
6222 nsDisplayListBuilder
* aBuilder
);
6224 float GetHitDepthAtPoint(nsDisplayListBuilder
* aBuilder
,
6225 const nsPoint
& aPoint
);
6227 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
6228 * space) and returns the smallest rectangle (in aFrame's coordinate space)
6229 * containing the transformed image of that rectangle. That is, it takes
6230 * the four corners of the rectangle, transforms them according to the
6231 * matrix associated with the specified frame, then returns the smallest
6232 * rectangle containing the four transformed points.
6234 * @param untransformedBounds The rectangle (in app units) to transform.
6235 * @param aFrame The frame whose transformation should be applied. This
6236 * function raises an assertion if aFrame is null or doesn't have a
6237 * transform applied to it.
6238 * @param aRefBox the reference box to use, which would usually be just
6239 * TransformReferemceBox(aFrame), but callers may override it if
6242 static nsRect
TransformRect(const nsRect
& aUntransformedBounds
,
6243 const nsIFrame
* aFrame
,
6244 TransformReferenceBox
& aRefBox
);
6246 /* UntransformRect is like TransformRect, except that it inverts the
6249 static bool UntransformRect(const nsRect
& aTransformedBounds
,
6250 const nsRect
& aChildBounds
,
6251 const nsIFrame
* aFrame
, nsRect
* aOutRect
);
6252 static bool UntransformRect(const nsRect
& aTransformedBounds
,
6253 const nsRect
& aChildBounds
,
6254 const Matrix4x4
& aMatrix
, float aAppUnitsPerPixel
,
6257 bool UntransformRect(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6258 nsRect
* aOutRect
) const;
6260 bool UntransformBuildingRect(nsDisplayListBuilder
* aBuilder
,
6261 nsRect
* aOutRect
) const {
6262 return UntransformRect(aBuilder
, GetBuildingRect(), aOutRect
);
6265 static gfx::Point3D
GetDeltaToTransformOrigin(const nsIFrame
* aFrame
,
6266 TransformReferenceBox
&,
6267 float aAppUnitsPerPixel
);
6270 * Returns true if aFrame has perspective applied from its containing
6272 * Returns the matrix to append to apply the persective (taking
6273 * perspective-origin into account), relative to aFrames coordinate
6275 * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
6278 static bool ComputePerspectiveMatrix(const nsIFrame
* aFrame
,
6279 float aAppUnitsPerPixel
,
6280 Matrix4x4
& aOutMatrix
);
6282 struct MOZ_STACK_CLASS FrameTransformProperties
{
6283 FrameTransformProperties(const nsIFrame
* aFrame
,
6284 TransformReferenceBox
& aRefBox
,
6285 float aAppUnitsPerPixel
);
6286 FrameTransformProperties(const StyleTranslate
& aTranslate
,
6287 const StyleRotate
& aRotate
,
6288 const StyleScale
& aScale
,
6289 const StyleTransform
& aTransform
,
6290 const Maybe
<ResolvedMotionPathData
>& aMotion
,
6291 const gfx::Point3D
& aToTransformOrigin
)
6293 mTranslate(aTranslate
),
6296 mTransform(aTransform
),
6298 mToTransformOrigin(aToTransformOrigin
) {}
6300 bool HasTransform() const {
6301 return !mTranslate
.IsNone() || !mRotate
.IsNone() || !mScale
.IsNone() ||
6302 !mTransform
.IsNone() || mMotion
.isSome();
6305 const nsIFrame
* mFrame
;
6306 const StyleTranslate
& mTranslate
;
6307 const StyleRotate
& mRotate
;
6308 const StyleScale
& mScale
;
6309 const StyleTransform
& mTransform
;
6310 const Maybe
<ResolvedMotionPathData
> mMotion
;
6311 const gfx::Point3D mToTransformOrigin
;
6315 * Given a frame with the transform property or an SVG transform,
6316 * returns the transformation matrix for that frame.
6318 * @param aFrame The frame to get the matrix from.
6319 * @param aOrigin Relative to which point this transform should be applied.
6320 * @param aAppUnitsPerPixel The number of app units per graphics unit.
6321 * @param aBoundsOverride [optional] If this is nullptr (the default), the
6322 * computation will use the value of TransformReferenceBox(aFrame).
6323 * Otherwise, it will use the value of aBoundsOverride. This is
6324 * mostly for internal use and in most cases you will not need to
6326 * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
6327 * by aOrigin. This translation is applied *before* the CSS transform.
6328 * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
6329 * include the transform of any ancestors participating in the same
6330 * 3d rendering context.
6331 * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
6332 * perspective transform from the containing block if applicable.
6335 OFFSET_BY_ORIGIN
= 1 << 0,
6336 INCLUDE_PRESERVE3D_ANCESTORS
= 1 << 1,
6337 INCLUDE_PERSPECTIVE
= 1 << 2,
6339 static constexpr uint32_t kTransformRectFlags
=
6340 INCLUDE_PERSPECTIVE
| OFFSET_BY_ORIGIN
| INCLUDE_PRESERVE3D_ANCESTORS
;
6341 static Matrix4x4
GetResultingTransformMatrix(const nsIFrame
* aFrame
,
6342 const nsPoint
& aOrigin
,
6343 float aAppUnitsPerPixel
,
6345 static Matrix4x4
GetResultingTransformMatrix(
6346 const FrameTransformProperties
& aProperties
, TransformReferenceBox
&,
6347 float aAppUnitsPerPixel
);
6349 struct PrerenderInfo
{
6350 bool CanUseAsyncAnimations() const {
6351 return mDecision
!= PrerenderDecision::No
&& mHasAnimations
;
6353 PrerenderDecision mDecision
= PrerenderDecision::No
;
6354 bool mHasAnimations
= true;
6357 * Decide whether we should prerender some or all of the contents of the
6358 * transformed frame even when it's not completely visible (yet).
6359 * Return PrerenderDecision::Full if the entire contents should be
6360 * prerendered, PrerenderDecision::Partial if some but not all of the
6361 * contents should be prerendered, or PrerenderDecision::No if only the
6362 * visible area should be rendered.
6363 * |mNoAffectDecisionInPreserve3D| is set if the prerender decision should not
6364 * affect the decision on other frames in the preserve 3d tree.
6365 * |aDirtyRect| is updated to the area that should be prerendered.
6367 static PrerenderInfo
ShouldPrerenderTransformedContent(
6368 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsRect
* aDirtyRect
);
6370 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
6372 bool MayBeAnimated(nsDisplayListBuilder
* aBuilder
) const;
6374 void WriteDebugInfo(std::stringstream
& aStream
) override
;
6376 bool CanMoveAsync() override
{
6377 return EffectCompositor::HasAnimationsForCompositor(
6378 mFrame
, DisplayItemType::TYPE_TRANSFORM
);
6382 * This item is an additional item as the boundary between parent
6383 * and child 3D rendering context.
6384 * \see nsIFrame::BuildDisplayListForStackingContext().
6386 bool IsTransformSeparator() const { return mIsTransformSeparator
; }
6388 * This item is the boundary between parent and child 3D rendering
6391 bool IsLeafOf3DContext() const {
6392 return (IsTransformSeparator() ||
6393 (!mFrame
->Extend3DContext() && Combines3DTransformWithAncestors()));
6396 * The backing frame of this item participates a 3D rendering
6399 bool IsParticipating3DContext() const {
6400 return mFrame
->Extend3DContext() || Combines3DTransformWithAncestors();
6403 bool IsPartialPrerender() const {
6404 return mPrerenderDecision
== PrerenderDecision::Partial
;
6408 * Mark this item as created together with `nsDisplayPerspective`.
6409 * \see nsIFrame::BuildDisplayListForStackingContext().
6411 void MarkWithAssociatedPerspective() { mHasAssociatedPerspective
= true; }
6413 void AddSizeOfExcludingThis(nsWindowSizes
&) const override
;
6415 bool CreatesStackingContextHelper() override
{ return true; }
6418 void ComputeBounds(nsDisplayListBuilder
* aBuilder
);
6419 nsRect
TransformUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
6420 const Matrix4x4Flagged
& aMatrix
) const;
6421 void UpdateUntransformedBounds(nsDisplayListBuilder
* aBuilder
);
6423 void SetReferenceFrameToAncestor(nsDisplayListBuilder
* aBuilder
);
6424 void Init(nsDisplayListBuilder
* aBuilder
, nsDisplayList
* aChildren
);
6426 static Matrix4x4
GetResultingTransformMatrixInternal(
6427 const FrameTransformProperties
& aProperties
,
6428 TransformReferenceBox
& aRefBox
, const nsPoint
& aOrigin
,
6429 float aAppUnitsPerPixel
, uint32_t aFlags
);
6431 void Collect3DTransformLeaves(nsDisplayListBuilder
* aBuilder
,
6432 nsTArray
<nsDisplayTransform
*>& aLeaves
);
6433 using TransformPolygon
= layers::BSPPolygon
<nsDisplayTransform
>;
6434 void CollectSorted3DTransformLeaves(nsDisplayListBuilder
* aBuilder
,
6435 nsTArray
<TransformPolygon
>& aLeaves
);
6437 mutable RetainedDisplayList mChildren
;
6438 mutable Maybe
<Matrix4x4Flagged
> mTransform
;
6439 mutable Maybe
<Matrix4x4Flagged
> mInverseTransform
;
6440 // Accumulated transform of ancestors on the preserves-3d chain.
6441 UniquePtr
<Matrix4x4
> mTransformPreserves3D
;
6442 nsRect mChildrenBuildingRect
;
6444 // The untransformed bounds of |mChildren|.
6445 nsRect mChildBounds
;
6446 // The transformed bounds of this display item.
6448 PrerenderDecision mPrerenderDecision
: 8;
6449 // This item is a separator between 3D rendering contexts, and
6450 // mTransform have been presetted by the constructor.
6451 // This also forces us not to extend the 3D context. Since we don't create a
6452 // transform item, a container layer, for every frame in a preserves3d
6453 // context, the transform items of a child preserves3d context may extend the
6454 // parent context unintendedly if the root of the child preserves3d context
6455 // doesn't create a transform item.
6456 bool mIsTransformSeparator
: 1;
6457 // True if we have a transform getter.
6458 bool mHasTransformGetter
: 1;
6459 // True if this item is created together with `nsDisplayPerspective`
6460 // from the same CSS stacking context.
6461 bool mHasAssociatedPerspective
: 1;
6464 /* A display item that applies a perspective transformation to a single
6465 * nsDisplayTransform child item. We keep this as a separate item since the
6466 * perspective-origin is relative to an ancestor of the transformed frame, and
6467 * APZ can scroll the child separately.
6469 class nsDisplayPerspective
: public nsPaintedDisplayItem
{
6471 nsDisplayPerspective(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6472 nsDisplayList
* aList
);
6473 ~nsDisplayPerspective() override
= default;
6475 NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE
)
6477 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
6478 mList
.DeleteAll(aBuilder
);
6479 nsPaintedDisplayItem::Destroy(aBuilder
);
6482 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6483 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
{
6484 return GetChildren()->HitTest(aBuilder
, aRect
, aState
, aOutFrames
);
6487 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
6489 return GetChildren()->GetClippedBoundsWithRespectToASR(aBuilder
,
6490 mActiveScrolledRoot
);
6493 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6494 const nsDisplayItemGeometry
* aGeometry
,
6495 nsRegion
* aInvalidRegion
) const override
{}
6497 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6498 bool* aSnap
) const override
;
6500 bool CreateWebRenderCommands(
6501 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6502 const StackingContextHelper
& aSc
,
6503 layers::RenderRootStateManager
* aManager
,
6504 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6506 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6508 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
6512 RetainedDisplayList
* GetChildren() const override
{ return &mList
; }
6514 nsRect
GetComponentAlphaBounds(
6515 nsDisplayListBuilder
* aBuilder
) const override
{
6516 return GetChildren()->GetComponentAlphaBounds(aBuilder
);
6519 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
{
6520 if (GetChildren()->GetTop()) {
6521 static_cast<nsDisplayTransform
*>(GetChildren()->GetTop())
6522 ->DoUpdateBoundsPreserves3D(aBuilder
);
6526 bool CreatesStackingContextHelper() override
{ return true; }
6529 mutable RetainedDisplayList mList
;
6532 class nsDisplayTextGeometry
;
6535 * This class adds basic support for limiting the rendering (in the inline axis
6536 * of the writing mode) to the part inside the specified edges.
6537 * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
6538 * of the frame's scrollable overflow rectangle and are the amount to suppress
6541 * Setting none, both or only one edge is allowed.
6542 * The values must be non-negative.
6543 * The default value for both edges is zero, which means everything is painted.
6545 class nsDisplayText final
: public nsPaintedDisplayItem
{
6547 nsDisplayText(nsDisplayListBuilder
* aBuilder
, nsTextFrame
* aFrame
);
6548 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayText
)
6550 NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT
)
6552 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const final
{
6557 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6558 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
{
6559 if (nsRect(ToReferenceFrame(), mFrame
->GetSize()).Intersects(aRect
)) {
6560 aOutFrames
->AppendElement(mFrame
);
6564 bool CreateWebRenderCommands(wr::DisplayListBuilder
& aBuilder
,
6565 wr::IpcResourceUpdateQueue
& aResources
,
6566 const StackingContextHelper
& aSc
,
6567 layers::RenderRootStateManager
* aManager
,
6568 nsDisplayListBuilder
* aDisplayListBuilder
) final
;
6569 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) final
;
6571 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const final
{
6572 if (gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()) {
6573 // On OS X, web authors can turn off subpixel text rendering using the
6574 // CSS property -moz-osx-font-smoothing. If they do that, we don't need
6575 // to use component alpha layers for the affected text.
6576 if (mFrame
->StyleFont()->mFont
.smoothing
== NS_FONT_SMOOTHING_GRAYSCALE
) {
6581 return GetBounds(aBuilder
, &snap
);
6584 nsDisplayItemGeometry
* AllocateGeometry(nsDisplayListBuilder
* aBuilder
) final
;
6586 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6587 const nsDisplayItemGeometry
* aGeometry
,
6588 nsRegion
* aInvalidRegion
) const final
;
6590 void RenderToContext(gfxContext
* aCtx
, nsDisplayListBuilder
* aBuilder
,
6591 const nsRect
& aVisibleRect
, float aOpacity
= 1.0f
,
6592 bool aIsRecording
= false);
6594 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
6595 nsDisplayListBuilder
* aBuilder
) const final
;
6597 void WriteDebugInfo(std::stringstream
& aStream
) final
;
6599 static nsDisplayText
* CheckCast(nsDisplayItem
* aItem
) {
6600 return (aItem
->GetType() == DisplayItemType::TYPE_TEXT
)
6601 ? static_cast<nsDisplayText
*>(aItem
)
6605 nscoord
& VisIStartEdge() { return mVisIStartEdge
; }
6606 nscoord
& VisIEndEdge() { return mVisIEndEdge
; }
6610 nsRect mVisibleRect
;
6612 // Lengths measured from the visual inline start and end sides
6613 // (i.e. left and right respectively in horizontal writing modes,
6614 // regardless of bidi directionality; top and bottom in vertical modes).
6615 nscoord mVisIStartEdge
;
6616 nscoord mVisIEndEdge
;
6620 * A display item that for webrender to handle SVG
6622 class nsDisplaySVGWrapper
: public nsDisplayWrapList
{
6624 nsDisplaySVGWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6625 nsDisplayList
* aList
);
6627 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySVGWrapper
)
6629 NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER
)
6631 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6632 GetChildren()->Paint(aBuilder
, aCtx
,
6633 mFrame
->PresContext()->AppUnitsPerDevPixel());
6635 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6636 bool CreateWebRenderCommands(
6637 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6638 const StackingContextHelper
& aSc
,
6639 layers::RenderRootStateManager
* aManager
,
6640 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6644 * A display item for webrender to handle SVG foreign object
6646 class nsDisplayForeignObject
: public nsDisplayWrapList
{
6648 nsDisplayForeignObject(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6649 nsDisplayList
* aList
);
6650 #ifdef NS_BUILD_REFCNT_LOGGING
6651 virtual ~nsDisplayForeignObject();
6654 NS_DISPLAY_DECL_NAME("ForeignObject", TYPE_FOREIGN_OBJECT
)
6656 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6657 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6658 GetChildren()->Paint(aBuilder
, aCtx
,
6659 mFrame
->PresContext()->AppUnitsPerDevPixel());
6662 bool CreateWebRenderCommands(
6663 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6664 const StackingContextHelper
& aSc
,
6665 layers::RenderRootStateManager
* aManager
,
6666 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6670 * A display item to represent a hyperlink.
6672 class nsDisplayLink
: public nsPaintedDisplayItem
{
6674 nsDisplayLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6675 const char* aLinkSpec
, const nsRect
& aRect
)
6676 : nsPaintedDisplayItem(aBuilder
, aFrame
),
6677 mLinkSpec(aLinkSpec
),
6680 NS_DISPLAY_DECL_NAME("Link", TYPE_LINK
)
6682 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6685 nsCString mLinkSpec
;
6690 * A display item to represent a destination within the document.
6692 class nsDisplayDestination
: public nsPaintedDisplayItem
{
6694 nsDisplayDestination(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6695 const char* aDestinationName
, const nsPoint
& aPosition
)
6696 : nsPaintedDisplayItem(aBuilder
, aFrame
),
6697 mDestinationName(aDestinationName
),
6698 mPosition(aPosition
) {}
6700 NS_DISPLAY_DECL_NAME("Destination", TYPE_DESTINATION
)
6702 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6705 nsCString mDestinationName
;
6709 class MOZ_STACK_CLASS FlattenedDisplayListIterator
{
6711 FlattenedDisplayListIterator(nsDisplayListBuilder
* aBuilder
,
6712 nsDisplayList
* aList
)
6713 : mBuilder(aBuilder
), mStart(aList
->begin()), mEnd(aList
->end()) {
6714 ResolveFlattening();
6717 bool HasNext() const { return !AtEndOfCurrentList(); }
6719 nsDisplayItem
* GetNextItem() {
6720 MOZ_ASSERT(HasNext());
6722 nsDisplayItem
* current
= NextItem();
6725 if (!AtEndOfCurrentList() && current
->CanMerge(NextItem())) {
6726 // Since we can merge at least two display items, create an array and
6727 // collect mergeable display items there.
6728 AutoTArray
<nsDisplayItem
*, 2> willMerge
{current
};
6731 while (it
!= mEnd
) {
6732 nsDisplayItem
* next
= *it
;
6733 if (current
->CanMerge(next
)) {
6734 willMerge
.AppendElement(next
);
6742 current
= mBuilder
->MergeItems(willMerge
);
6745 ResolveFlattening();
6750 void Advance() { ++mStart
; }
6752 bool AtEndOfNestedList() const {
6753 return AtEndOfCurrentList() && mStack
.Length() > 0;
6756 bool AtEndOfCurrentList() const { return mStart
== mEnd
; }
6758 nsDisplayItem
* NextItem() {
6759 MOZ_ASSERT(HasNext());
6763 bool ShouldFlattenNextItem() {
6764 return HasNext() && NextItem()->ShouldFlattenAway(mBuilder
);
6767 void ResolveFlattening() {
6768 // Handle the case where we reach the end of a nested list, or the current
6769 // item should start a new nested list. Repeat this until we find an actual
6770 // item, or the very end of the outer list.
6771 while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
6772 if (AtEndOfNestedList()) {
6773 // We reached the end of the list, pop the next list from the stack.
6774 std::tie(mStart
, mEnd
) = mStack
.PopLastElement();
6776 // The next item wants to be flattened. This means that we will skip the
6777 // flattened item and directly iterate over its sublist.
6778 MOZ_ASSERT(ShouldFlattenNextItem());
6780 nsDisplayList
* sublist
= NextItem()->GetChildren();
6781 MOZ_ASSERT(sublist
);
6783 // Skip the flattened item.
6786 // Store the current position on the stack.
6787 if (!AtEndOfCurrentList()) {
6788 mStack
.AppendElement(std::make_pair(mStart
, mEnd
));
6791 // Iterate over the sublist.
6792 mStart
= sublist
->begin();
6793 mEnd
= sublist
->end();
6799 nsDisplayListBuilder
* mBuilder
;
6800 nsDisplayList::iterator mStart
;
6801 nsDisplayList::iterator mEnd
;
6802 AutoTArray
<std::pair
<nsDisplayList::iterator
, nsDisplayList::iterator
>, 3>
6806 class PaintTelemetry
{
6808 class AutoRecordPaint
{
6818 static uint32_t sPaintLevel
;
6821 } // namespace mozilla
6823 #endif /*NSDISPLAYLIST_H_*/