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