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