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