1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * structures that represent things to be painted (ordered in z-order),
10 * used during painting and hit testing
13 #ifndef NSDISPLAYLIST_H_
14 #define NSDISPLAYLIST_H_
16 #include "DisplayItemClipChain.h"
17 #include "DisplayListClipState.h"
18 #include "FrameMetrics.h"
19 #include "HitTestInfo.h"
20 #include "ImgDrawResult.h"
21 #include "RetainedDisplayListHelpers.h"
23 #include "gfxContext.h"
24 #include "mozilla/ArenaAllocator.h"
25 #include "mozilla/Array.h"
26 #include "mozilla/ArrayIterator.h"
27 #include "mozilla/Assertions.h"
28 #include "mozilla/Attributes.h"
29 #include "mozilla/DebugOnly.h"
30 #include "mozilla/EffectCompositor.h"
31 #include "mozilla/EnumSet.h"
32 #include "mozilla/EnumeratedArray.h"
33 #include "mozilla/Logging.h"
34 #include "mozilla/Maybe.h"
35 #include "mozilla/MotionPathUtils.h"
36 #include "mozilla/RefPtr.h"
37 #include "mozilla/TemplateLib.h"
38 #include "mozilla/TimeStamp.h"
39 #include "mozilla/UniquePtr.h"
40 #include "mozilla/dom/EffectsInfo.h"
41 #include "mozilla/gfx/UserData.h"
42 #include "mozilla/layers/BSPTree.h"
43 #include "mozilla/layers/ScrollableLayerGuid.h"
44 #include "mozilla/layers/ScrollbarData.h"
45 #include "nsAutoLayoutPhase.h"
47 #include "nsCSSRenderingBorders.h"
48 #include "nsContainerFrame.h"
49 #include "nsDisplayItemTypes.h"
50 #include "nsDisplayListInvalidation.h"
52 #include "nsPresArena.h"
55 #include "nsClassHashtable.h"
56 #include "nsTHashSet.h"
57 #include "nsTHashMap.h"
60 #include <unordered_set>
62 // XXX Includes that could be avoided by moving function implementations to the
64 #include "gfxPlatform.h"
68 class nsIScrollableFrame
;
69 class nsSubDocumentFrame
;
71 struct WrFiltersHolder
;
73 namespace nsStyleTransformMatrix
{
74 class TransformReferenceBox
;
79 enum class nsDisplayOwnLayerFlags
;
80 class nsDisplayCompositorHitTestInfo
;
81 class nsDisplayScrollInfoLayer
;
83 class StickyScrollContainer
;
87 class RenderRootStateManager
;
90 class StackingContextHelper
;
91 class WebRenderScrollData
;
92 class WebRenderLayerScrollData
;
93 class WebRenderLayerManager
;
97 class DisplayListBuilder
;
105 enum class DisplayListArenaObjectId
{
106 #define DISPLAY_LIST_ARENA_OBJECT(name_) name_,
107 #include "nsDisplayListArenaTypes.h"
108 #undef DISPLAY_LIST_ARENA_OBJECT
112 extern LazyLogModule sContentDisplayListLog
;
113 extern LazyLogModule sParentDisplayListLog
;
115 LazyLogModule
& GetLoggerByProcess();
117 #define DL_LOG(lvl, ...) MOZ_LOG(GetLoggerByProcess(), lvl, (__VA_ARGS__))
118 #define DL_LOGI(...) DL_LOG(LogLevel::Info, __VA_ARGS__)
119 #define DL_LOG_TEST(lvl) MOZ_LOG_TEST(GetLoggerByProcess(), lvl)
122 # define DL_LOGD(...) DL_LOG(LogLevel::Debug, __VA_ARGS__)
123 # define DL_LOGV(...) DL_LOG(LogLevel::Verbose, __VA_ARGS__)
125 // Disable Debug and Verbose logs for release builds.
126 # define DL_LOGD(...)
127 # define DL_LOGV(...)
131 * An nsIFrame can have many different visual parts. For example an image frame
132 * can have a background, border, and outline, the image itself, and a
133 * translucent selection overlay. In general these parts can be drawn at
134 * discontiguous z-levels; see CSS2.1 appendix E:
135 * http://www.w3.org/TR/CSS21/zindex.html
137 * We construct a display list for a frame tree that contains one item
138 * for each visual part. The display list is itself a tree since some items
139 * are containers for other items; however, its structure does not match
140 * the structure of its source frame tree. The display list items are sorted
141 * by z-order. A display list can be used to paint the frames, to determine
142 * which frame is the target of a mouse event, and to determine what areas
143 * need to be repainted when scrolling. The display lists built for each task
144 * may be different for efficiency; in particular some frames need special
145 * display list items only for event handling, and do not create these items
146 * when the display list will be used for painting (the common case). For
147 * example, when painting we avoid creating nsDisplayBackground items for
148 * frames that don't display a visible background, but for event handling
149 * we need those backgrounds because they are not transparent to events.
151 * We could avoid constructing an explicit display list by traversing the
152 * frame tree multiple times in clever ways. However, reifying the display list
153 * reduces code complexity and reduces the number of times each frame must be
154 * traversed to one, which seems to be good for performance. It also means
155 * we can share code for painting, event handling and scroll analysis.
157 * Display lists are short-lived; content and frame trees cannot change
158 * between a display list being created and destroyed. Display lists should
159 * not be created during reflow because the frame tree may be in an
160 * inconsistent state (e.g., a frame's stored overflow-area may not include
161 * the bounds of all its children). However, it should be fine to create
162 * a display list while a reflow is pending, before it starts.
164 * A display list covers the "extended" frame tree; the display list for
165 * a frame tree containing FRAME/IFRAME elements can include frames from
168 * Display item's coordinates are relative to their nearest reference frame
169 * ancestor. Both the display root and any frame with a transform act as a
170 * reference frame for their frame subtrees.
174 * An active scrolled root (ASR) is similar to an animated geometry root (AGR).
175 * The differences are:
176 * - ASRs are only created for async-scrollable scroll frames. This is a
177 * (hopefully) temporary restriction. In the future we will want to create
178 * ASRs for all the things that are currently creating AGRs, and then
179 * replace AGRs with ASRs and rename them from "active scrolled root" to
180 * "animated geometry root".
181 * - ASR objects are created during display list construction by the nsIFrames
182 * that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter.
183 * The current ASR is returned by
184 * nsDisplayListBuilder::CurrentActiveScrolledRoot().
185 * - There is no way to go from an nsIFrame pointer to the ASR of that frame.
186 * If you need to look up an ASR after display list construction, you need
187 * to store it while the AutoCurrentActiveScrolledRootSetter that creates it
190 struct ActiveScrolledRoot
{
191 static already_AddRefed
<ActiveScrolledRoot
> CreateASRForFrame(
192 const ActiveScrolledRoot
* aParent
, nsIScrollableFrame
* aScrollableFrame
,
195 static const ActiveScrolledRoot
* PickAncestor(
196 const ActiveScrolledRoot
* aOne
, const ActiveScrolledRoot
* aTwo
) {
197 MOZ_ASSERT(IsAncestor(aOne
, aTwo
) || IsAncestor(aTwo
, aOne
));
198 return Depth(aOne
) <= Depth(aTwo
) ? aOne
: aTwo
;
201 static const ActiveScrolledRoot
* PickDescendant(
202 const ActiveScrolledRoot
* aOne
, const ActiveScrolledRoot
* aTwo
) {
203 MOZ_ASSERT(IsAncestor(aOne
, aTwo
) || IsAncestor(aTwo
, aOne
));
204 return Depth(aOne
) >= Depth(aTwo
) ? aOne
: aTwo
;
207 static bool IsAncestor(const ActiveScrolledRoot
* aAncestor
,
208 const ActiveScrolledRoot
* aDescendant
);
209 static bool IsProperAncestor(const ActiveScrolledRoot
* aAncestor
,
210 const ActiveScrolledRoot
* aDescendant
);
212 static nsCString
ToString(const ActiveScrolledRoot
* aActiveScrolledRoot
);
214 // Call this when inserting an ancestor.
215 void IncrementDepth() { mDepth
++; }
218 * Find the view ID (or generate a new one) for the content element
219 * corresponding to the ASR.
221 layers::ScrollableLayerGuid::ViewID
GetViewId() const {
222 if (!mViewId
.isSome()) {
223 mViewId
= Some(ComputeViewId());
228 RefPtr
<const ActiveScrolledRoot
> mParent
;
229 nsIScrollableFrame
* mScrollableFrame
;
231 NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot
)
235 : mScrollableFrame(nullptr), mDepth(0), mRetained(false) {}
237 ~ActiveScrolledRoot();
239 static void DetachASR(ActiveScrolledRoot
* aASR
) {
240 aASR
->mParent
= nullptr;
241 aASR
->mScrollableFrame
= nullptr;
244 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache
,
245 ActiveScrolledRoot
, DetachASR
)
247 static uint32_t Depth(const ActiveScrolledRoot
* aActiveScrolledRoot
) {
248 return aActiveScrolledRoot
? aActiveScrolledRoot
->mDepth
: 0;
251 layers::ScrollableLayerGuid::ViewID
ComputeViewId() const;
253 // This field is lazily populated in GetViewId(). We don't want to do the
254 // work of populating if webrender is disabled, because it is often not
256 mutable Maybe
<layers::ScrollableLayerGuid::ViewID
> mViewId
;
262 enum class nsDisplayListBuilderMode
: uint8_t {
270 using ListArenaAllocator
= ArenaAllocator
<4096, 8>;
273 class nsPaintedDisplayItem
;
275 class nsDisplayWrapList
;
276 class nsDisplayTableBackgroundSet
;
277 class nsDisplayTableItem
;
279 class RetainedDisplayList
;
282 * This manages a display list and is passed as a parameter to
283 * nsIFrame::BuildDisplayList.
284 * It contains the parameters that don't change from frame to frame and manages
285 * the display list memory using an arena. It also establishes the reference
286 * coordinate system for all display list items. Some of the parameters are
287 * available from the prescontext/presshell, but we copy them into the builder
288 * for faster/more convenient access.
290 class nsDisplayListBuilder
{
292 * This manages status of a 3d context to collect visible rects of
293 * descendants and passing a dirty rect.
295 * Since some transforms maybe singular, passing visible rects or
296 * the dirty rect level by level from parent to children may get a
297 * wrong result, being different from the result of appling with
298 * effective transform directly.
300 * nsIFrame::BuildDisplayListForStackingContext() uses
301 * AutoPreserves3DContext to install an instance on the builder.
303 * \see AutoAccumulateTransform, AutoAccumulateRect,
304 * AutoPreserves3DContext, Accumulate, GetCurrentTransform,
307 class Preserves3DContext
{
310 : mAccumulatedRectLevels(0), mAllowAsyncAnimation(true) {}
312 Preserves3DContext(const Preserves3DContext
& aOther
)
313 : mAccumulatedRectLevels(0),
314 mVisibleRect(aOther
.mVisibleRect
),
315 mAllowAsyncAnimation(aOther
.mAllowAsyncAnimation
) {}
317 // Accmulate transforms of ancestors on the preserves-3d chain.
318 gfx::Matrix4x4 mAccumulatedTransform
;
319 // Accmulate visible rect of descendants in the preserves-3d context.
320 nsRect mAccumulatedRect
;
321 // How far this frame is from the root of the current 3d context.
322 int mAccumulatedRectLevels
;
324 // Allow async animation for this 3D context.
325 bool mAllowAsyncAnimation
;
329 using ViewID
= layers::ScrollableLayerGuid::ViewID
;
332 * @param aReferenceFrame the frame at the root of the subtree; its origin
333 * is the origin of the reference coordinate system for this display list
334 * @param aMode encodes what the builder is being used for.
335 * @param aBuildCaret whether or not we should include the caret in any
336 * display lists that we make.
338 nsDisplayListBuilder(nsIFrame
* aReferenceFrame
,
339 nsDisplayListBuilderMode aMode
, bool aBuildCaret
,
340 bool aRetainingDisplayList
= false);
341 ~nsDisplayListBuilder();
346 void AddTemporaryItem(nsDisplayItem
* aItem
) {
347 mTemporaryItems
.AppendElement(aItem
);
350 WindowRenderer
* GetWidgetWindowRenderer(nsView
** aView
= nullptr);
351 layers::WebRenderLayerManager
* GetWidgetLayerManager(
352 nsView
** aView
= nullptr);
355 * @return true if the display is being built in order to determine which
356 * frame is under the mouse position.
358 bool IsForEventDelivery() const {
359 return mMode
== nsDisplayListBuilderMode::EventDelivery
;
363 * @return true if the display list is being built for painting. This
364 * includes both painting to a window or other buffer and painting to
365 * a print/pdf destination.
367 bool IsForPainting() const {
368 return mMode
== nsDisplayListBuilderMode::Painting
||
369 mMode
== nsDisplayListBuilderMode::PaintForPrinting
;
373 * @return true if the display list is being built specifically for printing.
375 bool IsForPrinting() const {
376 return mMode
== nsDisplayListBuilderMode::PaintForPrinting
;
380 * @return true if the display list is being built for determining frame
383 bool IsForFrameVisibility() const {
384 return mMode
== nsDisplayListBuilderMode::FrameVisibility
;
388 * @return true if the display list is being built for creating the glyph
389 * mask from text items.
391 bool IsForGenerateGlyphMask() const {
392 return mMode
== nsDisplayListBuilderMode::GenerateGlyph
;
395 bool BuildCompositorHitTestInfo() const {
396 return mBuildCompositorHitTestInfo
;
400 * @return true if "painting is suppressed" during page load and we
401 * should paint only the background of the document.
403 bool IsBackgroundOnly() {
404 NS_ASSERTION(mPresShellStates
.Length() > 0,
405 "don't call this if we're not in a presshell");
406 return CurrentPresShellState()->mIsBackgroundOnly
;
410 * @return the root of given frame's (sub)tree, whose origin
411 * establishes the coordinate system for the child display items.
413 const nsIFrame
* FindReferenceFrameFor(const nsIFrame
* aFrame
,
414 nsPoint
* aOffset
= nullptr) const;
416 const Maybe
<nsPoint
>& AdditionalOffset() const { return mAdditionalOffset
; }
419 * @return the root of the display list's frame (sub)tree, whose origin
420 * establishes the coordinate system for the display list
422 nsIFrame
* RootReferenceFrame() const { return mReferenceFrame
; }
425 * @return a point pt such that adding pt to a coordinate relative to aFrame
426 * makes it relative to ReferenceFrame(), i.e., returns
427 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
428 * the appunits of aFrame.
430 const nsPoint
ToReferenceFrame(const nsIFrame
* aFrame
) const {
432 FindReferenceFrameFor(aFrame
, &result
);
436 * When building the display list, the scrollframe aFrame will be "ignored"
437 * for the purposes of clipping, and its scrollbars will be hidden. We use
438 * this to allow RenderOffscreen to render a whole document without beign
439 * clipped by the viewport or drawing the viewport scrollbars.
441 void SetIgnoreScrollFrame(nsIFrame
* aFrame
) { mIgnoreScrollFrame
= aFrame
; }
443 * Get the scrollframe to ignore, if any.
445 nsIFrame
* GetIgnoreScrollFrame() { return mIgnoreScrollFrame
; }
446 void SetIsRelativeToLayoutViewport();
447 bool IsRelativeToLayoutViewport() const {
448 return mIsRelativeToLayoutViewport
;
451 * Get the ViewID of the nearest scrolling ancestor frame.
453 ViewID
GetCurrentScrollParentId() const { return mCurrentScrollParentId
; }
455 * Get and set the flag that indicates if scroll parents should have layers
456 * forcibly created. This flag is set when a deeply nested scrollframe has
457 * a displayport, and for scroll handoff to work properly the ancestor
458 * scrollframes should also get their own scrollable layers.
460 void ForceLayerForScrollParent() { mForceLayerForScrollParent
= true; }
462 * Set the flag that indicates there is a non-minimal display port in the
463 * current subtree. This is used to determine display port expiry.
465 void SetContainsNonMinimalDisplayPort() {
466 mContainsNonMinimalDisplayPort
= true;
469 * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
470 * which we are building display items at the moment.
472 ViewID
GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget
; }
473 Maybe
<layers::ScrollDirection
> GetCurrentScrollbarDirection() const {
474 return mCurrentScrollbarDirection
;
477 * Returns true if building a scrollbar, and the scrollbar will not be
480 bool IsBuildingNonLayerizedScrollbar() const {
481 return mIsBuildingScrollbar
&& !mCurrentScrollbarWillHaveLayer
;
484 * Calling this setter makes us include all out-of-flow descendant
485 * frames in the display list, wherever they may be positioned (even
486 * outside the dirty rects).
488 void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows
= true; }
489 bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows
; }
491 * Calling this setter makes us exclude all leaf frames that aren't
494 void SetSelectedFramesOnly() { mSelectedFramesOnly
= true; }
495 bool GetSelectedFramesOnly() { return mSelectedFramesOnly
; }
497 * @return Returns true if we should include the caret in any display lists
500 bool IsBuildingCaret() const { return mBuildCaret
; }
502 bool IsRetainingDisplayList() const { return mRetainingDisplayList
; }
504 bool IsPartialUpdate() const { return mPartialUpdate
; }
505 void SetPartialUpdate(bool aPartial
) { mPartialUpdate
= aPartial
; }
507 bool IsBuilding() const { return mIsBuilding
; }
508 void SetIsBuilding(bool aIsBuilding
) { mIsBuilding
= aIsBuilding
; }
510 bool InInvalidSubtree() const { return mInInvalidSubtree
; }
513 * Allows callers to selectively override the regular paint suppression
514 * checks, so that methods like GetFrameForPoint work when painting is
517 void IgnorePaintSuppression() { mIgnoreSuppression
= true; }
519 * @return Returns if this builder will ignore paint suppression.
521 bool IsIgnoringPaintSuppression() { return mIgnoreSuppression
; }
523 * Call this if we're doing normal painting to the window.
525 void SetPaintingToWindow(bool aToWindow
) { mIsPaintingToWindow
= aToWindow
; }
526 bool IsPaintingToWindow() const { return mIsPaintingToWindow
; }
528 * Call this if we're using high quality scaling for image decoding.
529 * It is also implied by IsPaintingToWindow.
531 void SetUseHighQualityScaling(bool aUseHighQualityScaling
) {
532 mUseHighQualityScaling
= aUseHighQualityScaling
;
534 bool UseHighQualityScaling() const {
535 return mIsPaintingToWindow
|| mUseHighQualityScaling
;
538 * Call this if we're doing painting for WebRender
540 void SetPaintingForWebRender(bool aForWebRender
) {
541 mIsPaintingForWebRender
= true;
543 bool IsPaintingForWebRender() const { return mIsPaintingForWebRender
; }
545 * Call this to prevent descending into subdocuments.
547 void SetDescendIntoSubdocuments(bool aDescend
) {
548 mDescendIntoSubdocuments
= aDescend
;
551 bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments
; }
554 * Get dirty rect relative to current frame (the frame that we're calling
555 * BuildDisplayList on right now).
557 const nsRect
& GetVisibleRect() { return mVisibleRect
; }
558 const nsRect
& GetDirtyRect() { return mDirtyRect
; }
560 void SetVisibleRect(const nsRect
& aVisibleRect
) {
561 mVisibleRect
= aVisibleRect
;
564 void IntersectVisibleRect(const nsRect
& aVisibleRect
) {
565 mVisibleRect
.IntersectRect(mVisibleRect
, aVisibleRect
);
568 void SetDirtyRect(const nsRect
& aDirtyRect
) { mDirtyRect
= aDirtyRect
; }
570 void IntersectDirtyRect(const nsRect
& aDirtyRect
) {
571 mDirtyRect
.IntersectRect(mDirtyRect
, aDirtyRect
);
574 const nsIFrame
* GetCurrentFrame() { return mCurrentFrame
; }
575 const nsIFrame
* GetCurrentReferenceFrame() { return mCurrentReferenceFrame
; }
577 const nsPoint
& GetCurrentFrameOffsetToReferenceFrame() const {
578 return mCurrentOffsetToReferenceFrame
;
581 void Check() { mPool
.Check(); }
584 * Get the paint sequence number of the current paint.
586 static uint32_t GetPaintSequenceNumber() { return sPaintSequenceNumber
; }
589 * Increment the paint sequence number.
591 static void IncrementPaintSequenceNumber() { ++sPaintSequenceNumber
; }
594 * Returns true if merging and flattening of display lists should be
595 * performed while computing visibility.
597 bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening
; }
598 void SetAllowMergingAndFlattening(bool aAllow
) {
599 mAllowMergingAndFlattening
= aAllow
;
602 void SetCompositorHitTestInfo(const gfx::CompositorHitTestInfo
& aInfo
) {
603 mCompositorHitTestInfo
= aInfo
;
606 const gfx::CompositorHitTestInfo
& GetCompositorHitTestInfo() const {
607 return mCompositorHitTestInfo
;
611 * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
612 * needed, and adds it to the top of |aList|.
614 void BuildCompositorHitTestInfoIfNeeded(nsIFrame
* aFrame
,
615 nsDisplayList
* aList
);
617 bool IsInsidePointerEventsNoneDoc() {
618 return CurrentPresShellState()->mInsidePointerEventsNoneDoc
;
621 bool IsTouchEventPrefEnabledDoc() {
622 return CurrentPresShellState()->mTouchEventPrefEnabledDoc
;
625 bool GetAncestorHasApzAwareEventHandler() const {
626 return mAncestorHasApzAwareEventHandler
;
629 void SetAncestorHasApzAwareEventHandler(bool aValue
) {
630 mAncestorHasApzAwareEventHandler
= aValue
;
633 bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort
; }
634 void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort
= true; }
635 void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort
= false; }
637 bool SetIsCompositingCheap(bool aCompositingCheap
) {
638 bool temp
= mIsCompositingCheap
;
639 mIsCompositingCheap
= aCompositingCheap
;
643 bool IsCompositingCheap() const { return mIsCompositingCheap
; }
645 * Display the caret if needed.
647 bool DisplayCaret(nsIFrame
* aFrame
, nsDisplayList
* aList
) {
648 nsIFrame
* frame
= GetCaretFrame();
649 if (aFrame
== frame
&& !IsBackgroundOnly()) {
650 frame
->DisplayCaret(this, aList
);
656 * Get the frame that the caret is supposed to draw in.
657 * If the caret is currently invisible, this will be null.
659 nsIFrame
* GetCaretFrame() { return mCaretFrame
; }
661 * Get the rectangle we're supposed to draw the caret into.
663 const nsRect
& GetCaretRect() { return mCaretRect
; }
665 * Get the caret associated with the current presshell.
670 * Returns the root scroll frame for the current PresShell, if the PresShell
671 * is ignoring viewport scrolling.
673 nsIFrame
* GetPresShellIgnoreScrollFrame() {
674 return CurrentPresShellState()->mPresShellIgnoreScrollFrame
;
678 * Notify the display list builder that we're entering a presshell.
679 * aReferenceFrame should be a frame in the new presshell.
680 * aPointerEventsNoneDoc should be set to true if the frame generating this
681 * document is pointer-events:none.
683 void EnterPresShell(const nsIFrame
* aReferenceFrame
,
684 bool aPointerEventsNoneDoc
= false);
686 * For print-preview documents, we sometimes need to build display items for
687 * the same frames multiple times in the same presentation, with different
688 * clipping. Between each such batch of items, call
689 * ResetMarkedFramesForDisplayList to make sure that the results of
690 * MarkFramesForDisplayList do not carry over between batches.
692 void ResetMarkedFramesForDisplayList(const nsIFrame
* aReferenceFrame
);
694 * Notify the display list builder that we're leaving a presshell.
696 void LeavePresShell(const nsIFrame
* aReferenceFrame
,
697 nsDisplayList
* aPaintedContents
);
699 void IncrementPresShellPaintCount(PresShell
* aPresShell
);
702 * Returns true if we're currently building a display list that's
703 * directly or indirectly under an nsDisplayTransform.
705 bool IsInTransform() const { return mInTransform
; }
707 bool InEventsOnly() const { return mInEventsOnly
; }
709 * Indicate whether or not we're directly or indirectly under and
710 * nsDisplayTransform or SVG foreignObject.
712 void SetInTransform(bool aInTransform
) { mInTransform
= aInTransform
; }
715 * Returns true if we're currently building a display list that's
716 * under an nsDisplayFilters.
718 bool IsInFilter() const { return mInFilter
; }
721 * Return true if we're currently building a display list for a
724 bool IsInSubdocument() const { return mPresShellStates
.Length() > 1; }
726 void SetDisablePartialUpdates(bool aDisable
) {
727 mDisablePartialUpdates
= aDisable
;
729 bool DisablePartialUpdates() const { return mDisablePartialUpdates
; }
731 void SetPartialBuildFailed(bool aFailed
) { mPartialBuildFailed
= aFailed
; }
732 bool PartialBuildFailed() const { return mPartialBuildFailed
; }
734 bool IsInActiveDocShell() const { return mIsInActiveDocShell
; }
735 void SetInActiveDocShell(bool aActive
) { mIsInActiveDocShell
= aActive
; }
738 * Return true if we're currently building a display list for the presshell
739 * of a chrome document, or if we're building the display list for a popup.
741 bool IsInChromeDocumentOrPopup() const {
742 return mIsInChromePresContext
|| mIsBuildingForPopup
;
746 * @return true if images have been set to decode synchronously.
748 bool ShouldSyncDecodeImages() const { return mSyncDecodeImages
; }
751 * Indicates whether we should synchronously decode images. If true, we decode
752 * and draw whatever image data has been loaded. If false, we just draw
753 * whatever has already been decoded.
755 void SetSyncDecodeImages(bool aSyncDecodeImages
) {
756 mSyncDecodeImages
= aSyncDecodeImages
;
759 nsDisplayTableBackgroundSet
* SetTableBackgroundSet(
760 nsDisplayTableBackgroundSet
* aTableSet
) {
761 nsDisplayTableBackgroundSet
* old
= mTableBackgroundSet
;
762 mTableBackgroundSet
= aTableSet
;
765 nsDisplayTableBackgroundSet
* GetTableBackgroundSet() const {
766 return mTableBackgroundSet
;
769 void FreeClipChains();
772 * Frees the temporary display items created during merging.
774 void FreeTemporaryItems();
777 * Helper method to generate background painting flags based on the
778 * information available in the display list builder.
780 uint32_t GetBackgroundPaintFlags();
783 * Helper method to generate nsImageRenderer flags based on the information
784 * available in the display list builder.
786 uint32_t GetImageRendererFlags() const;
789 * Helper method to generate image decoding flags based on the
790 * information available in the display list builder.
792 uint32_t GetImageDecodeFlags() const;
795 * Subtracts aRegion from *aVisibleRegion. We avoid letting
796 * aVisibleRegion become overcomplex by simplifying it if necessary.
798 void SubtractFromVisibleRegion(nsRegion
* aVisibleRegion
,
799 const nsRegion
& aRegion
);
802 * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
803 * (which is relative to aDirtyFrame). If the frames have placeholders
804 * that might not be displayed, we mark the placeholders and their ancestors
805 * to ensure that display list construction descends into them
806 * anyway. nsDisplayListBuilder will take care of unmarking them when it is
809 void MarkFramesForDisplayList(nsIFrame
* aDirtyFrame
,
810 const nsFrameList
& aFrames
);
811 void MarkFrameForDisplay(nsIFrame
* aFrame
, const nsIFrame
* aStopAtFrame
);
812 void MarkFrameForDisplayIfVisible(nsIFrame
* aFrame
,
813 const nsIFrame
* aStopAtFrame
);
814 void AddFrameMarkedForDisplayIfVisible(nsIFrame
* aFrame
);
816 void ClearFixedBackgroundDisplayData();
818 * Mark all child frames that Preserve3D() as needing display.
819 * Because these frames include transforms set on their parent, dirty rects
820 * for intermediate frames may be empty, yet child frames could still be
823 void MarkPreserve3DFramesForDisplayList(nsIFrame
* aDirtyFrame
);
826 * Returns true if we need to descend into this frame when building
827 * the display list, even though it doesn't intersect the dirty
828 * rect, because it may have out-of-flows that do so.
830 bool ShouldDescendIntoFrame(nsIFrame
* aFrame
, bool aVisible
) const {
831 return aFrame
->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO
) ||
832 (aVisible
&& aFrame
->ForceDescendIntoIfVisible()) ||
833 GetIncludeAllOutOfFlows();
837 * Returns the list of registered theme geometries.
839 nsTArray
<nsIWidget::ThemeGeometry
> GetThemeGeometries() const {
840 nsTArray
<nsIWidget::ThemeGeometry
> geometries
;
842 for (const auto& data
: mThemeGeometries
.Values()) {
843 geometries
.AppendElements(*data
);
850 * Notifies the builder that a particular themed widget exists
851 * at the given rectangle within the currently built display list.
852 * For certain appearance values (currently only StyleAppearance::Toolbar and
853 * StyleAppearance::WindowTitlebar) this gets called during every display list
854 * construction, for every themed widget of the right type within the
855 * display list, except for themed widgets which are transformed or have
856 * effects applied to them (e.g. CSS opacity or filters).
858 * @param aWidgetType the -moz-appearance value for the themed widget
859 * @param aItem the item associated with the theme geometry
860 * @param aRect the device-pixel rect relative to the widget's displayRoot
861 * for the themed widget
863 void RegisterThemeGeometry(uint8_t aWidgetType
, nsDisplayItem
* aItem
,
864 const LayoutDeviceIntRect
& aRect
) {
865 if (!mIsPaintingToWindow
) {
869 nsTArray
<nsIWidget::ThemeGeometry
>* geometries
=
870 mThemeGeometries
.GetOrInsertNew(aItem
);
871 geometries
->AppendElement(nsIWidget::ThemeGeometry(aWidgetType
, aRect
));
875 * Removes theme geometries associated with the given display item |aItem|.
877 void UnregisterThemeGeometry(nsDisplayItem
* aItem
) {
878 mThemeGeometries
.Remove(aItem
);
882 * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
883 * -moz-window-dragging value is |drag|, its border box is added to the
884 * collected dragging region; if the value is |no-drag|, the border box is
885 * subtracted from the region; if the value is |default|, that frame does
886 * not influence the window dragging region.
888 void AdjustWindowDraggingRegion(nsIFrame
* aFrame
);
890 LayoutDeviceIntRegion
GetWindowDraggingRegion() const;
892 void RemoveModifiedWindowRegions();
893 void ClearRetainedWindowRegions();
895 const nsTHashMap
<nsPtrHashKey
<dom::RemoteBrowser
>, dom::EffectsInfo
>&
896 GetEffectUpdates() const {
897 return mEffectsUpdates
;
900 void AddEffectUpdate(dom::RemoteBrowser
* aBrowser
,
901 const dom::EffectsInfo
& aUpdate
);
904 * Allocate memory in our arena. It will only be freed when this display list
905 * builder is destroyed. This memory holds nsDisplayItems and
906 * DisplayItemClipChain objects.
908 * Destructors are called as soon as the item is no longer used.
910 void* Allocate(size_t aSize
, DisplayListArenaObjectId aId
) {
911 return mPool
.Allocate(aId
, aSize
);
913 void* Allocate(size_t aSize
, DisplayItemType aType
) {
914 #define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) \
915 static_assert(size_t(DisplayItemType::TYPE_##name_) == \
916 size_t(DisplayListArenaObjectId::name_), \
918 #include "nsDisplayItemTypesList.h"
919 static_assert(size_t(DisplayItemType::TYPE_MAX
) ==
920 size_t(DisplayListArenaObjectId::CLIPCHAIN
),
922 static_assert(size_t(DisplayItemType::TYPE_MAX
) + 1 ==
923 size_t(DisplayListArenaObjectId::LISTNODE
),
925 #undef DECLARE_DISPLAY_ITEM_TYPE
926 return Allocate(aSize
, DisplayListArenaObjectId(size_t(aType
)));
929 void Destroy(DisplayListArenaObjectId aId
, void* aPtr
) {
930 return mPool
.Free(aId
, aPtr
);
932 void Destroy(DisplayItemType aType
, void* aPtr
) {
933 return Destroy(DisplayListArenaObjectId(size_t(aType
)), aPtr
);
937 * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
938 * automatically when the arena goes away.
940 ActiveScrolledRoot
* AllocateActiveScrolledRoot(
941 const ActiveScrolledRoot
* aParent
, nsIScrollableFrame
* aScrollableFrame
);
944 * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
945 * up automatically when the arena goes away.
947 const DisplayItemClipChain
* AllocateDisplayItemClipChain(
948 const DisplayItemClip
& aClip
, const ActiveScrolledRoot
* aASR
,
949 const DisplayItemClipChain
* aParent
);
952 * Intersect two clip chains, allocating the new clip chain items in this
953 * builder's arena. The result is parented to aAncestor, and no intersections
954 * happen past aAncestor's ASR.
955 * That means aAncestor has to be living in this builder's arena already.
956 * aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
957 * their values are copied into the newly-allocated intersected clip chain
958 * and this function does not hold on to any pointers to them.
960 const DisplayItemClipChain
* CreateClipChainIntersection(
961 const DisplayItemClipChain
* aAncestor
,
962 const DisplayItemClipChain
* aLeafClip1
,
963 const DisplayItemClipChain
* aLeafClip2
);
966 * Same as above, except aAncestor is computed as the nearest common
967 * ancestor of the two provided clips.
969 const DisplayItemClipChain
* CreateClipChainIntersection(
970 const DisplayItemClipChain
* aLeafClip1
,
971 const DisplayItemClipChain
* aLeafClip2
);
974 * Clone the supplied clip chain's chain items into this builder's arena.
976 const DisplayItemClipChain
* CopyWholeChain(
977 const DisplayItemClipChain
* aClipChain
);
979 const ActiveScrolledRoot
* GetFilterASR() const { return mFilterASR
; }
982 * Merges the display items in |aMergedItems| and returns a new temporary
984 * The display items in |aMergedItems| have to be mergeable with each other.
986 nsDisplayWrapList
* MergeItems(nsTArray
<nsDisplayItem
*>& aItems
);
989 * A helper class used to temporarily set nsDisplayListBuilder properties for
990 * building display items.
991 * aVisibleRect and aDirtyRect are relative to aForChild.
993 class AutoBuildingDisplayList
{
995 AutoBuildingDisplayList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aForChild
,
996 const nsRect
& aVisibleRect
,
997 const nsRect
& aDirtyRect
)
998 : AutoBuildingDisplayList(aBuilder
, aForChild
, aVisibleRect
, aDirtyRect
,
999 aForChild
->IsTransformed()) {}
1001 AutoBuildingDisplayList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aForChild
,
1002 const nsRect
& aVisibleRect
,
1003 const nsRect
& aDirtyRect
,
1004 const bool aIsTransformed
);
1006 void SetReferenceFrameAndCurrentOffset(const nsIFrame
* aFrame
,
1007 const nsPoint
& aOffset
) {
1008 mBuilder
->mCurrentReferenceFrame
= aFrame
;
1009 mBuilder
->mCurrentOffsetToReferenceFrame
= aOffset
;
1012 void SetAdditionalOffset(const nsPoint
& aOffset
) {
1013 MOZ_ASSERT(!mBuilder
->mAdditionalOffset
);
1014 mBuilder
->mAdditionalOffset
= Some(aOffset
);
1016 mBuilder
->mCurrentOffsetToReferenceFrame
+= aOffset
;
1019 void RestoreBuildingInvisibleItemsValue() {
1020 mBuilder
->mBuildingInvisibleItems
= mPrevBuildingInvisibleItems
;
1023 ~AutoBuildingDisplayList() {
1024 mBuilder
->mCurrentFrame
= mPrevFrame
;
1025 mBuilder
->mCurrentReferenceFrame
= mPrevReferenceFrame
;
1026 mBuilder
->mCurrentOffsetToReferenceFrame
= mPrevOffset
;
1027 mBuilder
->mVisibleRect
= mPrevVisibleRect
;
1028 mBuilder
->mDirtyRect
= mPrevDirtyRect
;
1029 mBuilder
->mAncestorHasApzAwareEventHandler
=
1030 mPrevAncestorHasApzAwareEventHandler
;
1031 mBuilder
->mBuildingInvisibleItems
= mPrevBuildingInvisibleItems
;
1032 mBuilder
->mInInvalidSubtree
= mPrevInInvalidSubtree
;
1033 mBuilder
->mAdditionalOffset
= mPrevAdditionalOffset
;
1034 mBuilder
->mCompositorHitTestInfo
= mPrevCompositorHitTestInfo
;
1038 nsDisplayListBuilder
* mBuilder
;
1039 const nsIFrame
* mPrevFrame
;
1040 const nsIFrame
* mPrevReferenceFrame
;
1041 nsPoint mPrevOffset
;
1042 Maybe
<nsPoint
> mPrevAdditionalOffset
;
1043 nsRect mPrevVisibleRect
;
1044 nsRect mPrevDirtyRect
;
1045 gfx::CompositorHitTestInfo mPrevCompositorHitTestInfo
;
1046 bool mPrevAncestorHasApzAwareEventHandler
;
1047 bool mPrevBuildingInvisibleItems
;
1048 bool mPrevInInvalidSubtree
;
1052 * A helper class to temporarily set the value of mInTransform.
1054 class AutoInTransformSetter
{
1056 AutoInTransformSetter(nsDisplayListBuilder
* aBuilder
, bool aInTransform
)
1057 : mBuilder(aBuilder
), mOldValue(aBuilder
->mInTransform
) {
1058 aBuilder
->mInTransform
= aInTransform
;
1061 ~AutoInTransformSetter() { mBuilder
->mInTransform
= mOldValue
; }
1064 nsDisplayListBuilder
* mBuilder
;
1068 class AutoInEventsOnly
{
1070 AutoInEventsOnly(nsDisplayListBuilder
* aBuilder
, bool aInEventsOnly
)
1071 : mBuilder(aBuilder
), mOldValue(aBuilder
->mInEventsOnly
) {
1072 aBuilder
->mInEventsOnly
|= aInEventsOnly
;
1075 ~AutoInEventsOnly() { mBuilder
->mInEventsOnly
= mOldValue
; }
1078 nsDisplayListBuilder
* mBuilder
;
1083 * A helper class to temporarily set the value of mFilterASR and
1086 class AutoEnterFilter
{
1088 AutoEnterFilter(nsDisplayListBuilder
* aBuilder
, bool aUsingFilter
)
1089 : mBuilder(aBuilder
),
1090 mOldValue(aBuilder
->mFilterASR
),
1091 mOldInFilter(aBuilder
->mInFilter
) {
1092 if (!aBuilder
->mFilterASR
&& aUsingFilter
) {
1093 aBuilder
->mFilterASR
= aBuilder
->CurrentActiveScrolledRoot();
1094 aBuilder
->mInFilter
= true;
1098 ~AutoEnterFilter() {
1099 mBuilder
->mFilterASR
= mOldValue
;
1100 mBuilder
->mInFilter
= mOldInFilter
;
1104 nsDisplayListBuilder
* mBuilder
;
1105 const ActiveScrolledRoot
* mOldValue
;
1110 * Used to update the current active scrolled root on the display list
1111 * builder, and to create new active scrolled roots.
1113 class AutoCurrentActiveScrolledRootSetter
{
1115 explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder
* aBuilder
)
1116 : mBuilder(aBuilder
),
1117 mSavedActiveScrolledRoot(aBuilder
->mCurrentActiveScrolledRoot
),
1118 mContentClipASR(aBuilder
->ClipState().GetContentClipASR()),
1119 mDescendantsStartIndex(aBuilder
->mActiveScrolledRoots
.Length()),
1121 mOldScrollParentId(aBuilder
->mCurrentScrollParentId
),
1122 mOldForceLayer(aBuilder
->mForceLayerForScrollParent
),
1123 mOldContainsNonMinimalDisplayPort(
1124 mBuilder
->mContainsNonMinimalDisplayPort
),
1125 mCanBeScrollParent(false) {}
1127 void SetCurrentScrollParentId(ViewID aScrollId
) {
1128 // Update the old scroll parent id.
1129 mOldScrollParentId
= mBuilder
->mCurrentScrollParentId
;
1130 // If this AutoCurrentActiveScrolledRootSetter has the same aScrollId as
1131 // the previous one on the stack, then that means the scrollframe that
1132 // created this isn't actually scrollable and cannot participate in
1133 // scroll handoff. We set mCanBeScrollParent to false to indicate this.
1134 mCanBeScrollParent
= (mOldScrollParentId
!= aScrollId
);
1135 mBuilder
->mCurrentScrollParentId
= aScrollId
;
1136 mBuilder
->mForceLayerForScrollParent
= false;
1137 mBuilder
->mContainsNonMinimalDisplayPort
= false;
1140 bool ShouldForceLayerForScrollParent() const {
1141 // Only scrollframes participating in scroll handoff can be forced to
1143 return mCanBeScrollParent
&& mBuilder
->mForceLayerForScrollParent
;
1146 bool GetContainsNonMinimalDisplayPort() const {
1147 // Only for scrollframes participating in scroll handoff can we return
1149 return mCanBeScrollParent
&& mBuilder
->mContainsNonMinimalDisplayPort
;
1152 ~AutoCurrentActiveScrolledRootSetter() {
1153 mBuilder
->mCurrentActiveScrolledRoot
= mSavedActiveScrolledRoot
;
1154 mBuilder
->mCurrentScrollParentId
= mOldScrollParentId
;
1155 if (mCanBeScrollParent
) {
1156 // If this flag is set, caller code is responsible for having dealt
1157 // with the current value of mBuilder->mForceLayerForScrollParent, so
1158 // we can just restore the old value.
1159 mBuilder
->mForceLayerForScrollParent
= mOldForceLayer
;
1161 // Otherwise we need to keep propagating the force-layerization flag
1162 // upwards to the next ancestor scrollframe that does participate in
1164 mBuilder
->mForceLayerForScrollParent
|= mOldForceLayer
;
1166 mBuilder
->mContainsNonMinimalDisplayPort
|=
1167 mOldContainsNonMinimalDisplayPort
;
1170 void SetCurrentActiveScrolledRoot(
1171 const ActiveScrolledRoot
* aActiveScrolledRoot
);
1173 void EnterScrollFrame(nsIScrollableFrame
* aScrollableFrame
) {
1175 ActiveScrolledRoot
* asr
= mBuilder
->AllocateActiveScrolledRoot(
1176 mBuilder
->mCurrentActiveScrolledRoot
, aScrollableFrame
);
1177 mBuilder
->mCurrentActiveScrolledRoot
= asr
;
1181 void InsertScrollFrame(nsIScrollableFrame
* aScrollableFrame
);
1184 nsDisplayListBuilder
* mBuilder
;
1186 * The builder's mCurrentActiveScrolledRoot at construction time which
1187 * needs to be restored at destruction time.
1189 const ActiveScrolledRoot
* mSavedActiveScrolledRoot
;
1191 * If there's a content clip on the builder at construction time, then
1192 * mContentClipASR is that content clip's ASR, otherwise null. The
1193 * assumption is that the content clip doesn't get relaxed while this
1194 * object is on the stack.
1196 const ActiveScrolledRoot
* mContentClipASR
;
1198 * InsertScrollFrame needs to mutate existing ASRs (those that were
1199 * created while this object was on the stack), and mDescendantsStartIndex
1200 * makes it easier to skip ASRs that were created in the past.
1202 size_t mDescendantsStartIndex
;
1204 * Flag to make sure that only one of SetCurrentActiveScrolledRoot /
1205 * EnterScrollFrame / InsertScrollFrame is called per instance of this
1209 ViewID mOldScrollParentId
;
1210 bool mOldForceLayer
;
1211 bool mOldContainsNonMinimalDisplayPort
;
1212 bool mCanBeScrollParent
;
1216 * Keeps track of the innermost ASR that can be used as the ASR for a
1217 * container item that wraps all items that were created while this
1218 * object was on the stack.
1219 * The rule is: all child items of the container item need to have
1220 * clipped bounds with respect to the container ASR.
1222 class AutoContainerASRTracker
{
1224 explicit AutoContainerASRTracker(nsDisplayListBuilder
* aBuilder
);
1226 const ActiveScrolledRoot
* GetContainerASR() {
1227 return mBuilder
->mCurrentContainerASR
;
1230 ~AutoContainerASRTracker() {
1231 mBuilder
->mCurrentContainerASR
= ActiveScrolledRoot::PickAncestor(
1232 mBuilder
->mCurrentContainerASR
, mSavedContainerASR
);
1236 nsDisplayListBuilder
* mBuilder
;
1237 const ActiveScrolledRoot
* mSavedContainerASR
;
1241 * A helper class to temporarily set the value of mCurrentScrollbarTarget
1242 * and mCurrentScrollbarFlags.
1244 class AutoCurrentScrollbarInfoSetter
{
1246 AutoCurrentScrollbarInfoSetter(
1247 nsDisplayListBuilder
* aBuilder
, ViewID aScrollTargetID
,
1248 const Maybe
<layers::ScrollDirection
>& aScrollbarDirection
,
1249 bool aWillHaveLayer
)
1250 : mBuilder(aBuilder
) {
1251 aBuilder
->mIsBuildingScrollbar
= true;
1252 aBuilder
->mCurrentScrollbarTarget
= aScrollTargetID
;
1253 aBuilder
->mCurrentScrollbarDirection
= aScrollbarDirection
;
1254 aBuilder
->mCurrentScrollbarWillHaveLayer
= aWillHaveLayer
;
1257 ~AutoCurrentScrollbarInfoSetter() {
1258 // No need to restore old values because scrollbars cannot be nested.
1259 mBuilder
->mIsBuildingScrollbar
= false;
1260 mBuilder
->mCurrentScrollbarTarget
=
1261 layers::ScrollableLayerGuid::NULL_SCROLL_ID
;
1262 mBuilder
->mCurrentScrollbarDirection
.reset();
1263 mBuilder
->mCurrentScrollbarWillHaveLayer
= false;
1267 nsDisplayListBuilder
* mBuilder
;
1271 * A helper class to temporarily set mBuildingExtraPagesForPageNum.
1273 class MOZ_RAII AutoPageNumberSetter
{
1275 AutoPageNumberSetter(nsDisplayListBuilder
* aBuilder
, const uint8_t aPageNum
)
1276 : mBuilder(aBuilder
),
1277 mOldPageNum(aBuilder
->GetBuildingExtraPagesForPageNum()) {
1278 mBuilder
->SetBuildingExtraPagesForPageNum(aPageNum
);
1280 ~AutoPageNumberSetter() {
1281 mBuilder
->SetBuildingExtraPagesForPageNum(mOldPageNum
);
1285 nsDisplayListBuilder
* mBuilder
;
1286 uint8_t mOldPageNum
;
1290 * A helper class to track current effective transform for items.
1292 * For frames that is Combines3DTransformWithAncestors(), we need to
1293 * apply all transforms of ancestors on the same preserves3D chain
1294 * on the bounds of current frame to the coordination of the 3D
1295 * context root. The 3D context root computes it's bounds from
1296 * these transformed bounds.
1298 class AutoAccumulateTransform
{
1300 explicit AutoAccumulateTransform(nsDisplayListBuilder
* aBuilder
)
1301 : mBuilder(aBuilder
),
1302 mSavedTransform(aBuilder
->mPreserves3DCtx
.mAccumulatedTransform
) {}
1304 ~AutoAccumulateTransform() {
1305 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
= mSavedTransform
;
1308 void Accumulate(const gfx::Matrix4x4
& aTransform
) {
1309 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
=
1310 aTransform
* mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
;
1313 const gfx::Matrix4x4
& GetCurrentTransform() {
1314 return mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
;
1318 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
= gfx::Matrix4x4();
1322 nsDisplayListBuilder
* mBuilder
;
1323 gfx::Matrix4x4 mSavedTransform
;
1327 * A helper class to collect bounds rects of descendants.
1329 * For a 3D context root, it's bounds is computed from the bounds of
1330 * descendants. If we transform bounds frame by frame applying
1331 * transforms, the bounds may turn to empty for any singular
1332 * transform on the path, but it is not empty for the accumulated
1335 class AutoAccumulateRect
{
1337 explicit AutoAccumulateRect(nsDisplayListBuilder
* aBuilder
)
1338 : mBuilder(aBuilder
),
1339 mSavedRect(aBuilder
->mPreserves3DCtx
.mAccumulatedRect
) {
1340 aBuilder
->mPreserves3DCtx
.mAccumulatedRect
= nsRect();
1341 aBuilder
->mPreserves3DCtx
.mAccumulatedRectLevels
++;
1344 ~AutoAccumulateRect() {
1345 mBuilder
->mPreserves3DCtx
.mAccumulatedRect
= mSavedRect
;
1346 mBuilder
->mPreserves3DCtx
.mAccumulatedRectLevels
--;
1350 nsDisplayListBuilder
* mBuilder
;
1354 void AccumulateRect(const nsRect
& aRect
) {
1355 mPreserves3DCtx
.mAccumulatedRect
.UnionRect(mPreserves3DCtx
.mAccumulatedRect
,
1359 const nsRect
& GetAccumulatedRect() {
1360 return mPreserves3DCtx
.mAccumulatedRect
;
1364 * The level is increased by one for items establishing 3D rendering
1365 * context and starting a new accumulation.
1367 int GetAccumulatedRectLevels() {
1368 return mPreserves3DCtx
.mAccumulatedRectLevels
;
1371 struct OutOfFlowDisplayData
{
1372 OutOfFlowDisplayData(
1373 const DisplayItemClipChain
* aContainingBlockClipChain
,
1374 const DisplayItemClipChain
* aCombinedClipChain
,
1375 const ActiveScrolledRoot
* aContainingBlockActiveScrolledRoot
,
1376 const ViewID
& aScrollParentId
, const nsRect
& aVisibleRect
,
1377 const nsRect
& aDirtyRect
)
1378 : mContainingBlockClipChain(aContainingBlockClipChain
),
1379 mCombinedClipChain(aCombinedClipChain
),
1380 mContainingBlockActiveScrolledRoot(
1381 aContainingBlockActiveScrolledRoot
),
1382 mVisibleRect(aVisibleRect
),
1383 mDirtyRect(aDirtyRect
),
1384 mScrollParentId(aScrollParentId
) {}
1385 const DisplayItemClipChain
* mContainingBlockClipChain
;
1386 const DisplayItemClipChain
*
1387 mCombinedClipChain
; // only necessary for the special case of top layer
1388 const ActiveScrolledRoot
* mContainingBlockActiveScrolledRoot
;
1390 // If this OutOfFlowDisplayData is associated with the ViewportFrame
1391 // of a document that has a resolution (creating separate visual and
1392 // layout viewports with their own coordinate spaces), these rects
1393 // are in layout coordinates. Similarly, GetVisibleRectForFrame() in
1394 // such a case returns a quantity in layout coordinates.
1395 nsRect mVisibleRect
;
1397 ViewID mScrollParentId
;
1399 static nsRect
ComputeVisibleRectForFrame(nsDisplayListBuilder
* aBuilder
,
1401 const nsRect
& aVisibleRect
,
1402 const nsRect
& aDirtyRect
,
1403 nsRect
* aOutDirtyRect
);
1405 nsRect
GetVisibleRectForFrame(nsDisplayListBuilder
* aBuilder
,
1406 nsIFrame
* aFrame
, nsRect
* aDirtyRect
) {
1407 return ComputeVisibleRectForFrame(aBuilder
, aFrame
, mVisibleRect
,
1408 mDirtyRect
, aDirtyRect
);
1412 NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty
,
1413 OutOfFlowDisplayData
)
1415 struct DisplayListBuildingData
{
1416 nsIFrame
* mModifiedAGR
= nullptr;
1419 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect
,
1420 DisplayListBuildingData
)
1422 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect
,
1425 static OutOfFlowDisplayData
* GetOutOfFlowData(nsIFrame
* aFrame
) {
1426 if (!aFrame
->GetParent()) {
1429 return aFrame
->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
1432 nsPresContext
* CurrentPresContext();
1434 OutOfFlowDisplayData
* GetCurrentFixedBackgroundDisplayData() {
1435 auto& displayData
= CurrentPresShellState()->mFixedBackgroundDisplayData
;
1436 return displayData
? displayData
.ptr() : nullptr;
1440 * Accumulates opaque stuff into the window opaque region.
1442 void AddWindowOpaqueRegion(nsIFrame
* aFrame
, const nsRect
& aBounds
) {
1443 if (IsRetainingDisplayList()) {
1444 mRetainedWindowOpaqueRegion
.Add(aFrame
, aBounds
);
1447 mWindowOpaqueRegion
.Or(mWindowOpaqueRegion
, aBounds
);
1450 * Returns the window opaque region built so far. This may be incomplete
1451 * since the opaque region is built during layer construction.
1453 const nsRegion
GetWindowOpaqueRegion() {
1454 return IsRetainingDisplayList() ? mRetainedWindowOpaqueRegion
.ToRegion()
1455 : mWindowOpaqueRegion
;
1459 * mContainsBlendMode is true if we processed a display item that
1460 * has a blend mode attached. We do this so we can insert a
1461 * nsDisplayBlendContainer in the parent stacking context.
1463 void SetContainsBlendMode(bool aContainsBlendMode
) {
1464 mContainsBlendMode
= aContainsBlendMode
;
1466 bool ContainsBlendMode() const { return mContainsBlendMode
; }
1468 DisplayListClipState
& ClipState() { return mClipState
; }
1469 const ActiveScrolledRoot
* CurrentActiveScrolledRoot() {
1470 return mCurrentActiveScrolledRoot
;
1472 const ActiveScrolledRoot
* CurrentAncestorASRStackingContextContents() {
1473 return mCurrentContainerASR
;
1477 * Add the current frame to the will-change budget if possible and
1478 * remeber the outcome. Subsequent calls to IsInWillChangeBudget
1479 * will return the same value as return here.
1481 bool AddToWillChangeBudget(nsIFrame
* aFrame
, const nsSize
& aSize
);
1484 * This will add the current frame to the will-change budget the first
1485 * time it is seen. On subsequent calls this will return the same
1486 * answer. This effectively implements a first-come, first-served
1487 * allocation of the will-change budget.
1489 bool IsInWillChangeBudget(nsIFrame
* aFrame
, const nsSize
& aSize
);
1492 * Clears the will-change budget status for the given |aFrame|.
1493 * This will also remove the frame from will-change budgets.
1495 void ClearWillChangeBudgetStatus(nsIFrame
* aFrame
);
1498 * Removes the given |aFrame| from will-change budgets.
1500 void RemoveFromWillChangeBudgets(const nsIFrame
* aFrame
);
1503 * Clears the will-change budgets.
1505 void ClearWillChangeBudgets();
1507 void EnterSVGEffectsContents(nsIFrame
* aEffectsFrame
,
1508 nsDisplayList
* aHoistedItemsStorage
);
1509 void ExitSVGEffectsContents();
1511 bool ShouldBuildScrollInfoItemsForHoisting() const;
1513 void AppendNewScrollInfoItemForHoisting(
1514 nsDisplayScrollInfoLayer
* aScrollInfoItem
);
1517 * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
1519 * mPreserves3DCtx is used by class AutoAccumulateTransform &
1520 * AutoAccumulateRect to passing data between frames in the 3D
1521 * context. If a frame create a new 3D context, it should restore
1522 * the value of mPreserves3DCtx before returning back to the parent.
1523 * This class do it for the users.
1525 class AutoPreserves3DContext
{
1527 explicit AutoPreserves3DContext(nsDisplayListBuilder
* aBuilder
)
1528 : mBuilder(aBuilder
), mSavedCtx(aBuilder
->mPreserves3DCtx
) {}
1530 ~AutoPreserves3DContext() { mBuilder
->mPreserves3DCtx
= mSavedCtx
; }
1533 nsDisplayListBuilder
* mBuilder
;
1534 Preserves3DContext mSavedCtx
;
1537 const nsRect
GetPreserves3DRect() const {
1538 return mPreserves3DCtx
.mVisibleRect
;
1541 void SavePreserves3DRect() { mPreserves3DCtx
.mVisibleRect
= mVisibleRect
; }
1543 void SavePreserves3DAllowAsyncAnimation(bool aValue
) {
1544 mPreserves3DCtx
.mAllowAsyncAnimation
= aValue
;
1547 bool GetPreserves3DAllowAsyncAnimation() const {
1548 return mPreserves3DCtx
.mAllowAsyncAnimation
;
1551 bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems
; }
1553 void SetBuildingInvisibleItems(bool aBuildingInvisibleItems
) {
1554 mBuildingInvisibleItems
= aBuildingInvisibleItems
;
1557 void SetBuildingExtraPagesForPageNum(uint8_t aPageNum
) {
1558 mBuildingExtraPagesForPageNum
= aPageNum
;
1560 uint8_t GetBuildingExtraPagesForPageNum() const {
1561 return mBuildingExtraPagesForPageNum
;
1564 bool HitTestIsForVisibility() const { return mVisibleThreshold
.isSome(); }
1566 float VisibilityThreshold() const {
1567 MOZ_DIAGNOSTIC_ASSERT(HitTestIsForVisibility());
1568 return mVisibleThreshold
.valueOr(1.0f
);
1571 void SetHitTestIsForVisibility(float aVisibleThreshold
) {
1572 mVisibleThreshold
= Some(aVisibleThreshold
);
1575 bool ShouldBuildAsyncZoomContainer() const {
1576 return mBuildAsyncZoomContainer
;
1578 void UpdateShouldBuildAsyncZoomContainer();
1580 void UpdateShouldBuildBackdropRootContainer();
1582 bool ShouldRebuildDisplayListDueToPrefChange();
1585 * Represents a region composed of frame/rect pairs.
1586 * WeakFrames are used to track whether a rect still belongs to the region.
1587 * Modified frames and rects are removed and re-added to the region if needed.
1589 struct WeakFrameRegion
{
1591 * A wrapper to store WeakFrame and the pointer to the underlying frame.
1592 * This is needed because WeakFrame does not store the frame pointer after
1593 * the frame has been deleted.
1595 struct WeakFrameWrapper
{
1596 explicit WeakFrameWrapper(nsIFrame
* aFrame
)
1597 : mWeakFrame(new WeakFrame(aFrame
)), mFrame(aFrame
) {}
1599 UniquePtr
<WeakFrame
> mWeakFrame
;
1603 nsTHashSet
<void*> mFrameSet
;
1604 nsTArray
<WeakFrameWrapper
> mFrames
;
1605 nsTArray
<pixman_box32_t
> mRects
;
1607 template <typename RectType
>
1608 void Add(nsIFrame
* aFrame
, const RectType
& aRect
) {
1609 if (mFrameSet
.Contains(aFrame
)) {
1613 mFrameSet
.Insert(aFrame
);
1614 mFrames
.AppendElement(WeakFrameWrapper(aFrame
));
1615 mRects
.AppendElement(nsRegion::RectToBox(aRect
));
1624 void RemoveModifiedFramesAndRects();
1626 size_t SizeOfExcludingThis(MallocSizeOf
) const;
1628 typedef gfx::ArrayView
<pixman_box32_t
> BoxArrayView
;
1630 nsRegion
ToRegion() const { return nsRegion(BoxArrayView(mRects
)); }
1632 LayoutDeviceIntRegion
ToLayoutDeviceIntRegion() const {
1633 return LayoutDeviceIntRegion(BoxArrayView(mRects
));
1637 void AddScrollFrameToNotify(nsIScrollableFrame
* aScrollFrame
);
1638 void NotifyAndClearScrollFrames();
1640 // Helper class to find what link spec (if any) to associate with a frame,
1641 // recording it in the builder, and generate the corresponding DisplayItem.
1642 // This also takes care of generating a named destination for internal links
1643 // if the element has an id or name attribute.
1646 Linkifier(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
1647 nsDisplayList
* aList
);
1650 if (mBuilderToReset
) {
1651 mBuilderToReset
->mLinkSpec
.Truncate(0);
1655 void MaybeAppendLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
1658 nsDisplayListBuilder
* mBuilderToReset
= nullptr;
1659 nsDisplayList
* mList
;
1663 * Returns the nearest ancestor frame to aFrame that is considered to have
1664 * (or will have) animated geometry. This can return aFrame.
1666 nsIFrame
* FindAnimatedGeometryRootFrameFor(nsIFrame
* aFrame
);
1669 * Returns true if this is a retained builder and reuse stacking contexts
1670 * mode is enabled by pref.
1672 bool IsReusingStackingContextItems() const {
1673 return mIsReusingStackingContextItems
;
1677 * Adds display item |aItem| to the reuseable display items set.
1679 void AddReusableDisplayItem(nsDisplayItem
* aItem
);
1682 * Removes display item |aItem| from the reuseable display items set.
1683 * This is needed because display items are sometimes deleted during
1684 * display list building.
1685 * Called by |nsDisplayItem::Destroy()| when the item has been reused.
1687 void RemoveReusedDisplayItem(nsDisplayItem
* aItem
);
1690 * Clears the reuseable display items set.
1692 void ClearReuseableDisplayItems();
1695 * Marks the given display item |aItem| as reused, and updates the necessary
1696 * display list builder state.
1698 void ReuseDisplayItem(nsDisplayItem
* aItem
);
1701 bool MarkOutOfFlowFrameForDisplay(nsIFrame
* aDirtyFrame
, nsIFrame
* aFrame
,
1702 const nsRect
& aVisibleRect
,
1703 const nsRect
& aDirtyRect
);
1705 friend class nsDisplayBackgroundImage
;
1706 friend class RetainedDisplayListBuilder
;
1709 * Returns whether a frame acts as an animated geometry root, optionally
1710 * returning the next ancestor to check.
1712 bool IsAnimatedGeometryRoot(nsIFrame
* aFrame
, nsIFrame
** aParent
= nullptr);
1714 struct PresShellState
{
1715 PresShell
* mPresShell
;
1717 Maybe
<nsAutoLayoutPhase
> mAutoLayoutPhase
;
1719 Maybe
<OutOfFlowDisplayData
> mFixedBackgroundDisplayData
;
1720 uint32_t mFirstFrameMarkedForDisplay
;
1721 uint32_t mFirstFrameWithOOFData
;
1722 bool mIsBackgroundOnly
;
1723 // This is a per-document flag turning off event handling for all content
1724 // in the document, and is set when we enter a subdocument for a pointer-
1725 // events:none frame.
1726 bool mInsidePointerEventsNoneDoc
;
1727 bool mTouchEventPrefEnabledDoc
;
1728 nsIFrame
* mPresShellIgnoreScrollFrame
;
1731 PresShellState
* CurrentPresShellState() {
1732 NS_ASSERTION(mPresShellStates
.Length() > 0,
1733 "Someone forgot to enter a presshell");
1734 return &mPresShellStates
[mPresShellStates
.Length() - 1];
1737 void AddSizeOfExcludingThis(nsWindowSizes
&) const;
1739 struct FrameWillChangeBudget
{
1740 FrameWillChangeBudget() : mPresContext(nullptr), mUsage(0) {}
1742 FrameWillChangeBudget(const nsPresContext
* aPresContext
, uint32_t aUsage
)
1743 : mPresContext(aPresContext
), mUsage(aUsage
) {}
1745 const nsPresContext
* mPresContext
;
1749 // will-change budget tracker
1750 typedef uint32_t DocumentWillChangeBudget
;
1752 nsIFrame
* const mReferenceFrame
;
1753 nsIFrame
* mIgnoreScrollFrame
;
1755 const ActiveScrolledRoot
* mCurrentActiveScrolledRoot
;
1756 const ActiveScrolledRoot
* mCurrentContainerASR
;
1757 // mCurrentFrame is the frame that we're currently calling (or about to call)
1758 // BuildDisplayList on.
1759 const nsIFrame
* mCurrentFrame
;
1760 // The reference frame for mCurrentFrame.
1761 const nsIFrame
* mCurrentReferenceFrame
;
1763 nsIFrame
* mCaretFrame
;
1764 // A temporary list that we append scroll info items to while building
1765 // display items for the contents of frames with SVG effects.
1766 // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
1767 // This is a pointer and not a real nsDisplayList value because the
1768 // nsDisplayList class is defined below this class, so we can't use it here.
1769 nsDisplayList
* mScrollInfoItemsForHoisting
;
1770 nsTArray
<RefPtr
<ActiveScrolledRoot
>> mActiveScrolledRoots
;
1771 DisplayItemClipChain
* mFirstClipChainToDestroy
;
1772 nsTArray
<nsDisplayItem
*> mTemporaryItems
;
1773 nsDisplayTableBackgroundSet
* mTableBackgroundSet
;
1774 ViewID mCurrentScrollParentId
;
1775 ViewID mCurrentScrollbarTarget
;
1777 nsTArray
<nsIFrame
*> mSVGEffectsFrames
;
1778 // When we are inside a filter, the current ASR at the time we entered the
1779 // filter. Otherwise nullptr.
1780 const ActiveScrolledRoot
* mFilterASR
;
1781 nsCString mLinkSpec
; // Destination of link currently being emitted, if any.
1783 // Optimized versions for non-retained display list.
1784 LayoutDeviceIntRegion mWindowDraggingRegion
;
1785 LayoutDeviceIntRegion mWindowNoDraggingRegion
;
1786 nsRegion mWindowOpaqueRegion
;
1788 nsClassHashtable
<nsPtrHashKey
<nsDisplayItem
>,
1789 nsTArray
<nsIWidget::ThemeGeometry
>>
1791 DisplayListClipState mClipState
;
1792 nsTHashMap
<nsPtrHashKey
<const nsPresContext
>, DocumentWillChangeBudget
>
1793 mDocumentWillChangeBudgets
;
1795 // Any frame listed in this set is already counted in the budget
1796 // and thus is in-budget.
1797 nsTHashMap
<nsPtrHashKey
<const nsIFrame
>, FrameWillChangeBudget
>
1798 mFrameWillChangeBudgets
;
1800 nsTHashMap
<nsPtrHashKey
<dom::RemoteBrowser
>, dom::EffectsInfo
>
1803 nsTHashSet
<nsCString
> mDestinations
; // Destination names emitted.
1805 // Stores reusable items collected during display list preprocessing.
1806 nsTHashSet
<nsDisplayItem
*> mReuseableItems
;
1808 // Tracked regions used for retained display list.
1809 WeakFrameRegion mRetainedWindowDraggingRegion
;
1810 WeakFrameRegion mRetainedWindowNoDraggingRegion
;
1812 // Window opaque region is calculated during layer building.
1813 WeakFrameRegion mRetainedWindowOpaqueRegion
;
1815 std::unordered_set
<const DisplayItemClipChain
*, DisplayItemClipChainHasher
,
1816 DisplayItemClipChainEqualer
>
1818 std::unordered_set
<nsIScrollableFrame
*> mScrollFramesToNotify
;
1820 AutoTArray
<nsIFrame
*, 20> mFramesWithOOFData
;
1821 AutoTArray
<nsIFrame
*, 40> mFramesMarkedForDisplayIfVisible
;
1822 AutoTArray
<PresShellState
, 8> mPresShellStates
;
1824 using Arena
= nsPresArena
<32768, DisplayListArenaObjectId
,
1825 size_t(DisplayListArenaObjectId::COUNT
)>;
1828 AutoTArray
<nsIFrame
*, 400> mFramesMarkedForDisplay
;
1830 gfx::CompositorHitTestInfo mCompositorHitTestInfo
;
1832 // The offset from mCurrentFrame to mCurrentReferenceFrame.
1833 nsPoint mCurrentOffsetToReferenceFrame
;
1835 Maybe
<float> mVisibleThreshold
;
1837 Maybe
<nsPoint
> mAdditionalOffset
;
1839 // Relative to mCurrentFrame.
1840 nsRect mVisibleRect
;
1844 Preserves3DContext mPreserves3DCtx
;
1846 uint8_t mBuildingExtraPagesForPageNum
;
1848 nsDisplayListBuilderMode mMode
;
1849 static uint32_t sPaintSequenceNumber
;
1851 bool mContainsBlendMode
;
1852 bool mIsBuildingScrollbar
;
1853 bool mCurrentScrollbarWillHaveLayer
;
1855 bool mRetainingDisplayList
;
1856 bool mPartialUpdate
;
1857 bool mIgnoreSuppression
;
1858 bool mIncludeAllOutOfFlows
;
1859 bool mDescendIntoSubdocuments
;
1860 bool mSelectedFramesOnly
;
1861 bool mAllowMergingAndFlattening
;
1862 // True when we're building a display list that's directly or indirectly
1863 // under an nsDisplayTransform
1867 bool mInPageSequence
;
1868 bool mIsInChromePresContext
;
1869 bool mSyncDecodeImages
;
1870 bool mIsPaintingToWindow
;
1871 bool mUseHighQualityScaling
;
1872 bool mIsPaintingForWebRender
;
1873 bool mIsCompositingCheap
;
1874 bool mAncestorHasApzAwareEventHandler
;
1875 // True when the first async-scrollable scroll frame for which we build a
1876 // display list has a display port. An async-scrollable scroll frame is one
1877 // which WantsAsyncScroll().
1878 bool mHaveScrollableDisplayPort
;
1879 bool mWindowDraggingAllowed
;
1880 bool mIsBuildingForPopup
;
1881 bool mForceLayerForScrollParent
;
1882 bool mContainsNonMinimalDisplayPort
;
1883 bool mAsyncPanZoomEnabled
;
1884 bool mBuildingInvisibleItems
;
1886 bool mInInvalidSubtree
;
1887 bool mBuildCompositorHitTestInfo
;
1888 bool mDisablePartialUpdates
;
1889 bool mPartialBuildFailed
;
1890 bool mIsInActiveDocShell
;
1891 bool mBuildAsyncZoomContainer
;
1892 bool mIsRelativeToLayoutViewport
;
1893 bool mUseOverlayScrollbars
;
1894 bool mAlwaysLayerizeScrollbars
;
1896 bool mIsReusingStackingContextItems
;
1898 Maybe
<layers::ScrollDirection
> mCurrentScrollbarDirection
;
1901 // All types are defined in nsDisplayItemTypes.h
1902 #define NS_DISPLAY_DECL_NAME(n, e) \
1903 const char* Name() const override { return n; } \
1904 constexpr static DisplayItemType ItemType() { return DisplayItemType::e; } \
1907 void* operator new(size_t aSize, nsDisplayListBuilder* aBuilder) { \
1908 return aBuilder->Allocate(aSize, DisplayItemType::e); \
1911 template <typename T, typename F, typename... Args> \
1912 friend T* mozilla::MakeDisplayItemWithIndex( \
1913 nsDisplayListBuilder* aBuilder, F* aFrame, const uint16_t aIndex, \
1918 #define NS_DISPLAY_ALLOW_CLONING() \
1919 template <typename T> \
1920 friend T* mozilla::MakeClone(nsDisplayListBuilder* aBuilder, \
1923 nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override { \
1924 return MakeClone(aBuilder, this); \
1927 template <typename T
>
1928 MOZ_ALWAYS_INLINE T
* MakeClone(nsDisplayListBuilder
* aBuilder
, const T
* aItem
) {
1929 static_assert(std::is_base_of
<nsDisplayWrapList
, T
>::value
,
1930 "Display item type should be derived from nsDisplayWrapList");
1931 T
* item
= new (aBuilder
) T(aBuilder
, *aItem
);
1932 item
->SetType(T::ItemType());
1936 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1937 void AssertUniqueItem(nsDisplayItem
* aItem
);
1941 * Returns true, if a display item of given |aType| needs to be built within
1942 * opacity:0 container.
1944 bool ShouldBuildItemForEvents(const DisplayItemType aType
);
1947 * Initializes the hit test information of |aItem| if the item type supports it.
1949 void InitializeHitTestInfo(nsDisplayListBuilder
* aBuilder
,
1950 nsPaintedDisplayItem
* aItem
,
1951 const DisplayItemType aType
);
1953 template <typename T
, typename F
, typename
... Args
>
1954 MOZ_ALWAYS_INLINE T
* MakeDisplayItemWithIndex(nsDisplayListBuilder
* aBuilder
,
1955 F
* aFrame
, const uint16_t aIndex
,
1957 static_assert(std::is_base_of
<nsDisplayItem
, T
>::value
,
1958 "Display item type should be derived from nsDisplayItem");
1959 static_assert(std::is_base_of
<nsIFrame
, F
>::value
,
1960 "Frame type should be derived from nsIFrame");
1962 const DisplayItemType type
= T::ItemType();
1963 if (aBuilder
->InEventsOnly() && !ShouldBuildItemForEvents(type
)) {
1964 // This item is not needed for events.
1968 T
* item
= new (aBuilder
) T(aBuilder
, aFrame
, std::forward
<Args
>(aArgs
)...);
1970 if (type
!= DisplayItemType::TYPE_GENERIC
) {
1971 item
->SetType(type
);
1974 item
->SetPerFrameIndex(aIndex
);
1975 item
->SetExtraPageForPageNum(aBuilder
->GetBuildingExtraPagesForPageNum());
1977 nsPaintedDisplayItem
* paintedItem
= item
->AsPaintedDisplayItem();
1979 InitializeHitTestInfo(aBuilder
, paintedItem
, type
);
1982 if (aBuilder
->InInvalidSubtree() ||
1983 item
->FrameForInvalidation()->IsFrameModified()) {
1984 item
->SetModifiedFrame(true);
1987 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1988 if (aBuilder
->IsRetainingDisplayList() && aBuilder
->IsBuilding()) {
1989 AssertUniqueItem(item
);
1992 // Verify that InInvalidSubtree matches invalidation frame's modified state.
1993 if (aBuilder
->InInvalidSubtree()) {
1994 MOZ_DIAGNOSTIC_ASSERT(
1995 AnyContentAncestorModified(item
->FrameForInvalidation()));
1998 DebugOnly
<bool> isContainerType
=
1999 (GetDisplayItemFlagsForType(type
) & TYPE_IS_CONTAINER
);
2001 MOZ_ASSERT(item
->HasChildren() == isContainerType
,
2002 "Container items must have container display item flag set.");
2005 DL_LOGV("Created display item %p (%s) (frame: %p)", item
, item
->Name(),
2011 template <typename T
, typename F
, typename
... Args
>
2012 MOZ_ALWAYS_INLINE T
* MakeDisplayItem(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
2014 return MakeDisplayItemWithIndex
<T
>(aBuilder
, aFrame
, 0,
2015 std::forward
<Args
>(aArgs
)...);
2019 * nsDisplayItemBase is a base-class for all display items. It is mainly
2020 * responsible for handling the frame-display item 1:n relationship, as well as
2021 * storing the state needed for display list merging.
2023 * Display items are arena-allocated during display list construction.
2025 * Display items can be containers --- i.e., they can perform hit testing
2026 * and painting by recursively traversing a list of child items.
2028 * Display items belong to a list at all times (except temporarily as they
2029 * move from one list to another).
2031 class nsDisplayItem
{
2033 using LayerManager
= layers::LayerManager
;
2034 using WebRenderLayerManager
= layers::WebRenderLayerManager
;
2035 using StackingContextHelper
= layers::StackingContextHelper
;
2036 using ViewID
= layers::ScrollableLayerGuid::ViewID
;
2039 * Downcasts this item to nsPaintedDisplayItem, if possible.
2041 virtual nsPaintedDisplayItem
* AsPaintedDisplayItem() { return nullptr; }
2042 virtual const nsPaintedDisplayItem
* AsPaintedDisplayItem() const {
2047 * Downcasts this item to nsDisplayWrapList, if possible.
2049 virtual nsDisplayWrapList
* AsDisplayWrapList() { return nullptr; }
2050 virtual const nsDisplayWrapList
* AsDisplayWrapList() const { return nullptr; }
2053 * Create a clone of this item.
2055 virtual nsDisplayWrapList
* Clone(nsDisplayListBuilder
* aBuilder
) const {
2060 * Checks if the given display item can be merged with this item.
2061 * @return true if the merging is possible, otherwise false.
2063 virtual bool CanMerge(const nsDisplayItem
* aItem
) const { return false; }
2066 * Frees the memory allocated for this display item.
2067 * The given display list builder must have allocated this display item.
2069 virtual void Destroy(nsDisplayListBuilder
* aBuilder
) {
2070 const DisplayItemType type
= GetType();
2071 DL_LOGV("Destroying display item %p (%s)", this, Name());
2073 if (IsReusedItem()) {
2074 aBuilder
->RemoveReusedDisplayItem(this);
2077 this->~nsDisplayItem();
2078 aBuilder
->Destroy(type
, this);
2082 * Returns the frame that this display item was created for.
2083 * Never returns null.
2085 inline nsIFrame
* Frame() const {
2086 MOZ_ASSERT(mFrame
, "Trying to use display item after frame deletion!");
2091 * Called when the display item is prepared for deletion. The display item
2092 * should not be used after calling this function.
2094 virtual void RemoveFrame(nsIFrame
* aFrame
) {
2097 if (mFrame
&& aFrame
== mFrame
) {
2104 * A display item can depend on multiple different frames for invalidation.
2106 virtual nsIFrame
* GetDependentFrame() { return nullptr; }
2109 * Returns the frame that provides the style data, and should
2110 * be checked when deciding if this display item can be reused.
2112 virtual nsIFrame
* FrameForInvalidation() const { return Frame(); }
2115 * Display items can override this to communicate that they won't
2116 * contribute any visual information (for example fully transparent).
2118 virtual bool IsInvisible() const { return false; }
2121 * Returns the printable name of this display item.
2123 virtual const char* Name() const = 0;
2126 * Some consecutive items should be rendered together as a unit, e.g.,
2127 * outlines for the same element. For this, we need a way for items to
2128 * identify their type. We use the type for other purposes too.
2130 DisplayItemType
GetType() const {
2131 MOZ_ASSERT(mType
!= DisplayItemType::TYPE_ZERO
,
2132 "Display item should have a valid type!");
2137 * Pairing this with the Frame() pointer gives a key that
2138 * uniquely identifies this display item in the display item tree.
2140 uint32_t GetPerFrameKey() const {
2141 // The top 8 bits are the page index
2142 // The middle 16 bits of the per frame key uniquely identify the display
2143 // item when there are more than one item of the same type for a frame.
2144 // The low 8 bits are the display item type.
2145 return (static_cast<uint32_t>(mExtraPageForPageNum
)
2146 << (TYPE_BITS
+ (sizeof(mPerFrameIndex
) * 8))) |
2147 (static_cast<uint32_t>(mPerFrameIndex
) << TYPE_BITS
) |
2148 static_cast<uint32_t>(mType
);
2152 * Returns true if this item was reused during display list merging.
2154 bool IsReused() const { return mItemFlags
.contains(ItemFlag::ReusedItem
); }
2156 void SetReused(bool aReused
) { SetItemFlag(ItemFlag::ReusedItem
, aReused
); }
2159 * Returns true if this item can be reused during display list merging.
2161 bool CanBeReused() const {
2162 return !mItemFlags
.contains(ItemFlag::CantBeReused
);
2165 void SetCantBeReused() { mItemFlags
+= ItemFlag::CantBeReused
; }
2167 bool CanBeCached() const {
2168 return !mItemFlags
.contains(ItemFlag::CantBeCached
);
2171 void SetCantBeCached() { mItemFlags
+= ItemFlag::CantBeCached
; }
2173 bool IsOldItem() const { return !!mOldList
; }
2176 * Returns true if the frame of this display item is in a modified subtree.
2178 bool HasModifiedFrame() const {
2179 return mItemFlags
.contains(ItemFlag::ModifiedFrame
);
2182 void SetModifiedFrame(bool aModified
) {
2183 SetItemFlag(ItemFlag::ModifiedFrame
, aModified
);
2186 bool HasDeletedFrame() const;
2189 * Set the nsDisplayList that this item belongs to, and what index it is
2191 * Temporary state for merging used by RetainedDisplayListBuilder.
2193 void SetOldListIndex(nsDisplayList
* aList
, OldListIndex aIndex
,
2194 uint32_t aListKey
, uint32_t aNestingDepth
) {
2195 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2196 mOldListKey
= aListKey
;
2197 mOldNestingDepth
= aNestingDepth
;
2199 mOldList
= reinterpret_cast<uintptr_t>(aList
);
2200 mOldListIndex
= aIndex
;
2203 bool GetOldListIndex(nsDisplayList
* aList
, uint32_t aListKey
,
2204 OldListIndex
* aOutIndex
) {
2205 if (mOldList
!= reinterpret_cast<uintptr_t>(aList
)) {
2206 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2207 MOZ_CRASH_UNSAFE_PRINTF(
2208 "Item found was in the wrong list! type %d "
2209 "(outer type was %d at depth %d, now is %d)",
2210 GetPerFrameKey(), mOldListKey
, mOldNestingDepth
, aListKey
);
2214 *aOutIndex
= mOldListIndex
;
2219 * Returns the display list containing the children of this display item.
2220 * The children may be in a different coordinate system than this item.
2222 virtual RetainedDisplayList
* GetChildren() const { return nullptr; }
2223 bool HasChildren() const { return GetChildren(); }
2226 * Display items with children may return true here. This causes the
2227 * display list iterator to descend into the child display list.
2229 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) {
2233 virtual bool CreatesStackingContextHelper() { return false; }
2236 * Returns true if this item can be moved asynchronously on the compositor,
2237 * see RetainedDisplayListBuilder.cpp comments.
2239 virtual bool CanMoveAsync() { return false; }
2242 // This is never instantiated directly (it has pure virtual methods), so no
2243 // need to count constructors and destructors.
2244 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
2245 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
2246 const ActiveScrolledRoot
* aActiveScrolledRoot
);
2249 * The custom copy-constructor is implemented to prevent copying the saved
2250 * state of the item.
2251 * This is currently only used when creating temporary items for merging.
2253 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, const nsDisplayItem
& aOther
)
2254 : mFrame(aOther
.mFrame
),
2255 mItemFlags(aOther
.mItemFlags
),
2256 mType(aOther
.mType
),
2257 mExtraPageForPageNum(aOther
.mExtraPageForPageNum
),
2258 mPerFrameIndex(aOther
.mPerFrameIndex
),
2259 mBuildingRect(aOther
.mBuildingRect
),
2260 mToReferenceFrame(aOther
.mToReferenceFrame
),
2261 mActiveScrolledRoot(aOther
.mActiveScrolledRoot
),
2262 mClipChain(aOther
.mClipChain
) {
2263 MOZ_COUNT_CTOR(nsDisplayItem
);
2264 // TODO: It might be better to remove the flags that aren't copied.
2265 if (aOther
.ForceNotVisible()) {
2266 mItemFlags
+= ItemFlag::ForceNotVisible
;
2268 if (mFrame
->In3DContextAndBackfaceIsHidden()) {
2269 mItemFlags
+= ItemFlag::BackfaceHidden
;
2271 if (aOther
.Combines3DTransformWithAncestors()) {
2272 mItemFlags
+= ItemFlag::Combines3DTransformWithAncestors
;
2276 virtual ~nsDisplayItem() {
2277 MOZ_COUNT_DTOR(nsDisplayItem
);
2279 mFrame
->RemoveDisplayItem(this);
2283 void SetType(const DisplayItemType aType
) { mType
= aType
; }
2285 void SetPerFrameIndex(const uint16_t aIndex
) { mPerFrameIndex
= aIndex
; }
2287 // Display list building for printing can build duplicate
2288 // container display items when they contain a mixture of
2289 // OOF and normal content that is spread across multiple
2290 // pages. We include the page number for the duplicates
2291 // to make our GetPerFrameKey unique.
2292 void SetExtraPageForPageNum(const uint8_t aPageNum
) {
2293 mExtraPageForPageNum
= aPageNum
;
2296 void SetDeletedFrame();
2299 nsDisplayItem() = delete;
2300 nsDisplayItem(const nsDisplayItem
&) = delete;
2303 * Invalidate cached information that depends on this node's contents, after
2304 * a mutation of those contents.
2306 * Specifically, if you mutate an |nsDisplayItem| in a way that would change
2307 * the WebRender display list items generated for it, you should call this
2310 * If a |RestoreState| method exists to restore some piece of state, that's a
2311 * good indication that modifications to said state should be accompanied by a
2312 * call to this method. Opacity flattening's effects on
2313 * |nsDisplayBackgroundColor| items are one example.
2315 virtual void InvalidateItemCacheEntry() {}
2317 struct HitTestState
{
2318 explicit HitTestState() = default;
2321 NS_ASSERTION(mItemBuffer
.Length() == 0,
2322 "mItemBuffer should have been cleared");
2325 // Handling transform items for preserve 3D frames.
2326 bool mInPreserves3D
= false;
2327 // When hit-testing for visibility, we may hit an fully opaque item in a
2328 // nested display list. We want to stop at that point, without looking
2329 // further on other items.
2330 bool mHitOccludingItem
= false;
2332 float mCurrentOpacity
= 1.0f
;
2334 AutoTArray
<nsDisplayItem
*, 100> mItemBuffer
;
2337 uint8_t GetFlags() const { return GetDisplayItemFlagsForType(GetType()); }
2339 virtual bool IsContentful() const { return GetFlags() & TYPE_IS_CONTENTFUL
; }
2342 * This is called after we've constructed a display list for event handling.
2343 * When this is called, we've already ensured that aRect intersects the
2344 * item's bounds and that clipping has been taking into account.
2346 * @param aRect the point or rect being tested, relative to the reference
2347 * frame. If the width and height are both 1 app unit, it indicates we're
2348 * hit testing a point, not a rect.
2349 * @param aState must point to a HitTestState. If you don't have one,
2350 * just create one with the default constructor and pass it in.
2351 * @param aOutFrames each item appends the frame(s) in this display item that
2352 * the rect is considered over (if any) to aOutFrames.
2354 virtual void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
2355 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) {}
2357 virtual nsIFrame
* StyleFrame() const { return mFrame
; }
2360 * Compute the used z-index of our frame; returns zero for elements to which
2361 * z-index does not apply, and for z-index:auto.
2362 * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
2364 virtual int32_t ZIndex() const;
2366 * The default bounds is the frame border rect.
2367 * @param aSnap *aSnap is set to true if the returned rect will be
2368 * snapped to nearest device pixel edges during actual drawing.
2369 * It might be set to false and snap anyway, so code computing the set of
2370 * pixels affected by this display item needs to round outwards to pixel
2371 * boundaries when *aSnap is set to false.
2372 * This does not take the item's clipping into account.
2373 * @return a rectangle relative to aBuilder->ReferenceFrame() that
2374 * contains the area drawn by this display item
2376 virtual nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const {
2378 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2382 * Returns the untransformed bounds of this display item.
2384 virtual nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
2385 bool* aSnap
) const {
2386 return GetBounds(aBuilder
, aSnap
);
2389 virtual nsRegion
GetTightBounds(nsDisplayListBuilder
* aBuilder
,
2390 bool* aSnap
) const {
2396 * Returns true if nothing will be rendered inside aRect, false if uncertain.
2397 * aRect is assumed to be contained in this item's bounds.
2399 virtual bool IsInvisibleInRect(const nsRect
& aRect
) const { return false; }
2402 * Returns the result of GetBounds intersected with the item's clip.
2403 * The intersection is approximate since rounded corners are not taking into
2406 nsRect
GetClippedBounds(nsDisplayListBuilder
* aBuilder
) const;
2408 nsRect
GetBorderRect() const {
2409 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2412 nsRect
GetPaddingRect() const {
2413 return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
2416 nsRect
GetContentRect() const {
2417 return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
2421 * Checks if the frame(s) owning this display item have been marked as
2422 * invalid, and needing repainting.
2424 virtual bool IsInvalid(nsRect
& aRect
) const {
2425 bool result
= mFrame
? mFrame
->IsInvalid(aRect
) : false;
2426 aRect
+= ToReferenceFrame();
2431 * Creates and initializes an nsDisplayItemGeometry object that retains the
2432 * current areas covered by this display item. These need to retain enough
2433 * information such that they can be compared against a future nsDisplayItem
2434 * of the same type, and determine if repainting needs to happen.
2436 * Subclasses wishing to store more information need to override both this
2437 * and ComputeInvalidationRegion, as well as implementing an
2438 * nsDisplayItemGeometry subclass.
2440 * The default implementation tracks both the display item bounds, and the
2441 * frame's border rect.
2443 virtual nsDisplayItemGeometry
* AllocateGeometry(
2444 nsDisplayListBuilder
* aBuilder
) {
2445 return new nsDisplayItemGenericGeometry(this, aBuilder
);
2449 * Compares an nsDisplayItemGeometry object from a previous paint against the
2450 * current item. Computes if the geometry of the item has changed, and the
2451 * invalidation area required for correct repainting.
2453 * The existing geometry will have been created from a display item with a
2454 * matching GetPerFrameKey()/mFrame pair to the current item.
2456 * The default implementation compares the display item bounds, and the
2457 * frame's border rect, and invalidates the entire bounds if either rect
2460 * @param aGeometry The geometry of the matching display item from the
2462 * @param aInvalidRegion Output param, the region to invalidate, or
2463 * unchanged if none.
2465 virtual void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
2466 const nsDisplayItemGeometry
* aGeometry
,
2467 nsRegion
* aInvalidRegion
) const {
2468 const nsDisplayItemGenericGeometry
* geometry
=
2469 static_cast<const nsDisplayItemGenericGeometry
*>(aGeometry
);
2471 if (!geometry
->mBounds
.IsEqualInterior(GetBounds(aBuilder
, &snap
)) ||
2472 !geometry
->mBorderRect
.IsEqualInterior(GetBorderRect())) {
2473 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
2478 * An alternative default implementation of ComputeInvalidationRegion,
2479 * that instead invalidates only the changed area between the two items.
2481 void ComputeInvalidationRegionDifference(
2482 nsDisplayListBuilder
* aBuilder
,
2483 const nsDisplayItemBoundsGeometry
* aGeometry
,
2484 nsRegion
* aInvalidRegion
) const {
2486 nsRect bounds
= GetBounds(aBuilder
, &snap
);
2488 if (!aGeometry
->mBounds
.IsEqualInterior(bounds
)) {
2490 if (aGeometry
->mHasRoundedCorners
|| Frame()->GetBorderRadii(radii
)) {
2491 aInvalidRegion
->Or(aGeometry
->mBounds
, bounds
);
2493 aInvalidRegion
->Xor(aGeometry
->mBounds
, bounds
);
2499 * This function is called when an item's list of children has been modified
2500 * by RetainedDisplayListBuilder.
2502 virtual void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) {}
2504 virtual void AddSizeOfExcludingThis(nsWindowSizes
&) const {}
2507 * @param aSnap set to true if the edges of the rectangles of the opaque
2508 * region would be snapped to device pixels when drawing
2509 * @return a region of the item that is opaque --- that is, every pixel
2510 * that is visible is painted with an opaque
2511 * color. This is useful for determining when one piece
2512 * of content completely obscures another so that we can do occlusion
2514 * This does not take clipping into account.
2515 * This must return a simple region (1 rect) for painting display lists.
2516 * It is only allowed to be a complex region for hit testing.
2518 virtual nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
2519 bool* aSnap
) const {
2524 * @return Some(nscolor) if the item is guaranteed to paint every pixel in its
2525 * bounds with the same (possibly translucent) color
2527 virtual Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const {
2532 * @return true if the contents of this item are rendered fixed relative
2533 * to the nearest viewport.
2535 virtual bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const {
2540 * Returns true if all layers that can be active should be forced to be
2541 * active. Requires setting the pref layers.force-active=true.
2543 static bool ForceActiveLayers();
2545 #ifdef MOZ_DUMP_PAINTING
2547 * Mark this display item as being painted via
2548 * FrameLayerBuilder::DrawPaintedLayer.
2550 bool Painted() const { return mItemFlags
.contains(ItemFlag::Painted
); }
2553 * Check if this display item has been painted.
2555 void SetPainted() { mItemFlags
+= ItemFlag::Painted
; }
2559 * Function to create the WebRenderCommands.
2560 * We should check if the layer state is
2561 * active first and have an early return if the layer state is
2564 * @return true if successfully creating webrender commands.
2566 virtual bool CreateWebRenderCommands(
2567 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
2568 const StackingContextHelper
& aSc
,
2569 layers::RenderRootStateManager
* aManager
,
2570 nsDisplayListBuilder
* aDisplayListBuilder
) {
2575 * Updates the provided aLayerData with any APZ-relevant scroll data
2576 * that is specific to this display item. This is stuff that would normally
2577 * be put on the layer during BuildLayer, but this is only called in
2578 * layers-free webrender mode, where we don't have layers.
2580 * This function returns true if and only if it has APZ-relevant scroll data
2581 * to provide. Note that the arguments passed in may be nullptr, in which case
2582 * the function should still return true if and only if it has APZ-relevant
2583 * scroll data, but obviously in this case it can't actually put the
2584 * data onto aLayerData, because there isn't one.
2586 * This function assumes that aData and aLayerData will either both be null,
2587 * or will both be non-null. The caller is responsible for enforcing this.
2589 virtual bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
2590 layers::WebRenderLayerScrollData
* aLayerData
) {
2595 * Returns true if this item needs to have its geometry updated, despite
2596 * returning empty invalidation region.
2598 virtual bool NeedsGeometryUpdates() const { return false; }
2601 * When this item is rendered using fallback rendering, whether it should use
2602 * blob rendering (i.e. a recording DrawTarget), as opposed to a pixel-backed
2604 * Some items, such as those calling into the native themed widget machinery,
2605 * are more efficiently painted without blob recording. Those should return
2608 virtual bool ShouldUseBlobRenderingForFallback() const { return true; }
2611 * If this has a child list where the children are in the same coordinate
2612 * system as this item (i.e., they have the same reference frame),
2615 virtual RetainedDisplayList
* GetSameCoordinateSystemChildren() const {
2619 virtual void UpdateBounds(nsDisplayListBuilder
* aBuilder
) {}
2621 * Do UpdateBounds() for items with frames establishing or extending
2622 * 3D rendering context.
2624 * This function is called by UpdateBoundsFor3D() of
2625 * nsDisplayTransform(), and it is called by
2626 * BuildDisplayListForStackingContext() on transform items
2627 * establishing 3D rendering context.
2629 * The bounds of a transform item with the frame establishing 3D
2630 * rendering context should be computed by calling
2631 * DoUpdateBoundsPreserves3D() on all descendants that participate
2632 * the same 3d rendering context.
2634 virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) {}
2637 * Returns the building rectangle used by nsDisplayListBuilder when
2638 * this item was constructed.
2640 const nsRect
& GetBuildingRect() const { return mBuildingRect
; }
2642 void SetBuildingRect(const nsRect
& aBuildingRect
) {
2643 mBuildingRect
= aBuildingRect
;
2647 * Returns the building rect for the children, relative to their
2648 * reference frame. Can be different from mBuildingRect for
2649 * nsDisplayTransform, since the reference frame for the children is different
2650 * from the reference frame for the item itself.
2652 virtual const nsRect
& GetBuildingRectForChildren() const {
2653 return mBuildingRect
;
2656 virtual void WriteDebugInfo(std::stringstream
& aStream
) {}
2659 * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
2661 const nsPoint
& ToReferenceFrame() const {
2662 NS_ASSERTION(mFrame
, "No frame?");
2663 return mToReferenceFrame
;
2667 * Returns the reference frame for display item children of this item.
2669 virtual const nsIFrame
* ReferenceFrameForChildren() const { return nullptr; }
2672 * Checks if this display item (or any children) contains content that might
2673 * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
2674 * bounds of the area that needs component alpha, or an empty rect if nothing
2677 virtual nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const {
2682 * Check if we can add async animations to the layer for this display item.
2684 virtual bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) {
2688 virtual bool SupportsOptimizingToImage() const { return false; }
2690 virtual const DisplayItemClip
& GetClip() const;
2691 void IntersectClip(nsDisplayListBuilder
* aBuilder
,
2692 const DisplayItemClipChain
* aOther
, bool aStore
);
2694 virtual void SetActiveScrolledRoot(
2695 const ActiveScrolledRoot
* aActiveScrolledRoot
) {
2696 mActiveScrolledRoot
= aActiveScrolledRoot
;
2698 const ActiveScrolledRoot
* GetActiveScrolledRoot() const {
2699 return mActiveScrolledRoot
;
2702 virtual void SetClipChain(const DisplayItemClipChain
* aClipChain
,
2704 const DisplayItemClipChain
* GetClipChain() const { return mClipChain
; }
2706 bool BackfaceIsHidden() const {
2707 return mItemFlags
.contains(ItemFlag::BackfaceHidden
);
2710 bool Combines3DTransformWithAncestors() const {
2711 return mItemFlags
.contains(ItemFlag::Combines3DTransformWithAncestors
);
2714 bool ForceNotVisible() const {
2715 return mItemFlags
.contains(ItemFlag::ForceNotVisible
);
2718 bool In3DContextAndBackfaceIsHidden() const {
2719 return mItemFlags
.contains(ItemFlag::BackfaceHidden
) &&
2720 mItemFlags
.contains(ItemFlag::Combines3DTransformWithAncestors
);
2723 bool HasDifferentFrame(const nsDisplayItem
* aOther
) const {
2724 return mFrame
!= aOther
->mFrame
;
2727 bool HasHitTestInfo() const {
2728 return mItemFlags
.contains(ItemFlag::HasHitTestInfo
);
2731 bool HasSameTypeAndClip(const nsDisplayItem
* aOther
) const {
2732 return GetPerFrameKey() == aOther
->GetPerFrameKey() &&
2733 GetClipChain() == aOther
->GetClipChain();
2736 bool HasSameContent(const nsDisplayItem
* aOther
) const {
2737 return mFrame
->GetContent() == aOther
->Frame()->GetContent();
2740 virtual void NotifyUsed(nsDisplayListBuilder
* aBuilder
) {}
2742 virtual Maybe
<nsRect
> GetClipWithRespectToASR(
2743 nsDisplayListBuilder
* aBuilder
, const ActiveScrolledRoot
* aASR
) const;
2745 virtual const nsRect
& GetUntransformedPaintRect() const {
2746 return GetBuildingRect();
2749 nsRect
GetPaintRect(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
);
2751 virtual const HitTestInfo
& GetHitTestInfo() { return HitTestInfo::Empty(); }
2753 enum class ReuseState
: uint8_t {
2755 // Set during display list building.
2757 // Set during display list preprocessing.
2759 // Set during partial display list build.
2763 void SetReusable() {
2764 MOZ_ASSERT(mReuseState
== ReuseState::None
||
2765 mReuseState
== ReuseState::Reused
);
2766 mReuseState
= ReuseState::Reusable
;
2769 bool IsReusable() const { return mReuseState
== ReuseState::Reusable
; }
2771 void SetPreProcessed() {
2772 MOZ_ASSERT(mReuseState
== ReuseState::Reusable
);
2773 mReuseState
= ReuseState::PreProcessed
;
2776 bool IsPreProcessed() const {
2777 return mReuseState
== ReuseState::PreProcessed
;
2780 void SetReusedItem() {
2781 MOZ_ASSERT(mReuseState
== ReuseState::PreProcessed
);
2782 mReuseState
= ReuseState::Reused
;
2785 bool IsReusedItem() const { return mReuseState
== ReuseState::Reused
; }
2787 void ResetReuseState() { mReuseState
= ReuseState::None
; }
2789 ReuseState
GetReuseState() const { return mReuseState
; }
2791 nsIFrame
* mFrame
; // 8
2794 enum class ItemFlag
: uint16_t {
2800 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2805 Combines3DTransformWithAncestors
,
2808 #ifdef MOZ_DUMP_PAINTING
2809 // True if this frame has been painted.
2814 EnumSet
<ItemFlag
, uint16_t> mItemFlags
; // 2
2815 DisplayItemType mType
= DisplayItemType::TYPE_ZERO
; // 1
2816 uint8_t mExtraPageForPageNum
= 0; // 1
2817 uint16_t mPerFrameIndex
= 0; // 2
2818 ReuseState mReuseState
= ReuseState::None
;
2819 OldListIndex mOldListIndex
; // 4
2820 uintptr_t mOldList
= 0; // 8
2822 // This is the rectangle that nsDisplayListBuilder was using as the visible
2823 // rect to decide which items to construct.
2824 nsRect mBuildingRect
;
2827 void SetItemFlag(ItemFlag aFlag
, const bool aValue
) {
2829 mItemFlags
+= aFlag
;
2831 mItemFlags
-= aFlag
;
2835 void SetHasHitTestInfo() { mItemFlags
+= ItemFlag::HasHitTestInfo
; }
2837 // Result of ToReferenceFrame(mFrame), if mFrame is non-null
2838 nsPoint mToReferenceFrame
;
2840 RefPtr
<const ActiveScrolledRoot
> mActiveScrolledRoot
;
2841 RefPtr
<const DisplayItemClipChain
> mClipChain
;
2843 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2845 bool IsMergedItem() const {
2846 return mItemFlags
.contains(ItemFlag::MergedItem
);
2849 bool IsPreProcessedItem() const {
2850 return mItemFlags
.contains(ItemFlag::PreProcessedItem
);
2853 void SetMergedPreProcessed(bool aMerged
, bool aPreProcessed
) {
2854 SetItemFlag(ItemFlag::MergedItem
, aMerged
);
2855 SetItemFlag(ItemFlag::PreProcessedItem
, aPreProcessed
);
2858 uint32_t mOldListKey
= 0;
2859 uint32_t mOldNestingDepth
= 0;
2863 class nsPaintedDisplayItem
: public nsDisplayItem
{
2865 nsPaintedDisplayItem
* AsPaintedDisplayItem() final
{ return this; }
2866 const nsPaintedDisplayItem
* AsPaintedDisplayItem() const final
{
2871 * Returns true if this display item would return true from ApplyOpacity
2872 * without actually applying the opacity. Otherwise returns false.
2874 virtual bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
2875 nsDisplayListBuilder
* aBuilder
) const {
2880 * Returns true if this item supports PaintWithClip, where the clipping
2881 * is used directly as the primitive geometry instead of needing an explicit
2884 virtual bool CanPaintWithClip(const DisplayItemClip
& aClip
) { return false; }
2887 * Same as |Paint()|, except provides a clip to use the geometry to draw with.
2888 * Must not be called unless |CanPaintWithClip()| returned true.
2890 virtual void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
2891 const DisplayItemClip
& aClip
) {
2892 MOZ_ASSERT_UNREACHABLE("PaintWithClip() is not implemented!");
2896 * Paint this item to some rendering context.
2898 virtual void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) = 0;
2901 * External storage used by |DisplayItemCache| to avoid hashmap lookups.
2902 * If an item is reused and has the cache index set, it means that
2903 * |DisplayItemCache| has assigned a cache slot for the item.
2905 Maybe
<uint16_t>& CacheIndex() { return mCacheIndex
; }
2907 void InvalidateItemCacheEntry() override
{
2908 // |nsPaintedDisplayItem|s may have |DisplayItemCache| entries
2909 // that no longer match after a mutation. The cache will notice
2910 // on its own that the entry is no longer in use, and free it.
2911 mCacheIndex
= Nothing();
2914 const HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
2915 void InitializeHitTestInfo(nsDisplayListBuilder
* aBuilder
) {
2916 mHitTestInfo
.Initialize(aBuilder
, Frame());
2917 SetHasHitTestInfo();
2921 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
2922 : nsPaintedDisplayItem(aBuilder
, aFrame
,
2923 aBuilder
->CurrentActiveScrolledRoot()) {}
2925 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
2926 const ActiveScrolledRoot
* aActiveScrolledRoot
)
2927 : nsDisplayItem(aBuilder
, aFrame
, aActiveScrolledRoot
) {}
2929 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
,
2930 const nsPaintedDisplayItem
& aOther
)
2931 : nsDisplayItem(aBuilder
, aOther
), mHitTestInfo(aOther
.mHitTestInfo
) {}
2934 HitTestInfo mHitTestInfo
;
2935 Maybe
<uint16_t> mCacheIndex
;
2938 template <typename T
>
2939 struct MOZ_HEAP_CLASS LinkedListNode
{
2940 explicit LinkedListNode(T aValue
) : mNext(nullptr), mValue(aValue
) {}
2941 LinkedListNode
* mNext
;
2945 template <typename T
>
2946 struct LinkedListIterator
{
2947 using iterator_category
= std::forward_iterator_tag
;
2948 using difference_type
= std::ptrdiff_t;
2949 using value_type
= T
;
2951 using reference
= T
&;
2952 using Node
= LinkedListNode
<T
>;
2954 explicit LinkedListIterator(Node
* aNode
= nullptr) : mNode(aNode
) {}
2956 bool HasNext() const { return mNode
!= nullptr; }
2958 LinkedListIterator
<T
>& operator++() {
2960 mNode
= mNode
->mNext
;
2964 bool operator==(const LinkedListIterator
<T
>& aOther
) const {
2965 return mNode
== aOther
.mNode
;
2968 bool operator!=(const LinkedListIterator
<T
>& aOther
) const {
2969 return mNode
!= aOther
.mNode
;
2972 const T
operator*() const {
2974 return mNode
->mValue
;
2979 return mNode
->mValue
;
2986 * Manages a singly-linked list of display list items.
2988 * Stepping upward through this list is very fast. Stepping downward is very
2989 * slow so we don't support it. The methods that need to step downward
2990 * (HitTest()) internally build a temporary array of all
2991 * the items while they do the downward traversal, so overall they're still
2992 * linear time. We have optimized for efficient AppendToTop() of both
2993 * items and lists, with minimal codesize.
2995 * Internal linked list nodes are allocated using arena allocator.
2997 class nsDisplayList
{
2999 using Node
= LinkedListNode
<nsDisplayItem
*>;
3000 using iterator
= LinkedListIterator
<nsDisplayItem
*>;
3001 using const_iterator
= iterator
;
3003 iterator
begin() { return iterator(mBottom
); }
3004 iterator
end() { return iterator(nullptr); }
3005 const_iterator
begin() const { return iterator(mBottom
); }
3006 const_iterator
end() const { return iterator(nullptr); }
3008 explicit nsDisplayList(nsDisplayListBuilder
* aBuilder
) : mBuilder(aBuilder
) {}
3010 nsDisplayList() = delete;
3011 nsDisplayList(const nsDisplayList
&) = delete;
3012 nsDisplayList
& operator=(const nsDisplayList
&) = delete;
3014 virtual ~nsDisplayList() {
3015 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3016 if (!mAllowNonEmptyDestruction
) {
3017 MOZ_RELEASE_ASSERT(IsEmpty(), "Nonempty list left over?");
3024 nsDisplayList(nsDisplayList
&& aOther
)
3025 : mBottom(aOther
.mBottom
),
3027 mLength(aOther
.mLength
),
3028 mBuilder(aOther
.mBuilder
) {
3032 nsDisplayList
& operator=(nsDisplayList
&& aOther
) {
3033 MOZ_RELEASE_ASSERT(mBuilder
== aOther
.mBuilder
);
3035 if (this != &aOther
) {
3036 MOZ_RELEASE_ASSERT(IsEmpty());
3037 mBottom
= std::move(aOther
.mBottom
);
3038 mTop
= std::move(aOther
.mTop
);
3039 mLength
= std::move(aOther
.mLength
);
3046 * Append an item to the top of the list.
3048 void AppendToTop(nsDisplayItem
* aItem
) {
3053 auto* next
= Allocate(aItem
);
3066 MOZ_ASSERT(mBottom
&& mTop
);
3067 MOZ_ASSERT(mTop
->mNext
== nullptr);
3070 template <typename T
, typename F
, typename
... Args
>
3071 void AppendNewToTop(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3073 AppendNewToTopWithIndex
<T
>(aBuilder
, aFrame
, 0,
3074 std::forward
<Args
>(aArgs
)...);
3077 template <typename T
, typename F
, typename
... Args
>
3078 void AppendNewToTopWithIndex(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3079 const uint16_t aIndex
, Args
&&... aArgs
) {
3080 nsDisplayItem
* item
= MakeDisplayItemWithIndex
<T
>(
3081 aBuilder
, aFrame
, aIndex
, std::forward
<Args
>(aArgs
)...);
3086 * Removes all items from aList and appends them to the top of this list.
3088 void AppendToTop(nsDisplayList
* aList
) {
3089 MOZ_ASSERT(aList
!= this);
3090 MOZ_RELEASE_ASSERT(mBuilder
== aList
->mBuilder
);
3092 if (aList
->IsEmpty()) {
3097 std::swap(mBottom
, aList
->mBottom
);
3098 std::swap(mTop
, aList
->mTop
);
3099 std::swap(mLength
, aList
->mLength
);
3101 MOZ_ASSERT(mTop
&& mTop
->mNext
== nullptr);
3102 mTop
->mNext
= aList
->mBottom
;
3104 mLength
+= aList
->mLength
;
3111 * Clears the display list.
3119 * Creates a shallow copy of this display list to |aDestination|.
3121 void CopyTo(nsDisplayList
* aDestination
) const {
3122 for (auto* item
: *this) {
3123 aDestination
->AppendToTop(item
);
3128 * Calls the function |aFn| for each display item in the display list.
3130 void ForEach(const std::function
<void(nsDisplayItem
*)>& aFn
) {
3131 for (auto* item
: *this) {
3136 * Remove all items from the list and call their destructors.
3138 virtual void DeleteAll(nsDisplayListBuilder
* aBuilder
);
3141 * @return the item at the bottom of the list, or null if the list is empty
3143 nsDisplayItem
* GetBottom() const {
3144 return mBottom
? mBottom
->mValue
: nullptr;
3148 * @return the item at the top of the list, or null if the list is empty
3150 nsDisplayItem
* GetTop() const { return mTop
? mTop
->mValue
: nullptr; }
3152 bool IsEmpty() const { return mBottom
== nullptr; }
3155 * @return the number of items in the list
3157 size_t Length() const { return mLength
; }
3160 * Stable sort the list by the z-order of Frame() on
3161 * each item. 'auto' is counted as zero.
3162 * It is assumed that the list is already in content document order.
3164 void SortByZOrder();
3167 * Stable sort the list by the tree order of the content of
3168 * Frame() on each item. z-index is ignored.
3169 * @param aCommonAncestor a common ancestor of all the content elements
3170 * associated with the display items, for speeding up tree order
3171 * checks, or nullptr if not known; it's only a hint, if it is not an
3172 * ancestor of some elements, then we lose performance but not correctness
3174 void SortByContentOrder(nsIContent
* aCommonAncestor
);
3177 * Sort the display list using a stable sort.
3178 * aComparator(Item item1, Item item2) should return true if item1 should go
3180 * We sort the items into increasing order.
3182 template <typename Item
, typename Comparator
>
3183 void Sort(const Comparator
& aComparator
) {
3185 // Only sort lists with more than one item.
3189 // Some casual local browsing testing suggests that a local preallocated
3190 // array of 20 items should be able to avoid a lot of dynamic allocations
3192 AutoTArray
<Item
, 20> items
;
3194 for (nsDisplayItem
* item
: TakeItems()) {
3195 items
.AppendElement(Item(item
));
3198 std::stable_sort(items
.begin(), items
.end(), aComparator
);
3200 for (Item
& item
: items
) {
3205 nsDisplayList
TakeItems() {
3206 nsDisplayList list
= std::move(*this);
3207 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3208 list
.mAllowNonEmptyDestruction
= true;
3213 nsDisplayItem
* RemoveBottom() {
3218 nsDisplayItem
* bottom
= mBottom
->mValue
;
3220 auto next
= mBottom
->mNext
;
3221 Deallocate(mBottom
);
3225 // No bottom item means no items at all.
3229 MOZ_ASSERT(mLength
> 0);
3236 * Paint the list to the rendering context. We assume that (0,0) in aCtx
3237 * corresponds to the origin of the reference frame. For best results,
3238 * aCtx's current transform should make (0,0) pixel-aligned. The
3239 * rectangle in aDirtyRect is painted, which *must* be contained in the
3240 * dirty rect used to construct the display list.
3242 * If aFlags contains PAINT_USE_WIDGET_LAYERS and
3243 * ShouldUseWidgetLayerManager() is set, then we will paint using
3244 * the reference frame's widget's layer manager (and ctx may be null),
3245 * otherwise we will use a temporary BasicLayerManager and ctx must
3248 * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
3249 * layer manager has already had BeginTransaction() called on it and
3250 * we should not call it again.
3252 * This must only be called on the root display list of the display list
3255 * We return the layer manager used for painting --- mainly so that
3256 * callers can dump its layer tree if necessary.
3260 PAINT_USE_WIDGET_LAYERS
= 0x01,
3261 PAINT_EXISTING_TRANSACTION
= 0x04,
3262 PAINT_IDENTICAL_DISPLAY_LIST
= 0x08
3264 void PaintRoot(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
3265 uint32_t aFlags
, Maybe
<double> aDisplayListBuildTime
);
3267 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
3268 int32_t aAppUnitsPerDevPixel
);
3271 * Get the bounds. Takes the union of the bounds of all children.
3272 * The result is not cached.
3274 nsRect
GetClippedBounds(nsDisplayListBuilder
* aBuilder
) const;
3277 * Get this list's bounds, respecting clips relative to aASR. The result is
3278 * the union of each item's clipped bounds with respect to aASR. That means
3279 * that if an item can move asynchronously with an ASR that is a descendant
3280 * of aASR, then the clipped bounds with respect to aASR will be the clip of
3281 * that item for aASR, because the item can move anywhere inside that clip.
3282 * If there is an item in this list which is not bounded with respect to
3283 * aASR (i.e. which does not have "finite bounds" with respect to aASR),
3284 * then this method trigger an assertion failure.
3285 * The optional aBuildingRect out argument can be set to non-null if the
3286 * caller is also interested to know the building rect. This can be used
3287 * to get the visible rect efficiently without traversing the display list
3290 nsRect
GetClippedBoundsWithRespectToASR(
3291 nsDisplayListBuilder
* aBuilder
, const ActiveScrolledRoot
* aASR
,
3292 nsRect
* aBuildingRect
= nullptr) const;
3295 * Returns the opaque region of this display list.
3297 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
) {
3300 for (nsDisplayItem
* item
: *this) {
3301 result
.OrWith(item
->GetOpaqueRegion(aBuilder
, &snap
));
3307 * Returns the bounds of the area that needs component alpha.
3309 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const {
3311 for (nsDisplayItem
* item
: *this) {
3312 bounds
.UnionRect(bounds
, item
->GetComponentAlphaBounds(aBuilder
));
3318 * Find the topmost display item that returns a non-null frame, and return
3321 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
3322 nsDisplayItem::HitTestState
* aState
,
3323 nsTArray
<nsIFrame
*>* aOutFrames
) const;
3325 * Compute the union of the visible rects of the items in the list. The
3326 * result is not cached.
3328 nsRect
GetBuildingRect() const;
3331 inline Node
* Allocate(nsDisplayItem
* aItem
) {
3333 mBuilder
->Allocate(sizeof(Node
), DisplayListArenaObjectId::LISTNODE
);
3334 return new (ptr
) Node(aItem
);
3337 inline void Deallocate(Node
* aNode
) {
3339 mBuilder
->Destroy(DisplayListArenaObjectId::LISTNODE
, aNode
);
3342 void DeallocateNodes() {
3343 Node
* current
= mBottom
;
3344 Node
* next
= nullptr;
3347 next
= current
->mNext
;
3348 Deallocate(current
);
3353 inline void SetEmpty() {
3359 Node
* mBottom
= nullptr;
3360 Node
* mTop
= nullptr;
3362 nsDisplayListBuilder
* mBuilder
= nullptr;
3364 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3365 // This checks that the invariant of display lists owning their items is held.
3366 bool mAllowNonEmptyDestruction
= false;
3371 * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
3372 * will put any generated items onto the appropriate list given here. It's
3373 * basically just a collection with one list for each separate stacking layer.
3374 * The lists themselves are external to this object and thus can be shared
3375 * with others. Some of the list pointers may even refer to the same list.
3377 class nsDisplayListSet
{
3380 * @return a list where one should place the border and/or background for
3381 * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
3383 nsDisplayList
* BorderBackground() const { return mLists
[0]; }
3385 * @return a list where one should place the borders and/or backgrounds for
3386 * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
3388 nsDisplayList
* BlockBorderBackgrounds() const { return mLists
[1]; }
3390 * @return a list where one should place descendant floats (step 5 of
3391 * CSS 2.1 appendix E)
3393 nsDisplayList
* Floats() const { return mLists
[2]; }
3395 * @return a list where one should place the (pseudo) stacking contexts
3396 * for descendants of this frame (everything from steps 3, 7 and 8
3397 * of CSS 2.1 appendix E)
3399 nsDisplayList
* PositionedDescendants() const { return mLists
[3]; }
3401 * @return a list where one should place the outlines
3402 * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
3404 nsDisplayList
* Outlines() const { return mLists
[4]; }
3406 * @return a list where one should place all other content
3408 nsDisplayList
* Content() const { return mLists
[5]; }
3410 const std::array
<nsDisplayList
*, 6>& Lists() const { return mLists
; }
3413 * Clears all the display lists in the set.
3416 for (auto* list
: mLists
) {
3423 * Deletes all the display items in the set.
3425 void DeleteAll(nsDisplayListBuilder
* aBuilder
) {
3426 for (auto* list
: mLists
) {
3427 list
->DeleteAll(aBuilder
);
3431 nsDisplayListSet(nsDisplayList
* aBorderBackground
,
3432 nsDisplayList
* aBlockBorderBackgrounds
,
3433 nsDisplayList
* aFloats
, nsDisplayList
* aContent
,
3434 nsDisplayList
* aPositionedDescendants
,
3435 nsDisplayList
* aOutlines
)
3436 : mLists
{aBorderBackground
, aBlockBorderBackgrounds
, aFloats
,
3437 aContent
, aPositionedDescendants
, aOutlines
} {}
3440 * A copy constructor that lets the caller override the BorderBackground
3443 nsDisplayListSet(const nsDisplayListSet
& aLists
,
3444 nsDisplayList
* aBorderBackground
)
3445 : mLists(aLists
.mLists
) {
3446 mLists
[0] = aBorderBackground
;
3450 * Returns true if all the display lists in the display list set are empty.
3452 bool IsEmpty() const {
3453 for (auto* list
: mLists
) {
3454 if (!list
->IsEmpty()) {
3463 * Calls the function |aFn| for each display item in the display list set.
3465 void ForEach(const std::function
<void(nsDisplayItem
*)>& aFn
) const {
3466 for (auto* list
: mLists
) {
3472 * Creates a shallow copy of this display list set to |aDestination|.
3474 void CopyTo(const nsDisplayListSet
& aDestination
) const;
3477 * Move all display items in our lists to top of the corresponding lists in
3480 void MoveTo(const nsDisplayListSet
& aDestination
) const;
3483 // This class is only used on stack, so we don't have to worry about leaking
3484 // it. Don't let us be heap-allocated!
3485 void* operator new(size_t sz
) noexcept(true);
3487 std::array
<nsDisplayList
*, 6> mLists
;
3491 * A specialization of nsDisplayListSet where the lists are actually internal
3492 * to the object, and all distinct.
3494 struct nsDisplayListCollection
: public nsDisplayListSet
{
3495 explicit nsDisplayListCollection(nsDisplayListBuilder
* aBuilder
)
3496 : nsDisplayListSet(&mLists
[0], &mLists
[1], &mLists
[2], &mLists
[3],
3497 &mLists
[4], &mLists
[5]),
3498 mLists
{nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
},
3499 nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
},
3500 nsDisplayList
{aBuilder
}, nsDisplayList
{aBuilder
}} {}
3503 * Sort all lists by content order.
3505 void SortAllByContentOrder(nsIContent
* aCommonAncestor
) {
3506 for (auto& mList
: mLists
) {
3507 mList
.SortByContentOrder(aCommonAncestor
);
3512 * Serialize this display list collection into a display list with the items
3513 * in the correct Z order.
3514 * @param aOutList the result display list
3515 * @param aContent the content element to use for content ordering
3517 void SerializeWithCorrectZOrder(nsDisplayList
* aOutResultList
,
3518 nsIContent
* aContent
);
3521 // This class is only used on stack, so we don't have to worry about leaking
3522 // it. Don't let us be heap-allocated!
3523 void* operator new(size_t sz
) noexcept(true);
3525 nsDisplayList mLists
[6];
3529 * A display list that also retains the partial build
3530 * information (in the form of a DAG) used to create it.
3532 * Display lists built from a partial list aren't necessarily
3533 * in the same order as a full build, and the DAG retains
3534 * the information needing to interpret the current
3537 class RetainedDisplayList
: public nsDisplayList
{
3539 explicit RetainedDisplayList(nsDisplayListBuilder
* aBuilder
)
3540 : nsDisplayList(aBuilder
) {}
3542 RetainedDisplayList(RetainedDisplayList
&& aOther
)
3543 : nsDisplayList(std::move(aOther
)), mDAG(std::move(aOther
.mDAG
)) {}
3545 RetainedDisplayList(const RetainedDisplayList
&) = delete;
3546 RetainedDisplayList
& operator=(const RetainedDisplayList
&) = delete;
3548 ~RetainedDisplayList() override
{
3549 MOZ_ASSERT(mOldItems
.IsEmpty(), "Must empty list before destroying");
3552 RetainedDisplayList
& operator=(RetainedDisplayList
&& aOther
) {
3553 MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
3554 MOZ_ASSERT(mOldItems
.IsEmpty(), "Can only move into an empty list!");
3556 nsDisplayList::operator=(std::move(aOther
));
3557 mDAG
= std::move(aOther
.mDAG
);
3558 mOldItems
= std::move(aOther
.mOldItems
);
3562 RetainedDisplayList
& operator=(nsDisplayList
&& aOther
) {
3563 MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
3564 MOZ_ASSERT(mOldItems
.IsEmpty(), "Can only move into an empty list!");
3565 nsDisplayList::operator=(std::move(aOther
));
3569 void DeleteAll(nsDisplayListBuilder
* aBuilder
) override
{
3570 for (OldItemInfo
& i
: mOldItems
) {
3571 if (i
.mItem
&& i
.mOwnsItem
) {
3572 i
.mItem
->Destroy(aBuilder
);
3573 MOZ_ASSERT(!GetBottom(),
3574 "mOldItems should not be owning items if we also have items "
3575 "in the normal list");
3580 nsDisplayList::DeleteAll(aBuilder
);
3583 void AddSizeOfExcludingThis(nsWindowSizes
&) const;
3585 DirectedAcyclicGraph
<MergedListUnits
> mDAG
;
3587 // Temporary state initialized during the preprocess pass
3588 // of RetainedDisplayListBuilder and then used during merging.
3589 nsTArray
<OldItemInfo
> mOldItems
;
3592 class nsDisplayContainer final
: public nsDisplayItem
{
3594 nsDisplayContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3595 const ActiveScrolledRoot
* aActiveScrolledRoot
,
3596 nsDisplayList
* aList
);
3598 ~nsDisplayContainer() override
{ MOZ_COUNT_DTOR(nsDisplayContainer
); }
3600 NS_DISPLAY_DECL_NAME("nsDisplayContainer", TYPE_CONTAINER
)
3602 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
3603 mChildren
.DeleteAll(aBuilder
);
3604 nsDisplayItem::Destroy(aBuilder
);
3607 bool CreateWebRenderCommands(
3608 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3609 const StackingContextHelper
& aSc
,
3610 layers::RenderRootStateManager
* aManager
,
3611 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3613 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3615 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
3617 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
3618 bool* aSnap
) const override
;
3620 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
{
3624 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
3625 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
3626 return GetChildren();
3629 Maybe
<nsRect
> GetClipWithRespectToASR(
3630 nsDisplayListBuilder
* aBuilder
,
3631 const ActiveScrolledRoot
* aASR
) const override
;
3633 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
3634 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
3636 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
3640 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
3641 bool aStore
) override
{
3642 MOZ_ASSERT_UNREACHABLE("nsDisplayContainer does not support clipping");
3645 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
3648 mutable RetainedDisplayList mChildren
;
3653 * Use this class to implement not-very-frequently-used display items
3654 * that are not opaque, do not receive events, and are bounded by a frame's
3657 * This should not be used for display items which are created frequently,
3658 * because each item is one or two pointers bigger than an item from a
3659 * custom display item class could be, and fractionally slower. However it does
3660 * save code size. We use this for infrequently-used item types.
3662 class nsDisplayGeneric
: public nsPaintedDisplayItem
{
3664 typedef void (*PaintCallback
)(nsIFrame
* aFrame
, gfx::DrawTarget
* aDrawTarget
,
3665 const nsRect
& aDirtyRect
, nsPoint aFramePt
);
3667 // XXX: should be removed eventually
3668 typedef void (*OldPaintCallback
)(nsIFrame
* aFrame
, gfxContext
* aCtx
,
3669 const nsRect
& aDirtyRect
, nsPoint aFramePt
);
3671 nsDisplayGeneric(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3672 PaintCallback aPaint
, const char* aName
,
3673 DisplayItemType aType
)
3674 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3678 MOZ_COUNT_CTOR(nsDisplayGeneric
);
3682 // XXX: should be removed eventually
3683 nsDisplayGeneric(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3684 OldPaintCallback aOldPaint
, const char* aName
,
3685 DisplayItemType aType
)
3686 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3688 mOldPaint(aOldPaint
),
3690 MOZ_COUNT_CTOR(nsDisplayGeneric
);
3694 constexpr static DisplayItemType
ItemType() {
3695 return DisplayItemType::TYPE_GENERIC
;
3698 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayGeneric
)
3700 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
3701 MOZ_ASSERT(!!mPaint
!= !!mOldPaint
);
3703 mPaint(mFrame
, aCtx
->GetDrawTarget(), GetPaintRect(aBuilder
, aCtx
),
3704 ToReferenceFrame());
3706 mOldPaint(mFrame
, aCtx
, GetPaintRect(aBuilder
, aCtx
), ToReferenceFrame());
3710 const char* Name() const override
{ return mName
; }
3712 // This override is needed because GetType() for nsDisplayGeneric subclasses
3713 // does not match TYPE_GENERIC that was used to allocate the object.
3714 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
3715 this->~nsDisplayGeneric();
3716 aBuilder
->Destroy(DisplayItemType::TYPE_GENERIC
, this);
3720 void* operator new(size_t aSize
, nsDisplayListBuilder
* aBuilder
) {
3721 return aBuilder
->Allocate(aSize
, DisplayItemType::TYPE_GENERIC
);
3724 template <typename T
, typename F
, typename
... Args
>
3725 friend T
* MakeDisplayItemWithIndex(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3726 const uint16_t aIndex
, Args
&&... aArgs
);
3728 PaintCallback mPaint
;
3729 OldPaintCallback mOldPaint
; // XXX: should be removed eventually
3733 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
3735 * This class implements painting of reflow counts. Ideally, we would simply
3736 * make all the frame names be those returned by nsIFrame::GetFrameName
3737 * (except that tosses in the content tag name!) and support only one color
3738 * and eliminate this class altogether in favor of nsDisplayGeneric, but for
3739 * the time being we can't pass args to a PaintCallback, so just have a
3740 * separate class to do the right thing. Sadly, this alsmo means we need to
3741 * hack all leaf frame classes to handle this.
3743 * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
3744 * here... I could switch it all to nscolor, but why bother?
3746 class nsDisplayReflowCount
: public nsPaintedDisplayItem
{
3748 nsDisplayReflowCount(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3749 const char* aFrameName
, uint32_t aColor
= 0)
3750 : nsPaintedDisplayItem(aBuilder
, aFrame
),
3751 mFrameName(aFrameName
),
3753 MOZ_COUNT_CTOR(nsDisplayReflowCount
);
3756 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayReflowCount
)
3758 NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT
)
3760 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3763 const char* mFrameName
;
3767 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
3769 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3770 PresShell()->IsPaintingFrameCounts()) { \
3771 aLists.Outlines()->AppendNewToTop<mozilla::nsDisplayReflowCount>( \
3772 aBuilder, this, _name); \
3776 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
3778 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3779 PresShell()->IsPaintingFrameCounts()) { \
3780 aLists.Outlines()->AppendNewToTop<mozilla::nsDisplayReflowCount>( \
3781 aBuilder, this, _name, _color); \
3786 Macro to be used for classes that don't actually implement BuildDisplayList
3788 # define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
3789 void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
3790 const nsRect& aDirtyRect, \
3791 const nsDisplayListSet& aLists) { \
3792 DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
3793 _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
3796 #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3798 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
3799 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
3800 # define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
3802 #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3804 class nsDisplayCaret
: public nsPaintedDisplayItem
{
3806 nsDisplayCaret(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aCaretFrame
);
3808 #ifdef NS_BUILD_REFCNT_LOGGING
3809 ~nsDisplayCaret() override
;
3812 NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET
)
3814 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3815 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3816 bool CreateWebRenderCommands(
3817 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3818 const StackingContextHelper
& aSc
,
3819 layers::RenderRootStateManager
* aManager
,
3820 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3823 RefPtr
<nsCaret
> mCaret
;
3828 * The standard display item to paint the CSS borders of a frame.
3830 class nsDisplayBorder
: public nsPaintedDisplayItem
{
3832 nsDisplayBorder(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
3834 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBorder
)
3836 NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER
)
3838 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
3839 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3840 bool CreateWebRenderCommands(
3841 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3842 const StackingContextHelper
& aSc
,
3843 layers::RenderRootStateManager
* aManager
,
3844 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3845 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3846 nsDisplayItemGeometry
* AllocateGeometry(
3847 nsDisplayListBuilder
* aBuilder
) override
;
3848 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
3849 const nsDisplayItemGeometry
* aGeometry
,
3850 nsRegion
* aInvalidRegion
) const override
;
3852 nsRegion
GetTightBounds(nsDisplayListBuilder
* aBuilder
,
3853 bool* aSnap
) const override
{
3855 return CalculateBounds
<nsRegion
>(*mFrame
->StyleBorder());
3859 template <typename T
>
3860 T
CalculateBounds(const nsStyleBorder
& aStyleBorder
) const {
3861 nsRect
borderBounds(ToReferenceFrame(), mFrame
->GetSize());
3862 if (aStyleBorder
.IsBorderImageSizeAvailable()) {
3863 borderBounds
.Inflate(aStyleBorder
.GetImageOutset());
3864 return borderBounds
;
3867 nsMargin border
= aStyleBorder
.GetComputedBorder();
3869 if (border
.top
> 0) {
3870 result
= nsRect(borderBounds
.X(), borderBounds
.Y(), borderBounds
.Width(),
3873 if (border
.right
> 0) {
3874 result
.OrWith(nsRect(borderBounds
.XMost() - border
.right
,
3875 borderBounds
.Y(), border
.right
,
3876 borderBounds
.Height()));
3878 if (border
.bottom
> 0) {
3879 result
.OrWith(nsRect(borderBounds
.X(),
3880 borderBounds
.YMost() - border
.bottom
,
3881 borderBounds
.Width(), border
.bottom
));
3883 if (border
.left
> 0) {
3884 result
.OrWith(nsRect(borderBounds
.X(), borderBounds
.Y(), border
.left
,
3885 borderBounds
.Height()));
3889 if (mFrame
->GetBorderRadii(radii
)) {
3890 if (border
.left
> 0 || border
.top
> 0) {
3891 nsSize
cornerSize(radii
[eCornerTopLeftX
], radii
[eCornerTopLeftY
]);
3892 result
.OrWith(nsRect(borderBounds
.TopLeft(), cornerSize
));
3894 if (border
.top
> 0 || border
.right
> 0) {
3895 nsSize
cornerSize(radii
[eCornerTopRightX
], radii
[eCornerTopRightY
]);
3897 nsRect(borderBounds
.TopRight() - nsPoint(cornerSize
.width
, 0),
3900 if (border
.right
> 0 || border
.bottom
> 0) {
3901 nsSize
cornerSize(radii
[eCornerBottomRightX
],
3902 radii
[eCornerBottomRightY
]);
3903 result
.OrWith(nsRect(borderBounds
.BottomRight() -
3904 nsPoint(cornerSize
.width
, cornerSize
.height
),
3907 if (border
.bottom
> 0 || border
.left
> 0) {
3908 nsSize
cornerSize(radii
[eCornerBottomLeftX
], radii
[eCornerBottomLeftY
]);
3910 nsRect(borderBounds
.BottomLeft() - nsPoint(0, cornerSize
.height
),
3921 * A simple display item that just renders a solid color across the
3922 * specified bounds. For canvas frames (in the CSS sense) we split off the
3923 * drawing of the background color into this class (from nsDisplayBackground
3924 * via nsDisplayCanvasBackground). This is done so that we can always draw a
3925 * background color to avoid ugly flashes of white when we can't draw a full
3926 * frame tree (ie when a page is loading). The bounds can differ from the
3927 * frame's bounds -- this is needed when a frame/iframe is loading and there
3928 * is not yet a frame tree to go in the frame/iframe so we use the subdoc
3929 * frame of the parent document as a standin.
3931 class nsDisplaySolidColorBase
: public nsPaintedDisplayItem
{
3933 nsDisplaySolidColorBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3935 : nsPaintedDisplayItem(aBuilder
, aFrame
), mColor(aColor
) {}
3937 nsDisplayItemGeometry
* AllocateGeometry(
3938 nsDisplayListBuilder
* aBuilder
) override
{
3939 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
);
3942 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
3943 const nsDisplayItemGeometry
* aGeometry
,
3944 nsRegion
* aInvalidRegion
) const override
{
3945 const nsDisplaySolidColorGeometry
* geometry
=
3946 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
3947 if (mColor
!= geometry
->mColor
) {
3949 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
3952 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
3955 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
3956 bool* aSnap
) const override
{
3959 if (NS_GET_A(mColor
) == 255) {
3960 result
= GetBounds(aBuilder
, aSnap
);
3965 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
{
3966 return Some(mColor
);
3973 class nsDisplaySolidColor
: public nsDisplaySolidColorBase
{
3975 nsDisplaySolidColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3976 const nsRect
& aBounds
, nscolor aColor
,
3977 bool aCanBeReused
= true)
3978 : nsDisplaySolidColorBase(aBuilder
, aFrame
, aColor
),
3980 mIsCheckerboardBackground(false) {
3981 NS_ASSERTION(NS_GET_A(aColor
) > 0,
3982 "Don't create invisible nsDisplaySolidColors!");
3983 MOZ_COUNT_CTOR(nsDisplaySolidColor
);
3984 if (!aCanBeReused
) {
3989 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColor
)
3991 NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR
)
3993 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3994 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
3995 void WriteDebugInfo(std::stringstream
& aStream
) override
;
3996 void SetIsCheckerboardBackground() { mIsCheckerboardBackground
= true; }
3997 bool CreateWebRenderCommands(
3998 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
3999 const StackingContextHelper
& aSc
,
4000 layers::RenderRootStateManager
* aManager
,
4001 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4003 int32_t ZIndex() const override
{
4004 if (mOverrideZIndex
) {
4005 return mOverrideZIndex
.value();
4007 return nsDisplaySolidColorBase::ZIndex();
4010 void SetOverrideZIndex(int32_t aZIndex
) { mOverrideZIndex
= Some(aZIndex
); }
4014 bool mIsCheckerboardBackground
;
4015 Maybe
<int32_t> mOverrideZIndex
;
4019 * A display item that renders a solid color over a region. This is not
4020 * exposed through CSS, its only purpose is efficient invalidation of
4021 * the find bar highlighter dimmer.
4023 class nsDisplaySolidColorRegion
: public nsPaintedDisplayItem
{
4025 nsDisplaySolidColorRegion(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4026 const nsRegion
& aRegion
, nscolor aColor
)
4027 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4029 mColor(gfx::sRGBColor::FromABGR(aColor
)) {
4030 NS_ASSERTION(NS_GET_A(aColor
) > 0,
4031 "Don't create invisible nsDisplaySolidColorRegions!");
4032 MOZ_COUNT_CTOR(nsDisplaySolidColorRegion
);
4035 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColorRegion
)
4037 NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION
)
4039 nsDisplayItemGeometry
* AllocateGeometry(
4040 nsDisplayListBuilder
* aBuilder
) override
{
4041 return new nsDisplaySolidColorRegionGeometry(this, aBuilder
, mRegion
,
4045 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4046 const nsDisplayItemGeometry
* aGeometry
,
4047 nsRegion
* aInvalidRegion
) const override
{
4048 const nsDisplaySolidColorRegionGeometry
* geometry
=
4049 static_cast<const nsDisplaySolidColorRegionGeometry
*>(aGeometry
);
4050 if (mColor
== geometry
->mColor
) {
4051 aInvalidRegion
->Xor(geometry
->mRegion
, mRegion
);
4053 aInvalidRegion
->Or(geometry
->mRegion
.GetBounds(), mRegion
.GetBounds());
4057 bool CreateWebRenderCommands(
4058 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4059 const StackingContextHelper
& aSc
,
4060 layers::RenderRootStateManager
* aManager
,
4061 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4064 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4065 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4066 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4070 gfx::sRGBColor mColor
;
4073 enum class AppendedBackgroundType
: uint8_t {
4080 * A display item to paint one background-image for a frame. Each background
4081 * image layer gets its own nsDisplayBackgroundImage.
4083 class nsDisplayBackgroundImage
: public nsPaintedDisplayItem
{
4086 nsDisplayListBuilder
* builder
;
4087 const ComputedStyle
* backgroundStyle
;
4088 nsCOMPtr
<imgIContainer
> image
;
4089 nsRect backgroundRect
;
4094 bool shouldFixToViewport
;
4098 * aLayer signifies which background layer this item represents.
4099 * aIsThemed should be the value of aFrame->IsThemed.
4100 * aBackgroundStyle should be the result of
4101 * nsCSSRendering::FindBackground, or null if FindBackground returned false.
4102 * aBackgroundRect is relative to aFrame.
4104 static InitData
GetInitData(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4105 uint16_t aLayer
, const nsRect
& aBackgroundRect
,
4106 const ComputedStyle
* aBackgroundStyle
);
4108 explicit nsDisplayBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4109 nsIFrame
* aFrame
, const InitData
& aInitData
,
4110 nsIFrame
* aFrameForBounds
= nullptr);
4111 ~nsDisplayBackgroundImage() override
;
4113 NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND
)
4116 * This will create and append new items for all the layers of the
4117 * background. Returns the type of background that was appended.
4118 * aAllowWillPaintBorderOptimization should usually be left at true, unless
4119 * aFrame has special border drawing that causes opaque borders to not
4120 * actually be opaque.
4122 static AppendedBackgroundType
AppendBackgroundItemsToTop(
4123 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4124 const nsRect
& aBackgroundRect
, nsDisplayList
* aList
,
4125 bool aAllowWillPaintBorderOptimization
= true,
4126 const nsRect
& aBackgroundOriginRect
= nsRect(),
4127 nsIFrame
* aSecondaryReferenceFrame
= nullptr,
4128 Maybe
<nsDisplayListBuilder::AutoBuildingDisplayList
>*
4129 aAutoBuildingDisplayList
= nullptr);
4131 bool CreateWebRenderCommands(
4132 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4133 const StackingContextHelper
& aSc
,
4134 layers::RenderRootStateManager
* aManager
,
4135 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4136 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4137 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4138 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4139 bool* aSnap
) const override
;
4140 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4142 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4143 nsDisplayListBuilder
* aBuilder
) const override
;
4146 * GetBounds() returns the background painting area.
4148 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4150 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4153 * Return the background positioning area.
4154 * (GetBounds() returns the background painting area.)
4155 * Can be called only when mBackgroundStyle is non-null.
4157 nsRect
GetPositioningArea() const;
4160 * Returns true if existing rendered pixels of this display item may need
4161 * to be redrawn if the positioning area size changes but its position does
4163 * If false, only the changed painting area needs to be redrawn when the
4164 * positioning area size changes but its position does not.
4166 bool RenderingMightDependOnPositioningAreaSizeChange() const;
4168 nsDisplayItemGeometry
* AllocateGeometry(
4169 nsDisplayListBuilder
* aBuilder
) override
{
4170 return new nsDisplayBackgroundGeometry(this, aBuilder
);
4173 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4174 const nsDisplayItemGeometry
* aGeometry
,
4175 nsRegion
* aInvalidRegion
) const override
;
4176 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
4177 return mShouldFixToViewport
;
4180 nsRect
GetDestRect() const { return mDestRect
; }
4182 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4184 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4185 if (!aBuilder
->IsRetainingDisplayList() || mDependentFrame
== aFrame
) {
4188 mDependentFrame
= aFrame
;
4190 mDependentFrame
->AddDisplayItem(this);
4194 void RemoveFrame(nsIFrame
* aFrame
) override
{
4195 if (aFrame
== mDependentFrame
) {
4196 mDependentFrame
= nullptr;
4198 nsPaintedDisplayItem::RemoveFrame(aFrame
);
4201 // Match https://w3c.github.io/paint-timing/#contentful-image
4202 bool IsContentful() const override
{
4203 const auto& styleImage
=
4204 mBackgroundStyle
->StyleBackground()->mImage
.mLayers
[mLayer
].mImage
;
4206 return styleImage
.IsSizeAvailable() && styleImage
.FinalImage().IsUrl();
4210 bool CanBuildWebRenderDisplayItems(layers::WebRenderLayerManager
* aManager
,
4211 nsDisplayListBuilder
* aBuilder
) const;
4212 nsRect
GetBoundsInternal(nsDisplayListBuilder
* aBuilder
,
4213 nsIFrame
* aFrameForBounds
= nullptr);
4215 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4216 const nsRect
& aBounds
, nsRect
* aClipRect
);
4218 // Cache the result of nsCSSRendering::FindBackground. Always null if
4219 // mIsThemed is true or if FindBackground returned false.
4220 RefPtr
<const ComputedStyle
> mBackgroundStyle
;
4221 nsCOMPtr
<imgIContainer
> mImage
;
4222 nsIFrame
* mDependentFrame
;
4223 nsRect mBackgroundRect
; // relative to the reference frame
4226 /* Bounds of this display item */
4229 bool mIsRasterImage
;
4230 /* Whether the image should be treated as fixed to the viewport. */
4231 bool mShouldFixToViewport
;
4235 * A display item to paint background image for table. For table parts, such
4236 * as row, row group, col, col group, when drawing its background, we'll
4237 * create separate background image display item for its containning cell.
4238 * Those background image display items will reference to same DisplayItemData
4239 * if we keep the mFrame point to cell's ancestor frame. We don't want to this
4240 * happened bacause share same DisplatItemData will cause many bugs. So that
4241 * we let mFrame point to cell frame and store the table type of the ancestor
4242 * frame. And use mFrame and table type as key to generate DisplayItemData to
4243 * avoid sharing DisplayItemData.
4245 * Also store ancestor frame as mStyleFrame for all rendering informations.
4247 class nsDisplayTableBackgroundImage
: public nsDisplayBackgroundImage
{
4249 nsDisplayTableBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4250 nsIFrame
* aFrame
, const InitData
& aData
,
4251 nsIFrame
* aCellFrame
);
4252 ~nsDisplayTableBackgroundImage() override
;
4254 NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE
)
4256 bool IsInvalid(nsRect
& aRect
) const override
;
4258 nsIFrame
* FrameForInvalidation() const override
{ return mStyleFrame
; }
4260 void RemoveFrame(nsIFrame
* aFrame
) override
{
4261 if (aFrame
== mStyleFrame
) {
4262 mStyleFrame
= nullptr;
4265 nsDisplayBackgroundImage::RemoveFrame(aFrame
);
4269 nsIFrame
* StyleFrame() const override
{ return mStyleFrame
; }
4270 nsIFrame
* mStyleFrame
;
4274 * A display item to paint the native theme background for a frame.
4276 class nsDisplayThemedBackground
: public nsPaintedDisplayItem
{
4278 nsDisplayThemedBackground(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4279 const nsRect
& aBackgroundRect
);
4281 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayThemedBackground
)
4283 NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND
)
4285 void Init(nsDisplayListBuilder
* aBuilder
);
4287 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4288 aBuilder
->UnregisterThemeGeometry(this);
4289 nsPaintedDisplayItem::Destroy(aBuilder
);
4292 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4293 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4294 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4295 bool* aSnap
) const override
;
4296 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4297 bool CreateWebRenderCommands(
4298 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4299 const StackingContextHelper
& aSc
,
4300 layers::RenderRootStateManager
* aManager
,
4301 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4303 bool ShouldUseBlobRenderingForFallback() const override
{
4304 return !XRE_IsParentProcess();
4308 * GetBounds() returns the background painting area.
4310 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4312 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4315 * Return the background positioning area.
4316 * (GetBounds() returns the background painting area.)
4317 * Can be called only when mBackgroundStyle is non-null.
4319 nsRect
GetPositioningArea() const;
4322 * Return whether our frame's document does not have the state
4323 * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
4325 bool IsWindowActive() const;
4327 nsDisplayItemGeometry
* AllocateGeometry(
4328 nsDisplayListBuilder
* aBuilder
) override
{
4329 return new nsDisplayThemedBackgroundGeometry(this, aBuilder
);
4332 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4333 const nsDisplayItemGeometry
* aGeometry
,
4334 nsRegion
* aInvalidRegion
) const override
;
4336 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4339 nsRect
GetBoundsInternal();
4341 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4342 const nsRect
& aBounds
, nsRect
* aClipRect
);
4344 nsRect mBackgroundRect
;
4346 nsITheme::Transparency mThemeTransparency
;
4347 StyleAppearance mAppearance
;
4350 class nsDisplayTableThemedBackground
: public nsDisplayThemedBackground
{
4352 nsDisplayTableThemedBackground(nsDisplayListBuilder
* aBuilder
,
4354 const nsRect
& aBackgroundRect
,
4355 nsIFrame
* aAncestorFrame
)
4356 : nsDisplayThemedBackground(aBuilder
, aFrame
, aBackgroundRect
),
4357 mAncestorFrame(aAncestorFrame
) {
4358 if (aBuilder
->IsRetainingDisplayList()) {
4359 mAncestorFrame
->AddDisplayItem(this);
4363 ~nsDisplayTableThemedBackground() override
{
4364 if (mAncestorFrame
) {
4365 mAncestorFrame
->RemoveDisplayItem(this);
4369 NS_DISPLAY_DECL_NAME("TableThemedBackground",
4370 TYPE_TABLE_THEMED_BACKGROUND_IMAGE
)
4372 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4374 void RemoveFrame(nsIFrame
* aFrame
) override
{
4375 if (aFrame
== mAncestorFrame
) {
4376 mAncestorFrame
= nullptr;
4379 nsDisplayThemedBackground::RemoveFrame(aFrame
);
4383 nsIFrame
* StyleFrame() const override
{ return mAncestorFrame
; }
4384 nsIFrame
* mAncestorFrame
;
4387 class nsDisplayBackgroundColor
: public nsPaintedDisplayItem
{
4389 nsDisplayBackgroundColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4390 const nsRect
& aBackgroundRect
,
4391 const ComputedStyle
* aBackgroundStyle
,
4392 const nscolor
& aColor
)
4393 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4394 mBackgroundRect(aBackgroundRect
),
4395 mHasStyle(aBackgroundStyle
),
4396 mDependentFrame(nullptr),
4397 mColor(gfx::sRGBColor::FromABGR(aColor
)) {
4400 aBackgroundStyle
->StyleBackground()->BottomLayer().mClip
;
4402 MOZ_ASSERT(aBuilder
->IsForEventDelivery());
4406 ~nsDisplayBackgroundColor() override
{
4407 if (mDependentFrame
) {
4408 mDependentFrame
->RemoveDisplayItem(this);
4412 NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR
)
4414 bool HasBackgroundClipText() const {
4415 MOZ_ASSERT(mHasStyle
);
4416 return mBottomLayerClip
== StyleGeometryBox::Text
;
4419 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4420 void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4421 const DisplayItemClip
& aClip
) override
;
4422 bool CreateWebRenderCommands(
4423 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4424 const StackingContextHelper
& aSc
,
4425 layers::RenderRootStateManager
* aManager
,
4426 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4427 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4428 bool* aSnap
) const override
;
4429 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4430 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4431 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4432 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4433 nsDisplayListBuilder
* aBuilder
) const override
;
4435 float GetOpacity() const { return mColor
.a
; }
4437 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
4439 return mBackgroundRect
;
4442 bool CanPaintWithClip(const DisplayItemClip
& aClip
) override
{
4443 if (HasBackgroundClipText()) {
4447 if (aClip
.GetRoundedRectCount() > 1) {
4454 nsDisplayItemGeometry
* AllocateGeometry(
4455 nsDisplayListBuilder
* aBuilder
) override
{
4456 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
.ToABGR());
4459 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4460 const nsDisplayItemGeometry
* aGeometry
,
4461 nsRegion
* aInvalidRegion
) const override
{
4462 const nsDisplaySolidColorGeometry
* geometry
=
4463 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
4465 if (mColor
.ToABGR() != geometry
->mColor
) {
4467 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
4470 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
4473 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4475 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4476 if (!aBuilder
->IsRetainingDisplayList() || mDependentFrame
== aFrame
) {
4479 mDependentFrame
= aFrame
;
4481 mDependentFrame
->AddDisplayItem(this);
4485 void RemoveFrame(nsIFrame
* aFrame
) override
{
4486 if (aFrame
== mDependentFrame
) {
4487 mDependentFrame
= nullptr;
4490 nsPaintedDisplayItem::RemoveFrame(aFrame
);
4493 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4495 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
4498 const nsRect mBackgroundRect
;
4499 const bool mHasStyle
;
4500 StyleGeometryBox mBottomLayerClip
;
4501 nsIFrame
* mDependentFrame
;
4502 gfx::sRGBColor mColor
;
4505 class nsDisplayTableBackgroundColor
: public nsDisplayBackgroundColor
{
4507 nsDisplayTableBackgroundColor(nsDisplayListBuilder
* aBuilder
,
4508 nsIFrame
* aFrame
, const nsRect
& aBackgroundRect
,
4509 const ComputedStyle
* aBackgroundStyle
,
4510 const nscolor
& aColor
, nsIFrame
* aAncestorFrame
)
4511 : nsDisplayBackgroundColor(aBuilder
, aFrame
, aBackgroundRect
,
4512 aBackgroundStyle
, aColor
),
4513 mAncestorFrame(aAncestorFrame
) {
4514 if (aBuilder
->IsRetainingDisplayList()) {
4515 mAncestorFrame
->AddDisplayItem(this);
4519 ~nsDisplayTableBackgroundColor() override
{
4520 if (mAncestorFrame
) {
4521 mAncestorFrame
->RemoveDisplayItem(this);
4525 NS_DISPLAY_DECL_NAME("TableBackgroundColor", TYPE_TABLE_BACKGROUND_COLOR
)
4527 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4529 void RemoveFrame(nsIFrame
* aFrame
) override
{
4530 if (aFrame
== mAncestorFrame
) {
4531 mAncestorFrame
= nullptr;
4534 nsDisplayBackgroundColor::RemoveFrame(aFrame
);
4537 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
{
4542 nsIFrame
* mAncestorFrame
;
4546 * The standard display item to paint the outer CSS box-shadows of a frame.
4548 class nsDisplayBoxShadowOuter final
: public nsPaintedDisplayItem
{
4550 nsDisplayBoxShadowOuter(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4551 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4552 MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter
);
4553 mBounds
= GetBoundsInternal();
4556 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowOuter
)
4558 NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER
)
4560 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4561 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4562 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
4563 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4564 const nsDisplayItemGeometry
* aGeometry
,
4565 nsRegion
* aInvalidRegion
) const override
;
4567 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
4568 nsDisplayListBuilder
* aBuilder
) const override
{
4569 return CanBuildWebRenderDisplayItems();
4572 bool CanBuildWebRenderDisplayItems() const;
4573 bool CreateWebRenderCommands(
4574 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4575 const StackingContextHelper
& aSc
,
4576 layers::RenderRootStateManager
* aManager
,
4577 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4578 nsRect
GetBoundsInternal();
4585 * The standard display item to paint the inner CSS box-shadows of a frame.
4587 class nsDisplayBoxShadowInner
: public nsPaintedDisplayItem
{
4589 nsDisplayBoxShadowInner(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4590 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4591 MOZ_COUNT_CTOR(nsDisplayBoxShadowInner
);
4594 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowInner
)
4596 NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER
)
4598 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4600 nsDisplayItemGeometry
* AllocateGeometry(
4601 nsDisplayListBuilder
* aBuilder
) override
{
4602 return new nsDisplayBoxShadowInnerGeometry(this, aBuilder
);
4605 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4606 const nsDisplayItemGeometry
* aGeometry
,
4607 nsRegion
* aInvalidRegion
) const override
{
4608 const nsDisplayBoxShadowInnerGeometry
* geometry
=
4609 static_cast<const nsDisplayBoxShadowInnerGeometry
*>(aGeometry
);
4610 if (!geometry
->mPaddingRect
.IsEqualInterior(GetPaddingRect())) {
4611 // nsDisplayBoxShadowInner is based around the padding rect, but it can
4612 // touch pixels outside of this. We should invalidate the entire bounds.
4614 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &snap
));
4618 static bool CanCreateWebRenderCommands(nsDisplayListBuilder
* aBuilder
,
4620 const nsPoint
& aReferenceOffset
);
4621 static void CreateInsetBoxShadowWebRenderCommands(
4622 wr::DisplayListBuilder
& aBuilder
, const StackingContextHelper
& aSc
,
4623 nsRect
& aVisibleRect
, nsIFrame
* aFrame
, const nsRect
& aBorderRect
);
4624 bool CreateWebRenderCommands(
4625 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4626 const StackingContextHelper
& aSc
,
4627 layers::RenderRootStateManager
* aManager
,
4628 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4632 * The standard display item to paint the CSS outline of a frame.
4634 class nsDisplayOutline final
: public nsPaintedDisplayItem
{
4636 nsDisplayOutline(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4637 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
4638 MOZ_COUNT_CTOR(nsDisplayOutline
);
4641 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOutline
)
4643 NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE
)
4645 bool ShouldUseBlobRenderingForFallback() const override
{
4646 MOZ_ASSERT(IsThemedOutline(),
4647 "The only fallback path we have is for themed outlines");
4648 return !XRE_IsParentProcess();
4651 bool CreateWebRenderCommands(
4652 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4653 const StackingContextHelper
& aSc
,
4654 layers::RenderRootStateManager
* aManager
,
4655 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4656 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
4657 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4658 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4661 nsRect
GetInnerRect() const;
4662 bool IsThemedOutline() const;
4663 bool HasRadius() const;
4667 * A class that lets you receive events within the frame bounds but never
4670 class nsDisplayEventReceiver final
: public nsDisplayItem
{
4672 nsDisplayEventReceiver(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4673 : nsDisplayItem(aBuilder
, aFrame
) {
4674 MOZ_COUNT_CTOR(nsDisplayEventReceiver
);
4677 MOZ_COUNTED_DTOR_FINAL(nsDisplayEventReceiver
)
4679 NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER
)
4681 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4682 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
;
4686 * Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
4687 * this gets built when we're doing widget painting and we need to send the
4688 * compositor some hit-test info for a frame. This is effectively a dummy item
4689 * whose sole purpose is to carry the hit-test info to the compositor.
4691 class nsDisplayCompositorHitTestInfo final
: public nsDisplayItem
{
4693 nsDisplayCompositorHitTestInfo(nsDisplayListBuilder
* aBuilder
,
4695 : nsDisplayItem(aBuilder
, aFrame
) {
4696 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
4697 mHitTestInfo
.Initialize(aBuilder
, aFrame
);
4698 SetHasHitTestInfo();
4701 nsDisplayCompositorHitTestInfo(
4702 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, const nsRect
& aArea
,
4703 const gfx::CompositorHitTestInfo
& aHitTestFlags
)
4704 : nsDisplayItem(aBuilder
, aFrame
) {
4705 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
4706 mHitTestInfo
.SetAreaAndInfo(aArea
, aHitTestFlags
);
4707 mHitTestInfo
.InitializeScrollTarget(aBuilder
);
4708 SetHasHitTestInfo();
4711 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo
)
4713 NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO
)
4715 bool CreateWebRenderCommands(
4716 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4717 const StackingContextHelper
& aSc
,
4718 layers::RenderRootStateManager
* aManager
,
4719 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4721 bool isInvisible() const { return true; }
4723 int32_t ZIndex() const override
;
4724 void SetOverrideZIndex(int32_t aZIndex
);
4726 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
4731 const HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
4734 HitTestInfo mHitTestInfo
;
4735 Maybe
<int32_t> mOverrideZIndex
;
4738 class nsDisplayWrapper
;
4741 * A class that lets you wrap a display list as a display item.
4743 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
4744 * list has many items, it's not clear which one has the 'underlying frame'.
4745 * Thus we force the creator to specify what the underlying frame is. The
4746 * underlying frame should be the root of a stacking context, because sorting
4747 * a list containing this item will not get at the children.
4749 * In some cases (e.g., clipping) we want to wrap a list but we don't have a
4750 * particular underlying frame that is a stacking context root. In that case
4751 * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
4752 * detect and handle this case.
4754 class nsDisplayWrapList
: public nsPaintedDisplayItem
{
4757 * Takes all the items from aList and puts them in our list.
4759 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4760 nsDisplayList
* aList
);
4762 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4763 nsDisplayItem
* aItem
);
4765 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4766 nsDisplayList
* aList
,
4767 const ActiveScrolledRoot
* aActiveScrolledRoot
,
4768 bool aClearClipChain
= false);
4770 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4771 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4773 mFrameActiveScrolledRoot(aBuilder
->CurrentActiveScrolledRoot()),
4775 mHasZIndexOverride(false) {
4776 MOZ_COUNT_CTOR(nsDisplayWrapList
);
4777 mBaseBuildingRect
= GetBuildingRect();
4779 mOriginalClipChain
= mClipChain
;
4782 nsDisplayWrapList() = delete;
4785 * A custom copy-constructor that does not copy mList, as this would mutate
4788 nsDisplayWrapList(const nsDisplayWrapList
& aOther
) = delete;
4789 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
,
4790 const nsDisplayWrapList
& aOther
)
4791 : nsPaintedDisplayItem(aBuilder
, aOther
),
4794 mFrameActiveScrolledRoot(aOther
.mFrameActiveScrolledRoot
),
4795 mMergedFrames(aOther
.mMergedFrames
.Clone()),
4796 mBounds(aOther
.mBounds
),
4797 mBaseBuildingRect(aOther
.mBaseBuildingRect
),
4798 mOriginalClipChain(aOther
.mClipChain
),
4799 mOverrideZIndex(aOther
.mOverrideZIndex
),
4800 mHasZIndexOverride(aOther
.mHasZIndexOverride
),
4801 mClearingClipChain(aOther
.mClearingClipChain
) {
4802 MOZ_COUNT_CTOR(nsDisplayWrapList
);
4805 ~nsDisplayWrapList() override
;
4807 const nsDisplayWrapList
* AsDisplayWrapList() const final
{ return this; }
4808 nsDisplayWrapList
* AsDisplayWrapList() final
{ return this; }
4810 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4811 mList
.DeleteAll(aBuilder
);
4812 nsPaintedDisplayItem::Destroy(aBuilder
);
4816 * Creates a new nsDisplayWrapper that holds a pointer to the display list
4817 * owned by the given nsDisplayItem.
4819 nsDisplayWrapper
* CreateShallowCopy(nsDisplayListBuilder
* aBuilder
);
4822 * Call this if the wrapped list is changed.
4824 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
{
4825 // Clear the clip chain up to the asr, but don't store it, so that we'll
4826 // recover it when we reuse the item.
4827 if (mClearingClipChain
) {
4828 const DisplayItemClipChain
* clip
= mOriginalClipChain
;
4829 while (clip
&& ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(),
4831 clip
= clip
->mParent
;
4833 SetClipChain(clip
, false);
4836 nsRect buildingRect
;
4837 mBounds
= mListPtr
->GetClippedBoundsWithRespectToASR(
4838 aBuilder
, mActiveScrolledRoot
, &buildingRect
);
4839 // The display list may contain content that's visible outside the visible
4840 // rect (i.e. the current dirty rect) passed in when the item was created.
4841 // This happens when the dirty rect has been restricted to the visual
4842 // overflow rect of a frame for some reason (e.g. when setting up dirty
4843 // rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
4844 // frame contains placeholders for out-of-flows that aren't descendants of
4846 buildingRect
.UnionRect(mBaseBuildingRect
, buildingRect
);
4847 SetBuildingRect(buildingRect
);
4850 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
4851 bool aStore
) override
{
4852 nsDisplayItem::SetClipChain(aClipChain
, aStore
);
4855 mOriginalClipChain
= mClipChain
;
4859 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4860 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4861 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4862 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4863 bool* aSnap
) const override
;
4864 Maybe
<nscolor
> IsUniform(nsDisplayListBuilder
* aBuilder
) const override
;
4867 * Try to merge with the other item (which is below us in the display
4868 * list). This gets used by nsDisplayClip to coalesce clipping operations
4869 * (optimization), by nsDisplayOpacity to merge rendering for the same
4870 * content element into a single opacity group (correctness), and will be
4871 * used by nsDisplayOutline to merge multiple outlines for the same element
4872 * (also for correctness).
4874 virtual void Merge(const nsDisplayItem
* aItem
) {
4875 MOZ_ASSERT(CanMerge(aItem
));
4876 MOZ_ASSERT(Frame() != aItem
->Frame());
4877 MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList
*>(aItem
));
4881 * Returns the underlying frames of all display items that have been
4882 * merged into this one (excluding this item's own underlying frame)
4885 const nsTArray
<nsIFrame
*>& GetMergedFrames() const { return mMergedFrames
; }
4887 bool HasMergedFrames() const { return !mMergedFrames
.IsEmpty(); }
4889 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
4893 bool IsInvalid(nsRect
& aRect
) const override
{
4894 if (mFrame
->IsInvalid(aRect
) && aRect
.IsEmpty()) {
4898 for (uint32_t i
= 0; i
< mMergedFrames
.Length(); i
++) {
4899 if (mMergedFrames
[i
]->IsInvalid(temp
) && temp
.IsEmpty()) {
4903 aRect
= aRect
.Union(temp
);
4905 aRect
+= ToReferenceFrame();
4906 return !aRect
.IsEmpty();
4909 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
4911 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
4915 RetainedDisplayList
* GetChildren() const override
{ return mListPtr
; }
4917 int32_t ZIndex() const override
{
4918 return (mHasZIndexOverride
) ? mOverrideZIndex
4919 : nsPaintedDisplayItem::ZIndex();
4922 void SetOverrideZIndex(int32_t aZIndex
) {
4923 mHasZIndexOverride
= true;
4924 mOverrideZIndex
= aZIndex
;
4928 * This creates a copy of this item, but wrapping aItem instead of
4929 * our existing list. Only gets called if this item returned nullptr
4930 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
4931 * GetUnderlyingFrame().
4933 nsDisplayWrapList
* WrapWithClone(nsDisplayListBuilder
* aBuilder
,
4934 nsDisplayItem
* aItem
) {
4935 MOZ_ASSERT_UNREACHABLE("We never returned nullptr for GetUnderlyingFrame!");
4939 bool CreateWebRenderCommands(
4940 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4941 const StackingContextHelper
& aSc
,
4942 layers::RenderRootStateManager
* aManager
,
4943 nsDisplayListBuilder
* aDisplayListBuilder
) override
{
4944 return CreateWebRenderCommandsNewClipListOption(
4945 aBuilder
, aResources
, aSc
, aManager
, aDisplayListBuilder
, true);
4948 // Same as the above but with the option to pass the aNewClipList argument to
4949 // WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList.
4950 bool CreateWebRenderCommandsNewClipListOption(
4951 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
4952 const StackingContextHelper
& aSc
,
4953 layers::RenderRootStateManager
* aManager
,
4954 nsDisplayListBuilder
* aDisplayListBuilder
, bool aNewClipList
);
4956 const ActiveScrolledRoot
* GetFrameActiveScrolledRoot() {
4957 return mFrameActiveScrolledRoot
;
4961 void MergeFromTrackingMergedFrames(const nsDisplayWrapList
* aOther
) {
4962 mBounds
.UnionRect(mBounds
, aOther
->mBounds
);
4963 nsRect buildingRect
;
4964 buildingRect
.UnionRect(GetBuildingRect(), aOther
->GetBuildingRect());
4965 SetBuildingRect(buildingRect
);
4966 mMergedFrames
.AppendElement(aOther
->mFrame
);
4967 mMergedFrames
.AppendElements(aOther
->mMergedFrames
.Clone());
4970 RetainedDisplayList mList
;
4971 RetainedDisplayList
* mListPtr
;
4972 // The active scrolled root for the frame that created this
4974 RefPtr
<const ActiveScrolledRoot
> mFrameActiveScrolledRoot
;
4975 // The frames from items that have been merged into this item, excluding
4976 // this item's own frame.
4977 nsTArray
<nsIFrame
*> mMergedFrames
;
4979 // Displaylist building rect contributed by this display item itself.
4980 // Our mBuildingRect may include the visible areas of children.
4981 nsRect mBaseBuildingRect
;
4982 RefPtr
<const DisplayItemClipChain
> mOriginalClipChain
;
4983 int32_t mOverrideZIndex
;
4984 bool mHasZIndexOverride
;
4985 bool mClearingClipChain
= false;
4988 class nsDisplayWrapper
: public nsDisplayWrapList
{
4990 NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST
)
4992 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4993 nsDisplayList
* aList
,
4994 const ActiveScrolledRoot
* aActiveScrolledRoot
,
4995 bool aClearClipChain
= false)
4996 : nsDisplayWrapList(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
4999 nsDisplayWrapper(const nsDisplayWrapper
& aOther
) = delete;
5000 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
,
5001 const nsDisplayWrapList
& aOther
)
5002 : nsDisplayWrapList(aBuilder
, aOther
) {}
5004 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5007 NS_DISPLAY_ALLOW_CLONING()
5008 friend class nsDisplayListBuilder
;
5009 friend class nsDisplayWrapList
;
5013 * We call WrapDisplayList on the in-flow lists: BorderBackground(),
5014 * BlockBorderBackgrounds() and Content().
5015 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
5016 * and Floats(). This is done to support special wrapping processing for frames
5017 * that may not be in-flow descendants of the current frame.
5019 class nsDisplayItemWrapper
{
5021 // This is never instantiated directly (it has pure virtual methods), so no
5022 // need to count constructors and destructors.
5024 bool WrapBorderBackground() { return true; }
5025 virtual nsDisplayItem
* WrapList(nsDisplayListBuilder
* aBuilder
,
5026 nsIFrame
* aFrame
, nsDisplayList
* aList
) = 0;
5027 virtual nsDisplayItem
* WrapItem(nsDisplayListBuilder
* aBuilder
,
5028 nsDisplayItem
* aItem
) = 0;
5030 nsresult
WrapLists(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5031 const nsDisplayListSet
& aIn
, const nsDisplayListSet
& aOut
);
5032 nsresult
WrapListsInPlace(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5033 const nsDisplayListSet
& aLists
);
5036 nsDisplayItemWrapper() = default;
5040 * The standard display item to paint a stacking context with translucency
5041 * set by the stacking context root frame's 'opacity' style.
5043 class nsDisplayOpacity
: public nsDisplayWrapList
{
5045 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5046 nsDisplayList
* aList
,
5047 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5048 bool aForEventsOnly
, bool aNeedsActiveLayer
,
5049 bool aWrapsBackdropFilter
);
5051 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
,
5052 const nsDisplayOpacity
& aOther
)
5053 : nsDisplayWrapList(aBuilder
, aOther
),
5054 mOpacity(aOther
.mOpacity
),
5055 mForEventsOnly(aOther
.mForEventsOnly
),
5056 mNeedsActiveLayer(aOther
.mNeedsActiveLayer
),
5057 mChildOpacityState(ChildOpacityState::Unknown
),
5058 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
5059 MOZ_COUNT_CTOR(nsDisplayOpacity
);
5060 // We should not try to merge flattened opacities.
5061 MOZ_ASSERT(aOther
.mChildOpacityState
!= ChildOpacityState::Applied
);
5064 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5065 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5067 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOpacity
)
5069 NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY
)
5071 void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) override
{
5072 mChildOpacityState
= ChildOpacityState::Unknown
;
5075 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5076 bool* aSnap
) const override
;
5077 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5079 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5080 // items for the same content element should be merged into a single
5081 // compositing group
5082 // aItem->GetUnderlyingFrame() returns non-null because it's
5084 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5085 HasSameContent(aItem
);
5088 nsDisplayItemGeometry
* AllocateGeometry(
5089 nsDisplayListBuilder
* aBuilder
) override
{
5090 return new nsDisplayOpacityGeometry(this, aBuilder
, mOpacity
);
5093 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5094 const nsDisplayItemGeometry
* aGeometry
,
5095 nsRegion
* aInvalidRegion
) const override
;
5097 bool IsInvalid(nsRect
& aRect
) const override
{
5098 if (mForEventsOnly
) {
5101 return nsDisplayWrapList::IsInvalid(aRect
);
5103 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
5104 nsDisplayListBuilder
* aBuilder
) const override
;
5105 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5109 bool CanApplyOpacityToChildren(WebRenderLayerManager
* aManager
,
5110 nsDisplayListBuilder
* aBuilder
,
5111 float aInheritedOpacity
);
5113 bool NeedsGeometryUpdates() const override
{
5114 // For flattened nsDisplayOpacity items, ComputeInvalidationRegion() only
5115 // handles invalidation for changed |mOpacity|. In order to keep track of
5116 // the current bounds of the item for invalidation, nsDisplayOpacityGeometry
5117 // for the corresponding DisplayItemData needs to be updated, even if the
5118 // reported invalidation region is empty.
5119 return mChildOpacityState
== ChildOpacityState::Deferred
;
5123 * Returns true if ShouldFlattenAway() applied opacity to children.
5125 bool OpacityAppliedToChildren() const {
5126 return mChildOpacityState
== ChildOpacityState::Applied
;
5129 static bool NeedsActiveLayer(nsDisplayListBuilder
* aBuilder
,
5131 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5132 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
5133 bool CreateWebRenderCommands(
5134 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5135 const StackingContextHelper
& aSc
,
5136 layers::RenderRootStateManager
* aManager
,
5137 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5139 float GetOpacity() const { return mOpacity
; }
5141 bool CreatesStackingContextHelper() override
{ return true; }
5144 NS_DISPLAY_ALLOW_CLONING()
5146 bool CanApplyToChildren(WebRenderLayerManager
* aManager
,
5147 nsDisplayListBuilder
* aBuilder
);
5151 bool mForEventsOnly
: 1;
5152 enum class ChildOpacityState
: uint8_t {
5153 // Our child list has changed since the last time ApplyToChildren was
5156 // Our children defer opacity handling to us.
5158 // Opacity is applied to our children.
5161 bool mNeedsActiveLayer
: 1;
5163 ChildOpacityState mChildOpacityState
: 2;
5165 ChildOpacityState mChildOpacityState
;
5167 bool mWrapsBackdropFilter
;
5170 class nsDisplayBlendMode
: public nsDisplayWrapList
{
5172 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5173 nsDisplayList
* aList
, StyleBlend aBlendMode
,
5174 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5175 const bool aIsForBackground
);
5176 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
,
5177 const nsDisplayBlendMode
& aOther
)
5178 : nsDisplayWrapList(aBuilder
, aOther
),
5179 mBlendMode(aOther
.mBlendMode
),
5180 mIsForBackground(aOther
.mIsForBackground
) {
5181 MOZ_COUNT_CTOR(nsDisplayBlendMode
);
5184 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendMode
)
5186 NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE
)
5188 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5189 bool* aSnap
) const override
;
5190 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5191 const nsDisplayItemGeometry
* aGeometry
,
5192 nsRegion
* aInvalidRegion
) const override
{
5193 // We don't need to compute an invalidation region since we have
5194 // LayerTreeInvalidation
5197 bool CreateWebRenderCommands(
5198 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5199 const StackingContextHelper
& aSc
,
5200 layers::RenderRootStateManager
* aManager
,
5201 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5202 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5204 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
5206 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5210 gfx::CompositionOp
BlendMode();
5212 bool CreatesStackingContextHelper() override
{ return true; }
5215 StyleBlend mBlendMode
;
5216 bool mIsForBackground
;
5219 NS_DISPLAY_ALLOW_CLONING()
5222 class nsDisplayTableBlendMode
: public nsDisplayBlendMode
{
5224 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5225 nsDisplayList
* aList
, StyleBlend aBlendMode
,
5226 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5227 nsIFrame
* aAncestorFrame
, const bool aIsForBackground
)
5228 : nsDisplayBlendMode(aBuilder
, aFrame
, aList
, aBlendMode
,
5229 aActiveScrolledRoot
, aIsForBackground
),
5230 mAncestorFrame(aAncestorFrame
) {
5231 if (aBuilder
->IsRetainingDisplayList()) {
5232 mAncestorFrame
->AddDisplayItem(this);
5236 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
,
5237 const nsDisplayTableBlendMode
& aOther
)
5238 : nsDisplayBlendMode(aBuilder
, aOther
),
5239 mAncestorFrame(aOther
.mAncestorFrame
) {
5240 if (aBuilder
->IsRetainingDisplayList()) {
5241 mAncestorFrame
->AddDisplayItem(this);
5245 ~nsDisplayTableBlendMode() override
{
5246 if (mAncestorFrame
) {
5247 mAncestorFrame
->RemoveDisplayItem(this);
5251 NS_DISPLAY_DECL_NAME("TableBlendMode", TYPE_TABLE_BLEND_MODE
)
5253 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5255 void RemoveFrame(nsIFrame
* aFrame
) override
{
5256 if (aFrame
== mAncestorFrame
) {
5257 mAncestorFrame
= nullptr;
5260 nsDisplayBlendMode::RemoveFrame(aFrame
);
5264 nsIFrame
* mAncestorFrame
;
5267 NS_DISPLAY_ALLOW_CLONING()
5270 class nsDisplayBlendContainer
: public nsDisplayWrapList
{
5272 static nsDisplayBlendContainer
* CreateForMixBlendMode(
5273 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5274 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5276 static nsDisplayBlendContainer
* CreateForBackgroundBlendMode(
5277 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5278 nsIFrame
* aSecondaryFrame
, nsDisplayList
* aList
,
5279 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5281 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendContainer
)
5283 NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER
)
5285 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5286 bool CreateWebRenderCommands(
5287 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5288 const StackingContextHelper
& aSc
,
5289 layers::RenderRootStateManager
* aManager
,
5290 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5292 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5293 // Items for the same content element should be merged into a single
5294 // compositing group.
5295 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5296 HasSameContent(aItem
) &&
5298 static_cast<const nsDisplayBlendContainer
*>(aItem
)
5302 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5306 bool CreatesStackingContextHelper() override
{ return true; }
5309 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5310 nsDisplayList
* aList
,
5311 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5312 bool aIsForBackground
);
5313 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
,
5314 const nsDisplayBlendContainer
& aOther
)
5315 : nsDisplayWrapList(aBuilder
, aOther
),
5316 mIsForBackground(aOther
.mIsForBackground
) {
5317 MOZ_COUNT_CTOR(nsDisplayBlendContainer
);
5320 // Used to distinguish containers created at building stacking
5321 // context or appending background.
5322 bool mIsForBackground
;
5325 NS_DISPLAY_ALLOW_CLONING()
5328 class nsDisplayTableBlendContainer
: public nsDisplayBlendContainer
{
5330 NS_DISPLAY_DECL_NAME("TableBlendContainer", TYPE_TABLE_BLEND_CONTAINER
)
5332 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5334 void RemoveFrame(nsIFrame
* aFrame
) override
{
5335 if (aFrame
== mAncestorFrame
) {
5336 mAncestorFrame
= nullptr;
5339 nsDisplayBlendContainer::RemoveFrame(aFrame
);
5343 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5344 nsDisplayList
* aList
,
5345 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5346 bool aIsForBackground
, nsIFrame
* aAncestorFrame
)
5347 : nsDisplayBlendContainer(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5349 mAncestorFrame(aAncestorFrame
) {
5350 if (aBuilder
->IsRetainingDisplayList()) {
5351 mAncestorFrame
->AddDisplayItem(this);
5355 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
,
5356 const nsDisplayTableBlendContainer
& aOther
)
5357 : nsDisplayBlendContainer(aBuilder
, aOther
),
5358 mAncestorFrame(aOther
.mAncestorFrame
) {}
5360 ~nsDisplayTableBlendContainer() override
{
5361 if (mAncestorFrame
) {
5362 mAncestorFrame
->RemoveDisplayItem(this);
5366 nsIFrame
* mAncestorFrame
;
5369 NS_DISPLAY_ALLOW_CLONING()
5373 * nsDisplayOwnLayer constructor flags. If we nest this class inside
5374 * nsDisplayOwnLayer then we can't forward-declare it up at the top of this
5375 * file and that makes it hard to use in all the places that we need to use it.
5377 enum class nsDisplayOwnLayerFlags
{
5379 GenerateSubdocInvalidations
= 1 << 0,
5380 GenerateScrollableLayer
= 1 << 1,
5383 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags
)
5386 * A display item that has no purpose but to ensure its contents get
5389 class nsDisplayOwnLayer
: public nsDisplayWrapList
{
5392 OwnLayerForTransformWithRoundedClip
,
5393 OwnLayerForStackingContext
,
5394 OwnLayerForScrollbar
,
5395 OwnLayerForScrollThumb
,
5401 * @param aFlags eGenerateSubdocInvalidations :
5402 * Add UserData to the created ContainerLayer, so that invalidations
5403 * for this layer are send to our nsPresContext.
5404 * eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and
5405 * subclasses), indicates this layer is to be a scrollable layer, so call
5406 * ComputeFrameMetrics, etc.
5407 * @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar
5408 * is set in the flags, this parameter should be the ViewID of the
5409 * scrollable content this scrollbar is for.
5412 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5413 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5414 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
,
5415 const layers::ScrollbarData
& aScrollbarData
= layers::ScrollbarData
{},
5416 bool aForceActive
= true, bool aClearClipChain
= false);
5418 nsDisplayOwnLayer(nsDisplayListBuilder
* aBuilder
,
5419 const nsDisplayOwnLayer
& aOther
)
5420 : nsDisplayWrapList(aBuilder
, aOther
),
5421 mFlags(aOther
.mFlags
),
5422 mScrollbarData(aOther
.mScrollbarData
),
5423 mForceActive(aOther
.mForceActive
),
5424 mWrAnimationId(aOther
.mWrAnimationId
) {
5425 MOZ_COUNT_CTOR(nsDisplayOwnLayer
);
5428 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOwnLayer
)
5430 NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER
)
5432 bool CreateWebRenderCommands(
5433 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5434 const StackingContextHelper
& aSc
,
5435 layers::RenderRootStateManager
* aManager
,
5436 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5437 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5438 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5439 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5440 GetChildren()->Paint(aBuilder
, aCtx
,
5441 mFrame
->PresContext()->AppUnitsPerDevPixel());
5444 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5445 // Don't allow merging, each sublist must have its own layer
5449 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5453 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5454 nsDisplayOwnLayerFlags
GetFlags() { return mFlags
; }
5455 bool IsScrollThumbLayer() const;
5456 bool IsScrollbarContainer() const;
5457 bool IsRootScrollbarContainer() const;
5458 bool IsScrollbarLayerForRoot() const;
5459 bool IsZoomingLayer() const;
5460 bool IsFixedPositionLayer() const;
5461 bool IsStickyPositionLayer() const;
5462 bool HasDynamicToolbar() const;
5463 bool ShouldFixedAndStickyContentGetAnimationIds() const;
5465 bool CreatesStackingContextHelper() override
{ return true; }
5468 nsDisplayOwnLayerFlags mFlags
;
5471 * If this nsDisplayOwnLayer represents a scroll thumb layer or a
5472 * scrollbar container layer, mScrollbarData stores information
5473 * about the scrollbar. Otherwise, mScrollbarData will be
5474 * default-constructed (in particular with mDirection == Nothing())
5475 * and can be ignored.
5477 layers::ScrollbarData mScrollbarData
;
5479 uint64_t mWrAnimationId
;
5483 * A display item for subdocuments. This is more or less the same as
5484 * nsDisplayOwnLayer, except that it always populates the FrameMetrics instance
5485 * on the ContainerLayer it builds.
5487 class nsDisplaySubDocument
: public nsDisplayOwnLayer
{
5489 nsDisplaySubDocument(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5490 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
5491 nsDisplayOwnLayerFlags aFlags
);
5492 ~nsDisplaySubDocument() override
;
5494 NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT
)
5496 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5498 virtual nsSubDocumentFrame
* SubDocumentFrame() { return mSubDocFrame
; }
5500 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5501 return mShouldFlatten
;
5504 void SetShouldFlattenAway(bool aShouldFlatten
) {
5505 mShouldFlatten
= aShouldFlatten
;
5508 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5509 bool* aSnap
) const override
;
5511 nsIFrame
* FrameForInvalidation() const override
;
5512 void RemoveFrame(nsIFrame
* aFrame
) override
;
5515 ViewID mScrollParentId
;
5516 bool mForceDispatchToContentRegion
{};
5517 bool mShouldFlatten
;
5518 nsSubDocumentFrame
* mSubDocFrame
;
5522 * A display item used to represent sticky position elements. The contents
5523 * gets its own layer and creates a stacking context, and the layer will have
5524 * position-related metadata set on it.
5526 class nsDisplayStickyPosition
: public nsDisplayOwnLayer
{
5528 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5529 nsDisplayList
* aList
,
5530 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5531 const ActiveScrolledRoot
* aContainerASR
,
5532 bool aClippedToDisplayPort
);
5533 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
,
5534 const nsDisplayStickyPosition
& aOther
)
5535 : nsDisplayOwnLayer(aBuilder
, aOther
),
5536 mContainerASR(aOther
.mContainerASR
),
5537 mClippedToDisplayPort(aOther
.mClippedToDisplayPort
),
5538 mShouldFlatten(false) {
5539 MOZ_COUNT_CTOR(nsDisplayStickyPosition
);
5542 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayStickyPosition
)
5544 const DisplayItemClip
& GetClip() const override
{
5545 return DisplayItemClip::NoClip();
5547 bool IsClippedToDisplayPort() const { return mClippedToDisplayPort
; }
5549 NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION
)
5550 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5551 GetChildren()->Paint(aBuilder
, aCtx
,
5552 mFrame
->PresContext()->AppUnitsPerDevPixel());
5555 bool CreateWebRenderCommands(
5556 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5557 const StackingContextHelper
& aSc
,
5558 layers::RenderRootStateManager
* aManager
,
5559 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5561 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5562 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5564 const ActiveScrolledRoot
* GetContainerASR() const { return mContainerASR
; }
5566 bool CreatesStackingContextHelper() override
{ return true; }
5568 bool CanMoveAsync() override
{ return true; }
5570 void SetShouldFlatten(bool aShouldFlatten
) {
5571 mShouldFlatten
= aShouldFlatten
;
5574 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) final
{
5575 return mShouldFlatten
;
5579 NS_DISPLAY_ALLOW_CLONING()
5581 void CalculateLayerScrollRanges(StickyScrollContainer
* aStickyScrollContainer
,
5582 float aAppUnitsPerDevPixel
, float aScaleX
,
5584 LayerRectAbsolute
& aStickyOuter
,
5585 LayerRectAbsolute
& aStickyInner
);
5587 StickyScrollContainer
* GetStickyScrollContainer();
5589 // This stores the ASR that this sticky container item would have assuming it
5590 // has no fixed descendants. This may be the same as the ASR returned by
5591 // GetActiveScrolledRoot(), or it may be a descendant of that.
5592 RefPtr
<const ActiveScrolledRoot
> mContainerASR
;
5593 // This flag tracks if this sticky item is just clipped to the enclosing
5594 // scrollframe's displayport, or if there are additional clips in play. In
5595 // the former case, we can skip setting the displayport clip as the scrolled-
5596 // clip of the corresponding layer. This allows sticky items to remain
5597 // unclipped when the enclosing scrollframe is scrolled past the displayport.
5598 // i.e. when the rest of the scrollframe checkerboards, the sticky item will
5599 // not. This makes sense to do because the sticky item has abnormal scrolling
5600 // behavior and may still be visible even if the rest of the scrollframe is
5601 // checkerboarded. Note that the sticky item will still be subject to the
5603 bool mClippedToDisplayPort
;
5605 // True if this item should be flattened away.
5606 bool mShouldFlatten
;
5609 class nsDisplayFixedPosition
: public nsDisplayOwnLayer
{
5611 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5612 nsDisplayList
* aList
,
5613 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5614 const ActiveScrolledRoot
* aScrollTargetASR
);
5615 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
,
5616 const nsDisplayFixedPosition
& aOther
)
5617 : nsDisplayOwnLayer(aBuilder
, aOther
),
5618 mScrollTargetASR(aOther
.mScrollTargetASR
),
5619 mIsFixedBackground(aOther
.mIsFixedBackground
) {
5620 MOZ_COUNT_CTOR(nsDisplayFixedPosition
);
5623 static nsDisplayFixedPosition
* CreateForFixedBackground(
5624 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5625 nsIFrame
* aSecondaryFrame
, nsDisplayBackgroundImage
* aImage
,
5626 const uint16_t aIndex
, const ActiveScrolledRoot
* aScrollTargetASR
);
5628 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFixedPosition
)
5630 NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION
)
5632 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5633 GetChildren()->Paint(aBuilder
, aCtx
,
5634 mFrame
->PresContext()->AppUnitsPerDevPixel());
5637 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
5638 return mIsFixedBackground
;
5641 bool CreateWebRenderCommands(
5642 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5643 const StackingContextHelper
& aSc
,
5644 layers::RenderRootStateManager
* aManager
,
5645 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5646 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5647 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5648 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5651 // For background-attachment:fixed
5652 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5653 nsDisplayList
* aList
,
5654 const ActiveScrolledRoot
* aScrollTargetASR
);
5655 ViewID
GetScrollTargetId();
5657 RefPtr
<const ActiveScrolledRoot
> mScrollTargetASR
;
5658 bool mIsFixedBackground
;
5661 NS_DISPLAY_ALLOW_CLONING()
5664 class nsDisplayTableFixedPosition
: public nsDisplayFixedPosition
{
5666 NS_DISPLAY_DECL_NAME("TableFixedPosition", TYPE_TABLE_FIXED_POSITION
)
5668 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5670 void RemoveFrame(nsIFrame
* aFrame
) override
{
5671 if (aFrame
== mAncestorFrame
) {
5672 mAncestorFrame
= nullptr;
5675 nsDisplayFixedPosition::RemoveFrame(aFrame
);
5679 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5680 nsDisplayList
* aList
, nsIFrame
* aAncestorFrame
,
5681 const ActiveScrolledRoot
* aScrollTargetASR
);
5683 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
,
5684 const nsDisplayTableFixedPosition
& aOther
)
5685 : nsDisplayFixedPosition(aBuilder
, aOther
),
5686 mAncestorFrame(aOther
.mAncestorFrame
) {}
5688 ~nsDisplayTableFixedPosition() override
{
5689 if (mAncestorFrame
) {
5690 mAncestorFrame
->RemoveDisplayItem(this);
5694 nsIFrame
* mAncestorFrame
;
5697 NS_DISPLAY_ALLOW_CLONING()
5701 * This creates an empty scrollable layer. It has no child layers.
5702 * It is used to record the existence of a scrollable frame in the layer
5705 class nsDisplayScrollInfoLayer
: public nsDisplayWrapList
{
5707 nsDisplayScrollInfoLayer(nsDisplayListBuilder
* aBuilder
,
5708 nsIFrame
* aScrolledFrame
, nsIFrame
* aScrollFrame
,
5709 const gfx::CompositorHitTestInfo
& aHitInfo
,
5710 const nsRect
& aHitArea
);
5712 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayScrollInfoLayer
)
5714 NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER
)
5716 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5717 bool* aSnap
) const override
{
5722 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5726 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5730 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5731 UniquePtr
<layers::ScrollMetadata
> ComputeScrollMetadata(
5732 nsDisplayListBuilder
* aBuilder
,
5733 layers::WebRenderLayerManager
* aLayerManager
);
5734 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5735 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5736 bool CreateWebRenderCommands(
5737 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5738 const StackingContextHelper
& aSc
,
5739 layers::RenderRootStateManager
* aManager
,
5740 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5743 nsIFrame
* mScrollFrame
;
5744 nsIFrame
* mScrolledFrame
;
5745 ViewID mScrollParentId
;
5746 gfx::CompositorHitTestInfo mHitInfo
;
5751 * nsDisplayZoom is used for subdocuments that have a different full zoom than
5752 * their parent documents. This item creates a container layer.
5754 class nsDisplayZoom
: public nsDisplaySubDocument
{
5757 * @param aFrame is the root frame of the subdocument.
5758 * @param aList contains the display items for the subdocument.
5759 * @param aAPD is the app units per dev pixel ratio of the subdocument.
5760 * @param aParentAPD is the app units per dev pixel ratio of the parent
5762 * @param aFlags eGenerateSubdocInvalidations :
5763 * Add UserData to the created ContainerLayer, so that invalidations
5764 * for this layer are send to our nsPresContext.
5766 nsDisplayZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5767 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
5768 int32_t aAPD
, int32_t aParentAPD
,
5769 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
);
5771 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayZoom
)
5773 NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM
)
5775 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5776 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5777 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5778 // Get the app units per dev pixel ratio of the child document.
5779 int32_t GetChildAppUnitsPerDevPixel() { return mAPD
; }
5780 // Get the app units per dev pixel ratio of the parent document.
5781 int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD
; }
5784 int32_t mAPD
, mParentAPD
;
5788 * nsDisplayAsyncZoom is used for APZ zooming. It wraps the contents of the
5789 * root content document's scroll frame, including fixed position content. It
5790 * does not contain the scroll frame's scrollbars. It is clipped to the scroll
5791 * frame's scroll port clip. It is not scrolled; only its non-fixed contents
5792 * are scrolled. This item creates a container layer.
5794 class nsDisplayAsyncZoom
: public nsDisplayOwnLayer
{
5796 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5797 nsDisplayList
* aList
,
5798 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5799 layers::FrameMetrics::ViewID aViewID
);
5800 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
,
5801 const nsDisplayAsyncZoom
& aOther
)
5802 : nsDisplayOwnLayer(aBuilder
, aOther
), mViewID(aOther
.mViewID
) {
5803 MOZ_COUNT_CTOR(nsDisplayAsyncZoom
);
5806 #ifdef NS_BUILD_REFCNT_LOGGING
5807 virtual ~nsDisplayAsyncZoom();
5810 NS_DISPLAY_DECL_NAME("AsyncZoom", TYPE_ASYNC_ZOOM
)
5812 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5813 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5814 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
5815 layers::WebRenderLayerScrollData
* aLayerData
) override
;
5818 layers::FrameMetrics::ViewID mViewID
;
5822 * A base class for different effects types.
5824 class nsDisplayEffectsBase
: public nsDisplayWrapList
{
5826 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5827 nsDisplayList
* aList
,
5828 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5829 bool aClearClipChain
= false);
5830 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5831 nsDisplayList
* aList
);
5833 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
,
5834 const nsDisplayEffectsBase
& aOther
)
5835 : nsDisplayWrapList(aBuilder
, aOther
),
5836 mEffectsBounds(aOther
.mEffectsBounds
) {
5837 MOZ_COUNT_CTOR(nsDisplayEffectsBase
);
5840 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayEffectsBase
)
5842 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5843 bool* aSnap
) const override
;
5844 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5845 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5847 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5851 gfxRect
BBoxInUserSpace() const;
5852 gfxPoint
UserSpaceOffset() const;
5854 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5855 const nsDisplayItemGeometry
* aGeometry
,
5856 nsRegion
* aInvalidRegion
) const override
;
5859 bool ValidateSVGFrame();
5861 // relative to mFrame
5862 nsRect mEffectsBounds
;
5866 * A display item to paint a stacking context with 'mask' and 'clip-path'
5867 * effects set by the stacking context root frame's style. The 'mask' and
5868 * 'clip-path' properties may both contain multiple masks and clip paths,
5871 * Note that 'mask' and 'clip-path' may just contain CSS simple-images and CSS
5872 * basic shapes, respectively. That is, they don't necessarily reference
5873 * resources such as SVG 'mask' and 'clipPath' elements.
5875 class nsDisplayMasksAndClipPaths
: public nsDisplayEffectsBase
{
5877 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5878 nsDisplayList
* aList
,
5879 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5880 bool aWrapsBackdropFilter
);
5881 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
,
5882 const nsDisplayMasksAndClipPaths
& aOther
)
5883 : nsDisplayEffectsBase(aBuilder
, aOther
),
5884 mDestRects(aOther
.mDestRects
.Clone()),
5885 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
5886 MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths
);
5889 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayMasksAndClipPaths
)
5891 NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK
)
5893 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
5895 void Merge(const nsDisplayItem
* aItem
) override
{
5896 nsDisplayWrapList::Merge(aItem
);
5898 const nsDisplayMasksAndClipPaths
* other
=
5899 static_cast<const nsDisplayMasksAndClipPaths
*>(aItem
);
5900 mEffectsBounds
.UnionRect(
5902 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
5905 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5907 nsDisplayItemGeometry
* AllocateGeometry(
5908 nsDisplayListBuilder
* aBuilder
) override
{
5909 return new nsDisplayMasksAndClipPathsGeometry(this, aBuilder
);
5912 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5913 const nsDisplayItemGeometry
* aGeometry
,
5914 nsRegion
* aInvalidRegion
) const override
;
5915 #ifdef MOZ_DUMP_PAINTING
5916 void PrintEffects(nsACString
& aTo
);
5921 void PaintWithContentsPaintCallback(
5922 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
5923 const std::function
<void()>& aPaintChildren
);
5926 * Paint mask onto aMaskContext in mFrame's coordinate space and
5927 * return whether the mask layer was painted successfully.
5929 bool PaintMask(nsDisplayListBuilder
* aBuilder
, gfxContext
* aMaskContext
,
5930 bool aHandleOpacity
, bool* aMaskPainted
= nullptr);
5932 const nsTArray
<nsRect
>& GetDestRects() { return mDestRects
; }
5934 bool CreateWebRenderCommands(
5935 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5936 const StackingContextHelper
& aSc
,
5937 layers::RenderRootStateManager
* aManager
,
5938 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5940 Maybe
<nsRect
> GetClipWithRespectToASR(
5941 nsDisplayListBuilder
* aBuilder
,
5942 const ActiveScrolledRoot
* aASR
) const override
;
5944 bool CreatesStackingContextHelper() override
{ return true; }
5947 NS_DISPLAY_ALLOW_CLONING()
5949 nsTArray
<nsRect
> mDestRects
;
5950 bool mWrapsBackdropFilter
;
5953 class nsDisplayBackdropFilters
: public nsDisplayWrapList
{
5955 nsDisplayBackdropFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5956 nsDisplayList
* aList
, const nsRect
& aBackdropRect
,
5957 nsIFrame
* aStyleFrame
)
5958 : nsDisplayWrapList(aBuilder
, aFrame
, aList
),
5959 mStyle(aFrame
== aStyleFrame
? nullptr : aStyleFrame
->Style()),
5960 mBackdropRect(aBackdropRect
) {
5961 MOZ_COUNT_CTOR(nsDisplayBackdropFilters
);
5964 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropFilters
)
5966 NS_DISPLAY_DECL_NAME("BackdropFilter", TYPE_BACKDROP_FILTER
)
5968 bool CreateWebRenderCommands(
5969 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
5970 const StackingContextHelper
& aSc
,
5971 layers::RenderRootStateManager
* aManager
,
5972 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5973 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5975 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5976 return !aBuilder
->IsPaintingForWebRender();
5979 bool CreatesStackingContextHelper() override
{ return true; }
5981 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5984 RefPtr
<ComputedStyle
> mStyle
;
5985 nsRect mBackdropRect
;
5989 * A display item to paint a stacking context with filter effects set by the
5990 * stacking context root frame's style.
5992 * Note that the filters may just be simple CSS filter functions. That is,
5993 * they won't necessarily be references to SVG 'filter' elements.
5995 class nsDisplayFilters
: public nsDisplayEffectsBase
{
5997 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5998 nsDisplayList
* aList
, nsIFrame
* aStyleFrame
,
5999 bool aWrapsBackdropFilter
);
6001 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
,
6002 const nsDisplayFilters
& aOther
)
6003 : nsDisplayEffectsBase(aBuilder
, aOther
),
6004 mStyle(aOther
.mStyle
),
6005 mEffectsBounds(aOther
.mEffectsBounds
),
6006 mWrapsBackdropFilter(aOther
.mWrapsBackdropFilter
) {
6007 MOZ_COUNT_CTOR(nsDisplayFilters
);
6010 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFilters
)
6012 NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER
)
6014 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
6015 // Items for the same content element should be merged into a single
6016 // compositing group.
6017 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
6018 HasSameContent(aItem
);
6021 void Merge(const nsDisplayItem
* aItem
) override
{
6022 nsDisplayWrapList::Merge(aItem
);
6024 const nsDisplayFilters
* other
= static_cast<const nsDisplayFilters
*>(aItem
);
6025 mEffectsBounds
.UnionRect(
6027 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
6030 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6032 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
6034 return mEffectsBounds
+ ToReferenceFrame();
6037 nsDisplayItemGeometry
* AllocateGeometry(
6038 nsDisplayListBuilder
* aBuilder
) override
{
6039 return new nsDisplaySVGEffectGeometry(this, aBuilder
);
6042 #ifdef MOZ_DUMP_PAINTING
6043 void PrintEffects(nsACString
& aTo
);
6046 void PaintWithContentsPaintCallback(
6047 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6048 const std::function
<void(gfxContext
* aContext
)>& aPaintChildren
);
6050 bool CreateWebRenderCommands(
6051 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6052 const StackingContextHelper
& aSc
,
6053 layers::RenderRootStateManager
* aManager
,
6054 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6055 bool CanCreateWebRenderCommands() const;
6057 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
6058 nsDisplayListBuilder
* aBuilder
) const override
{
6059 return CanCreateWebRenderCommands();
6062 bool CreatesStackingContextHelper() override
{ return true; }
6065 NS_DISPLAY_ALLOW_CLONING()
6067 RefPtr
<ComputedStyle
> mStyle
;
6068 // relative to mFrame
6069 nsRect mEffectsBounds
;
6070 nsRect mVisibleRect
;
6071 bool mWrapsBackdropFilter
;
6074 /* A display item that applies a transformation to all of its descendant
6075 * elements. This wrapper should only be used if there is a transform applied
6076 * to the root element.
6078 * The reason that a "bounds" rect is involved in transform calculations is
6079 * because CSS-transforms allow percentage values for the x and y components
6080 * of <translation-value>s, where percentages are percentages of the element's
6083 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
6085 * INVARIANT: The wrapped frame is non-null.
6087 class nsDisplayTransform
: public nsPaintedDisplayItem
{
6088 using Matrix4x4
= gfx::Matrix4x4
;
6089 using Matrix4x4Flagged
= gfx::Matrix4x4Flagged
;
6090 using TransformReferenceBox
= nsStyleTransformMatrix::TransformReferenceBox
;
6093 enum class PrerenderDecision
: uint8_t { No
, Full
, Partial
};
6096 WithTransformGetter
,
6099 /* Constructor accepts a display list, empties it, and wraps it up. It also
6100 * ferries the underlying frame to the nsDisplayItem constructor.
6102 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6103 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
);
6105 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6106 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6107 PrerenderDecision aPrerenderDecision
);
6109 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6110 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6111 decltype(WithTransformGetter
));
6113 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayTransform
)
6115 NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM
)
6117 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
6120 * This function updates bounds for items with a frame establishing
6121 * 3D rendering context.
6123 void UpdateBoundsFor3D(nsDisplayListBuilder
* aBuilder
);
6125 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
;
6127 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
6128 GetChildren()->DeleteAll(aBuilder
);
6129 nsPaintedDisplayItem::Destroy(aBuilder
);
6132 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
6134 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
6136 nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
6137 bool* aSnap
) const override
{
6139 return mChildBounds
;
6142 const nsRect
& GetUntransformedPaintRect() const override
{
6143 return mChildrenBuildingRect
;
6146 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6148 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6149 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6150 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6151 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6152 bool* aSnap
) const override
;
6153 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6154 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6155 const Maybe
<gfx::Polygon
>& aPolygon
);
6156 bool CreateWebRenderCommands(
6157 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6158 const StackingContextHelper
& aSc
,
6159 layers::RenderRootStateManager
* aManager
,
6160 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6161 bool UpdateScrollData(layers::WebRenderScrollData
* aData
,
6162 layers::WebRenderLayerScrollData
* aLayerData
) override
;
6164 nsDisplayItemGeometry
* AllocateGeometry(
6165 nsDisplayListBuilder
* aBuilder
) override
{
6166 return new nsDisplayTransformGeometry(
6167 this, aBuilder
, GetTransformForRendering(),
6168 mFrame
->PresContext()->AppUnitsPerDevPixel());
6171 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6172 const nsDisplayItemGeometry
* aGeometry
,
6173 nsRegion
* aInvalidRegion
) const override
{
6174 const nsDisplayTransformGeometry
* geometry
=
6175 static_cast<const nsDisplayTransformGeometry
*>(aGeometry
);
6177 // This code is only called for flattened, inactive transform items.
6178 // Only check if the transform has changed. The bounds invalidation should
6179 // be handled by the children themselves.
6180 if (!geometry
->mTransform
.FuzzyEqual(GetTransformForRendering())) {
6182 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
6186 const nsIFrame
* ReferenceFrameForChildren() const override
{
6187 // If we were created using a transform-getter, then we don't
6188 // belong to a transformed frame, and aren't a reference frame
6189 // for our children.
6190 if (!mHasTransformGetter
) {
6193 return nsPaintedDisplayItem::ReferenceFrameForChildren();
6196 const nsRect
& GetBuildingRectForChildren() const override
{
6197 return mChildrenBuildingRect
;
6200 enum { INDEX_MAX
= UINT32_MAX
>> TYPE_BITS
};
6203 * We include the perspective matrix from our containing block for the
6204 * purposes of visibility calculations, but we exclude it from the transform
6205 * we set on the layer (for rendering), since there will be an
6206 * nsDisplayPerspective created for that.
6208 const Matrix4x4Flagged
& GetTransform() const;
6209 const Matrix4x4Flagged
& GetInverseTransform() const;
6211 bool ShouldSkipTransform(nsDisplayListBuilder
* aBuilder
) const;
6212 Matrix4x4
GetTransformForRendering(
6213 LayoutDevicePoint
* aOutOrigin
= nullptr) const;
6216 * Return the transform that is aggregation of all transform on the
6217 * preserves3d chain.
6219 const Matrix4x4
& GetAccumulatedPreserved3DTransform(
6220 nsDisplayListBuilder
* aBuilder
);
6222 float GetHitDepthAtPoint(nsDisplayListBuilder
* aBuilder
,
6223 const nsPoint
& aPoint
);
6225 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
6226 * space) and returns the smallest rectangle (in aFrame's coordinate space)
6227 * containing the transformed image of that rectangle. That is, it takes
6228 * the four corners of the rectangle, transforms them according to the
6229 * matrix associated with the specified frame, then returns the smallest
6230 * rectangle containing the four transformed points.
6232 * @param untransformedBounds The rectangle (in app units) to transform.
6233 * @param aFrame The frame whose transformation should be applied. This
6234 * function raises an assertion if aFrame is null or doesn't have a
6235 * transform applied to it.
6236 * @param aRefBox the reference box to use, which would usually be just
6237 * TransformReferemceBox(aFrame), but callers may override it if
6240 static nsRect
TransformRect(const nsRect
& aUntransformedBounds
,
6241 const nsIFrame
* aFrame
,
6242 TransformReferenceBox
& aRefBox
);
6244 /* UntransformRect is like TransformRect, except that it inverts the
6247 static bool UntransformRect(const nsRect
& aTransformedBounds
,
6248 const nsRect
& aChildBounds
,
6249 const nsIFrame
* aFrame
, nsRect
* aOutRect
);
6250 static bool UntransformRect(const nsRect
& aTransformedBounds
,
6251 const nsRect
& aChildBounds
,
6252 const Matrix4x4
& aMatrix
, float aAppUnitsPerPixel
,
6255 bool UntransformRect(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6256 nsRect
* aOutRect
) const;
6258 bool UntransformBuildingRect(nsDisplayListBuilder
* aBuilder
,
6259 nsRect
* aOutRect
) const {
6260 return UntransformRect(aBuilder
, GetBuildingRect(), aOutRect
);
6263 static gfx::Point3D
GetDeltaToTransformOrigin(const nsIFrame
* aFrame
,
6264 TransformReferenceBox
&,
6265 float aAppUnitsPerPixel
);
6268 * Returns true if aFrame has perspective applied from its containing
6270 * Returns the matrix to append to apply the persective (taking
6271 * perspective-origin into account), relative to aFrames coordinate
6273 * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
6276 static bool ComputePerspectiveMatrix(const nsIFrame
* aFrame
,
6277 float aAppUnitsPerPixel
,
6278 Matrix4x4
& aOutMatrix
);
6280 struct MOZ_STACK_CLASS FrameTransformProperties
{
6281 FrameTransformProperties(const nsIFrame
* aFrame
,
6282 TransformReferenceBox
& aRefBox
,
6283 float aAppUnitsPerPixel
);
6284 FrameTransformProperties(const StyleTranslate
& aTranslate
,
6285 const StyleRotate
& aRotate
,
6286 const StyleScale
& aScale
,
6287 const StyleTransform
& aTransform
,
6288 const Maybe
<ResolvedMotionPathData
>& aMotion
,
6289 const gfx::Point3D
& aToTransformOrigin
)
6291 mTranslate(aTranslate
),
6294 mTransform(aTransform
),
6296 mToTransformOrigin(aToTransformOrigin
) {}
6298 bool HasTransform() const {
6299 return !mTranslate
.IsNone() || !mRotate
.IsNone() || !mScale
.IsNone() ||
6300 !mTransform
.IsNone() || mMotion
.isSome();
6303 const nsIFrame
* mFrame
;
6304 const StyleTranslate
& mTranslate
;
6305 const StyleRotate
& mRotate
;
6306 const StyleScale
& mScale
;
6307 const StyleTransform
& mTransform
;
6308 const Maybe
<ResolvedMotionPathData
> mMotion
;
6309 const gfx::Point3D mToTransformOrigin
;
6313 * Given a frame with the transform property or an SVG transform,
6314 * returns the transformation matrix for that frame.
6316 * @param aFrame The frame to get the matrix from.
6317 * @param aOrigin Relative to which point this transform should be applied.
6318 * @param aAppUnitsPerPixel The number of app units per graphics unit.
6319 * @param aBoundsOverride [optional] If this is nullptr (the default), the
6320 * computation will use the value of TransformReferenceBox(aFrame).
6321 * Otherwise, it will use the value of aBoundsOverride. This is
6322 * mostly for internal use and in most cases you will not need to
6324 * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
6325 * by aOrigin. This translation is applied *before* the CSS transform.
6326 * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
6327 * include the transform of any ancestors participating in the same
6328 * 3d rendering context.
6329 * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
6330 * perspective transform from the containing block if applicable.
6333 OFFSET_BY_ORIGIN
= 1 << 0,
6334 INCLUDE_PRESERVE3D_ANCESTORS
= 1 << 1,
6335 INCLUDE_PERSPECTIVE
= 1 << 2,
6337 static constexpr uint32_t kTransformRectFlags
=
6338 INCLUDE_PERSPECTIVE
| OFFSET_BY_ORIGIN
| INCLUDE_PRESERVE3D_ANCESTORS
;
6339 static Matrix4x4
GetResultingTransformMatrix(const nsIFrame
* aFrame
,
6340 const nsPoint
& aOrigin
,
6341 float aAppUnitsPerPixel
,
6343 static Matrix4x4
GetResultingTransformMatrix(
6344 const FrameTransformProperties
& aProperties
, TransformReferenceBox
&,
6345 float aAppUnitsPerPixel
);
6347 struct PrerenderInfo
{
6348 bool CanUseAsyncAnimations() const {
6349 return mDecision
!= PrerenderDecision::No
&& mHasAnimations
;
6351 PrerenderDecision mDecision
= PrerenderDecision::No
;
6352 bool mHasAnimations
= true;
6355 * Decide whether we should prerender some or all of the contents of the
6356 * transformed frame even when it's not completely visible (yet).
6357 * Return PrerenderDecision::Full if the entire contents should be
6358 * prerendered, PrerenderDecision::Partial if some but not all of the
6359 * contents should be prerendered, or PrerenderDecision::No if only the
6360 * visible area should be rendered.
6361 * |mNoAffectDecisionInPreserve3D| is set if the prerender decision should not
6362 * affect the decision on other frames in the preserve 3d tree.
6363 * |aDirtyRect| is updated to the area that should be prerendered.
6365 static PrerenderInfo
ShouldPrerenderTransformedContent(
6366 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsRect
* aDirtyRect
);
6368 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
6370 bool MayBeAnimated(nsDisplayListBuilder
* aBuilder
) const;
6372 void WriteDebugInfo(std::stringstream
& aStream
) override
;
6374 bool CanMoveAsync() override
{
6375 return EffectCompositor::HasAnimationsForCompositor(
6376 mFrame
, DisplayItemType::TYPE_TRANSFORM
);
6380 * This item is an additional item as the boundary between parent
6381 * and child 3D rendering context.
6382 * \see nsIFrame::BuildDisplayListForStackingContext().
6384 bool IsTransformSeparator() const { return mIsTransformSeparator
; }
6386 * This item is the boundary between parent and child 3D rendering
6389 bool IsLeafOf3DContext() const {
6390 return (IsTransformSeparator() ||
6391 (!mFrame
->Extend3DContext() && Combines3DTransformWithAncestors()));
6394 * The backing frame of this item participates a 3D rendering
6397 bool IsParticipating3DContext() const {
6398 return mFrame
->Extend3DContext() || Combines3DTransformWithAncestors();
6401 bool IsPartialPrerender() const {
6402 return mPrerenderDecision
== PrerenderDecision::Partial
;
6406 * Mark this item as created together with `nsDisplayPerspective`.
6407 * \see nsIFrame::BuildDisplayListForStackingContext().
6409 void MarkWithAssociatedPerspective() { mHasAssociatedPerspective
= true; }
6411 void AddSizeOfExcludingThis(nsWindowSizes
&) const override
;
6413 bool CreatesStackingContextHelper() override
{ return true; }
6416 void ComputeBounds(nsDisplayListBuilder
* aBuilder
);
6417 nsRect
TransformUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
6418 const Matrix4x4Flagged
& aMatrix
) const;
6419 void UpdateUntransformedBounds(nsDisplayListBuilder
* aBuilder
);
6421 void SetReferenceFrameToAncestor(nsDisplayListBuilder
* aBuilder
);
6422 void Init(nsDisplayListBuilder
* aBuilder
, nsDisplayList
* aChildren
);
6424 static Matrix4x4
GetResultingTransformMatrixInternal(
6425 const FrameTransformProperties
& aProperties
,
6426 TransformReferenceBox
& aRefBox
, const nsPoint
& aOrigin
,
6427 float aAppUnitsPerPixel
, uint32_t aFlags
);
6429 void Collect3DTransformLeaves(nsDisplayListBuilder
* aBuilder
,
6430 nsTArray
<nsDisplayTransform
*>& aLeaves
);
6431 using TransformPolygon
= layers::BSPPolygon
<nsDisplayTransform
>;
6432 void CollectSorted3DTransformLeaves(nsDisplayListBuilder
* aBuilder
,
6433 nsTArray
<TransformPolygon
>& aLeaves
);
6435 mutable RetainedDisplayList mChildren
;
6436 mutable Maybe
<Matrix4x4Flagged
> mTransform
;
6437 mutable Maybe
<Matrix4x4Flagged
> mInverseTransform
;
6438 // Accumulated transform of ancestors on the preserves-3d chain.
6439 UniquePtr
<Matrix4x4
> mTransformPreserves3D
;
6440 nsRect mChildrenBuildingRect
;
6442 // The untransformed bounds of |mChildren|.
6443 nsRect mChildBounds
;
6444 // The transformed bounds of this display item.
6446 PrerenderDecision mPrerenderDecision
: 8;
6447 // This item is a separator between 3D rendering contexts, and
6448 // mTransform have been presetted by the constructor.
6449 // This also forces us not to extend the 3D context. Since we don't create a
6450 // transform item, a container layer, for every frame in a preserves3d
6451 // context, the transform items of a child preserves3d context may extend the
6452 // parent context unintendedly if the root of the child preserves3d context
6453 // doesn't create a transform item.
6454 bool mIsTransformSeparator
: 1;
6455 // True if we have a transform getter.
6456 bool mHasTransformGetter
: 1;
6457 // True if this item is created together with `nsDisplayPerspective`
6458 // from the same CSS stacking context.
6459 bool mHasAssociatedPerspective
: 1;
6462 /* A display item that applies a perspective transformation to a single
6463 * nsDisplayTransform child item. We keep this as a separate item since the
6464 * perspective-origin is relative to an ancestor of the transformed frame, and
6465 * APZ can scroll the child separately.
6467 class nsDisplayPerspective
: public nsPaintedDisplayItem
{
6469 nsDisplayPerspective(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6470 nsDisplayList
* aList
);
6471 ~nsDisplayPerspective() override
= default;
6473 NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE
)
6475 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
6476 mList
.DeleteAll(aBuilder
);
6477 nsPaintedDisplayItem::Destroy(aBuilder
);
6480 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6481 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
{
6482 return GetChildren()->HitTest(aBuilder
, aRect
, aState
, aOutFrames
);
6485 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
6487 return GetChildren()->GetClippedBoundsWithRespectToASR(aBuilder
,
6488 mActiveScrolledRoot
);
6491 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6492 const nsDisplayItemGeometry
* aGeometry
,
6493 nsRegion
* aInvalidRegion
) const override
{}
6495 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6496 bool* aSnap
) const override
;
6498 bool CreateWebRenderCommands(
6499 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6500 const StackingContextHelper
& aSc
,
6501 layers::RenderRootStateManager
* aManager
,
6502 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6504 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6506 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
6510 RetainedDisplayList
* GetChildren() const override
{ return &mList
; }
6512 nsRect
GetComponentAlphaBounds(
6513 nsDisplayListBuilder
* aBuilder
) const override
{
6514 return GetChildren()->GetComponentAlphaBounds(aBuilder
);
6517 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
{
6518 if (GetChildren()->GetTop()) {
6519 static_cast<nsDisplayTransform
*>(GetChildren()->GetTop())
6520 ->DoUpdateBoundsPreserves3D(aBuilder
);
6524 bool CreatesStackingContextHelper() override
{ return true; }
6527 mutable RetainedDisplayList mList
;
6530 class nsDisplayTextGeometry
;
6533 * This class adds basic support for limiting the rendering (in the inline axis
6534 * of the writing mode) to the part inside the specified edges.
6535 * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
6536 * of the frame's scrollable overflow rectangle and are the amount to suppress
6539 * Setting none, both or only one edge is allowed.
6540 * The values must be non-negative.
6541 * The default value for both edges is zero, which means everything is painted.
6543 class nsDisplayText final
: public nsPaintedDisplayItem
{
6545 nsDisplayText(nsDisplayListBuilder
* aBuilder
, nsTextFrame
* aFrame
);
6546 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayText
)
6548 NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT
)
6550 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const final
{
6555 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6556 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
{
6557 if (nsRect(ToReferenceFrame(), mFrame
->GetSize()).Intersects(aRect
)) {
6558 aOutFrames
->AppendElement(mFrame
);
6562 bool CreateWebRenderCommands(wr::DisplayListBuilder
& aBuilder
,
6563 wr::IpcResourceUpdateQueue
& aResources
,
6564 const StackingContextHelper
& aSc
,
6565 layers::RenderRootStateManager
* aManager
,
6566 nsDisplayListBuilder
* aDisplayListBuilder
) final
;
6567 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) final
;
6569 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const final
{
6570 if (gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()) {
6571 // On OS X, web authors can turn off subpixel text rendering using the
6572 // CSS property -moz-osx-font-smoothing. If they do that, we don't need
6573 // to use component alpha layers for the affected text.
6574 if (mFrame
->StyleFont()->mFont
.smoothing
== NS_FONT_SMOOTHING_GRAYSCALE
) {
6579 return GetBounds(aBuilder
, &snap
);
6582 nsDisplayItemGeometry
* AllocateGeometry(nsDisplayListBuilder
* aBuilder
) final
;
6584 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6585 const nsDisplayItemGeometry
* aGeometry
,
6586 nsRegion
* aInvalidRegion
) const final
;
6588 void RenderToContext(gfxContext
* aCtx
, nsDisplayListBuilder
* aBuilder
,
6589 const nsRect
& aVisibleRect
, float aOpacity
= 1.0f
,
6590 bool aIsRecording
= false);
6592 bool CanApplyOpacity(WebRenderLayerManager
* aManager
,
6593 nsDisplayListBuilder
* aBuilder
) const final
;
6595 void WriteDebugInfo(std::stringstream
& aStream
) final
;
6597 static nsDisplayText
* CheckCast(nsDisplayItem
* aItem
) {
6598 return (aItem
->GetType() == DisplayItemType::TYPE_TEXT
)
6599 ? static_cast<nsDisplayText
*>(aItem
)
6603 nscoord
& VisIStartEdge() { return mVisIStartEdge
; }
6604 nscoord
& VisIEndEdge() { return mVisIEndEdge
; }
6608 nsRect mVisibleRect
;
6610 // Lengths measured from the visual inline start and end sides
6611 // (i.e. left and right respectively in horizontal writing modes,
6612 // regardless of bidi directionality; top and bottom in vertical modes).
6613 nscoord mVisIStartEdge
;
6614 nscoord mVisIEndEdge
;
6618 * A display item that for webrender to handle SVG
6620 class nsDisplaySVGWrapper
: public nsDisplayWrapList
{
6622 nsDisplaySVGWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6623 nsDisplayList
* aList
);
6625 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySVGWrapper
)
6627 NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER
)
6629 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6630 GetChildren()->Paint(aBuilder
, aCtx
,
6631 mFrame
->PresContext()->AppUnitsPerDevPixel());
6633 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6634 bool CreateWebRenderCommands(
6635 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6636 const StackingContextHelper
& aSc
,
6637 layers::RenderRootStateManager
* aManager
,
6638 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6642 * A display item for webrender to handle SVG foreign object
6644 class nsDisplayForeignObject
: public nsDisplayWrapList
{
6646 nsDisplayForeignObject(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6647 nsDisplayList
* aList
);
6648 #ifdef NS_BUILD_REFCNT_LOGGING
6649 virtual ~nsDisplayForeignObject();
6652 NS_DISPLAY_DECL_NAME("ForeignObject", TYPE_FOREIGN_OBJECT
)
6654 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6655 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6656 GetChildren()->Paint(aBuilder
, aCtx
,
6657 mFrame
->PresContext()->AppUnitsPerDevPixel());
6660 bool CreateWebRenderCommands(
6661 wr::DisplayListBuilder
& aBuilder
, wr::IpcResourceUpdateQueue
& aResources
,
6662 const StackingContextHelper
& aSc
,
6663 layers::RenderRootStateManager
* aManager
,
6664 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6668 * A display item to represent a hyperlink.
6670 class nsDisplayLink
: public nsPaintedDisplayItem
{
6672 nsDisplayLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6673 const char* aLinkSpec
, const nsRect
& aRect
)
6674 : nsPaintedDisplayItem(aBuilder
, aFrame
),
6675 mLinkSpec(aLinkSpec
),
6678 NS_DISPLAY_DECL_NAME("Link", TYPE_LINK
)
6680 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6683 nsCString mLinkSpec
;
6688 * A display item to represent a destination within the document.
6690 class nsDisplayDestination
: public nsPaintedDisplayItem
{
6692 nsDisplayDestination(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6693 const char* aDestinationName
, const nsPoint
& aPosition
)
6694 : nsPaintedDisplayItem(aBuilder
, aFrame
),
6695 mDestinationName(aDestinationName
),
6696 mPosition(aPosition
) {}
6698 NS_DISPLAY_DECL_NAME("Destination", TYPE_DESTINATION
)
6700 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6703 nsCString mDestinationName
;
6707 class MOZ_STACK_CLASS FlattenedDisplayListIterator
{
6709 FlattenedDisplayListIterator(nsDisplayListBuilder
* aBuilder
,
6710 nsDisplayList
* aList
)
6711 : mBuilder(aBuilder
), mStart(aList
->begin()), mEnd(aList
->end()) {
6712 ResolveFlattening();
6715 bool HasNext() const { return !AtEndOfCurrentList(); }
6717 nsDisplayItem
* GetNextItem() {
6718 MOZ_ASSERT(HasNext());
6720 nsDisplayItem
* current
= NextItem();
6723 if (!AtEndOfCurrentList() && current
->CanMerge(NextItem())) {
6724 // Since we can merge at least two display items, create an array and
6725 // collect mergeable display items there.
6726 AutoTArray
<nsDisplayItem
*, 2> willMerge
{current
};
6729 while (it
!= mEnd
) {
6730 nsDisplayItem
* next
= *it
;
6731 if (current
->CanMerge(next
)) {
6732 willMerge
.AppendElement(next
);
6740 current
= mBuilder
->MergeItems(willMerge
);
6743 ResolveFlattening();
6748 void Advance() { ++mStart
; }
6750 bool AtEndOfNestedList() const {
6751 return AtEndOfCurrentList() && mStack
.Length() > 0;
6754 bool AtEndOfCurrentList() const { return mStart
== mEnd
; }
6756 nsDisplayItem
* NextItem() {
6757 MOZ_ASSERT(HasNext());
6761 bool ShouldFlattenNextItem() {
6762 return HasNext() && NextItem()->ShouldFlattenAway(mBuilder
);
6765 void ResolveFlattening() {
6766 // Handle the case where we reach the end of a nested list, or the current
6767 // item should start a new nested list. Repeat this until we find an actual
6768 // item, or the very end of the outer list.
6769 while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
6770 if (AtEndOfNestedList()) {
6771 // We reached the end of the list, pop the next list from the stack.
6772 std::tie(mStart
, mEnd
) = mStack
.PopLastElement();
6774 // The next item wants to be flattened. This means that we will skip the
6775 // flattened item and directly iterate over its sublist.
6776 MOZ_ASSERT(ShouldFlattenNextItem());
6778 nsDisplayList
* sublist
= NextItem()->GetChildren();
6779 MOZ_ASSERT(sublist
);
6781 // Skip the flattened item.
6784 // Store the current position on the stack.
6785 if (!AtEndOfCurrentList()) {
6786 mStack
.AppendElement(std::make_pair(mStart
, mEnd
));
6789 // Iterate over the sublist.
6790 mStart
= sublist
->begin();
6791 mEnd
= sublist
->end();
6797 nsDisplayListBuilder
* mBuilder
;
6798 nsDisplayList::iterator mStart
;
6799 nsDisplayList::iterator mEnd
;
6800 AutoTArray
<std::pair
<nsDisplayList::iterator
, nsDisplayList::iterator
>, 3>
6804 class PaintTelemetry
{
6806 class AutoRecordPaint
{
6816 static uint32_t sPaintLevel
;
6819 } // namespace mozilla
6821 #endif /*NSDISPLAYLIST_H_*/