1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * structures that represent things to be painted (ordered in z-order),
10 * used during painting and hit testing
13 #ifndef NSDISPLAYLIST_H_
14 #define NSDISPLAYLIST_H_
16 #include "mozilla/Attributes.h"
17 #include "gfxContext.h"
18 #include "mozilla/ArenaAllocator.h"
19 #include "mozilla/Array.h"
20 #include "mozilla/Assertions.h"
21 #include "mozilla/Attributes.h"
22 #include "mozilla/DebugOnly.h"
23 #include "mozilla/EnumSet.h"
24 #include "mozilla/Maybe.h"
25 #include "mozilla/RefPtr.h"
26 #include "mozilla/TemplateLib.h" // mozilla::tl::Max
28 #include "nsContainerFrame.h"
32 #include "nsDisplayListInvalidation.h"
33 #include "DisplayItemClipChain.h"
34 #include "DisplayListClipState.h"
35 #include "LayerState.h"
36 #include "FrameMetrics.h"
37 #include "HitTestInfo.h"
38 #include "ImgDrawResult.h"
39 #include "mozilla/dom/EffectsInfo.h"
40 #include "mozilla/dom/RemoteBrowser.h"
41 #include "mozilla/EffectCompositor.h"
42 #include "mozilla/EnumeratedArray.h"
43 #include "mozilla/MotionPathUtils.h"
44 #include "mozilla/UniquePtr.h"
45 #include "mozilla/TimeStamp.h"
46 #include "mozilla/gfx/UserData.h"
47 #include "mozilla/layers/LayerAttributes.h"
48 #include "mozilla/layers/ScrollableLayerGuid.h"
49 #include "mozilla/layers/BSPTree.h"
50 #include "nsCSSRenderingBorders.h"
51 #include "nsPresArena.h"
52 #include "nsAutoLayoutPhase.h"
53 #include "nsDisplayItemTypes.h"
54 #include "RetainedDisplayListHelpers.h"
58 #include "nsClassHashtable.h"
59 #include "nsTHashSet.h"
60 #include "nsTHashMap.h"
64 #include <unordered_set>
66 // XXX Includes that could be avoided by moving function implementations to the
68 #include "gfxPlatform.h"
73 class nsDisplayTableItem
;
74 class nsIScrollableFrame
;
75 class nsSubDocumentFrame
;
76 class nsDisplayCompositorHitTestInfo
;
77 class nsDisplayScrollInfoLayer
;
78 class nsDisplayTableBackgroundSet
;
80 enum class nsDisplayOwnLayerFlags
;
81 struct WrFiltersHolder
;
83 namespace nsStyleTransformMatrix
{
84 class TransformReferenceBox
;
88 class FrameLayerBuilder
;
90 class StickyScrollContainer
;
93 class RenderRootStateManager
;
97 class StackingContextHelper
;
98 class WebRenderCommand
;
99 class WebRenderScrollData
;
100 class WebRenderLayerScrollData
;
101 } // namespace layers
103 class DisplayListBuilder
;
109 enum class DisplayListArenaObjectId
{
110 #define DISPLAY_LIST_ARENA_OBJECT(name_) name_,
111 #include "nsDisplayListArenaTypes.h"
112 #undef DISPLAY_LIST_ARENA_OBJECT
116 } // namespace mozilla
119 * An nsIFrame can have many different visual parts. For example an image frame
120 * can have a background, border, and outline, the image itself, and a
121 * translucent selection overlay. In general these parts can be drawn at
122 * discontiguous z-levels; see CSS2.1 appendix E:
123 * http://www.w3.org/TR/CSS21/zindex.html
125 * We construct a display list for a frame tree that contains one item
126 * for each visual part. The display list is itself a tree since some items
127 * are containers for other items; however, its structure does not match
128 * the structure of its source frame tree. The display list items are sorted
129 * by z-order. A display list can be used to paint the frames, to determine
130 * which frame is the target of a mouse event, and to determine what areas
131 * need to be repainted when scrolling. The display lists built for each task
132 * may be different for efficiency; in particular some frames need special
133 * display list items only for event handling, and do not create these items
134 * when the display list will be used for painting (the common case). For
135 * example, when painting we avoid creating nsDisplayBackground items for
136 * frames that don't display a visible background, but for event handling
137 * we need those backgrounds because they are not transparent to events.
139 * We could avoid constructing an explicit display list by traversing the
140 * frame tree multiple times in clever ways. However, reifying the display list
141 * reduces code complexity and reduces the number of times each frame must be
142 * traversed to one, which seems to be good for performance. It also means
143 * we can share code for painting, event handling and scroll analysis.
145 * Display lists are short-lived; content and frame trees cannot change
146 * between a display list being created and destroyed. Display lists should
147 * not be created during reflow because the frame tree may be in an
148 * inconsistent state (e.g., a frame's stored overflow-area may not include
149 * the bounds of all its children). However, it should be fine to create
150 * a display list while a reflow is pending, before it starts.
152 * A display list covers the "extended" frame tree; the display list for
153 * a frame tree containing FRAME/IFRAME elements can include frames from
156 * Display item's coordinates are relative to their nearest reference frame
157 * ancestor. Both the display root and any frame with a transform act as a
158 * reference frame for their frame subtrees.
162 * Represents a frame that is considered to have (or will have) "animated
163 * geometry" for itself and descendant frames.
165 * For example the scrolled frames of scrollframes which are actively being
166 * scrolled fall into this category. Frames with certain CSS properties that are
167 * being animated (e.g. 'left'/'top' etc) are also placed in this category.
168 * Frames with different active geometry roots are in different PaintedLayers,
169 * so that we can animate the geometry root by changing its transform (either on
170 * the main thread or in the compositor).
172 * nsDisplayListBuilder constructs a tree of these (for fast traversals) and
173 * assigns one for each display item.
175 * The animated geometry root for a display item is required to be a descendant
176 * (or equal to) the item's ReferenceFrame(), which means that we will fall back
177 * to returning aItem->ReferenceFrame() when we can't find another animated
180 * The animated geometry root isn't strongly defined for a frame as transforms
181 * and background-attachment:fixed can cause it to vary between display items
184 struct AnimatedGeometryRoot
{
185 static already_AddRefed
<AnimatedGeometryRoot
> CreateAGRForFrame(
186 nsIFrame
* aFrame
, AnimatedGeometryRoot
* aParent
, bool aIsAsync
,
188 RefPtr
<AnimatedGeometryRoot
> result
;
190 result
= aFrame
->GetProperty(AnimatedGeometryRootCache());
194 result
->mParentAGR
= aParent
;
195 result
->mIsAsync
= aIsAsync
;
197 result
= new AnimatedGeometryRoot(aFrame
, aParent
, aIsAsync
, aIsRetained
);
199 return result
.forget();
202 operator nsIFrame
*() { return mFrame
; }
204 nsIFrame
* operator->() const { return mFrame
; }
206 AnimatedGeometryRoot
* GetAsyncAGR() {
207 AnimatedGeometryRoot
* agr
= this;
208 while (!agr
->mIsAsync
&& agr
->mParentAGR
) {
209 agr
= agr
->mParentAGR
;
214 NS_INLINE_DECL_REFCOUNTING(AnimatedGeometryRoot
)
217 RefPtr
<AnimatedGeometryRoot
> mParentAGR
;
222 static void DetachAGR(AnimatedGeometryRoot
* aAGR
) {
223 aAGR
->mFrame
= nullptr;
224 aAGR
->mParentAGR
= nullptr;
228 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnimatedGeometryRootCache
,
229 AnimatedGeometryRoot
, DetachAGR
)
231 AnimatedGeometryRoot(nsIFrame
* aFrame
, AnimatedGeometryRoot
* aParent
,
232 bool aIsAsync
, bool aIsRetained
)
236 mIsRetained(aIsRetained
) {
237 MOZ_ASSERT(mParentAGR
|| mIsAsync
,
238 "The root AGR should always be treated as an async AGR.");
241 aFrame
->SetProperty(AnimatedGeometryRootCache(), this);
245 ~AnimatedGeometryRoot() {
246 if (mFrame
&& mIsRetained
) {
247 mFrame
->RemoveProperty(AnimatedGeometryRootCache());
255 * An active scrolled root (ASR) is similar to an animated geometry root (AGR).
256 * The differences are:
257 * - ASRs are only created for async-scrollable scroll frames. This is a
258 * (hopefully) temporary restriction. In the future we will want to create
259 * ASRs for all the things that are currently creating AGRs, and then
260 * replace AGRs with ASRs and rename them from "active scrolled root" to
261 * "animated geometry root".
262 * - ASR objects are created during display list construction by the nsIFrames
263 * that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter.
264 * The current ASR is returned by
265 * nsDisplayListBuilder::CurrentActiveScrolledRoot().
266 * - There is no way to go from an nsIFrame pointer to the ASR of that frame.
267 * If you need to look up an ASR after display list construction, you need
268 * to store it while the AutoCurrentActiveScrolledRootSetter that creates it
271 struct ActiveScrolledRoot
{
272 static already_AddRefed
<ActiveScrolledRoot
> CreateASRForFrame(
273 const ActiveScrolledRoot
* aParent
, nsIScrollableFrame
* aScrollableFrame
,
276 static const ActiveScrolledRoot
* PickAncestor(
277 const ActiveScrolledRoot
* aOne
, const ActiveScrolledRoot
* aTwo
) {
278 MOZ_ASSERT(IsAncestor(aOne
, aTwo
) || IsAncestor(aTwo
, aOne
));
279 return Depth(aOne
) <= Depth(aTwo
) ? aOne
: aTwo
;
282 static const ActiveScrolledRoot
* PickDescendant(
283 const ActiveScrolledRoot
* aOne
, const ActiveScrolledRoot
* aTwo
) {
284 MOZ_ASSERT(IsAncestor(aOne
, aTwo
) || IsAncestor(aTwo
, aOne
));
285 return Depth(aOne
) >= Depth(aTwo
) ? aOne
: aTwo
;
288 static bool IsAncestor(const ActiveScrolledRoot
* aAncestor
,
289 const ActiveScrolledRoot
* aDescendant
);
291 static nsCString
ToString(
292 const mozilla::ActiveScrolledRoot
* aActiveScrolledRoot
);
294 // Call this when inserting an ancestor.
295 void IncrementDepth() { mDepth
++; }
298 * Find the view ID (or generate a new one) for the content element
299 * corresponding to the ASR.
301 mozilla::layers::ScrollableLayerGuid::ViewID
GetViewId() const {
302 if (!mViewId
.isSome()) {
303 mViewId
= Some(ComputeViewId());
308 RefPtr
<const ActiveScrolledRoot
> mParent
;
309 nsIScrollableFrame
* mScrollableFrame
;
311 NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot
)
315 : mScrollableFrame(nullptr), mDepth(0), mRetained(false) {}
317 ~ActiveScrolledRoot();
319 static void DetachASR(ActiveScrolledRoot
* aASR
) {
320 aASR
->mParent
= nullptr;
321 aASR
->mScrollableFrame
= nullptr;
324 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache
,
325 ActiveScrolledRoot
, DetachASR
)
327 static uint32_t Depth(const ActiveScrolledRoot
* aActiveScrolledRoot
) {
328 return aActiveScrolledRoot
? aActiveScrolledRoot
->mDepth
: 0;
331 mozilla::layers::ScrollableLayerGuid::ViewID
ComputeViewId() const;
333 // This field is lazily populated in GetViewId(). We don't want to do the
334 // work of populating if webrender is disabled, because it is often not
336 mutable Maybe
<mozilla::layers::ScrollableLayerGuid::ViewID
> mViewId
;
341 } // namespace mozilla
343 enum class nsDisplayListBuilderMode
: uint8_t {
348 TransformComputation
,
352 class nsDisplayWrapList
;
355 * This manages a display list and is passed as a parameter to
356 * nsIFrame::BuildDisplayList.
357 * It contains the parameters that don't change from frame to frame and manages
358 * the display list memory using an arena. It also establishes the reference
359 * coordinate system for all display list items. Some of the parameters are
360 * available from the prescontext/presshell, but we copy them into the builder
361 * for faster/more convenient access.
363 class nsDisplayListBuilder
{
364 typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect
;
365 typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize
;
366 typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion
;
367 typedef mozilla::LayoutDeviceRect LayoutDeviceRect
;
370 * This manages status of a 3d context to collect visible rects of
371 * descendants and passing a dirty rect.
373 * Since some transforms maybe singular, passing visible rects or
374 * the dirty rect level by level from parent to children may get a
375 * wrong result, being different from the result of appling with
376 * effective transform directly.
378 * nsIFrame::BuildDisplayListForStackingContext() uses
379 * AutoPreserves3DContext to install an instance on the builder.
381 * \see AutoAccumulateTransform, AutoAccumulateRect,
382 * AutoPreserves3DContext, Accumulate, GetCurrentTransform,
385 class Preserves3DContext
{
387 typedef mozilla::gfx::Matrix4x4 Matrix4x4
;
390 : mAccumulatedRectLevels(0), mAllowAsyncAnimation(true) {}
392 Preserves3DContext(const Preserves3DContext
& aOther
)
393 : mAccumulatedTransform(),
395 mAccumulatedRectLevels(0),
396 mVisibleRect(aOther
.mVisibleRect
),
397 mAllowAsyncAnimation(aOther
.mAllowAsyncAnimation
) {}
399 // Accmulate transforms of ancestors on the preserves-3d chain.
400 Matrix4x4 mAccumulatedTransform
;
401 // Accmulate visible rect of descendants in the preserves-3d context.
402 nsRect mAccumulatedRect
;
403 // How far this frame is from the root of the current 3d context.
404 int mAccumulatedRectLevels
;
406 // Allow async animation for this 3D context.
407 bool mAllowAsyncAnimation
;
411 * A frame can be in one of three states of AGR.
412 * AGR_NO means the frame is not an AGR for now.
413 * AGR_YES means the frame is an AGR for now.
415 enum AGRState
{ AGR_NO
, AGR_YES
};
418 typedef mozilla::FrameLayerBuilder FrameLayerBuilder
;
419 typedef mozilla::DisplayItemClip DisplayItemClip
;
420 typedef mozilla::DisplayItemClipChain DisplayItemClipChain
;
421 typedef mozilla::DisplayItemClipChainHasher DisplayItemClipChainHasher
;
422 typedef mozilla::DisplayItemClipChainEqualer DisplayItemClipChainEqualer
;
423 typedef mozilla::DisplayListClipState DisplayListClipState
;
424 typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot
;
425 typedef nsIWidget::ThemeGeometry ThemeGeometry
;
426 typedef mozilla::layers::Layer Layer
;
427 typedef mozilla::layers::FrameMetrics FrameMetrics
;
428 typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid
;
429 typedef mozilla::layers::ScrollableLayerGuid::ViewID ViewID
;
430 typedef mozilla::gfx::CompositorHitTestInfo CompositorHitTestInfo
;
431 typedef mozilla::gfx::Matrix4x4 Matrix4x4
;
432 typedef mozilla::Maybe
<mozilla::layers::ScrollDirection
> MaybeScrollDirection
;
433 typedef mozilla::dom::EffectsInfo EffectsInfo
;
434 typedef mozilla::layers::LayersId LayersId
;
435 typedef mozilla::dom::RemoteBrowser RemoteBrowser
;
438 * @param aReferenceFrame the frame at the root of the subtree; its origin
439 * is the origin of the reference coordinate system for this display list
440 * @param aMode encodes what the builder is being used for.
441 * @param aBuildCaret whether or not we should include the caret in any
442 * display lists that we make.
444 nsDisplayListBuilder(nsIFrame
* aReferenceFrame
,
445 nsDisplayListBuilderMode aMode
, bool aBuildCaret
,
446 bool aRetainingDisplayList
= false);
447 ~nsDisplayListBuilder();
452 void AddTemporaryItem(nsDisplayItem
* aItem
) {
453 mTemporaryItems
.AppendElement(aItem
);
456 mozilla::layers::LayerManager
* GetWidgetLayerManager(
457 nsView
** aView
= nullptr);
460 * @return true if the display is being built in order to determine which
461 * frame is under the mouse position.
463 bool IsForEventDelivery() const {
464 return mMode
== nsDisplayListBuilderMode::EventDelivery
;
468 * @return true if the display list is being built for painting. This
469 * includes both painting to a window or other buffer and painting to
470 * a print/pdf destination.
472 bool IsForPainting() const {
473 return mMode
== nsDisplayListBuilderMode::Painting
||
474 mMode
== nsDisplayListBuilderMode::PaintForPrinting
;
478 * @return true if the display list is being built specifically for printing.
480 bool IsForPrinting() const {
481 return mMode
== nsDisplayListBuilderMode::PaintForPrinting
;
485 * @return true if the display list is being built for determining frame
488 bool IsForFrameVisibility() const {
489 return mMode
== nsDisplayListBuilderMode::FrameVisibility
;
493 * @return true if the display list is being built for creating the glyph
494 * mask from text items.
496 bool IsForGenerateGlyphMask() const {
497 return mMode
== nsDisplayListBuilderMode::GenerateGlyph
;
500 bool BuildCompositorHitTestInfo() const {
501 return mBuildCompositorHitTestInfo
;
505 * @return true if "painting is suppressed" during page load and we
506 * should paint only the background of the document.
508 bool IsBackgroundOnly() {
509 NS_ASSERTION(mPresShellStates
.Length() > 0,
510 "don't call this if we're not in a presshell");
511 return CurrentPresShellState()->mIsBackgroundOnly
;
515 * @return the root of given frame's (sub)tree, whose origin
516 * establishes the coordinate system for the child display items.
518 const nsIFrame
* FindReferenceFrameFor(const nsIFrame
* aFrame
,
519 nsPoint
* aOffset
= nullptr) const;
521 const mozilla::Maybe
<nsPoint
>& AdditionalOffset() const {
522 return mAdditionalOffset
;
526 * @return the root of the display list's frame (sub)tree, whose origin
527 * establishes the coordinate system for the display list
529 nsIFrame
* RootReferenceFrame() const { return mReferenceFrame
; }
532 * @return a point pt such that adding pt to a coordinate relative to aFrame
533 * makes it relative to ReferenceFrame(), i.e., returns
534 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
535 * the appunits of aFrame.
537 const nsPoint
ToReferenceFrame(const nsIFrame
* aFrame
) const {
539 FindReferenceFrameFor(aFrame
, &result
);
543 * When building the display list, the scrollframe aFrame will be "ignored"
544 * for the purposes of clipping, and its scrollbars will be hidden. We use
545 * this to allow RenderOffscreen to render a whole document without beign
546 * clipped by the viewport or drawing the viewport scrollbars.
548 void SetIgnoreScrollFrame(nsIFrame
* aFrame
) { mIgnoreScrollFrame
= aFrame
; }
550 * Get the scrollframe to ignore, if any.
552 nsIFrame
* GetIgnoreScrollFrame() { return mIgnoreScrollFrame
; }
553 void SetIsRelativeToLayoutViewport();
554 bool IsRelativeToLayoutViewport() const {
555 return mIsRelativeToLayoutViewport
;
558 * Get the ViewID of the nearest scrolling ancestor frame.
560 ViewID
GetCurrentScrollParentId() const { return mCurrentScrollParentId
; }
562 * Get and set the flag that indicates if scroll parents should have layers
563 * forcibly created. This flag is set when a deeply nested scrollframe has
564 * a displayport, and for scroll handoff to work properly the ancestor
565 * scrollframes should also get their own scrollable layers.
567 void ForceLayerForScrollParent() { mForceLayerForScrollParent
= true; }
569 * Set the flag that indicates there is a non-minimal display port in the
570 * current subtree. This is used to determine display port expiry.
572 void SetContainsNonMinimalDisplayPort() {
573 mContainsNonMinimalDisplayPort
= true;
576 * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
577 * which we are building display items at the moment.
579 ViewID
GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget
; }
580 MaybeScrollDirection
GetCurrentScrollbarDirection() const {
581 return mCurrentScrollbarDirection
;
584 * Returns true if building a scrollbar, and the scrollbar will not be
587 bool IsBuildingNonLayerizedScrollbar() const {
588 return mIsBuildingScrollbar
&& !mCurrentScrollbarWillHaveLayer
;
591 * Calling this setter makes us include all out-of-flow descendant
592 * frames in the display list, wherever they may be positioned (even
593 * outside the dirty rects).
595 void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows
= true; }
596 bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows
; }
598 * Calling this setter makes us exclude all leaf frames that aren't
601 void SetSelectedFramesOnly() { mSelectedFramesOnly
= true; }
602 bool GetSelectedFramesOnly() { return mSelectedFramesOnly
; }
604 * @return Returns true if we should include the caret in any display lists
607 bool IsBuildingCaret() const { return mBuildCaret
; }
609 bool IsRetainingDisplayList() const { return mRetainingDisplayList
; }
611 bool IsPartialUpdate() const { return mPartialUpdate
; }
612 void SetPartialUpdate(bool aPartial
) { mPartialUpdate
= aPartial
; }
614 bool IsBuilding() const { return mIsBuilding
; }
615 void SetIsBuilding(bool aIsBuilding
) { mIsBuilding
= aIsBuilding
; }
617 bool InInvalidSubtree() const { return mInInvalidSubtree
; }
620 * Allows callers to selectively override the regular paint suppression
621 * checks, so that methods like GetFrameForPoint work when painting is
624 void IgnorePaintSuppression() { mIgnoreSuppression
= true; }
626 * @return Returns if this builder will ignore paint suppression.
628 bool IsIgnoringPaintSuppression() { return mIgnoreSuppression
; }
630 * Call this if we're doing normal painting to the window.
632 void SetPaintingToWindow(bool aToWindow
) { mIsPaintingToWindow
= aToWindow
; }
633 bool IsPaintingToWindow() const { return mIsPaintingToWindow
; }
635 * Call this if we're using high quality scaling for image decoding.
636 * It is also implied by IsPaintingToWindow.
638 void SetUseHighQualityScaling(bool aUseHighQualityScaling
) {
639 mUseHighQualityScaling
= aUseHighQualityScaling
;
641 bool UseHighQualityScaling() const {
642 return mIsPaintingToWindow
|| mUseHighQualityScaling
;
645 * Call this if we're doing painting for WebRender
647 void SetPaintingForWebRender(bool aForWebRender
) {
648 mIsPaintingForWebRender
= true;
650 bool IsPaintingForWebRender() const { return mIsPaintingForWebRender
; }
652 * Call this to prevent descending into subdocuments.
654 void SetDescendIntoSubdocuments(bool aDescend
) {
655 mDescendIntoSubdocuments
= aDescend
;
658 bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments
; }
661 * Get dirty rect relative to current frame (the frame that we're calling
662 * BuildDisplayList on right now).
664 const nsRect
& GetVisibleRect() { return mVisibleRect
; }
665 const nsRect
& GetDirtyRect() { return mDirtyRect
; }
667 void SetVisibleRect(const nsRect
& aVisibleRect
) {
668 mVisibleRect
= aVisibleRect
;
671 void IntersectVisibleRect(const nsRect
& aVisibleRect
) {
672 mVisibleRect
.IntersectRect(mVisibleRect
, aVisibleRect
);
675 void SetDirtyRect(const nsRect
& aDirtyRect
) { mDirtyRect
= aDirtyRect
; }
677 void IntersectDirtyRect(const nsRect
& aDirtyRect
) {
678 mDirtyRect
.IntersectRect(mDirtyRect
, aDirtyRect
);
681 const nsIFrame
* GetCurrentFrame() { return mCurrentFrame
; }
682 const nsIFrame
* GetCurrentReferenceFrame() { return mCurrentReferenceFrame
; }
684 const nsPoint
& GetCurrentFrameOffsetToReferenceFrame() const {
685 return mCurrentOffsetToReferenceFrame
;
688 AnimatedGeometryRoot
* GetCurrentAnimatedGeometryRoot() { return mCurrentAGR
; }
689 AnimatedGeometryRoot
* GetRootAnimatedGeometryRoot() { return mRootAGR
; }
691 void RecomputeCurrentAnimatedGeometryRoot();
693 void Check() { mPool
.Check(); }
696 * Returns true if merging and flattening of display lists should be
697 * performed while computing visibility.
699 bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening
; }
700 void SetAllowMergingAndFlattening(bool aAllow
) {
701 mAllowMergingAndFlattening
= aAllow
;
704 void SetCompositorHitTestInfo(const CompositorHitTestInfo
& aInfo
) {
705 mCompositorHitTestInfo
= aInfo
;
708 const CompositorHitTestInfo
& GetCompositorHitTestInfo() const {
709 return mCompositorHitTestInfo
;
713 * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
714 * needed, and adds it to the top of |aList|.
716 void BuildCompositorHitTestInfoIfNeeded(nsIFrame
* aFrame
,
717 nsDisplayList
* aList
);
719 bool IsInsidePointerEventsNoneDoc() {
720 return CurrentPresShellState()->mInsidePointerEventsNoneDoc
;
723 bool IsTouchEventPrefEnabledDoc() {
724 return CurrentPresShellState()->mTouchEventPrefEnabledDoc
;
727 bool GetAncestorHasApzAwareEventHandler() const {
728 return mAncestorHasApzAwareEventHandler
;
731 void SetAncestorHasApzAwareEventHandler(bool aValue
) {
732 mAncestorHasApzAwareEventHandler
= aValue
;
735 bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort
; }
736 void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort
= true; }
737 void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort
= false; }
739 bool SetIsCompositingCheap(bool aCompositingCheap
) {
740 bool temp
= mIsCompositingCheap
;
741 mIsCompositingCheap
= aCompositingCheap
;
745 bool IsCompositingCheap() const { return mIsCompositingCheap
; }
747 * Display the caret if needed.
749 bool DisplayCaret(nsIFrame
* aFrame
, nsDisplayList
* aList
) {
750 nsIFrame
* frame
= GetCaretFrame();
751 if (aFrame
== frame
&& !IsBackgroundOnly()) {
752 frame
->DisplayCaret(this, aList
);
758 * Get the frame that the caret is supposed to draw in.
759 * If the caret is currently invisible, this will be null.
761 nsIFrame
* GetCaretFrame() { return mCaretFrame
; }
763 * Get the rectangle we're supposed to draw the caret into.
765 const nsRect
& GetCaretRect() { return mCaretRect
; }
767 * Get the caret associated with the current presshell.
772 * Returns the root scroll frame for the current PresShell, if the PresShell
773 * is ignoring viewport scrolling.
775 nsIFrame
* GetPresShellIgnoreScrollFrame() {
776 return CurrentPresShellState()->mPresShellIgnoreScrollFrame
;
780 * Notify the display list builder that we're entering a presshell.
781 * aReferenceFrame should be a frame in the new presshell.
782 * aPointerEventsNoneDoc should be set to true if the frame generating this
783 * document is pointer-events:none.
785 void EnterPresShell(const nsIFrame
* aReferenceFrame
,
786 bool aPointerEventsNoneDoc
= false);
788 * For print-preview documents, we sometimes need to build display items for
789 * the same frames multiple times in the same presentation, with different
790 * clipping. Between each such batch of items, call
791 * ResetMarkedFramesForDisplayList to make sure that the results of
792 * MarkFramesForDisplayList do not carry over between batches.
794 void ResetMarkedFramesForDisplayList(const nsIFrame
* aReferenceFrame
);
796 * Notify the display list builder that we're leaving a presshell.
798 void LeavePresShell(const nsIFrame
* aReferenceFrame
,
799 nsDisplayList
* aPaintedContents
);
801 void IncrementPresShellPaintCount(mozilla::PresShell
* aPresShell
);
804 * Returns true if we're currently building a display list that's
805 * directly or indirectly under an nsDisplayTransform.
807 bool IsInTransform() const { return mInTransform
; }
809 bool InEventsOnly() const { return mInEventsOnly
; }
811 * Indicate whether or not we're directly or indirectly under and
812 * nsDisplayTransform or SVG foreignObject.
814 void SetInTransform(bool aInTransform
) { mInTransform
= aInTransform
; }
817 * Returns true if we're currently building a display list that's
818 * under an nsDisplayFilters.
820 bool IsInFilter() const { return mInFilter
; }
823 * Return true if we're currently building a display list for a
826 bool IsInSubdocument() const { return mPresShellStates
.Length() > 1; }
828 void SetDisablePartialUpdates(bool aDisable
) {
829 mDisablePartialUpdates
= aDisable
;
831 bool DisablePartialUpdates() const { return mDisablePartialUpdates
; }
833 void SetPartialBuildFailed(bool aFailed
) { mPartialBuildFailed
= aFailed
; }
834 bool PartialBuildFailed() const { return mPartialBuildFailed
; }
836 bool IsInActiveDocShell() const { return mIsInActiveDocShell
; }
837 void SetInActiveDocShell(bool aActive
) { mIsInActiveDocShell
= aActive
; }
840 * Return true if we're currently building a display list for the presshell
841 * of a chrome document, or if we're building the display list for a popup.
843 bool IsInChromeDocumentOrPopup() const {
844 return mIsInChromePresContext
|| mIsBuildingForPopup
;
848 * @return true if images have been set to decode synchronously.
850 bool ShouldSyncDecodeImages() const { return mSyncDecodeImages
; }
853 * Indicates whether we should synchronously decode images. If true, we decode
854 * and draw whatever image data has been loaded. If false, we just draw
855 * whatever has already been decoded.
857 void SetSyncDecodeImages(bool aSyncDecodeImages
) {
858 mSyncDecodeImages
= aSyncDecodeImages
;
861 nsDisplayTableBackgroundSet
* SetTableBackgroundSet(
862 nsDisplayTableBackgroundSet
* aTableSet
) {
863 nsDisplayTableBackgroundSet
* old
= mTableBackgroundSet
;
864 mTableBackgroundSet
= aTableSet
;
867 nsDisplayTableBackgroundSet
* GetTableBackgroundSet() const {
868 return mTableBackgroundSet
;
871 void FreeClipChains();
874 * Frees the temporary display items created during merging.
876 void FreeTemporaryItems();
879 * Helper method to generate background painting flags based on the
880 * information available in the display list builder.
882 uint32_t GetBackgroundPaintFlags();
885 * Helper method to generate nsImageRenderer flags based on the information
886 * available in the display list builder.
888 uint32_t GetImageRendererFlags() const;
891 * Helper method to generate image decoding flags based on the
892 * information available in the display list builder.
894 uint32_t GetImageDecodeFlags() const;
897 * Subtracts aRegion from *aVisibleRegion. We avoid letting
898 * aVisibleRegion become overcomplex by simplifying it if necessary.
900 void SubtractFromVisibleRegion(nsRegion
* aVisibleRegion
,
901 const nsRegion
& aRegion
);
904 * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
905 * (which is relative to aDirtyFrame). If the frames have placeholders
906 * that might not be displayed, we mark the placeholders and their ancestors
907 * to ensure that display list construction descends into them
908 * anyway. nsDisplayListBuilder will take care of unmarking them when it is
911 void MarkFramesForDisplayList(nsIFrame
* aDirtyFrame
,
912 const nsFrameList
& aFrames
);
913 void MarkFrameForDisplay(nsIFrame
* aFrame
, const nsIFrame
* aStopAtFrame
);
914 void MarkFrameForDisplayIfVisible(nsIFrame
* aFrame
,
915 const nsIFrame
* aStopAtFrame
);
916 void AddFrameMarkedForDisplayIfVisible(nsIFrame
* aFrame
);
918 void ClearFixedBackgroundDisplayData();
920 * Mark all child frames that Preserve3D() as needing display.
921 * Because these frames include transforms set on their parent, dirty rects
922 * for intermediate frames may be empty, yet child frames could still be
925 void MarkPreserve3DFramesForDisplayList(nsIFrame
* aDirtyFrame
);
928 * Returns true if we need to descend into this frame when building
929 * the display list, even though it doesn't intersect the dirty
930 * rect, because it may have out-of-flows that do so.
932 bool ShouldDescendIntoFrame(nsIFrame
* aFrame
, bool aVisible
) const {
933 return aFrame
->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO
) ||
934 (aVisible
&& aFrame
->ForceDescendIntoIfVisible()) ||
935 GetIncludeAllOutOfFlows();
939 * Returns the list of registered theme geometries.
941 nsTArray
<ThemeGeometry
> GetThemeGeometries() const {
942 nsTArray
<ThemeGeometry
> geometries
;
944 for (const auto& data
: mThemeGeometries
.Values()) {
945 geometries
.AppendElements(*data
);
952 * Notifies the builder that a particular themed widget exists
953 * at the given rectangle within the currently built display list.
954 * For certain appearance values (currently only StyleAppearance::Toolbar and
955 * StyleAppearance::WindowTitlebar) this gets called during every display list
956 * construction, for every themed widget of the right type within the
957 * display list, except for themed widgets which are transformed or have
958 * effects applied to them (e.g. CSS opacity or filters).
960 * @param aWidgetType the -moz-appearance value for the themed widget
961 * @param aItem the item associated with the theme geometry
962 * @param aRect the device-pixel rect relative to the widget's displayRoot
963 * for the themed widget
965 void RegisterThemeGeometry(uint8_t aWidgetType
, nsDisplayItem
* aItem
,
966 const mozilla::LayoutDeviceIntRect
& aRect
) {
967 if (!mIsPaintingToWindow
) {
971 nsTArray
<ThemeGeometry
>* geometries
=
972 mThemeGeometries
.GetOrInsertNew(aItem
);
973 geometries
->AppendElement(ThemeGeometry(aWidgetType
, aRect
));
977 * Removes theme geometries associated with the given display item |aItem|.
979 void UnregisterThemeGeometry(nsDisplayItem
* aItem
) {
980 mThemeGeometries
.Remove(aItem
);
984 * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
985 * -moz-window-dragging value is |drag|, its border box is added to the
986 * collected dragging region; if the value is |no-drag|, the border box is
987 * subtracted from the region; if the value is |default|, that frame does
988 * not influence the window dragging region.
990 void AdjustWindowDraggingRegion(nsIFrame
* aFrame
);
992 LayoutDeviceIntRegion
GetWindowDraggingRegion() const;
994 void RemoveModifiedWindowRegions();
995 void ClearRetainedWindowRegions();
997 const nsTHashMap
<nsPtrHashKey
<RemoteBrowser
>, EffectsInfo
>& GetEffectUpdates()
999 return mEffectsUpdates
;
1002 void AddEffectUpdate(RemoteBrowser
* aBrowser
, EffectsInfo aUpdate
) {
1003 mEffectsUpdates
.InsertOrUpdate(aBrowser
, aUpdate
);
1007 * Allocate memory in our arena. It will only be freed when this display list
1008 * builder is destroyed. This memory holds nsDisplayItems and
1009 * DisplayItemClipChain objects.
1011 * Destructors are called as soon as the item is no longer used.
1013 void* Allocate(size_t aSize
, mozilla::DisplayListArenaObjectId aId
) {
1014 return mPool
.Allocate(aId
, aSize
);
1016 void* Allocate(size_t aSize
, DisplayItemType aType
) {
1017 static_assert(size_t(DisplayItemType::TYPE_ZERO
) ==
1018 size_t(mozilla::DisplayListArenaObjectId::CLIPCHAIN
),
1020 #define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) \
1021 static_assert(size_t(DisplayItemType::TYPE_##name_) == \
1022 size_t(mozilla::DisplayListArenaObjectId::name_), \
1024 #include "nsDisplayItemTypesList.h"
1025 #undef DECLARE_DISPLAY_ITEM_TYPE
1026 return Allocate(aSize
, mozilla::DisplayListArenaObjectId(size_t(aType
)));
1029 void Destroy(mozilla::DisplayListArenaObjectId aId
, void* aPtr
) {
1030 return mPool
.Free(aId
, aPtr
);
1032 void Destroy(DisplayItemType aType
, void* aPtr
) {
1033 return Destroy(mozilla::DisplayListArenaObjectId(size_t(aType
)), aPtr
);
1037 * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
1038 * automatically when the arena goes away.
1040 ActiveScrolledRoot
* AllocateActiveScrolledRoot(
1041 const ActiveScrolledRoot
* aParent
, nsIScrollableFrame
* aScrollableFrame
);
1044 * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
1045 * up automatically when the arena goes away.
1047 const DisplayItemClipChain
* AllocateDisplayItemClipChain(
1048 const DisplayItemClip
& aClip
, const ActiveScrolledRoot
* aASR
,
1049 const DisplayItemClipChain
* aParent
);
1052 * Intersect two clip chains, allocating the new clip chain items in this
1053 * builder's arena. The result is parented to aAncestor, and no intersections
1054 * happen past aAncestor's ASR.
1055 * That means aAncestor has to be living in this builder's arena already.
1056 * aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
1057 * their values are copied into the newly-allocated intersected clip chain
1058 * and this function does not hold on to any pointers to them.
1060 const DisplayItemClipChain
* CreateClipChainIntersection(
1061 const DisplayItemClipChain
* aAncestor
,
1062 const DisplayItemClipChain
* aLeafClip1
,
1063 const DisplayItemClipChain
* aLeafClip2
);
1066 * Clone the supplied clip chain's chain items into this builder's arena.
1068 const DisplayItemClipChain
* CopyWholeChain(
1069 const DisplayItemClipChain
* aClipChain
);
1072 * Returns a new clip chain containing an intersection of all clips of
1073 * |aClipChain| up to and including |aASR|.
1074 * If there is no clip, returns nullptr.
1076 const DisplayItemClipChain
* FuseClipChainUpTo(
1077 const DisplayItemClipChain
* aClipChain
, const ActiveScrolledRoot
* aASR
);
1079 const ActiveScrolledRoot
* GetFilterASR() const { return mFilterASR
; }
1082 * Transfer off main thread animations to the layer. May be called
1083 * with aBuilder and aItem both null, but only if the caller has
1084 * already checked that off main thread animations should be sent to
1085 * the layer. When they are both null, the animations are added to
1086 * the layer as pending animations.
1088 static void AddAnimationsAndTransitionsToLayer(Layer
* aLayer
,
1089 nsDisplayListBuilder
* aBuilder
,
1090 nsDisplayItem
* aItem
,
1092 DisplayItemType aType
);
1095 * Merges the display items in |aMergedItems| and returns a new temporary
1097 * The display items in |aMergedItems| have to be mergeable with each other.
1099 nsDisplayWrapList
* MergeItems(nsTArray
<nsDisplayWrapList
*>& aItems
);
1102 * A helper class used to temporarily set nsDisplayListBuilder properties for
1103 * building display items.
1104 * aVisibleRect and aDirtyRect are relative to aForChild.
1106 class AutoBuildingDisplayList
{
1108 AutoBuildingDisplayList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aForChild
,
1109 const nsRect
& aVisibleRect
,
1110 const nsRect
& aDirtyRect
)
1111 : AutoBuildingDisplayList(aBuilder
, aForChild
, aVisibleRect
, aDirtyRect
,
1112 aForChild
->IsTransformed()) {}
1114 AutoBuildingDisplayList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aForChild
,
1115 const nsRect
& aVisibleRect
,
1116 const nsRect
& aDirtyRect
,
1117 const bool aIsTransformed
);
1119 void SetReferenceFrameAndCurrentOffset(const nsIFrame
* aFrame
,
1120 const nsPoint
& aOffset
) {
1121 mBuilder
->mCurrentReferenceFrame
= aFrame
;
1122 mBuilder
->mCurrentOffsetToReferenceFrame
= aOffset
;
1125 void SetAdditionalOffset(const nsPoint
& aOffset
) {
1126 MOZ_ASSERT(!mBuilder
->mAdditionalOffset
);
1127 mBuilder
->mAdditionalOffset
= mozilla::Some(aOffset
);
1129 mBuilder
->mCurrentOffsetToReferenceFrame
+= aOffset
;
1130 mBuilder
->mAdditionalOffsetFrame
= mBuilder
->mCurrentReferenceFrame
;
1133 bool IsAnimatedGeometryRoot() const { return mCurrentAGRState
== AGR_YES
; }
1135 void RestoreBuildingInvisibleItemsValue() {
1136 mBuilder
->mBuildingInvisibleItems
= mPrevBuildingInvisibleItems
;
1139 ~AutoBuildingDisplayList() {
1140 mBuilder
->mCurrentFrame
= mPrevFrame
;
1141 mBuilder
->mCurrentReferenceFrame
= mPrevReferenceFrame
;
1142 mBuilder
->mCurrentOffsetToReferenceFrame
= mPrevOffset
;
1143 mBuilder
->mVisibleRect
= mPrevVisibleRect
;
1144 mBuilder
->mDirtyRect
= mPrevDirtyRect
;
1145 mBuilder
->mCurrentAGR
= mPrevAGR
;
1146 mBuilder
->mAncestorHasApzAwareEventHandler
=
1147 mPrevAncestorHasApzAwareEventHandler
;
1148 mBuilder
->mBuildingInvisibleItems
= mPrevBuildingInvisibleItems
;
1149 mBuilder
->mInInvalidSubtree
= mPrevInInvalidSubtree
;
1150 mBuilder
->mAdditionalOffset
= mPrevAdditionalOffset
;
1151 mBuilder
->mCompositorHitTestInfo
= mPrevCompositorHitTestInfo
;
1155 nsDisplayListBuilder
* mBuilder
;
1156 AGRState mCurrentAGRState
;
1157 const nsIFrame
* mPrevFrame
;
1158 const nsIFrame
* mPrevReferenceFrame
;
1159 nsPoint mPrevOffset
;
1160 mozilla::Maybe
<nsPoint
> mPrevAdditionalOffset
;
1161 nsRect mPrevVisibleRect
;
1162 nsRect mPrevDirtyRect
;
1163 RefPtr
<AnimatedGeometryRoot
> mPrevAGR
;
1164 CompositorHitTestInfo mPrevCompositorHitTestInfo
;
1165 bool mPrevAncestorHasApzAwareEventHandler
;
1166 bool mPrevBuildingInvisibleItems
;
1167 bool mPrevInInvalidSubtree
;
1171 * A helper class to temporarily set the value of mInTransform.
1173 class AutoInTransformSetter
{
1175 AutoInTransformSetter(nsDisplayListBuilder
* aBuilder
, bool aInTransform
)
1176 : mBuilder(aBuilder
), mOldValue(aBuilder
->mInTransform
) {
1177 aBuilder
->mInTransform
= aInTransform
;
1180 ~AutoInTransformSetter() { mBuilder
->mInTransform
= mOldValue
; }
1183 nsDisplayListBuilder
* mBuilder
;
1187 class AutoInEventsOnly
{
1189 AutoInEventsOnly(nsDisplayListBuilder
* aBuilder
, bool aInEventsOnly
)
1190 : mBuilder(aBuilder
), mOldValue(aBuilder
->mInEventsOnly
) {
1191 aBuilder
->mInEventsOnly
|= aInEventsOnly
;
1194 ~AutoInEventsOnly() { mBuilder
->mInEventsOnly
= mOldValue
; }
1197 nsDisplayListBuilder
* mBuilder
;
1202 * A helper class to temporarily set the value of mFilterASR and
1205 class AutoEnterFilter
{
1207 AutoEnterFilter(nsDisplayListBuilder
* aBuilder
, bool aUsingFilter
)
1208 : mBuilder(aBuilder
),
1209 mOldValue(aBuilder
->mFilterASR
),
1210 mOldInFilter(aBuilder
->mInFilter
) {
1211 if (!aBuilder
->mFilterASR
&& aUsingFilter
) {
1212 aBuilder
->mFilterASR
= aBuilder
->CurrentActiveScrolledRoot();
1213 aBuilder
->mInFilter
= true;
1217 ~AutoEnterFilter() {
1218 mBuilder
->mFilterASR
= mOldValue
;
1219 mBuilder
->mInFilter
= mOldInFilter
;
1223 nsDisplayListBuilder
* mBuilder
;
1224 const ActiveScrolledRoot
* mOldValue
;
1229 * A helper class to temporarily set the value of mCurrentScrollParentId.
1231 class AutoCurrentScrollParentIdSetter
{
1233 AutoCurrentScrollParentIdSetter(nsDisplayListBuilder
* aBuilder
,
1235 : mBuilder(aBuilder
),
1236 mOldValue(aBuilder
->mCurrentScrollParentId
),
1237 mOldForceLayer(aBuilder
->mForceLayerForScrollParent
),
1238 mOldContainsNonMinimalDisplayPort(
1239 mBuilder
->mContainsNonMinimalDisplayPort
) {
1240 // If this AutoCurrentScrollParentIdSetter has the same scrollId as the
1241 // previous one on the stack, then that means the scrollframe that
1242 // created this isn't actually scrollable and cannot participate in
1243 // scroll handoff. We set mCanBeScrollParent to false to indicate this.
1244 mCanBeScrollParent
= (mOldValue
!= aScrollId
);
1245 aBuilder
->mCurrentScrollParentId
= aScrollId
;
1246 aBuilder
->mForceLayerForScrollParent
= false;
1247 aBuilder
->mContainsNonMinimalDisplayPort
= false;
1250 bool ShouldForceLayerForScrollParent() const {
1251 // Only scrollframes participating in scroll handoff can be forced to
1253 return mCanBeScrollParent
&& mBuilder
->mForceLayerForScrollParent
;
1256 bool GetContainsNonMinimalDisplayPort() const {
1257 // Only for scrollframes participating in scroll handoff can we return
1259 return mCanBeScrollParent
&& mBuilder
->mContainsNonMinimalDisplayPort
;
1262 ~AutoCurrentScrollParentIdSetter() {
1263 mBuilder
->mCurrentScrollParentId
= mOldValue
;
1264 if (mCanBeScrollParent
) {
1265 // If this flag is set, caller code is responsible for having dealt
1266 // with the current value of mBuilder->mForceLayerForScrollParent, so
1267 // we can just restore the old value.
1268 mBuilder
->mForceLayerForScrollParent
= mOldForceLayer
;
1270 // Otherwise we need to keep propagating the force-layerization flag
1271 // upwards to the next ancestor scrollframe that does participate in
1273 mBuilder
->mForceLayerForScrollParent
|= mOldForceLayer
;
1275 mBuilder
->mContainsNonMinimalDisplayPort
|=
1276 mOldContainsNonMinimalDisplayPort
;
1280 nsDisplayListBuilder
* mBuilder
;
1282 bool mOldForceLayer
;
1283 bool mOldContainsNonMinimalDisplayPort
;
1284 bool mCanBeScrollParent
;
1288 * Used to update the current active scrolled root on the display list
1289 * builder, and to create new active scrolled roots.
1291 class AutoCurrentActiveScrolledRootSetter
{
1293 explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder
* aBuilder
)
1294 : mBuilder(aBuilder
),
1295 mSavedActiveScrolledRoot(aBuilder
->mCurrentActiveScrolledRoot
),
1296 mContentClipASR(aBuilder
->ClipState().GetContentClipASR()),
1297 mDescendantsStartIndex(aBuilder
->mActiveScrolledRoots
.Length()),
1300 ~AutoCurrentActiveScrolledRootSetter() {
1301 mBuilder
->mCurrentActiveScrolledRoot
= mSavedActiveScrolledRoot
;
1304 void SetCurrentActiveScrolledRoot(
1305 const ActiveScrolledRoot
* aActiveScrolledRoot
);
1307 void EnterScrollFrame(nsIScrollableFrame
* aScrollableFrame
) {
1309 ActiveScrolledRoot
* asr
= mBuilder
->AllocateActiveScrolledRoot(
1310 mBuilder
->mCurrentActiveScrolledRoot
, aScrollableFrame
);
1311 mBuilder
->mCurrentActiveScrolledRoot
= asr
;
1315 void InsertScrollFrame(nsIScrollableFrame
* aScrollableFrame
);
1318 nsDisplayListBuilder
* mBuilder
;
1320 * The builder's mCurrentActiveScrolledRoot at construction time which
1321 * needs to be restored at destruction time.
1323 const ActiveScrolledRoot
* mSavedActiveScrolledRoot
;
1325 * If there's a content clip on the builder at construction time, then
1326 * mContentClipASR is that content clip's ASR, otherwise null. The
1327 * assumption is that the content clip doesn't get relaxed while this
1328 * object is on the stack.
1330 const ActiveScrolledRoot
* mContentClipASR
;
1332 * InsertScrollFrame needs to mutate existing ASRs (those that were
1333 * created while this object was on the stack), and mDescendantsStartIndex
1334 * makes it easier to skip ASRs that were created in the past.
1336 size_t mDescendantsStartIndex
;
1338 * Flag to make sure that only one of SetCurrentActiveScrolledRoot /
1339 * EnterScrollFrame / InsertScrollFrame is called per instance of this
1346 * Keeps track of the innermost ASR that can be used as the ASR for a
1347 * container item that wraps all items that were created while this
1348 * object was on the stack.
1349 * The rule is: all child items of the container item need to have
1350 * clipped bounds with respect to the container ASR.
1352 class AutoContainerASRTracker
{
1354 explicit AutoContainerASRTracker(nsDisplayListBuilder
* aBuilder
)
1355 : mBuilder(aBuilder
),
1356 mSavedContainerASR(aBuilder
->mCurrentContainerASR
) {
1357 mBuilder
->mCurrentContainerASR
= ActiveScrolledRoot::PickDescendant(
1358 mBuilder
->ClipState().GetContentClipASR(),
1359 mBuilder
->mCurrentActiveScrolledRoot
);
1362 const ActiveScrolledRoot
* GetContainerASR() {
1363 return mBuilder
->mCurrentContainerASR
;
1366 ~AutoContainerASRTracker() {
1367 mBuilder
->mCurrentContainerASR
= ActiveScrolledRoot::PickAncestor(
1368 mBuilder
->mCurrentContainerASR
, mSavedContainerASR
);
1372 nsDisplayListBuilder
* mBuilder
;
1373 const ActiveScrolledRoot
* mSavedContainerASR
;
1377 * A helper class to temporarily set the value of mCurrentScrollbarTarget
1378 * and mCurrentScrollbarFlags.
1380 class AutoCurrentScrollbarInfoSetter
{
1382 AutoCurrentScrollbarInfoSetter(
1383 nsDisplayListBuilder
* aBuilder
, ViewID aScrollTargetID
,
1384 const MaybeScrollDirection
& aScrollbarDirection
, bool aWillHaveLayer
)
1385 : mBuilder(aBuilder
) {
1386 aBuilder
->mIsBuildingScrollbar
= true;
1387 aBuilder
->mCurrentScrollbarTarget
= aScrollTargetID
;
1388 aBuilder
->mCurrentScrollbarDirection
= aScrollbarDirection
;
1389 aBuilder
->mCurrentScrollbarWillHaveLayer
= aWillHaveLayer
;
1392 ~AutoCurrentScrollbarInfoSetter() {
1393 // No need to restore old values because scrollbars cannot be nested.
1394 mBuilder
->mIsBuildingScrollbar
= false;
1395 mBuilder
->mCurrentScrollbarTarget
= ScrollableLayerGuid::NULL_SCROLL_ID
;
1396 mBuilder
->mCurrentScrollbarDirection
.reset();
1397 mBuilder
->mCurrentScrollbarWillHaveLayer
= false;
1401 nsDisplayListBuilder
* mBuilder
;
1405 * A helper class to temporarily set mBuildingExtraPagesForPageNum.
1407 class MOZ_RAII AutoPageNumberSetter
{
1409 AutoPageNumberSetter(nsDisplayListBuilder
* aBuilder
, const uint8_t aPageNum
)
1410 : mBuilder(aBuilder
),
1411 mOldPageNum(aBuilder
->GetBuildingExtraPagesForPageNum()) {
1412 mBuilder
->SetBuildingExtraPagesForPageNum(aPageNum
);
1414 ~AutoPageNumberSetter() {
1415 mBuilder
->SetBuildingExtraPagesForPageNum(mOldPageNum
);
1419 nsDisplayListBuilder
* mBuilder
;
1420 uint8_t mOldPageNum
;
1424 * A helper class to track current effective transform for items.
1426 * For frames that is Combines3DTransformWithAncestors(), we need to
1427 * apply all transforms of ancestors on the same preserves3D chain
1428 * on the bounds of current frame to the coordination of the 3D
1429 * context root. The 3D context root computes it's bounds from
1430 * these transformed bounds.
1432 class AutoAccumulateTransform
{
1434 typedef mozilla::gfx::Matrix4x4 Matrix4x4
;
1436 explicit AutoAccumulateTransform(nsDisplayListBuilder
* aBuilder
)
1437 : mBuilder(aBuilder
),
1438 mSavedTransform(aBuilder
->mPreserves3DCtx
.mAccumulatedTransform
) {}
1440 ~AutoAccumulateTransform() {
1441 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
= mSavedTransform
;
1444 void Accumulate(const Matrix4x4
& aTransform
) {
1445 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
=
1446 aTransform
* mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
;
1449 const Matrix4x4
& GetCurrentTransform() {
1450 return mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
;
1454 mBuilder
->mPreserves3DCtx
.mAccumulatedTransform
= Matrix4x4();
1458 nsDisplayListBuilder
* mBuilder
;
1459 Matrix4x4 mSavedTransform
;
1463 * A helper class to collect bounds rects of descendants.
1465 * For a 3D context root, it's bounds is computed from the bounds of
1466 * descendants. If we transform bounds frame by frame applying
1467 * transforms, the bounds may turn to empty for any singular
1468 * transform on the path, but it is not empty for the accumulated
1471 class AutoAccumulateRect
{
1473 explicit AutoAccumulateRect(nsDisplayListBuilder
* aBuilder
)
1474 : mBuilder(aBuilder
),
1475 mSavedRect(aBuilder
->mPreserves3DCtx
.mAccumulatedRect
) {
1476 aBuilder
->mPreserves3DCtx
.mAccumulatedRect
= nsRect();
1477 aBuilder
->mPreserves3DCtx
.mAccumulatedRectLevels
++;
1480 ~AutoAccumulateRect() {
1481 mBuilder
->mPreserves3DCtx
.mAccumulatedRect
= mSavedRect
;
1482 mBuilder
->mPreserves3DCtx
.mAccumulatedRectLevels
--;
1486 nsDisplayListBuilder
* mBuilder
;
1490 void AccumulateRect(const nsRect
& aRect
) {
1491 mPreserves3DCtx
.mAccumulatedRect
.UnionRect(mPreserves3DCtx
.mAccumulatedRect
,
1495 const nsRect
& GetAccumulatedRect() {
1496 return mPreserves3DCtx
.mAccumulatedRect
;
1500 * The level is increased by one for items establishing 3D rendering
1501 * context and starting a new accumulation.
1503 int GetAccumulatedRectLevels() {
1504 return mPreserves3DCtx
.mAccumulatedRectLevels
;
1507 struct OutOfFlowDisplayData
{
1508 OutOfFlowDisplayData(
1509 const DisplayItemClipChain
* aContainingBlockClipChain
,
1510 const DisplayItemClipChain
* aCombinedClipChain
,
1511 const ActiveScrolledRoot
* aContainingBlockActiveScrolledRoot
,
1512 const nsRect
& aVisibleRect
, const nsRect
& aDirtyRect
)
1513 : mContainingBlockClipChain(aContainingBlockClipChain
),
1514 mCombinedClipChain(aCombinedClipChain
),
1515 mContainingBlockActiveScrolledRoot(
1516 aContainingBlockActiveScrolledRoot
),
1517 mVisibleRect(aVisibleRect
),
1518 mDirtyRect(aDirtyRect
) {}
1519 const DisplayItemClipChain
* mContainingBlockClipChain
;
1520 const DisplayItemClipChain
*
1521 mCombinedClipChain
; // only necessary for the special case of top layer
1522 const ActiveScrolledRoot
* mContainingBlockActiveScrolledRoot
;
1524 // If this OutOfFlowDisplayData is associated with the ViewportFrame
1525 // of a document that has a resolution (creating separate visual and
1526 // layout viewports with their own coordinate spaces), these rects
1527 // are in layout coordinates. Similarly, GetVisibleRectForFrame() in
1528 // such a case returns a quantity in layout coordinates.
1529 nsRect mVisibleRect
;
1532 static nsRect
ComputeVisibleRectForFrame(nsDisplayListBuilder
* aBuilder
,
1534 const nsRect
& aVisibleRect
,
1535 const nsRect
& aDirtyRect
,
1536 nsRect
* aOutDirtyRect
);
1538 nsRect
GetVisibleRectForFrame(nsDisplayListBuilder
* aBuilder
,
1539 nsIFrame
* aFrame
, nsRect
* aDirtyRect
) {
1540 return ComputeVisibleRectForFrame(aBuilder
, aFrame
, mVisibleRect
,
1541 mDirtyRect
, aDirtyRect
);
1545 NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty
,
1546 OutOfFlowDisplayData
)
1548 struct DisplayListBuildingData
{
1549 RefPtr
<AnimatedGeometryRoot
> mModifiedAGR
= nullptr;
1552 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect
,
1553 DisplayListBuildingData
)
1555 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect
,
1558 static OutOfFlowDisplayData
* GetOutOfFlowData(nsIFrame
* aFrame
) {
1559 if (!aFrame
->GetParent()) {
1562 return aFrame
->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
1565 nsPresContext
* CurrentPresContext();
1567 OutOfFlowDisplayData
* GetCurrentFixedBackgroundDisplayData() {
1568 auto& displayData
= CurrentPresShellState()->mFixedBackgroundDisplayData
;
1569 return displayData
? displayData
.ptr() : nullptr;
1573 * Accumulates the bounds of box frames that have moz-appearance
1574 * -moz-win-exclude-glass style. Used in setting glass margins on
1577 * We set the window opaque region (from which glass margins are computed)
1578 * to the intersection of the glass region specified here and the opaque
1579 * region computed during painting. So the excluded glass region actually
1580 * *limits* the extent of the opaque area reported to Windows. We limit it
1581 * so that changes to the computed opaque region (which can vary based on
1582 * region optimizations and the placement of UI elements) outside the
1583 * -moz-win-exclude-glass area don't affect the glass margins reported to
1584 * Windows; changing those margins willy-nilly can cause the Windows 7 glass
1585 * haze effect to jump around disconcertingly.
1587 void AddWindowExcludeGlassRegion(nsIFrame
* aFrame
, const nsRect
& aBounds
) {
1588 mWindowExcludeGlassRegion
.Add(aFrame
, aBounds
);
1592 * Returns the window exclude glass region.
1594 nsRegion
GetWindowExcludeGlassRegion() const {
1595 return mWindowExcludeGlassRegion
.ToRegion();
1599 * Accumulates opaque stuff into the window opaque region.
1601 void AddWindowOpaqueRegion(nsIFrame
* aFrame
, const nsRect
& aBounds
) {
1602 if (IsRetainingDisplayList()) {
1603 mRetainedWindowOpaqueRegion
.Add(aFrame
, aBounds
);
1606 mWindowOpaqueRegion
.Or(mWindowOpaqueRegion
, aBounds
);
1609 * Returns the window opaque region built so far. This may be incomplete
1610 * since the opaque region is built during layer construction.
1612 const nsRegion
GetWindowOpaqueRegion() {
1613 return IsRetainingDisplayList() ? mRetainedWindowOpaqueRegion
.ToRegion()
1614 : mWindowOpaqueRegion
;
1617 void SetGlassDisplayItem(nsDisplayItem
* aItem
);
1618 void ClearGlassDisplayItem() { mGlassDisplayItem
= nullptr; }
1619 nsDisplayItem
* GetGlassDisplayItem() { return mGlassDisplayItem
; }
1621 bool NeedToForceTransparentSurfaceForItem(nsDisplayItem
* aItem
);
1624 * mContainsBlendMode is true if we processed a display item that
1625 * has a blend mode attached. We do this so we can insert a
1626 * nsDisplayBlendContainer in the parent stacking context.
1628 void SetContainsBlendMode(bool aContainsBlendMode
) {
1629 mContainsBlendMode
= aContainsBlendMode
;
1631 bool ContainsBlendMode() const { return mContainsBlendMode
; }
1634 * mContainsBackdropFilter is true if we proccessed a display item that
1635 * has a backdrop filter set. We track this so we can insert a
1636 * nsDisplayBackdropRootContainer in the stacking context of the nearest
1637 * ancestor that forms a backdrop root.
1639 void SetContainsBackdropFilter(bool aContainsBackdropFilter
) {
1640 mContainsBackdropFilter
= aContainsBackdropFilter
;
1642 bool ContainsBackdropFilter() const { return mContainsBackdropFilter
; }
1644 DisplayListClipState
& ClipState() { return mClipState
; }
1645 const ActiveScrolledRoot
* CurrentActiveScrolledRoot() {
1646 return mCurrentActiveScrolledRoot
;
1648 const ActiveScrolledRoot
* CurrentAncestorASRStackingContextContents() {
1649 return mCurrentContainerASR
;
1653 * Add the current frame to the will-change budget if possible and
1654 * remeber the outcome. Subsequent calls to IsInWillChangeBudget
1655 * will return the same value as return here.
1657 bool AddToWillChangeBudget(nsIFrame
* aFrame
, const nsSize
& aSize
);
1660 * This will add the current frame to the will-change budget the first
1661 * time it is seen. On subsequent calls this will return the same
1662 * answer. This effectively implements a first-come, first-served
1663 * allocation of the will-change budget.
1665 bool IsInWillChangeBudget(nsIFrame
* aFrame
, const nsSize
& aSize
);
1668 * Clears the will-change budget status for the given |aFrame|.
1669 * This will also remove the frame from will-change budgets.
1671 void ClearWillChangeBudgetStatus(nsIFrame
* aFrame
);
1674 * Removes the given |aFrame| from will-change budgets.
1676 void RemoveFromWillChangeBudgets(const nsIFrame
* aFrame
);
1679 * Clears the will-change budgets.
1681 void ClearWillChangeBudgets();
1683 void EnterSVGEffectsContents(nsIFrame
* aEffectsFrame
,
1684 nsDisplayList
* aHoistedItemsStorage
);
1685 void ExitSVGEffectsContents();
1687 bool ShouldBuildScrollInfoItemsForHoisting() const;
1689 void AppendNewScrollInfoItemForHoisting(
1690 nsDisplayScrollInfoLayer
* aScrollInfoItem
);
1693 * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
1695 * mPreserves3DCtx is used by class AutoAccumulateTransform &
1696 * AutoAccumulateRect to passing data between frames in the 3D
1697 * context. If a frame create a new 3D context, it should restore
1698 * the value of mPreserves3DCtx before returning back to the parent.
1699 * This class do it for the users.
1701 class AutoPreserves3DContext
{
1703 explicit AutoPreserves3DContext(nsDisplayListBuilder
* aBuilder
)
1704 : mBuilder(aBuilder
), mSavedCtx(aBuilder
->mPreserves3DCtx
) {}
1706 ~AutoPreserves3DContext() { mBuilder
->mPreserves3DCtx
= mSavedCtx
; }
1709 nsDisplayListBuilder
* mBuilder
;
1710 Preserves3DContext mSavedCtx
;
1713 const nsRect
GetPreserves3DRect() const {
1714 return mPreserves3DCtx
.mVisibleRect
;
1717 void SavePreserves3DRect() { mPreserves3DCtx
.mVisibleRect
= mVisibleRect
; }
1719 void SavePreserves3DAllowAsyncAnimation(bool aValue
) {
1720 mPreserves3DCtx
.mAllowAsyncAnimation
= aValue
;
1723 bool GetPreserves3DAllowAsyncAnimation() const {
1724 return mPreserves3DCtx
.mAllowAsyncAnimation
;
1727 bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems
; }
1729 void SetBuildingInvisibleItems(bool aBuildingInvisibleItems
) {
1730 mBuildingInvisibleItems
= aBuildingInvisibleItems
;
1733 void SetBuildingExtraPagesForPageNum(uint8_t aPageNum
) {
1734 mBuildingExtraPagesForPageNum
= aPageNum
;
1736 uint8_t GetBuildingExtraPagesForPageNum() const {
1737 return mBuildingExtraPagesForPageNum
;
1741 * This is a convenience function to ease the transition until AGRs and ASRs
1744 AnimatedGeometryRoot
* AnimatedGeometryRootForASR(
1745 const ActiveScrolledRoot
* aASR
);
1747 bool HitTestIsForVisibility() const { return mVisibleThreshold
.isSome(); }
1749 float VisibilityThreshold() const {
1750 MOZ_DIAGNOSTIC_ASSERT(HitTestIsForVisibility());
1751 return mVisibleThreshold
.valueOr(1.0f
);
1754 void SetHitTestIsForVisibility(float aVisibleThreshold
) {
1755 mVisibleThreshold
= mozilla::Some(aVisibleThreshold
);
1758 bool ShouldBuildAsyncZoomContainer() const {
1759 return mBuildAsyncZoomContainer
;
1761 void UpdateShouldBuildAsyncZoomContainer();
1763 void UpdateShouldBuildBackdropRootContainer();
1765 bool ShouldRebuildDisplayListDueToPrefChange();
1768 * Represents a region composed of frame/rect pairs.
1769 * WeakFrames are used to track whether a rect still belongs to the region.
1770 * Modified frames and rects are removed and re-added to the region if needed.
1772 struct WeakFrameRegion
{
1774 * A wrapper to store WeakFrame and the pointer to the underlying frame.
1775 * This is needed because WeakFrame does not store the frame pointer after
1776 * the frame has been deleted.
1778 struct WeakFrameWrapper
{
1779 explicit WeakFrameWrapper(nsIFrame
* aFrame
)
1780 : mWeakFrame(new WeakFrame(aFrame
)), mFrame(aFrame
) {}
1782 mozilla::UniquePtr
<WeakFrame
> mWeakFrame
;
1786 nsTHashSet
<void*> mFrameSet
;
1787 nsTArray
<WeakFrameWrapper
> mFrames
;
1788 nsTArray
<pixman_box32_t
> mRects
;
1790 template <typename RectType
>
1791 void Add(nsIFrame
* aFrame
, const RectType
& aRect
) {
1792 if (mFrameSet
.Contains(aFrame
)) {
1796 mFrameSet
.Insert(aFrame
);
1797 mFrames
.AppendElement(WeakFrameWrapper(aFrame
));
1798 mRects
.AppendElement(nsRegion::RectToBox(aRect
));
1807 void RemoveModifiedFramesAndRects();
1809 size_t SizeOfExcludingThis(mozilla::MallocSizeOf
) const;
1811 typedef mozilla::gfx::ArrayView
<pixman_box32_t
> BoxArrayView
;
1813 nsRegion
ToRegion() const { return nsRegion(BoxArrayView(mRects
)); }
1815 LayoutDeviceIntRegion
ToLayoutDeviceIntRegion() const {
1816 return LayoutDeviceIntRegion(BoxArrayView(mRects
));
1820 void AddScrollFrameToNotify(nsIScrollableFrame
* aScrollFrame
);
1821 void NotifyAndClearScrollFrames();
1823 // Helper class to find what link spec (if any) to associate with a frame,
1824 // recording it in the builder, and generate the corresponding DisplayItem.
1827 Linkifier(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
1830 if (mBuilderToReset
) {
1831 mBuilderToReset
->mLinkSpec
.Truncate(0);
1835 void MaybeAppendLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
1836 nsDisplayList
* aList
);
1839 nsDisplayListBuilder
* mBuilderToReset
= nullptr;
1843 bool MarkOutOfFlowFrameForDisplay(nsIFrame
* aDirtyFrame
, nsIFrame
* aFrame
,
1844 const nsRect
& aVisibleRect
,
1845 const nsRect
& aDirtyRect
);
1848 * Returns whether a frame acts as an animated geometry root, optionally
1849 * returning the next ancestor to check.
1851 AGRState
IsAnimatedGeometryRoot(nsIFrame
* aFrame
, bool& aIsAsync
,
1852 nsIFrame
** aParent
= nullptr);
1855 * Returns the nearest ancestor frame to aFrame that is considered to have
1856 * (or will have) animated geometry. This can return aFrame.
1858 nsIFrame
* FindAnimatedGeometryRootFrameFor(nsIFrame
* aFrame
, bool& aIsAsync
);
1860 friend class nsDisplayCanvasBackgroundImage
;
1861 friend class nsDisplayBackgroundImage
;
1862 friend class nsDisplayFixedPosition
;
1863 friend class nsDisplayPerspective
;
1864 AnimatedGeometryRoot
* FindAnimatedGeometryRootFor(nsDisplayItem
* aItem
);
1866 friend class nsDisplayItem
;
1867 friend class nsDisplayOwnLayer
;
1868 friend struct RetainedDisplayListBuilder
;
1869 AnimatedGeometryRoot
* FindAnimatedGeometryRootFor(nsIFrame
* aFrame
);
1871 AnimatedGeometryRoot
* WrapAGRForFrame(
1872 nsIFrame
* aAnimatedGeometryRoot
, bool aIsAsync
,
1873 AnimatedGeometryRoot
* aParent
= nullptr);
1875 nsTHashMap
<nsIFrame
*, RefPtr
<AnimatedGeometryRoot
>>
1876 mFrameToAnimatedGeometryRootMap
;
1879 * Add the current frame to the AGR budget if possible and remember
1880 * the outcome. Subsequent calls will return the same value as
1883 bool AddToAGRBudget(nsIFrame
* aFrame
);
1885 struct PresShellState
{
1886 mozilla::PresShell
* mPresShell
;
1888 mozilla::Maybe
<nsAutoLayoutPhase
> mAutoLayoutPhase
;
1890 mozilla::Maybe
<OutOfFlowDisplayData
> mFixedBackgroundDisplayData
;
1891 uint32_t mFirstFrameMarkedForDisplay
;
1892 uint32_t mFirstFrameWithOOFData
;
1893 bool mIsBackgroundOnly
;
1894 // This is a per-document flag turning off event handling for all content
1895 // in the document, and is set when we enter a subdocument for a pointer-
1896 // events:none frame.
1897 bool mInsidePointerEventsNoneDoc
;
1898 bool mTouchEventPrefEnabledDoc
;
1899 nsIFrame
* mPresShellIgnoreScrollFrame
;
1902 PresShellState
* CurrentPresShellState() {
1903 NS_ASSERTION(mPresShellStates
.Length() > 0,
1904 "Someone forgot to enter a presshell");
1905 return &mPresShellStates
[mPresShellStates
.Length() - 1];
1908 void AddSizeOfExcludingThis(nsWindowSizes
&) const;
1910 struct FrameWillChangeBudget
{
1911 FrameWillChangeBudget() : mPresContext(nullptr), mUsage(0) {}
1913 FrameWillChangeBudget(const nsPresContext
* aPresContext
, uint32_t aUsage
)
1914 : mPresContext(aPresContext
), mUsage(aUsage
) {}
1916 const nsPresContext
* mPresContext
;
1920 nsIFrame
* const mReferenceFrame
;
1921 nsIFrame
* mIgnoreScrollFrame
;
1923 using Arena
= nsPresArena
<32768, mozilla::DisplayListArenaObjectId
,
1924 size_t(mozilla::DisplayListArenaObjectId::COUNT
)>;
1927 AutoTArray
<PresShellState
, 8> mPresShellStates
;
1928 AutoTArray
<nsIFrame
*, 400> mFramesMarkedForDisplay
;
1929 AutoTArray
<nsIFrame
*, 40> mFramesMarkedForDisplayIfVisible
;
1930 AutoTArray
<nsIFrame
*, 20> mFramesWithOOFData
;
1931 nsClassHashtable
<nsPtrHashKey
<nsDisplayItem
>, nsTArray
<ThemeGeometry
>>
1933 DisplayListClipState mClipState
;
1934 const ActiveScrolledRoot
* mCurrentActiveScrolledRoot
;
1935 const ActiveScrolledRoot
* mCurrentContainerASR
;
1936 // mCurrentFrame is the frame that we're currently calling (or about to call)
1937 // BuildDisplayList on.
1938 const nsIFrame
* mCurrentFrame
;
1939 // The reference frame for mCurrentFrame.
1940 const nsIFrame
* mCurrentReferenceFrame
;
1941 // The offset from mCurrentFrame to mCurrentReferenceFrame.
1942 nsPoint mCurrentOffsetToReferenceFrame
;
1944 const nsIFrame
* mAdditionalOffsetFrame
;
1945 mozilla::Maybe
<nsPoint
> mAdditionalOffset
;
1947 RefPtr
<AnimatedGeometryRoot
> mRootAGR
;
1948 RefPtr
<AnimatedGeometryRoot
> mCurrentAGR
;
1950 // will-change budget tracker
1951 typedef uint32_t DocumentWillChangeBudget
;
1952 nsTHashMap
<nsPtrHashKey
<const nsPresContext
>, DocumentWillChangeBudget
>
1953 mDocumentWillChangeBudgets
;
1955 // Any frame listed in this set is already counted in the budget
1956 // and thus is in-budget.
1957 nsTHashMap
<nsPtrHashKey
<const nsIFrame
>, FrameWillChangeBudget
>
1958 mFrameWillChangeBudgets
;
1960 uint8_t mBuildingExtraPagesForPageNum
;
1962 // Area of animated geometry root budget already allocated
1963 uint32_t mUsedAGRBudget
;
1964 // Set of frames already counted in budget
1965 nsTHashSet
<nsIFrame
*> mAGRBudgetSet
;
1967 nsTHashMap
<nsPtrHashKey
<RemoteBrowser
>, EffectsInfo
> mEffectsUpdates
;
1969 // Relative to mCurrentFrame.
1970 nsRect mVisibleRect
;
1973 // Tracked regions used for retained display list.
1974 WeakFrameRegion mWindowExcludeGlassRegion
;
1975 WeakFrameRegion mRetainedWindowDraggingRegion
;
1976 WeakFrameRegion mRetainedWindowNoDraggingRegion
;
1978 // Window opaque region is calculated during layer building.
1979 WeakFrameRegion mRetainedWindowOpaqueRegion
;
1981 // Optimized versions for non-retained display list.
1982 LayoutDeviceIntRegion mWindowDraggingRegion
;
1983 LayoutDeviceIntRegion mWindowNoDraggingRegion
;
1984 nsRegion mWindowOpaqueRegion
;
1986 // The display item for the Windows window glass background, if any
1987 // Set during full display list builds or during display list merging only,
1988 // partial display list builds don't touch this.
1989 nsDisplayItem
* mGlassDisplayItem
;
1990 // If we've encountered a glass item yet, only used during partial display
1992 bool mHasGlassItemDuringPartial
;
1994 nsIFrame
* mCaretFrame
;
1997 // A temporary list that we append scroll info items to while building
1998 // display items for the contents of frames with SVG effects.
1999 // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
2000 // This is a pointer and not a real nsDisplayList value because the
2001 // nsDisplayList class is defined below this class, so we can't use it here.
2002 nsDisplayList
* mScrollInfoItemsForHoisting
;
2003 nsTArray
<RefPtr
<ActiveScrolledRoot
>> mActiveScrolledRoots
;
2004 std::unordered_set
<const DisplayItemClipChain
*, DisplayItemClipChainHasher
,
2005 DisplayItemClipChainEqualer
>
2007 DisplayItemClipChain
* mFirstClipChainToDestroy
;
2008 nsTArray
<nsDisplayItem
*> mTemporaryItems
;
2009 nsDisplayListBuilderMode mMode
;
2010 nsDisplayTableBackgroundSet
* mTableBackgroundSet
;
2011 ViewID mCurrentScrollParentId
;
2012 ViewID mCurrentScrollbarTarget
;
2013 MaybeScrollDirection mCurrentScrollbarDirection
;
2014 Preserves3DContext mPreserves3DCtx
;
2015 nsTArray
<nsIFrame
*> mSVGEffectsFrames
;
2016 // When we are inside a filter, the current ASR at the time we entered the
2017 // filter. Otherwise nullptr.
2018 const ActiveScrolledRoot
* mFilterASR
;
2019 std::unordered_set
<nsIScrollableFrame
*> mScrollFramesToNotify
;
2020 nsCString mLinkSpec
; // Destination of link currently being emitted, if any.
2021 bool mContainsBlendMode
;
2022 bool mIsBuildingScrollbar
;
2023 bool mCurrentScrollbarWillHaveLayer
;
2025 bool mRetainingDisplayList
;
2026 bool mPartialUpdate
;
2027 bool mIgnoreSuppression
;
2028 bool mIncludeAllOutOfFlows
;
2029 bool mDescendIntoSubdocuments
;
2030 bool mSelectedFramesOnly
;
2031 bool mAllowMergingAndFlattening
;
2032 // True when we're building a display list that's directly or indirectly
2033 // under an nsDisplayTransform
2037 bool mInPageSequence
;
2038 bool mIsInChromePresContext
;
2039 bool mSyncDecodeImages
;
2040 bool mIsPaintingToWindow
;
2041 bool mUseHighQualityScaling
;
2042 bool mIsPaintingForWebRender
;
2043 bool mIsCompositingCheap
;
2044 bool mAncestorHasApzAwareEventHandler
;
2045 // True when the first async-scrollable scroll frame for which we build a
2046 // display list has a display port. An async-scrollable scroll frame is one
2047 // which WantsAsyncScroll().
2048 bool mHaveScrollableDisplayPort
;
2049 bool mWindowDraggingAllowed
;
2050 bool mIsBuildingForPopup
;
2051 bool mForceLayerForScrollParent
;
2052 bool mContainsNonMinimalDisplayPort
;
2053 bool mAsyncPanZoomEnabled
;
2054 bool mBuildingInvisibleItems
;
2056 bool mInInvalidSubtree
;
2057 bool mBuildCompositorHitTestInfo
;
2058 bool mDisablePartialUpdates
;
2059 bool mPartialBuildFailed
;
2060 bool mIsInActiveDocShell
;
2061 bool mBuildAsyncZoomContainer
;
2062 bool mContainsBackdropFilter
;
2063 bool mIsRelativeToLayoutViewport
;
2064 bool mUseOverlayScrollbars
;
2065 bool mAlwaysLayerizeScrollbars
;
2067 mozilla::Maybe
<float> mVisibleThreshold
;
2068 mozilla::gfx::CompositorHitTestInfo mCompositorHitTestInfo
;
2071 class nsDisplayItem
;
2072 class nsDisplayItemBase
;
2073 class nsPaintedDisplayItem
;
2074 class nsDisplayList
;
2075 class RetainedDisplayList
;
2077 // All types are defined in nsDisplayItemTypes.h
2078 #define NS_DISPLAY_DECL_NAME(n, e) \
2079 const char* Name() const override { return n; } \
2080 constexpr static DisplayItemType ItemType() { return DisplayItemType::e; } \
2083 void* operator new(size_t aSize, nsDisplayListBuilder* aBuilder) { \
2084 return aBuilder->Allocate(aSize, DisplayItemType::e); \
2087 template <typename T, typename F, typename... Args> \
2088 friend T* ::MakeDisplayItemWithIndex(nsDisplayListBuilder* aBuilder, \
2089 F* aFrame, const uint16_t aIndex, \
2094 #define NS_DISPLAY_ALLOW_CLONING() \
2095 template <typename T> \
2096 friend T* MakeClone(nsDisplayListBuilder* aBuilder, const T* aItem); \
2098 nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override { \
2099 return MakeClone(aBuilder, this); \
2102 template <typename T
>
2103 MOZ_ALWAYS_INLINE T
* MakeClone(nsDisplayListBuilder
* aBuilder
, const T
* aItem
) {
2104 static_assert(std::is_base_of
<nsDisplayWrapList
, T
>::value
,
2105 "Display item type should be derived from nsDisplayWrapList");
2106 T
* item
= new (aBuilder
) T(aBuilder
, *aItem
);
2107 item
->SetType(T::ItemType());
2111 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2112 void AssertUniqueItem(nsDisplayItem
* aItem
);
2116 * Returns true, if a display item of given |aType| needs to be built within
2117 * opacity:0 container.
2119 bool ShouldBuildItemForEvents(const DisplayItemType aType
);
2122 * Initializes the hit test information of |aItem| if the item type supports it.
2124 void InitializeHitTestInfo(nsDisplayListBuilder
* aBuilder
,
2125 nsPaintedDisplayItem
* aItem
,
2126 const DisplayItemType aType
);
2128 template <typename T
, typename F
, typename
... Args
>
2129 MOZ_ALWAYS_INLINE T
* MakeDisplayItemWithIndex(nsDisplayListBuilder
* aBuilder
,
2130 F
* aFrame
, const uint16_t aIndex
,
2132 static_assert(std::is_base_of
<nsDisplayItem
, T
>::value
,
2133 "Display item type should be derived from nsDisplayItem");
2134 static_assert(std::is_base_of
<nsIFrame
, F
>::value
,
2135 "Frame type should be derived from nsIFrame");
2137 const DisplayItemType type
= T::ItemType();
2138 if (aBuilder
->InEventsOnly() && !ShouldBuildItemForEvents(type
)) {
2139 // This item is not needed for events.
2143 T
* item
= new (aBuilder
) T(aBuilder
, aFrame
, std::forward
<Args
>(aArgs
)...);
2145 if (type
!= DisplayItemType::TYPE_GENERIC
) {
2146 item
->SetType(type
);
2149 item
->SetPerFrameIndex(aIndex
);
2150 item
->SetExtraPageForPageNum(aBuilder
->GetBuildingExtraPagesForPageNum());
2152 nsPaintedDisplayItem
* paintedItem
= item
->AsPaintedDisplayItem();
2154 InitializeHitTestInfo(aBuilder
, paintedItem
, type
);
2157 if (aBuilder
->InInvalidSubtree() ||
2158 item
->FrameForInvalidation()->IsFrameModified()) {
2159 item
->SetModifiedFrame(true);
2162 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2163 if (aBuilder
->IsRetainingDisplayList() && aBuilder
->IsBuilding()) {
2164 AssertUniqueItem(item
);
2167 // Verify that InInvalidSubtree matches invalidation frame's modified state.
2168 if (aBuilder
->InInvalidSubtree()) {
2169 MOZ_DIAGNOSTIC_ASSERT(
2170 AnyContentAncestorModified(item
->FrameForInvalidation()));
2173 mozilla::DebugOnly
<bool> isContainerType
=
2174 (GetDisplayItemFlagsForType(type
) & TYPE_IS_CONTAINER
);
2176 MOZ_ASSERT(item
->HasChildren() == isContainerType
,
2177 "Container items must have container display item flag set.");
2183 template <typename T
, typename F
, typename
... Args
>
2184 MOZ_ALWAYS_INLINE T
* MakeDisplayItem(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
2186 return MakeDisplayItemWithIndex
<T
>(aBuilder
, aFrame
, 0,
2187 std::forward
<Args
>(aArgs
)...);
2191 * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
2192 * nsDisplayItemLink holds the link. The lists are linked from lowest to
2193 * highest in z-order.
2195 class nsDisplayItemLink
{
2196 // This is never instantiated directly, so no need to count constructors and
2199 nsDisplayItemLink() : mAbove(nullptr) {}
2200 nsDisplayItemLink(const nsDisplayItemLink
&) : mAbove(nullptr) {}
2201 ~nsDisplayItemLink() { MOZ_RELEASE_ASSERT(!mAbove
); }
2202 nsDisplayItem
* mAbove
;
2204 friend class nsDisplayList
;
2208 * nsDisplayItemBase is a base-class for all display items. It is mainly
2209 * responsible for handling the frame-display item 1:n relationship, as well as
2210 * storing the state needed for display list merging.
2212 * Display items are arena-allocated during display list construction.
2214 * Display items can be containers --- i.e., they can perform hit testing
2215 * and painting by recursively traversing a list of child items.
2217 * Display items belong to a list at all times (except temporarily as they
2218 * move from one list to another).
2220 class nsDisplayItemBase
: public nsDisplayItemLink
{
2222 nsDisplayItemBase() = delete;
2225 * Downcasts this item to nsPaintedDisplayItem, if possible.
2227 virtual nsPaintedDisplayItem
* AsPaintedDisplayItem() { return nullptr; }
2228 virtual const nsPaintedDisplayItem
* AsPaintedDisplayItem() const {
2233 * Downcasts this item to nsDisplayWrapList, if possible.
2235 virtual nsDisplayWrapList
* AsDisplayWrapList() { return nullptr; }
2236 virtual const nsDisplayWrapList
* AsDisplayWrapList() const { return nullptr; }
2239 * Create a clone of this item.
2241 virtual nsDisplayWrapList
* Clone(nsDisplayListBuilder
* aBuilder
) const {
2246 * Frees the memory allocated for this display item.
2247 * The given display list builder must have allocated this display item.
2249 virtual void Destroy(nsDisplayListBuilder
* aBuilder
) {
2250 const DisplayItemType type
= GetType();
2251 this->~nsDisplayItemBase();
2252 aBuilder
->Destroy(type
, this);
2256 * Returns the frame that this display item was created for.
2257 * Never returns null.
2259 inline nsIFrame
* Frame() const {
2260 MOZ_ASSERT(mFrame
, "Trying to use display item after deletion!");
2265 * Called when the display item is prepared for deletion. The display item
2266 * should not be used after calling this function.
2268 virtual void RemoveFrame(nsIFrame
* aFrame
) {
2271 if (mFrame
&& aFrame
== mFrame
) {
2278 * A display item can depend on multiple different frames for invalidation.
2280 virtual nsIFrame
* GetDependentFrame() { return nullptr; }
2283 * Returns the frame that provides the style data, and should
2284 * be checked when deciding if this display item can be reused.
2286 virtual nsIFrame
* FrameForInvalidation() const { return Frame(); }
2289 * Returns the printable name of this display item.
2291 virtual const char* Name() const = 0;
2294 * Some consecutive items should be rendered together as a unit, e.g.,
2295 * outlines for the same element. For this, we need a way for items to
2296 * identify their type. We use the type for other purposes too.
2298 DisplayItemType
GetType() const {
2299 MOZ_ASSERT(mType
!= DisplayItemType::TYPE_ZERO
,
2300 "Display item should have a valid type!");
2305 * Pairing this with the Frame() pointer gives a key that
2306 * uniquely identifies this display item in the display item tree.
2308 uint32_t GetPerFrameKey() const {
2309 // The top 8 bits are the page index
2310 // The middle 16 bits of the per frame key uniquely identify the display
2311 // item when there are more than one item of the same type for a frame.
2312 // The low 8 bits are the display item type.
2313 return (static_cast<uint32_t>(mExtraPageForPageNum
)
2314 << (TYPE_BITS
+ (sizeof(mPerFrameIndex
) * 8))) |
2315 (static_cast<uint32_t>(mPerFrameIndex
) << TYPE_BITS
) |
2316 static_cast<uint32_t>(mType
);
2320 * Returns true if this item was reused during display list merging.
2322 bool IsReused() const {
2323 return mItemFlags
.contains(ItemBaseFlag::ReusedItem
);
2326 void SetReused(bool aReused
) {
2328 mItemFlags
+= ItemBaseFlag::ReusedItem
;
2330 mItemFlags
-= ItemBaseFlag::ReusedItem
;
2335 * Returns true if this item can be reused during display list merging.
2337 bool CanBeReused() const {
2338 return !mItemFlags
.contains(ItemBaseFlag::CantBeReused
);
2341 void SetCantBeReused() { mItemFlags
+= ItemBaseFlag::CantBeReused
; }
2343 bool CanBeCached() const {
2344 return !mItemFlags
.contains(ItemBaseFlag::CantBeCached
);
2347 void SetCantBeCached() { mItemFlags
+= ItemBaseFlag::CantBeCached
; }
2349 bool IsOldItem() const { return !!mOldList
; }
2352 * Returns true if the frame of this display item is in a modified subtree.
2354 bool HasModifiedFrame() const;
2355 void SetModifiedFrame(bool aModified
);
2356 bool HasDeletedFrame() const;
2359 * Set the nsDisplayList that this item belongs to, and what index it is
2361 * Temporary state for merging used by RetainedDisplayListBuilder.
2363 void SetOldListIndex(nsDisplayList
* aList
, OldListIndex aIndex
,
2364 uint32_t aListKey
, uint32_t aNestingDepth
) {
2365 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2366 mOldListKey
= aListKey
;
2367 mOldNestingDepth
= aNestingDepth
;
2369 mOldList
= reinterpret_cast<uintptr_t>(aList
);
2370 mOldListIndex
= aIndex
;
2373 bool GetOldListIndex(nsDisplayList
* aList
, uint32_t aListKey
,
2374 OldListIndex
* aOutIndex
) {
2375 if (mOldList
!= reinterpret_cast<uintptr_t>(aList
)) {
2376 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2377 MOZ_CRASH_UNSAFE_PRINTF(
2378 "Item found was in the wrong list! type %d "
2379 "(outer type was %d at depth %d, now is %d)",
2380 GetPerFrameKey(), mOldListKey
, mOldNestingDepth
, aListKey
);
2384 *aOutIndex
= mOldListIndex
;
2389 * Returns the display list containing the children of this display item.
2390 * The children may be in a different coordinate system than this item.
2392 virtual RetainedDisplayList
* GetChildren() const { return nullptr; }
2393 bool HasChildren() const { return GetChildren(); }
2396 * Display items with children may return true here. This causes the
2397 * display list iterator to descend into the child display list.
2399 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) {
2404 nsDisplayItemBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
2405 : mFrame(aFrame
), mType(DisplayItemType::TYPE_ZERO
) {
2406 MOZ_COUNT_CTOR(nsDisplayItemBase
);
2409 if (aBuilder
->IsRetainingDisplayList()) {
2410 mFrame
->AddDisplayItem(this);
2414 nsDisplayItemBase(nsDisplayListBuilder
* aBuilder
,
2415 const nsDisplayItemBase
& aOther
)
2416 : mFrame(aOther
.mFrame
),
2417 mItemFlags(aOther
.mItemFlags
),
2418 mType(aOther
.mType
),
2419 mExtraPageForPageNum(aOther
.mExtraPageForPageNum
),
2420 mPerFrameIndex(aOther
.mPerFrameIndex
) {
2421 MOZ_COUNT_CTOR(nsDisplayItemBase
);
2424 virtual ~nsDisplayItemBase() {
2425 MOZ_COUNT_DTOR(nsDisplayItemBase
);
2427 mFrame
->RemoveDisplayItem(this);
2431 void SetType(const DisplayItemType aType
) { mType
= aType
; }
2433 void SetPerFrameIndex(const uint16_t aIndex
) { mPerFrameIndex
= aIndex
; }
2435 // Display list building for printing can build duplicate
2436 // container display items when they contain a mixture of
2437 // OOF and normal content that is spread across multiple
2438 // pages. We include the page number for the duplicates
2439 // to make our GetPerFrameKey unique.
2440 void SetExtraPageForPageNum(const uint8_t aPageNum
) {
2441 mExtraPageForPageNum
= aPageNum
;
2444 void SetDeletedFrame();
2446 nsIFrame
* mFrame
; // 8
2449 enum class ItemBaseFlag
: uint8_t {
2455 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2461 mozilla::EnumSet
<ItemBaseFlag
, uint8_t> mItemFlags
; // 1
2462 DisplayItemType mType
; // 1
2463 uint8_t mExtraPageForPageNum
= 0; // 1
2464 uint16_t mPerFrameIndex
; // 2
2465 OldListIndex mOldListIndex
; // 4
2466 uintptr_t mOldList
= 0; // 8
2468 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2470 bool IsMergedItem() const {
2471 return mItemFlags
.contains(ItemBaseFlag::MergedItem
);
2474 bool IsPreProcessedItem() const {
2475 return mItemFlags
.contains(ItemBaseFlag::PreProcessedItem
);
2478 void SetMergedPreProcessed(bool aMerged
, bool aPreProcessed
) {
2480 mItemFlags
+= ItemBaseFlag::MergedItem
;
2482 mItemFlags
-= ItemBaseFlag::MergedItem
;
2485 if (aPreProcessed
) {
2486 mItemFlags
+= ItemBaseFlag::PreProcessedItem
;
2488 mItemFlags
-= ItemBaseFlag::PreProcessedItem
;
2492 uint32_t mOldListKey
= 0;
2493 uint32_t mOldNestingDepth
= 0;
2498 * This is the unit of rendering and event testing. Each instance of this
2499 * class represents an entity that can be drawn on the screen, e.g., a
2500 * frame's CSS background, or a frame's text string.
2502 class nsDisplayItem
: public nsDisplayItemBase
{
2504 typedef mozilla::ContainerLayerParameters ContainerLayerParameters
;
2505 typedef mozilla::DisplayItemClip DisplayItemClip
;
2506 typedef mozilla::DisplayItemClipChain DisplayItemClipChain
;
2507 typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot
;
2508 typedef mozilla::layers::FrameMetrics FrameMetrics
;
2509 typedef mozilla::layers::ScrollMetadata ScrollMetadata
;
2510 typedef mozilla::layers::ScrollableLayerGuid::ViewID ViewID
;
2511 typedef mozilla::layers::Layer Layer
;
2512 typedef mozilla::layers::LayerManager LayerManager
;
2513 typedef mozilla::layers::StackingContextHelper StackingContextHelper
;
2514 typedef mozilla::layers::WebRenderCommand WebRenderCommand
;
2515 typedef mozilla::layers::WebRenderParentCommand WebRenderParentCommand
;
2516 typedef mozilla::LayerState LayerState
;
2517 typedef mozilla::image::imgDrawingParams imgDrawingParams
;
2518 typedef mozilla::image::ImgDrawResult ImgDrawResult
;
2519 typedef class mozilla::gfx::DrawTarget DrawTarget
;
2520 typedef mozilla::gfx::CompositorHitTestInfo CompositorHitTestInfo
;
2523 // This is never instantiated directly (it has pure virtual methods), so no
2524 // need to count constructors and destructors.
2525 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
2526 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
2527 const ActiveScrolledRoot
* aActiveScrolledRoot
);
2529 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayItem
)
2532 * The custom copy-constructor is implemented to prevent copying the saved
2533 * state of the item.
2534 * This is currently only used when creating temporary items for merging.
2536 nsDisplayItem(nsDisplayListBuilder
* aBuilder
, const nsDisplayItem
& aOther
)
2537 : nsDisplayItemBase(aBuilder
, aOther
),
2538 mClipChain(aOther
.mClipChain
),
2539 mClip(aOther
.mClip
),
2540 mActiveScrolledRoot(aOther
.mActiveScrolledRoot
),
2541 mReferenceFrame(aOther
.mReferenceFrame
),
2542 mAnimatedGeometryRoot(aOther
.mAnimatedGeometryRoot
),
2543 mToReferenceFrame(aOther
.mToReferenceFrame
),
2544 mBuildingRect(aOther
.mBuildingRect
),
2545 mPaintRect(aOther
.mPaintRect
) {
2546 MOZ_COUNT_CTOR(nsDisplayItem
);
2547 // TODO: It might be better to remove the flags that aren't copied.
2548 if (aOther
.ForceNotVisible()) {
2549 mItemFlags
+= ItemFlag::ForceNotVisible
;
2551 if (aOther
.IsSubpixelAADisabled()) {
2552 mItemFlags
+= ItemFlag::DisableSubpixelAA
;
2554 if (mFrame
->In3DContextAndBackfaceIsHidden()) {
2555 mItemFlags
+= ItemFlag::BackfaceHidden
;
2557 if (aOther
.Combines3DTransformWithAncestors()) {
2558 mItemFlags
+= ItemFlag::Combines3DTransformWithAncestors
;
2563 nsDisplayItem() = delete;
2564 nsDisplayItem(const nsDisplayItem
&) = delete;
2567 * Roll back side effects carried out by processing the display list.
2569 * @return true if the rollback actually modified anything, to help the caller
2570 * decide whether to invalidate cached information about this node.
2572 virtual bool RestoreState() {
2573 if (mClipChain
== mState
.mClipChain
&& mClip
== mState
.mClip
&&
2574 !mItemFlags
.contains(ItemFlag::DisableSubpixelAA
)) {
2578 mClipChain
= mState
.mClipChain
;
2579 mClip
= mState
.mClip
;
2580 mItemFlags
-= ItemFlag::DisableSubpixelAA
;
2585 * Invalidate cached information that depends on this node's contents, after
2586 * a mutation of those contents.
2588 * Specifically, if you mutate an |nsDisplayItem| in a way that would change
2589 * the WebRender display list items generated for it, you should call this
2592 * If a |RestoreState| method exists to restore some piece of state, that's a
2593 * good indication that modifications to said state should be accompanied by a
2594 * call to this method. Opacity flattening's effects on
2595 * |nsDisplayBackgroundColor| items are one example.
2597 virtual void InvalidateItemCacheEntry() {}
2599 struct HitTestState
{
2600 explicit HitTestState() = default;
2603 NS_ASSERTION(mItemBuffer
.Length() == 0,
2604 "mItemBuffer should have been cleared");
2607 // Handling transform items for preserve 3D frames.
2608 bool mInPreserves3D
= false;
2609 // When hit-testing for visibility, we may hit an fully opaque item in a
2610 // nested display list. We want to stop at that point, without looking
2611 // further on other items.
2612 bool mHitOccludingItem
= false;
2614 float mCurrentOpacity
= 1.0f
;
2616 AutoTArray
<nsDisplayItem
*, 100> mItemBuffer
;
2619 uint8_t GetFlags() const { return GetDisplayItemFlagsForType(GetType()); }
2621 virtual bool IsContentful() const { return GetFlags() & TYPE_IS_CONTENTFUL
; }
2624 * This is called after we've constructed a display list for event handling.
2625 * When this is called, we've already ensured that aRect intersects the
2626 * item's bounds and that clipping has been taking into account.
2628 * @param aRect the point or rect being tested, relative to the reference
2629 * frame. If the width and height are both 1 app unit, it indicates we're
2630 * hit testing a point, not a rect.
2631 * @param aState must point to a HitTestState. If you don't have one,
2632 * just create one with the default constructor and pass it in.
2633 * @param aOutFrames each item appends the frame(s) in this display item that
2634 * the rect is considered over (if any) to aOutFrames.
2636 virtual void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
2637 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) {}
2639 virtual nsIFrame
* StyleFrame() const { return mFrame
; }
2642 * Compute the used z-index of our frame; returns zero for elements to which
2643 * z-index does not apply, and for z-index:auto.
2644 * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
2646 virtual int32_t ZIndex() const;
2648 * The default bounds is the frame border rect.
2649 * @param aSnap *aSnap is set to true if the returned rect will be
2650 * snapped to nearest device pixel edges during actual drawing.
2651 * It might be set to false and snap anyway, so code computing the set of
2652 * pixels affected by this display item needs to round outwards to pixel
2653 * boundaries when *aSnap is set to false.
2654 * This does not take the item's clipping into account.
2655 * @return a rectangle relative to aBuilder->ReferenceFrame() that
2656 * contains the area drawn by this display item
2658 virtual nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const {
2660 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2664 * Returns the untransformed bounds of this display item.
2666 virtual nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
2667 bool* aSnap
) const {
2668 return GetBounds(aBuilder
, aSnap
);
2671 virtual nsRegion
GetTightBounds(nsDisplayListBuilder
* aBuilder
,
2672 bool* aSnap
) const {
2678 * Returns true if nothing will be rendered inside aRect, false if uncertain.
2679 * aRect is assumed to be contained in this item's bounds.
2681 virtual bool IsInvisibleInRect(const nsRect
& aRect
) const { return false; }
2684 * Returns the result of GetBounds intersected with the item's clip.
2685 * The intersection is approximate since rounded corners are not taking into
2688 nsRect
GetClippedBounds(nsDisplayListBuilder
* aBuilder
) const;
2690 nsRect
GetBorderRect() const {
2691 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2694 nsRect
GetPaddingRect() const {
2695 return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
2698 nsRect
GetContentRect() const {
2699 return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
2703 * Checks if the frame(s) owning this display item have been marked as
2704 * invalid, and needing repainting.
2706 virtual bool IsInvalid(nsRect
& aRect
) const {
2707 bool result
= mFrame
? mFrame
->IsInvalid(aRect
) : false;
2708 aRect
+= ToReferenceFrame();
2713 * Creates and initializes an nsDisplayItemGeometry object that retains the
2714 * current areas covered by this display item. These need to retain enough
2715 * information such that they can be compared against a future nsDisplayItem
2716 * of the same type, and determine if repainting needs to happen.
2718 * Subclasses wishing to store more information need to override both this
2719 * and ComputeInvalidationRegion, as well as implementing an
2720 * nsDisplayItemGeometry subclass.
2722 * The default implementation tracks both the display item bounds, and the
2723 * frame's border rect.
2725 virtual nsDisplayItemGeometry
* AllocateGeometry(
2726 nsDisplayListBuilder
* aBuilder
) {
2727 return new nsDisplayItemGenericGeometry(this, aBuilder
);
2731 * Compares an nsDisplayItemGeometry object from a previous paint against the
2732 * current item. Computes if the geometry of the item has changed, and the
2733 * invalidation area required for correct repainting.
2735 * The existing geometry will have been created from a display item with a
2736 * matching GetPerFrameKey()/mFrame pair to the current item.
2738 * The default implementation compares the display item bounds, and the
2739 * frame's border rect, and invalidates the entire bounds if either rect
2742 * @param aGeometry The geometry of the matching display item from the
2744 * @param aInvalidRegion Output param, the region to invalidate, or
2745 * unchanged if none.
2747 virtual void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
2748 const nsDisplayItemGeometry
* aGeometry
,
2749 nsRegion
* aInvalidRegion
) const {
2750 const nsDisplayItemGenericGeometry
* geometry
=
2751 static_cast<const nsDisplayItemGenericGeometry
*>(aGeometry
);
2753 if (!geometry
->mBounds
.IsEqualInterior(GetBounds(aBuilder
, &snap
)) ||
2754 !geometry
->mBorderRect
.IsEqualInterior(GetBorderRect())) {
2755 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
2760 * An alternative default implementation of ComputeInvalidationRegion,
2761 * that instead invalidates only the changed area between the two items.
2763 void ComputeInvalidationRegionDifference(
2764 nsDisplayListBuilder
* aBuilder
,
2765 const nsDisplayItemBoundsGeometry
* aGeometry
,
2766 nsRegion
* aInvalidRegion
) const {
2768 nsRect bounds
= GetBounds(aBuilder
, &snap
);
2770 if (!aGeometry
->mBounds
.IsEqualInterior(bounds
)) {
2772 if (aGeometry
->mHasRoundedCorners
|| Frame()->GetBorderRadii(radii
)) {
2773 aInvalidRegion
->Or(aGeometry
->mBounds
, bounds
);
2775 aInvalidRegion
->Xor(aGeometry
->mBounds
, bounds
);
2781 * This function is called when an item's list of children has been modified
2782 * by RetainedDisplayListBuilder.
2784 virtual void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) {}
2786 virtual void AddSizeOfExcludingThis(nsWindowSizes
&) const {}
2789 * @param aSnap set to true if the edges of the rectangles of the opaque
2790 * region would be snapped to device pixels when drawing
2791 * @return a region of the item that is opaque --- that is, every pixel
2792 * that is visible is painted with an opaque
2793 * color. This is useful for determining when one piece
2794 * of content completely obscures another so that we can do occlusion
2796 * This does not take clipping into account.
2797 * This must return a simple region (1 rect) for painting display lists.
2798 * It is only allowed to be a complex region for hit testing.
2800 virtual nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
2801 bool* aSnap
) const {
2806 * @return Some(nscolor) if the item is guaranteed to paint every pixel in its
2807 * bounds with the same (possibly translucent) color
2809 virtual mozilla::Maybe
<nscolor
> IsUniform(
2810 nsDisplayListBuilder
* aBuilder
) const {
2811 return mozilla::Nothing();
2815 * @return true if the contents of this item are rendered fixed relative
2816 * to the nearest viewport.
2818 virtual bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const {
2823 * Returns true if all layers that can be active should be forced to be
2824 * active. Requires setting the pref layers.force-active=true.
2826 static bool ForceActiveLayers();
2829 * @return LAYER_NONE if BuildLayer will return null. In this case
2830 * there is no layer for the item, and Paint should be called instead
2831 * to paint the content using Thebes.
2832 * Return LAYER_INACTIVE if there is a layer --- BuildLayer will
2833 * not return null (unless there's an error) --- but the layer contents
2834 * are not changing frequently. In this case it makes sense to composite
2835 * the layer into a PaintedLayer with other content, so we don't have to
2836 * recomposite it every time we paint.
2837 * Note: GetLayerState is only allowed to return LAYER_INACTIVE if all
2838 * descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also,
2839 * all descendant display item frames must have an active scrolled root
2840 * that's either the same as this item's frame's active scrolled root, or
2841 * a descendant of this item's frame. This ensures that the entire
2842 * set of display items can be collapsed onto a single PaintedLayer.
2843 * Return LAYER_ACTIVE if the layer is active, that is, its contents are
2844 * changing frequently. In this case it makes sense to keep the layer
2845 * as a separate buffer in VRAM and composite it into the destination
2846 * every time we paint.
2848 * Users of GetLayerState should check ForceActiveLayers() and if it returns
2849 * true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE.
2851 virtual LayerState
GetLayerState(
2852 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
2853 const ContainerLayerParameters
& aParameters
) {
2854 return mozilla::LayerState::LAYER_NONE
;
2857 #ifdef MOZ_DUMP_PAINTING
2859 * Mark this display item as being painted via
2860 * FrameLayerBuilder::DrawPaintedLayer.
2862 bool Painted() const { return mItemFlags
.contains(ItemFlag::Painted
); }
2865 * Check if this display item has been painted.
2867 void SetPainted() { mItemFlags
+= ItemFlag::Painted
; }
2870 void SetIsGlassItem() { mItemFlags
+= ItemFlag::IsGlassItem
; }
2871 bool IsGlassItem() { return mItemFlags
.contains(ItemFlag::IsGlassItem
); }
2874 * Function to create the WebRenderCommands.
2875 * We should check if the layer state is
2876 * active first and have an early return if the layer state is
2879 * @return true if successfully creating webrender commands.
2881 virtual bool CreateWebRenderCommands(
2882 mozilla::wr::DisplayListBuilder
& aBuilder
,
2883 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
2884 const StackingContextHelper
& aSc
,
2885 mozilla::layers::RenderRootStateManager
* aManager
,
2886 nsDisplayListBuilder
* aDisplayListBuilder
) {
2891 * Updates the provided aLayerData with any APZ-relevant scroll data
2892 * that is specific to this display item. This is stuff that would normally
2893 * be put on the layer during BuildLayer, but this is only called in
2894 * layers-free webrender mode, where we don't have layers.
2896 * This function returns true if and only if it has APZ-relevant scroll data
2897 * to provide. Note that the arguments passed in may be nullptr, in which case
2898 * the function should still return true if and only if it has APZ-relevant
2899 * scroll data, but obviously in this case it can't actually put the
2900 * data onto aLayerData, because there isn't one.
2902 * This function assumes that aData and aLayerData will either both be null,
2903 * or will both be non-null. The caller is responsible for enforcing this.
2905 virtual bool UpdateScrollData(
2906 mozilla::layers::WebRenderScrollData
* aData
,
2907 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) {
2912 * On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
2913 * which may be visible. If the display item opaquely covers an area, it
2914 * can remove that area from aVisibleRegion before returning.
2915 * nsDisplayList::ComputeVisibility automatically subtracts the region
2916 * returned by GetOpaqueRegion, and automatically removes items whose bounds
2917 * do not intersect the visible area, so implementations of
2918 * nsDisplayItem::ComputeVisibility do not need to do these things.
2919 * nsDisplayList::ComputeVisibility will already have set mVisibleRect on
2920 * this item to the intersection of *aVisibleRegion and this item's bounds.
2921 * We rely on that, so this should only be called by
2922 * nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility.
2923 * This method needs to be idempotent.
2925 * @return true if the item is visible, false if no part of the item
2928 virtual bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
2929 nsRegion
* aVisibleRegion
);
2932 * Returns true if this item needs to have its geometry updated, despite
2933 * returning empty invalidation region.
2935 virtual bool NeedsGeometryUpdates() const { return false; }
2938 * Some items such as those calling into the native themed widget machinery
2939 * have to be painted on the content process. In this case it is best to avoid
2940 * allocating layers that serializes and forwards the work to the compositor.
2942 virtual bool MustPaintOnContentSide() const { return false; }
2945 * If this has a child list where the children are in the same coordinate
2946 * system as this item (i.e., they have the same reference frame),
2949 virtual RetainedDisplayList
* GetSameCoordinateSystemChildren() const {
2953 virtual void UpdateBounds(nsDisplayListBuilder
* aBuilder
) {}
2955 * Do UpdateBounds() for items with frames establishing or extending
2956 * 3D rendering context.
2958 * This function is called by UpdateBoundsFor3D() of
2959 * nsDisplayTransform(), and it is called by
2960 * BuildDisplayListForStackingContext() on transform items
2961 * establishing 3D rendering context.
2963 * The bounds of a transform item with the frame establishing 3D
2964 * rendering context should be computed by calling
2965 * DoUpdateBoundsPreserves3D() on all descendants that participate
2966 * the same 3d rendering context.
2968 virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) {}
2971 * Returns the building rectangle used by nsDisplayListBuilder when
2972 * this item was constructed.
2974 const nsRect
& GetBuildingRect() const { return mBuildingRect
; }
2976 void SetBuildingRect(const nsRect
& aBuildingRect
) {
2977 if (aBuildingRect
== mBuildingRect
) {
2978 // Avoid unnecessary paint rect recompution when the
2979 // building rect is staying the same.
2982 mPaintRect
= mBuildingRect
= aBuildingRect
;
2983 mItemFlags
-= ItemFlag::PaintRectValid
;
2986 void SetPaintRect(const nsRect
& aPaintRect
) {
2987 mPaintRect
= aPaintRect
;
2988 mItemFlags
+= ItemFlag::PaintRectValid
;
2990 bool HasPaintRect() const {
2991 return mItemFlags
.contains(ItemFlag::PaintRectValid
);
2995 * Returns the building rect for the children, relative to their
2996 * reference frame. Can be different from mBuildingRect for
2997 * nsDisplayTransform, since the reference frame for the children is different
2998 * from the reference frame for the item itself.
3000 virtual const nsRect
& GetBuildingRectForChildren() const {
3001 return mBuildingRect
;
3004 virtual void WriteDebugInfo(std::stringstream
& aStream
) {}
3006 nsDisplayItem
* GetAbove() { return mAbove
; }
3009 * Like ComputeVisibility, but does the work that nsDisplayList
3011 * -- Intersects GetBounds with aVisibleRegion and puts the result
3013 * -- Subtracts bounds from aVisibleRegion if the item is opaque
3015 bool RecomputeVisibility(nsDisplayListBuilder
* aBuilder
,
3016 nsRegion
* aVisibleRegion
);
3019 * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
3021 const nsPoint
& ToReferenceFrame() const {
3022 NS_ASSERTION(mFrame
, "No frame?");
3023 return mToReferenceFrame
;
3026 * @return the root of the display list's frame (sub)tree, whose origin
3027 * establishes the coordinate system for the display list
3029 const nsIFrame
* ReferenceFrame() const { return mReferenceFrame
; }
3032 * Returns the reference frame for display item children of this item.
3034 virtual const nsIFrame
* ReferenceFrameForChildren() const {
3035 return mReferenceFrame
;
3038 AnimatedGeometryRoot
* GetAnimatedGeometryRoot() const {
3039 MOZ_ASSERT(mAnimatedGeometryRoot
,
3040 "Must have cached AGR before accessing it!");
3041 return mAnimatedGeometryRoot
;
3044 virtual struct AnimatedGeometryRoot
* AnimatedGeometryRootForScrollMetadata()
3046 return GetAnimatedGeometryRoot();
3050 * Checks if this display item (or any children) contains content that might
3051 * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
3052 * bounds of the area that needs component alpha, or an empty rect if nothing
3055 virtual nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const {
3060 * Disable usage of component alpha. Currently only relevant for items that
3063 void DisableComponentAlpha() { mItemFlags
+= ItemFlag::DisableSubpixelAA
; }
3065 bool IsSubpixelAADisabled() const {
3066 return mItemFlags
.contains(ItemFlag::DisableSubpixelAA
);
3070 * Check if we can add async animations to the layer for this display item.
3072 virtual bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) {
3076 virtual bool SupportsOptimizingToImage() const { return false; }
3078 const DisplayItemClip
& GetClip() const {
3079 return mClip
? *mClip
: DisplayItemClip::NoClip();
3081 void IntersectClip(nsDisplayListBuilder
* aBuilder
,
3082 const DisplayItemClipChain
* aOther
, bool aStore
);
3084 virtual void SetActiveScrolledRoot(
3085 const ActiveScrolledRoot
* aActiveScrolledRoot
) {
3086 mActiveScrolledRoot
= aActiveScrolledRoot
;
3088 const ActiveScrolledRoot
* GetActiveScrolledRoot() const {
3089 return mActiveScrolledRoot
;
3092 virtual void SetClipChain(const DisplayItemClipChain
* aClipChain
,
3094 const DisplayItemClipChain
* GetClipChain() const { return mClipChain
; }
3097 * Intersect all clips in our clip chain up to (and including) aASR and set
3098 * set the intersection as this item's clip.
3100 void FuseClipChainUpTo(nsDisplayListBuilder
* aBuilder
,
3101 const ActiveScrolledRoot
* aASR
);
3103 bool BackfaceIsHidden() const {
3104 return mItemFlags
.contains(ItemFlag::BackfaceHidden
);
3107 bool Combines3DTransformWithAncestors() const {
3108 return mItemFlags
.contains(ItemFlag::Combines3DTransformWithAncestors
);
3111 bool ForceNotVisible() const {
3112 return mItemFlags
.contains(ItemFlag::ForceNotVisible
);
3115 bool In3DContextAndBackfaceIsHidden() const {
3116 return mItemFlags
.contains(ItemFlag::BackfaceHidden
) &&
3117 mItemFlags
.contains(ItemFlag::Combines3DTransformWithAncestors
);
3120 bool HasDifferentFrame(const nsDisplayItem
* aOther
) const {
3121 return mFrame
!= aOther
->mFrame
;
3124 bool HasHitTestInfo() const {
3125 return mItemFlags
.contains(ItemFlag::HasHitTestInfo
);
3128 bool HasSameTypeAndClip(const nsDisplayItem
* aOther
) const {
3129 return GetPerFrameKey() == aOther
->GetPerFrameKey() &&
3130 GetClipChain() == aOther
->GetClipChain();
3133 bool HasSameContent(const nsDisplayItem
* aOther
) const {
3134 return mFrame
->GetContent() == aOther
->Frame()->GetContent();
3137 virtual void NotifyUsed(nsDisplayListBuilder
* aBuilder
) {}
3139 virtual mozilla::Maybe
<nsRect
> GetClipWithRespectToASR(
3140 nsDisplayListBuilder
* aBuilder
, const ActiveScrolledRoot
* aASR
) const;
3142 const nsRect
& GetPaintRect() const { return mPaintRect
; }
3144 virtual const nsRect
& GetUntransformedPaintRect() const {
3145 return GetPaintRect();
3148 virtual const mozilla::HitTestInfo
& GetHitTestInfo() {
3149 return mozilla::HitTestInfo::Empty();
3153 typedef bool (*PrefFunc
)(void);
3154 void SetHasHitTestInfo() { mItemFlags
+= ItemFlag::HasHitTestInfo
; }
3156 RefPtr
<const DisplayItemClipChain
> mClipChain
;
3157 const DisplayItemClip
* mClip
;
3158 RefPtr
<const ActiveScrolledRoot
> mActiveScrolledRoot
;
3159 // Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
3160 const nsIFrame
* mReferenceFrame
;
3161 RefPtr
<struct AnimatedGeometryRoot
> mAnimatedGeometryRoot
;
3164 RefPtr
<const DisplayItemClipChain
> mClipChain
;
3165 const DisplayItemClip
* mClip
;
3168 // Result of ToReferenceFrame(mFrame), if mFrame is non-null
3169 nsPoint mToReferenceFrame
;
3172 // This is the rectangle that nsDisplayListBuilder was using as the visible
3173 // rect to decide which items to construct.
3174 nsRect mBuildingRect
;
3176 // nsDisplayList::ComputeVisibility sets this to the visible region
3177 // of the item by intersecting the visible region with the bounds
3178 // of the item. Paint implementations can use this to limit their drawing.
3179 // Guaranteed to be contained in GetBounds().
3182 enum class ItemFlag
: uint8_t {
3184 Combines3DTransformWithAncestors
,
3190 #ifdef MOZ_DUMP_PAINTING
3191 // True if this frame has been painted.
3196 mozilla::EnumSet
<ItemFlag
, uint8_t> mItemFlags
;
3199 class nsPaintedDisplayItem
: public nsDisplayItem
{
3201 nsPaintedDisplayItem
* AsPaintedDisplayItem() final
{ return this; }
3202 const nsPaintedDisplayItem
* AsPaintedDisplayItem() const final
{
3207 * Stores the given opacity value to be applied when drawing. It is an error
3208 * to call this if CanApplyOpacity returned false.
3210 virtual void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
3211 const DisplayItemClipChain
* aClip
) {
3212 MOZ_ASSERT(CanApplyOpacity(), "ApplyOpacity is not supported on this type");
3216 * Get the layer drawn by this display item. Call this only if
3217 * GetLayerState() returns something other than LAYER_NONE.
3218 * If GetLayerState returned LAYER_NONE then Paint will be called
3220 * This is called while aManager is in the construction phase.
3222 * The caller (nsDisplayList) is responsible for setting the visible
3223 * region of the layer.
3225 * @param aContainerParameters should be passed to
3226 * FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is
3229 virtual already_AddRefed
<Layer
> BuildLayer(
3230 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
3231 const ContainerLayerParameters
& aContainerParameters
) {
3236 * Returns true if this display item would return true from ApplyOpacity
3237 * without actually applying the opacity. Otherwise returns false.
3239 virtual bool CanApplyOpacity() const { return false; }
3242 * Returns true if this item supports PaintWithClip, where the clipping
3243 * is used directly as the primitive geometry instead of needing an explicit
3246 virtual bool CanPaintWithClip(const DisplayItemClip
& aClip
) { return false; }
3249 * Same as |Paint()|, except provides a clip to use the geometry to draw with.
3250 * Must not be called unless |CanPaintWithClip()| returned true.
3252 virtual void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
3253 const DisplayItemClip
& aClip
) {
3254 MOZ_ASSERT_UNREACHABLE("PaintWithClip() is not implemented!");
3258 * Paint this item to some rendering context.
3260 virtual void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) = 0;
3263 * External storage used by |DisplayItemCache| to avoid hashmap lookups.
3264 * If an item is reused and has the cache index set, it means that
3265 * |DisplayItemCache| has assigned a cache slot for the item.
3267 mozilla::Maybe
<uint16_t>& CacheIndex() { return mCacheIndex
; }
3269 void InvalidateItemCacheEntry() override
{
3270 // |nsPaintedDisplayItem|s may have |DisplayItemCache| entries
3271 // that no longer match after a mutation. The cache will notice
3272 // on its own that the entry is no longer in use, and free it.
3273 mCacheIndex
= mozilla::Nothing();
3276 const mozilla::HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
3277 void InitializeHitTestInfo(nsDisplayListBuilder
* aBuilder
) {
3278 mHitTestInfo
.Initialize(aBuilder
, Frame());
3279 SetHasHitTestInfo();
3283 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
3284 : nsPaintedDisplayItem(aBuilder
, aFrame
,
3285 aBuilder
->CurrentActiveScrolledRoot()) {}
3287 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3288 const ActiveScrolledRoot
* aActiveScrolledRoot
)
3289 : nsDisplayItem(aBuilder
, aFrame
, aActiveScrolledRoot
) {}
3291 nsPaintedDisplayItem(nsDisplayListBuilder
* aBuilder
,
3292 const nsPaintedDisplayItem
& aOther
)
3293 : nsDisplayItem(aBuilder
, aOther
), mHitTestInfo(aOther
.mHitTestInfo
) {}
3296 mozilla::HitTestInfo mHitTestInfo
;
3297 mozilla::Maybe
<uint16_t> mCacheIndex
;
3301 * Manages a singly-linked list of display list items.
3303 * mSentinel is the sentinel list value, the first value in the null-terminated
3304 * linked list of items. mTop is the last item in the list (whose 'above'
3305 * pointer is null). This class has no virtual methods. So list objects are just
3308 * Stepping upward through this list is very fast. Stepping downward is very
3309 * slow so we don't support it. The methods that need to step downward
3310 * (HitTest(), ComputeVisibility()) internally build a temporary array of all
3311 * the items while they do the downward traversal, so overall they're still
3312 * linear time. We have optimized for efficient AppendToTop() of both
3313 * items and lists, with minimal codesize. AppendToBottom() is efficient too.
3315 class nsDisplayList
{
3317 typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot
;
3318 typedef mozilla::layers::Layer Layer
;
3319 typedef mozilla::layers::LayerManager LayerManager
;
3320 typedef mozilla::layers::PaintedLayer PaintedLayer
;
3322 template <typename T
>
3325 Iterator() : mItem(nullptr) {}
3326 ~Iterator() = default;
3327 Iterator(const Iterator
& aOther
) = default;
3328 Iterator
& operator=(const Iterator
& aOther
) = default;
3330 explicit Iterator(const nsDisplayList
* aList
) : mItem(aList
->GetBottom()) {}
3331 explicit Iterator(const nsDisplayItem
* aItem
) : mItem(aItem
) {}
3333 Iterator
& operator++() {
3334 mItem
= mItem
? mItem
->GetAbove() : mItem
;
3338 bool operator==(const Iterator
& aOther
) const {
3339 return mItem
== aOther
.mItem
;
3342 bool operator!=(const Iterator
& aOther
) const {
3343 return !operator==(aOther
);
3346 T
* operator*() { return mItem
; }
3352 using DisplayItemIterator
= Iterator
<nsDisplayItem
>;
3354 DisplayItemIterator
begin() const { return DisplayItemIterator(this); }
3355 DisplayItemIterator
end() const { return DisplayItemIterator(); }
3358 * Create an empty list.
3361 : mLength(0), mIsOpaque(false), mForceTransparentSurface(false) {
3363 mSentinel
.mAbove
= nullptr;
3366 virtual ~nsDisplayList() {
3367 MOZ_RELEASE_ASSERT(!mSentinel
.mAbove
, "Nonempty list left over?");
3370 nsDisplayList(nsDisplayList
&& aOther
) {
3371 mIsOpaque
= aOther
.mIsOpaque
;
3372 mForceTransparentSurface
= aOther
.mForceTransparentSurface
;
3374 if (aOther
.mSentinel
.mAbove
) {
3375 AppendToTop(&aOther
);
3382 nsDisplayList
& operator=(nsDisplayList
&& aOther
) {
3383 if (this != &aOther
) {
3384 if (aOther
.mSentinel
.mAbove
) {
3386 tmp
.AppendToTop(&aOther
);
3387 aOther
.AppendToTop(this);
3393 mIsOpaque
= aOther
.mIsOpaque
;
3394 mForceTransparentSurface
= aOther
.mForceTransparentSurface
;
3399 nsDisplayList(const nsDisplayList
&) = delete;
3400 nsDisplayList
& operator=(const nsDisplayList
& aOther
) = delete;
3403 * Append an item to the top of the list. The item must not currently
3404 * be in a list and cannot be null.
3406 void AppendToTop(nsDisplayItem
* aItem
) {
3410 MOZ_ASSERT(!aItem
->mAbove
, "Already in a list!");
3411 mTop
->mAbove
= aItem
;
3416 template <typename T
, typename F
, typename
... Args
>
3417 void AppendNewToTop(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3419 AppendNewToTopWithIndex
<T
>(aBuilder
, aFrame
, 0,
3420 std::forward
<Args
>(aArgs
)...);
3423 template <typename T
, typename F
, typename
... Args
>
3424 void AppendNewToTopWithIndex(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3425 const uint16_t aIndex
, Args
&&... aArgs
) {
3426 nsDisplayItem
* item
= MakeDisplayItemWithIndex
<T
>(
3427 aBuilder
, aFrame
, aIndex
, std::forward
<Args
>(aArgs
)...);
3435 * Append a new item to the bottom of the list. The item must be non-null
3436 * and not already in a list.
3438 void AppendToBottom(nsDisplayItem
* aItem
) {
3442 MOZ_ASSERT(!aItem
->mAbove
, "Already in a list!");
3443 aItem
->mAbove
= mSentinel
.mAbove
;
3444 mSentinel
.mAbove
= aItem
;
3445 if (mTop
== &mSentinel
) {
3451 template <typename T
, typename F
, typename
... Args
>
3452 void AppendNewToBottom(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3454 AppendNewToBottomWithIndex
<T
>(aBuilder
, aFrame
, 0,
3455 std::forward
<Args
>(aArgs
)...);
3458 template <typename T
, typename F
, typename
... Args
>
3459 void AppendNewToBottomWithIndex(nsDisplayListBuilder
* aBuilder
, F
* aFrame
,
3460 const uint16_t aIndex
, Args
&&... aArgs
) {
3461 nsDisplayItem
* item
= MakeDisplayItemWithIndex
<T
>(
3462 aBuilder
, aFrame
, aIndex
, std::forward
<Args
>(aArgs
)...);
3465 AppendToBottom(item
);
3470 * Removes all items from aList and appends them to the top of this list
3472 void AppendToTop(nsDisplayList
* aList
) {
3473 if (aList
->mSentinel
.mAbove
) {
3474 mTop
->mAbove
= aList
->mSentinel
.mAbove
;
3476 aList
->mTop
= &aList
->mSentinel
;
3477 aList
->mSentinel
.mAbove
= nullptr;
3478 mLength
+= aList
->mLength
;
3484 * Removes all items from aList and prepends them to the bottom of this list
3486 void AppendToBottom(nsDisplayList
* aList
) {
3487 if (aList
->mSentinel
.mAbove
) {
3488 aList
->mTop
->mAbove
= mSentinel
.mAbove
;
3489 mSentinel
.mAbove
= aList
->mSentinel
.mAbove
;
3490 if (mTop
== &mSentinel
) {
3494 aList
->mTop
= &aList
->mSentinel
;
3495 aList
->mSentinel
.mAbove
= nullptr;
3496 mLength
+= aList
->mLength
;
3502 * Remove an item from the bottom of the list and return it.
3504 nsDisplayItem
* RemoveBottom();
3507 * Remove all items from the list and call their destructors.
3509 virtual void DeleteAll(nsDisplayListBuilder
* aBuilder
);
3512 * @return the item at the top of the list, or null if the list is empty
3514 nsDisplayItem
* GetTop() const {
3515 return mTop
!= &mSentinel
? static_cast<nsDisplayItem
*>(mTop
) : nullptr;
3518 * @return the item at the bottom of the list, or null if the list is empty
3520 nsDisplayItem
* GetBottom() const { return mSentinel
.mAbove
; }
3521 bool IsEmpty() const { return mTop
== &mSentinel
; }
3524 * @return the number of items in the list
3526 uint32_t Count() const { return mLength
; }
3528 * Stable sort the list by the z-order of GetUnderlyingFrame() on
3529 * each item. 'auto' is counted as zero.
3530 * It is assumed that the list is already in content document order.
3532 void SortByZOrder();
3534 * Stable sort the list by the tree order of the content of
3535 * GetUnderlyingFrame() on each item. z-index is ignored.
3536 * @param aCommonAncestor a common ancestor of all the content elements
3537 * associated with the display items, for speeding up tree order
3538 * checks, or nullptr if not known; it's only a hint, if it is not an
3539 * ancestor of some elements, then we lose performance but not correctness
3541 void SortByContentOrder(nsIContent
* aCommonAncestor
);
3544 * Sort the display list using a stable sort. Take care, because some of the
3545 * items might be nsDisplayLists themselves.
3546 * aComparator(Item item1, Item item2) should return true if item1 should go
3548 * We sort the items into increasing order.
3550 template <typename Item
, typename Comparator
>
3551 void Sort(const Comparator
& aComparator
) {
3553 // Only sort lists with more than one item.
3557 // Some casual local browsing testing suggests that a local preallocated
3558 // array of 20 items should be able to avoid a lot of dynamic allocations
3560 AutoTArray
<Item
, 20> items
;
3562 while (nsDisplayItem
* item
= RemoveBottom()) {
3563 items
.AppendElement(Item(item
));
3566 std::stable_sort(items
.begin(), items
.end(), aComparator
);
3568 for (Item
& item
: items
) {
3574 * Compute visiblity for the items in the list.
3575 * We put this logic here so it can be shared by top-level
3576 * painting and also display items that maintain child lists.
3577 * This is also a good place to put ComputeVisibility-related logic
3578 * that must be applied to every display item. In particular, this
3579 * sets mVisibleRect on each display item.
3580 * This sets mIsOpaque if the entire visible area of this list has
3581 * been removed from aVisibleRegion when we return.
3582 * This does not remove any items from the list, so we can recompute
3583 * visiblity with different regions later (see
3584 * FrameLayerBuilder::DrawPaintedLayer).
3585 * This method needs to be idempotent.
3587 * @param aVisibleRegion the area that is visible, relative to the
3588 * reference frame; on return, this contains the area visible under the list.
3589 * I.e., opaque contents of this list are subtracted from aVisibleRegion.
3590 * @param aListVisibleBounds must be equal to the bounds of the intersection
3591 * of aVisibleRegion and GetBounds() for this list.
3592 * @return true if any item in the list is visible.
3594 bool ComputeVisibilityForSublist(nsDisplayListBuilder
* aBuilder
,
3595 nsRegion
* aVisibleRegion
,
3596 const nsRect
& aListVisibleBounds
);
3599 * As ComputeVisibilityForSublist, but computes visibility for a root
3600 * list (a list that does not belong to an nsDisplayItem).
3601 * This method needs to be idempotent.
3603 * @param aVisibleRegion the area that is visible
3605 bool ComputeVisibilityForRoot(nsDisplayListBuilder
* aBuilder
,
3606 nsRegion
* aVisibleRegion
);
3609 * Returns true if the visible region output from ComputeVisiblity was
3610 * empty, i.e. everything visible in this list is opaque.
3612 bool IsOpaque() const { return mIsOpaque
; }
3615 * Returns true if any display item requires the surface to be transparent.
3617 bool NeedsTransparentSurface() const { return mForceTransparentSurface
; }
3619 * Paint the list to the rendering context. We assume that (0,0) in aCtx
3620 * corresponds to the origin of the reference frame. For best results,
3621 * aCtx's current transform should make (0,0) pixel-aligned. The
3622 * rectangle in aDirtyRect is painted, which *must* be contained in the
3623 * dirty rect used to construct the display list.
3625 * If aFlags contains PAINT_USE_WIDGET_LAYERS and
3626 * ShouldUseWidgetLayerManager() is set, then we will paint using
3627 * the reference frame's widget's layer manager (and ctx may be null),
3628 * otherwise we will use a temporary BasicLayerManager and ctx must
3631 * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
3632 * layer manager has already had BeginTransaction() called on it and
3633 * we should not call it again.
3635 * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to
3636 * compressed mode to avoid short cut optimizations.
3638 * This must only be called on the root display list of the display list
3641 * We return the layer manager used for painting --- mainly so that
3642 * callers can dump its layer tree if necessary.
3646 PAINT_USE_WIDGET_LAYERS
= 0x01,
3647 PAINT_EXISTING_TRANSACTION
= 0x04,
3648 PAINT_NO_COMPOSITE
= 0x08,
3649 PAINT_COMPRESSED
= 0x10,
3650 PAINT_IDENTICAL_DISPLAY_LIST
= 0x20
3652 already_AddRefed
<LayerManager
> PaintRoot(
3653 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
, uint32_t aFlags
,
3654 mozilla::Maybe
<double> aDisplayListBuildTime
);
3656 mozilla::FrameLayerBuilder
* BuildLayers(nsDisplayListBuilder
* aBuilder
,
3657 LayerManager
* aLayerManager
,
3659 bool aIsWidgetTransaction
);
3661 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
3662 int32_t aAppUnitsPerDevPixel
);
3665 * Get the bounds. Takes the union of the bounds of all children.
3666 * The result is not cached.
3668 nsRect
GetClippedBounds(nsDisplayListBuilder
* aBuilder
) const;
3671 * Get this list's bounds, respecting clips relative to aASR. The result is
3672 * the union of each item's clipped bounds with respect to aASR. That means
3673 * that if an item can move asynchronously with an ASR that is a descendant
3674 * of aASR, then the clipped bounds with respect to aASR will be the clip of
3675 * that item for aASR, because the item can move anywhere inside that clip.
3676 * If there is an item in this list which is not bounded with respect to
3677 * aASR (i.e. which does not have "finite bounds" with respect to aASR),
3678 * then this method trigger an assertion failure.
3679 * The optional aBuildingRect out argument can be set to non-null if the
3680 * caller is also interested to know the building rect. This can be used
3681 * to get the visible rect efficiently without traversing the display list
3684 nsRect
GetClippedBoundsWithRespectToASR(
3685 nsDisplayListBuilder
* aBuilder
, const ActiveScrolledRoot
* aASR
,
3686 nsRect
* aBuildingRect
= nullptr) const;
3689 * Returns the opaque region of this display list.
3691 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
) {
3694 for (nsDisplayItem
* item
: *this) {
3695 result
.OrWith(item
->GetOpaqueRegion(aBuilder
, &snap
));
3701 * Returns the bounds of the area that needs component alpha.
3703 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const {
3705 for (nsDisplayItem
* item
: *this) {
3706 bounds
.UnionRect(bounds
, item
->GetComponentAlphaBounds(aBuilder
));
3712 * Find the topmost display item that returns a non-null frame, and return
3715 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
3716 nsDisplayItem::HitTestState
* aState
,
3717 nsTArray
<nsIFrame
*>* aOutFrames
) const;
3719 * Compute the union of the visible rects of the items in the list. The
3720 * result is not cached.
3722 nsRect
GetBuildingRect() const;
3724 void SetIsOpaque() { mIsOpaque
= true; }
3726 void SetNeedsTransparentSurface() { mForceTransparentSurface
= true; }
3728 void RestoreState() {
3730 mForceTransparentSurface
= false;
3734 nsDisplayItemLink mSentinel
;
3735 nsDisplayItemLink
* mTop
;
3739 // This is set to true by FrameLayerBuilder if the final visible region
3740 // is empty (i.e. everything that was visible is covered by some
3741 // opaque content in this list).
3743 // This is set to true by FrameLayerBuilder if any display item in this
3744 // list needs to force the surface containing this list to be transparent.
3745 bool mForceTransparentSurface
;
3749 * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
3750 * will put any generated items onto the appropriate list given here. It's
3751 * basically just a collection with one list for each separate stacking layer.
3752 * The lists themselves are external to this object and thus can be shared
3753 * with others. Some of the list pointers may even refer to the same list.
3755 class nsDisplayListSet
{
3758 * @return a list where one should place the border and/or background for
3759 * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
3761 nsDisplayList
* BorderBackground() const { return mBorderBackground
; }
3763 * @return a list where one should place the borders and/or backgrounds for
3764 * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
3766 nsDisplayList
* BlockBorderBackgrounds() const {
3767 return mBlockBorderBackgrounds
;
3770 * @return a list where one should place descendant floats (step 5 of
3771 * CSS 2.1 appendix E)
3773 nsDisplayList
* Floats() const { return mFloats
; }
3775 * @return a list where one should place the (pseudo) stacking contexts
3776 * for descendants of this frame (everything from steps 3, 7 and 8
3777 * of CSS 2.1 appendix E)
3779 nsDisplayList
* PositionedDescendants() const { return mPositioned
; }
3781 * @return a list where one should place the outlines
3782 * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
3784 nsDisplayList
* Outlines() const { return mOutlines
; }
3786 * @return a list where one should place all other content
3788 nsDisplayList
* Content() const { return mContent
; }
3790 void DeleteAll(nsDisplayListBuilder
* aBuilder
) {
3791 BorderBackground()->DeleteAll(aBuilder
);
3792 BlockBorderBackgrounds()->DeleteAll(aBuilder
);
3793 Floats()->DeleteAll(aBuilder
);
3794 PositionedDescendants()->DeleteAll(aBuilder
);
3795 Outlines()->DeleteAll(aBuilder
);
3796 Content()->DeleteAll(aBuilder
);
3799 nsDisplayListSet(nsDisplayList
* aBorderBackground
,
3800 nsDisplayList
* aBlockBorderBackgrounds
,
3801 nsDisplayList
* aFloats
, nsDisplayList
* aContent
,
3802 nsDisplayList
* aPositionedDescendants
,
3803 nsDisplayList
* aOutlines
)
3804 : mBorderBackground(aBorderBackground
),
3805 mBlockBorderBackgrounds(aBlockBorderBackgrounds
),
3808 mPositioned(aPositionedDescendants
),
3809 mOutlines(aOutlines
) {}
3812 * A copy constructor that lets the caller override the BorderBackground
3815 nsDisplayListSet(const nsDisplayListSet
& aLists
,
3816 nsDisplayList
* aBorderBackground
)
3817 : mBorderBackground(aBorderBackground
),
3818 mBlockBorderBackgrounds(aLists
.BlockBorderBackgrounds()),
3819 mFloats(aLists
.Floats()),
3820 mContent(aLists
.Content()),
3821 mPositioned(aLists
.PositionedDescendants()),
3822 mOutlines(aLists
.Outlines()) {}
3825 * Move all display items in our lists to top of the corresponding lists in
3828 void MoveTo(const nsDisplayListSet
& aDestination
) const;
3831 // This class is only used on stack, so we don't have to worry about leaking
3832 // it. Don't let us be heap-allocated!
3833 void* operator new(size_t sz
) noexcept(true);
3836 nsDisplayList
* mBorderBackground
;
3837 nsDisplayList
* mBlockBorderBackgrounds
;
3838 nsDisplayList
* mFloats
;
3839 nsDisplayList
* mContent
;
3840 nsDisplayList
* mPositioned
;
3841 nsDisplayList
* mOutlines
;
3845 * A specialization of nsDisplayListSet where the lists are actually internal
3846 * to the object, and all distinct.
3848 struct nsDisplayListCollection
: public nsDisplayListSet
{
3849 explicit nsDisplayListCollection(nsDisplayListBuilder
* aBuilder
)
3850 : nsDisplayListSet(&mLists
[0], &mLists
[1], &mLists
[2], &mLists
[3],
3851 &mLists
[4], &mLists
[5]) {}
3853 explicit nsDisplayListCollection(nsDisplayListBuilder
* aBuilder
,
3854 nsDisplayList
* aBorderBackground
)
3855 : nsDisplayListSet(aBorderBackground
, &mLists
[1], &mLists
[2], &mLists
[3],
3856 &mLists
[4], &mLists
[5]) {}
3859 * Sort all lists by content order.
3861 void SortAllByContentOrder(nsIContent
* aCommonAncestor
) {
3862 for (auto& mList
: mLists
) {
3863 mList
.SortByContentOrder(aCommonAncestor
);
3868 * Serialize this display list collection into a display list with the items
3869 * in the correct Z order.
3870 * @param aOutList the result display list
3871 * @param aContent the content element to use for content ordering
3873 void SerializeWithCorrectZOrder(nsDisplayList
* aOutResultList
,
3874 nsIContent
* aContent
);
3877 // This class is only used on stack, so we don't have to worry about leaking
3878 // it. Don't let us be heap-allocated!
3879 void* operator new(size_t sz
) noexcept(true);
3881 nsDisplayList mLists
[6];
3885 * A display list that also retains the partial build
3886 * information (in the form of a DAG) used to create it.
3888 * Display lists built from a partial list aren't necessarily
3889 * in the same order as a full build, and the DAG retains
3890 * the information needing to interpret the current
3893 class RetainedDisplayList
: public nsDisplayList
{
3895 RetainedDisplayList() = default;
3896 RetainedDisplayList(RetainedDisplayList
&& aOther
) {
3897 AppendToTop(&aOther
);
3898 mDAG
= std::move(aOther
.mDAG
);
3901 ~RetainedDisplayList() override
{
3902 MOZ_ASSERT(mOldItems
.IsEmpty(), "Must empty list before destroying");
3905 RetainedDisplayList
& operator=(RetainedDisplayList
&& aOther
) {
3906 MOZ_ASSERT(!Count(), "Can only move into an empty list!");
3907 MOZ_ASSERT(mOldItems
.IsEmpty(), "Can only move into an empty list!");
3908 AppendToTop(&aOther
);
3909 mDAG
= std::move(aOther
.mDAG
);
3910 mOldItems
= std::move(aOther
.mOldItems
);
3914 void DeleteAll(nsDisplayListBuilder
* aBuilder
) override
{
3915 for (OldItemInfo
& i
: mOldItems
) {
3916 if (i
.mItem
&& i
.mOwnsItem
) {
3917 i
.mItem
->Destroy(aBuilder
);
3918 MOZ_ASSERT(!GetBottom(),
3919 "mOldItems should not be owning items if we also have items "
3920 "in the normal list");
3925 nsDisplayList::DeleteAll(aBuilder
);
3928 void AddSizeOfExcludingThis(nsWindowSizes
&) const;
3930 DirectedAcyclicGraph
<MergedListUnits
> mDAG
;
3932 // Temporary state initialized during the preprocess pass
3933 // of RetainedDisplayListBuilder and then used during merging.
3934 nsTArray
<OldItemInfo
> mOldItems
;
3937 class nsDisplayContainer final
: public nsDisplayItem
{
3939 nsDisplayContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
3940 const ActiveScrolledRoot
* aActiveScrolledRoot
,
3941 nsDisplayList
* aList
);
3943 ~nsDisplayContainer() override
{ MOZ_COUNT_DTOR(nsDisplayContainer
); }
3945 NS_DISPLAY_DECL_NAME("nsDisplayContainer", TYPE_CONTAINER
)
3947 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
3948 mChildren
.DeleteAll(aBuilder
);
3949 nsDisplayItem::Destroy(aBuilder
);
3952 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
3953 nsRegion
* aVisibleRegion
) override
;
3955 bool CreateWebRenderCommands(
3956 mozilla::wr::DisplayListBuilder
& aBuilder
,
3957 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
3958 const StackingContextHelper
& aSc
,
3959 mozilla::layers::RenderRootStateManager
* aManager
,
3960 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
3962 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
3964 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
3966 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
3967 bool* aSnap
) const override
;
3969 mozilla::Maybe
<nscolor
> IsUniform(
3970 nsDisplayListBuilder
* aBuilder
) const override
{
3971 return mozilla::Nothing();
3974 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
3975 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
3976 return GetChildren();
3979 mozilla::Maybe
<nsRect
> GetClipWithRespectToASR(
3980 nsDisplayListBuilder
* aBuilder
,
3981 const ActiveScrolledRoot
* aASR
) const override
;
3983 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
3984 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
3986 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
3990 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
3991 bool aStore
) override
{
3992 MOZ_ASSERT_UNREACHABLE("nsDisplayContainer does not support clipping");
3995 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
3998 mutable RetainedDisplayList mChildren
;
4002 class nsDisplayImageContainer
: public nsPaintedDisplayItem
{
4004 typedef mozilla::LayerIntPoint LayerIntPoint
;
4005 typedef mozilla::LayoutDeviceRect LayoutDeviceRect
;
4006 typedef mozilla::layers::ImageContainer ImageContainer
;
4007 typedef mozilla::layers::ImageLayer ImageLayer
;
4009 nsDisplayImageContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
4010 : nsPaintedDisplayItem(aBuilder
, aFrame
) {}
4013 * @return true if this display item can be optimized into an image layer.
4014 * It is an error to call GetContainer() unless you've called
4015 * CanOptimizeToImageLayer() first and it returned true.
4017 virtual bool CanOptimizeToImageLayer(LayerManager
* aManager
,
4018 nsDisplayListBuilder
* aBuilder
);
4020 already_AddRefed
<ImageContainer
> GetContainer(LayerManager
* aManager
,
4021 nsDisplayListBuilder
* aBuilder
);
4022 void ConfigureLayer(ImageLayer
* aLayer
,
4023 const ContainerLayerParameters
& aParameters
);
4025 virtual void UpdateDrawResult(mozilla::image::ImgDrawResult aResult
) = 0;
4026 virtual already_AddRefed
<imgIContainer
> GetImage() = 0;
4027 virtual nsRect
GetDestRect() const = 0;
4029 bool SupportsOptimizingToImage() const override
{ return true; }
4033 * Use this class to implement not-very-frequently-used display items
4034 * that are not opaque, do not receive events, and are bounded by a frame's
4037 * This should not be used for display items which are created frequently,
4038 * because each item is one or two pointers bigger than an item from a
4039 * custom display item class could be, and fractionally slower. However it does
4040 * save code size. We use this for infrequently-used item types.
4042 class nsDisplayGeneric
: public nsPaintedDisplayItem
{
4044 typedef void (*PaintCallback
)(nsIFrame
* aFrame
, DrawTarget
* aDrawTarget
,
4045 const nsRect
& aDirtyRect
, nsPoint aFramePt
);
4047 // XXX: should be removed eventually
4048 typedef void (*OldPaintCallback
)(nsIFrame
* aFrame
, gfxContext
* aCtx
,
4049 const nsRect
& aDirtyRect
, nsPoint aFramePt
);
4051 nsDisplayGeneric(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4052 PaintCallback aPaint
, const char* aName
,
4053 DisplayItemType aType
)
4054 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4058 MOZ_COUNT_CTOR(nsDisplayGeneric
);
4062 // XXX: should be removed eventually
4063 nsDisplayGeneric(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4064 OldPaintCallback aOldPaint
, const char* aName
,
4065 DisplayItemType aType
)
4066 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4068 mOldPaint(aOldPaint
),
4070 MOZ_COUNT_CTOR(nsDisplayGeneric
);
4074 constexpr static DisplayItemType
ItemType() {
4075 return DisplayItemType::TYPE_GENERIC
;
4078 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayGeneric
)
4080 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
4081 MOZ_ASSERT(!!mPaint
!= !!mOldPaint
);
4083 mPaint(mFrame
, aCtx
->GetDrawTarget(), GetPaintRect(), ToReferenceFrame());
4085 mOldPaint(mFrame
, aCtx
, GetPaintRect(), ToReferenceFrame());
4089 const char* Name() const override
{ return mName
; }
4091 // This override is needed because GetType() for nsDisplayGeneric subclasses
4092 // does not match TYPE_GENERIC that was used to allocate the object.
4093 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4094 this->~nsDisplayGeneric();
4095 aBuilder
->Destroy(DisplayItemType::TYPE_GENERIC
, this);
4099 void* operator new(size_t aSize
, nsDisplayListBuilder
* aBuilder
) {
4100 return aBuilder
->Allocate(aSize
, DisplayItemType::TYPE_GENERIC
);
4103 template <typename T
, typename F
, typename
... Args
>
4104 friend T
* ::MakeDisplayItemWithIndex(nsDisplayListBuilder
* aBuilder
,
4105 F
* aFrame
, const uint16_t aIndex
,
4108 PaintCallback mPaint
;
4109 OldPaintCallback mOldPaint
; // XXX: should be removed eventually
4113 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
4115 * This class implements painting of reflow counts. Ideally, we would simply
4116 * make all the frame names be those returned by nsIFrame::GetFrameName
4117 * (except that tosses in the content tag name!) and support only one color
4118 * and eliminate this class altogether in favor of nsDisplayGeneric, but for
4119 * the time being we can't pass args to a PaintCallback, so just have a
4120 * separate class to do the right thing. Sadly, this alsmo means we need to
4121 * hack all leaf frame classes to handle this.
4123 * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
4124 * here... I could switch it all to nscolor, but why bother?
4126 class nsDisplayReflowCount
: public nsPaintedDisplayItem
{
4128 nsDisplayReflowCount(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4129 const char* aFrameName
, uint32_t aColor
= 0)
4130 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4131 mFrameName(aFrameName
),
4133 MOZ_COUNT_CTOR(nsDisplayReflowCount
);
4136 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayReflowCount
)
4138 NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT
)
4140 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4143 const char* mFrameName
;
4147 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
4149 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
4150 PresShell()->IsPaintingFrameCounts()) { \
4151 aLists.Outlines()->AppendNewToTop<nsDisplayReflowCount>(aBuilder, this, \
4156 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
4158 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
4159 PresShell()->IsPaintingFrameCounts()) { \
4160 aLists.Outlines()->AppendNewToTop<nsDisplayReflowCount>(aBuilder, this, \
4166 Macro to be used for classes that don't actually implement BuildDisplayList
4168 # define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
4169 void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
4170 const nsRect& aDirtyRect, \
4171 const nsDisplayListSet& aLists) { \
4172 DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
4173 _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
4176 #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
4178 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
4179 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
4180 # define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
4182 #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
4184 class nsDisplayCaret
: public nsPaintedDisplayItem
{
4186 nsDisplayCaret(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aCaretFrame
);
4188 #ifdef NS_BUILD_REFCNT_LOGGING
4189 ~nsDisplayCaret() override
;
4192 NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET
)
4194 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4195 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4196 bool CreateWebRenderCommands(
4197 mozilla::wr::DisplayListBuilder
& aBuilder
,
4198 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4199 const StackingContextHelper
& aSc
,
4200 mozilla::layers::RenderRootStateManager
* aManager
,
4201 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4204 RefPtr
<nsCaret
> mCaret
;
4209 * The standard display item to paint the CSS borders of a frame.
4211 class nsDisplayBorder
: public nsPaintedDisplayItem
{
4213 nsDisplayBorder(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
);
4215 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBorder
)
4217 NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER
)
4219 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
4220 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4221 LayerState
GetLayerState(
4222 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4223 const ContainerLayerParameters
& aParameters
) override
;
4224 bool CreateWebRenderCommands(
4225 mozilla::wr::DisplayListBuilder
& aBuilder
,
4226 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4227 const StackingContextHelper
& aSc
,
4228 mozilla::layers::RenderRootStateManager
* aManager
,
4229 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4230 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4231 nsDisplayItemGeometry
* AllocateGeometry(
4232 nsDisplayListBuilder
* aBuilder
) override
;
4233 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4234 const nsDisplayItemGeometry
* aGeometry
,
4235 nsRegion
* aInvalidRegion
) const override
;
4237 nsRegion
GetTightBounds(nsDisplayListBuilder
* aBuilder
,
4238 bool* aSnap
) const override
{
4240 return CalculateBounds
<nsRegion
>(*mFrame
->StyleBorder());
4244 template <typename T
>
4245 T
CalculateBounds(const nsStyleBorder
& aStyleBorder
) const {
4246 nsRect
borderBounds(ToReferenceFrame(), mFrame
->GetSize());
4247 if (aStyleBorder
.IsBorderImageSizeAvailable()) {
4248 borderBounds
.Inflate(aStyleBorder
.GetImageOutset());
4249 return borderBounds
;
4252 nsMargin border
= aStyleBorder
.GetComputedBorder();
4254 if (border
.top
> 0) {
4255 result
= nsRect(borderBounds
.X(), borderBounds
.Y(), borderBounds
.Width(),
4258 if (border
.right
> 0) {
4259 result
.OrWith(nsRect(borderBounds
.XMost() - border
.right
,
4260 borderBounds
.Y(), border
.right
,
4261 borderBounds
.Height()));
4263 if (border
.bottom
> 0) {
4264 result
.OrWith(nsRect(borderBounds
.X(),
4265 borderBounds
.YMost() - border
.bottom
,
4266 borderBounds
.Width(), border
.bottom
));
4268 if (border
.left
> 0) {
4269 result
.OrWith(nsRect(borderBounds
.X(), borderBounds
.Y(), border
.left
,
4270 borderBounds
.Height()));
4274 if (mFrame
->GetBorderRadii(radii
)) {
4275 if (border
.left
> 0 || border
.top
> 0) {
4276 nsSize
cornerSize(radii
[mozilla::eCornerTopLeftX
],
4277 radii
[mozilla::eCornerTopLeftY
]);
4278 result
.OrWith(nsRect(borderBounds
.TopLeft(), cornerSize
));
4280 if (border
.top
> 0 || border
.right
> 0) {
4281 nsSize
cornerSize(radii
[mozilla::eCornerTopRightX
],
4282 radii
[mozilla::eCornerTopRightY
]);
4284 nsRect(borderBounds
.TopRight() - nsPoint(cornerSize
.width
, 0),
4287 if (border
.right
> 0 || border
.bottom
> 0) {
4288 nsSize
cornerSize(radii
[mozilla::eCornerBottomRightX
],
4289 radii
[mozilla::eCornerBottomRightY
]);
4290 result
.OrWith(nsRect(borderBounds
.BottomRight() -
4291 nsPoint(cornerSize
.width
, cornerSize
.height
),
4294 if (border
.bottom
> 0 || border
.left
> 0) {
4295 nsSize
cornerSize(radii
[mozilla::eCornerBottomLeftX
],
4296 radii
[mozilla::eCornerBottomLeftY
]);
4298 nsRect(borderBounds
.BottomLeft() - nsPoint(0, cornerSize
.height
),
4309 * A simple display item that just renders a solid color across the
4310 * specified bounds. For canvas frames (in the CSS sense) we split off the
4311 * drawing of the background color into this class (from nsDisplayBackground
4312 * via nsDisplayCanvasBackground). This is done so that we can always draw a
4313 * background color to avoid ugly flashes of white when we can't draw a full
4314 * frame tree (ie when a page is loading). The bounds can differ from the
4315 * frame's bounds -- this is needed when a frame/iframe is loading and there
4316 * is not yet a frame tree to go in the frame/iframe so we use the subdoc
4317 * frame of the parent document as a standin.
4319 class nsDisplaySolidColorBase
: public nsPaintedDisplayItem
{
4321 nsDisplaySolidColorBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4323 : nsPaintedDisplayItem(aBuilder
, aFrame
), mColor(aColor
) {}
4325 nsDisplayItemGeometry
* AllocateGeometry(
4326 nsDisplayListBuilder
* aBuilder
) override
{
4327 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
);
4330 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4331 const nsDisplayItemGeometry
* aGeometry
,
4332 nsRegion
* aInvalidRegion
) const override
{
4333 const nsDisplaySolidColorGeometry
* geometry
=
4334 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
4335 if (mColor
!= geometry
->mColor
) {
4337 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
4340 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
4343 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4344 bool* aSnap
) const override
{
4347 if (NS_GET_A(mColor
) == 255) {
4348 result
= GetBounds(aBuilder
, aSnap
);
4353 mozilla::Maybe
<nscolor
> IsUniform(
4354 nsDisplayListBuilder
* aBuilder
) const override
{
4355 return mozilla::Some(mColor
);
4362 class nsDisplaySolidColor
: public nsDisplaySolidColorBase
{
4364 nsDisplaySolidColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4365 const nsRect
& aBounds
, nscolor aColor
,
4366 bool aCanBeReused
= true)
4367 : nsDisplaySolidColorBase(aBuilder
, aFrame
, aColor
), mBounds(aBounds
) {
4368 NS_ASSERTION(NS_GET_A(aColor
) > 0,
4369 "Don't create invisible nsDisplaySolidColors!");
4370 MOZ_COUNT_CTOR(nsDisplaySolidColor
);
4371 if (!aCanBeReused
) {
4376 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColor
)
4378 NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR
)
4380 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4381 LayerState
GetLayerState(
4382 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4383 const ContainerLayerParameters
& aParameters
) override
;
4384 already_AddRefed
<Layer
> BuildLayer(
4385 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4386 const ContainerLayerParameters
& aContainerParameters
) override
;
4387 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4388 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4389 bool CreateWebRenderCommands(
4390 mozilla::wr::DisplayListBuilder
& aBuilder
,
4391 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4392 const StackingContextHelper
& aSc
,
4393 mozilla::layers::RenderRootStateManager
* aManager
,
4394 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4396 int32_t ZIndex() const override
{
4397 if (mOverrideZIndex
) {
4398 return mOverrideZIndex
.value();
4400 return nsDisplaySolidColorBase::ZIndex();
4403 void SetOverrideZIndex(int32_t aZIndex
) {
4404 mOverrideZIndex
= mozilla::Some(aZIndex
);
4409 mozilla::Maybe
<int32_t> mOverrideZIndex
;
4413 * A display item that renders a solid color over a region. This is not
4414 * exposed through CSS, its only purpose is efficient invalidation of
4415 * the find bar highlighter dimmer.
4417 class nsDisplaySolidColorRegion
: public nsPaintedDisplayItem
{
4418 typedef mozilla::gfx::sRGBColor sRGBColor
;
4421 nsDisplaySolidColorRegion(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4422 const nsRegion
& aRegion
, nscolor aColor
)
4423 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4425 mColor(sRGBColor::FromABGR(aColor
)) {
4426 NS_ASSERTION(NS_GET_A(aColor
) > 0,
4427 "Don't create invisible nsDisplaySolidColorRegions!");
4428 MOZ_COUNT_CTOR(nsDisplaySolidColorRegion
);
4431 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColorRegion
)
4433 NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION
)
4435 nsDisplayItemGeometry
* AllocateGeometry(
4436 nsDisplayListBuilder
* aBuilder
) override
{
4437 return new nsDisplaySolidColorRegionGeometry(this, aBuilder
, mRegion
,
4441 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4442 const nsDisplayItemGeometry
* aGeometry
,
4443 nsRegion
* aInvalidRegion
) const override
{
4444 const nsDisplaySolidColorRegionGeometry
* geometry
=
4445 static_cast<const nsDisplaySolidColorRegionGeometry
*>(aGeometry
);
4446 if (mColor
== geometry
->mColor
) {
4447 aInvalidRegion
->Xor(geometry
->mRegion
, mRegion
);
4449 aInvalidRegion
->Or(geometry
->mRegion
.GetBounds(), mRegion
.GetBounds());
4453 bool CreateWebRenderCommands(
4454 mozilla::wr::DisplayListBuilder
& aBuilder
,
4455 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4456 const StackingContextHelper
& aSc
,
4457 mozilla::layers::RenderRootStateManager
* aManager
,
4458 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4461 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4462 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4463 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4470 enum class AppendedBackgroundType
: uint8_t {
4477 * A display item to paint one background-image for a frame. Each background
4478 * image layer gets its own nsDisplayBackgroundImage.
4480 class nsDisplayBackgroundImage
: public nsDisplayImageContainer
{
4482 typedef mozilla::StyleGeometryBox StyleGeometryBox
;
4485 nsDisplayListBuilder
* builder
;
4486 mozilla::ComputedStyle
* backgroundStyle
;
4487 nsCOMPtr
<imgIContainer
> image
;
4488 nsRect backgroundRect
;
4493 bool shouldFixToViewport
;
4497 * aLayer signifies which background layer this item represents.
4498 * aIsThemed should be the value of aFrame->IsThemed.
4499 * aBackgroundStyle should be the result of
4500 * nsCSSRendering::FindBackground, or null if FindBackground returned false.
4501 * aBackgroundRect is relative to aFrame.
4503 static InitData
GetInitData(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4504 uint16_t aLayer
, const nsRect
& aBackgroundRect
,
4505 mozilla::ComputedStyle
* aBackgroundStyle
);
4507 explicit nsDisplayBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4508 nsIFrame
* aFrame
, const InitData
& aInitData
,
4509 nsIFrame
* aFrameForBounds
= nullptr);
4510 ~nsDisplayBackgroundImage() override
;
4512 NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND
)
4515 * This will create and append new items for all the layers of the
4516 * background. Returns the type of background that was appended.
4517 * aAllowWillPaintBorderOptimization should usually be left at true, unless
4518 * aFrame has special border drawing that causes opaque borders to not
4519 * actually be opaque.
4521 static AppendedBackgroundType
AppendBackgroundItemsToTop(
4522 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4523 const nsRect
& aBackgroundRect
, nsDisplayList
* aList
,
4524 bool aAllowWillPaintBorderOptimization
= true,
4525 mozilla::ComputedStyle
* aComputedStyle
= nullptr,
4526 const nsRect
& aBackgroundOriginRect
= nsRect(),
4527 nsIFrame
* aSecondaryReferenceFrame
= nullptr,
4528 mozilla::Maybe
<nsDisplayListBuilder::AutoBuildingDisplayList
>*
4529 aAutoBuildingDisplayList
= nullptr);
4531 LayerState
GetLayerState(
4532 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4533 const ContainerLayerParameters
& aParameters
) override
;
4534 already_AddRefed
<Layer
> BuildLayer(
4535 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4536 const ContainerLayerParameters
& aContainerParameters
) override
;
4537 bool CreateWebRenderCommands(
4538 mozilla::wr::DisplayListBuilder
& aBuilder
,
4539 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4540 const StackingContextHelper
& aSc
,
4541 mozilla::layers::RenderRootStateManager
* aManager
,
4542 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4543 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4544 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4545 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
4546 nsRegion
* aVisibleRegion
) override
;
4547 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4548 bool* aSnap
) const override
;
4549 mozilla::Maybe
<nscolor
> IsUniform(
4550 nsDisplayListBuilder
* aBuilder
) const override
;
4553 * GetBounds() returns the background painting area.
4555 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4557 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4560 * Return the background positioning area.
4561 * (GetBounds() returns the background painting area.)
4562 * Can be called only when mBackgroundStyle is non-null.
4564 nsRect
GetPositioningArea() const;
4567 * Returns true if existing rendered pixels of this display item may need
4568 * to be redrawn if the positioning area size changes but its position does
4570 * If false, only the changed painting area needs to be redrawn when the
4571 * positioning area size changes but its position does not.
4573 bool RenderingMightDependOnPositioningAreaSizeChange() const;
4575 nsDisplayItemGeometry
* AllocateGeometry(
4576 nsDisplayListBuilder
* aBuilder
) override
{
4577 return new nsDisplayBackgroundGeometry(this, aBuilder
);
4580 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4581 const nsDisplayItemGeometry
* aGeometry
,
4582 nsRegion
* aInvalidRegion
) const override
;
4583 bool CanOptimizeToImageLayer(LayerManager
* aManager
,
4584 nsDisplayListBuilder
* aBuilder
) override
;
4585 already_AddRefed
<imgIContainer
> GetImage() override
;
4586 nsRect
GetDestRect() const override
;
4588 void UpdateDrawResult(mozilla::image::ImgDrawResult aResult
) override
{
4589 nsDisplayBackgroundGeometry::UpdateDrawResult(this, aResult
);
4592 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
4593 return mShouldFixToViewport
;
4596 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4598 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4599 if (!aBuilder
->IsRetainingDisplayList()) {
4602 mDependentFrame
= aFrame
;
4604 mDependentFrame
->AddDisplayItem(this);
4608 void RemoveFrame(nsIFrame
* aFrame
) override
{
4609 if (aFrame
== mDependentFrame
) {
4610 mDependentFrame
= nullptr;
4612 nsDisplayImageContainer::RemoveFrame(aFrame
);
4615 // Match https://w3c.github.io/paint-timing/#contentful-image
4616 bool IsContentful() const override
{
4617 const auto& styleImage
=
4618 mBackgroundStyle
->StyleBackground()->mImage
.mLayers
[mLayer
].mImage
;
4620 return styleImage
.IsSizeAvailable() && styleImage
.FinalImage().IsUrl();
4624 typedef class mozilla::layers::ImageContainer ImageContainer
;
4625 typedef class mozilla::layers::ImageLayer ImageLayer
;
4627 bool CanBuildWebRenderDisplayItems(LayerManager
* aManager
,
4628 nsDisplayListBuilder
* aBuilder
);
4629 nsRect
GetBoundsInternal(nsDisplayListBuilder
* aBuilder
,
4630 nsIFrame
* aFrameForBounds
= nullptr);
4632 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4633 const nsRect
& aBounds
, nsRect
* aClipRect
);
4635 // Determine whether we want to be separated into our own layer, independent
4636 // of whether this item can actually be layerized.
4637 enum ImageLayerization
{
4642 ImageLayerization
ShouldCreateOwnLayer(nsDisplayListBuilder
* aBuilder
,
4643 LayerManager
* aManager
);
4645 // Cache the result of nsCSSRendering::FindBackground. Always null if
4646 // mIsThemed is true or if FindBackground returned false.
4647 RefPtr
<mozilla::ComputedStyle
> mBackgroundStyle
;
4648 nsCOMPtr
<imgIContainer
> mImage
;
4649 nsIFrame
* mDependentFrame
;
4650 nsRect mBackgroundRect
; // relative to the reference frame
4653 /* Bounds of this display item */
4656 bool mIsRasterImage
;
4657 /* Whether the image should be treated as fixed to the viewport. */
4658 bool mShouldFixToViewport
;
4659 uint32_t mImageFlags
;
4663 * A display item to paint background image for table. For table parts, such
4664 * as row, row group, col, col group, when drawing its background, we'll
4665 * create separate background image display item for its containning cell.
4666 * Those background image display items will reference to same DisplayItemData
4667 * if we keep the mFrame point to cell's ancestor frame. We don't want to this
4668 * happened bacause share same DisplatItemData will cause many bugs. So that
4669 * we let mFrame point to cell frame and store the table type of the ancestor
4670 * frame. And use mFrame and table type as key to generate DisplayItemData to
4671 * avoid sharing DisplayItemData.
4673 * Also store ancestor frame as mStyleFrame for all rendering informations.
4675 class nsDisplayTableBackgroundImage
: public nsDisplayBackgroundImage
{
4677 nsDisplayTableBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4678 nsIFrame
* aFrame
, const InitData
& aInitData
,
4679 nsIFrame
* aCellFrame
);
4680 ~nsDisplayTableBackgroundImage() override
;
4682 NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE
)
4684 bool IsInvalid(nsRect
& aRect
) const override
;
4686 nsIFrame
* FrameForInvalidation() const override
{ return mStyleFrame
; }
4688 void RemoveFrame(nsIFrame
* aFrame
) override
{
4689 if (aFrame
== mStyleFrame
) {
4690 mStyleFrame
= nullptr;
4693 nsDisplayBackgroundImage::RemoveFrame(aFrame
);
4697 nsIFrame
* StyleFrame() const override
{ return mStyleFrame
; }
4698 nsIFrame
* mStyleFrame
;
4702 * A display item to paint the native theme background for a frame.
4704 class nsDisplayThemedBackground
: public nsPaintedDisplayItem
{
4706 nsDisplayThemedBackground(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4707 const nsRect
& aBackgroundRect
);
4709 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayThemedBackground
)
4711 NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND
)
4713 void Init(nsDisplayListBuilder
* aBuilder
);
4715 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4716 aBuilder
->UnregisterThemeGeometry(this);
4717 nsPaintedDisplayItem::Destroy(aBuilder
);
4720 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4721 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4722 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4723 bool* aSnap
) const override
;
4724 mozilla::Maybe
<nscolor
> IsUniform(
4725 nsDisplayListBuilder
* aBuilder
) const override
;
4726 bool CreateWebRenderCommands(
4727 mozilla::wr::DisplayListBuilder
& aBuilder
,
4728 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4729 const StackingContextHelper
& aSc
,
4730 mozilla::layers::RenderRootStateManager
* aManager
,
4731 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4733 bool MustPaintOnContentSide() const override
{ return true; }
4736 * GetBounds() returns the background painting area.
4738 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4740 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4743 * Return the background positioning area.
4744 * (GetBounds() returns the background painting area.)
4745 * Can be called only when mBackgroundStyle is non-null.
4747 nsRect
GetPositioningArea() const;
4750 * Return whether our frame's document does not have the state
4751 * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
4753 bool IsWindowActive() const;
4755 nsDisplayItemGeometry
* AllocateGeometry(
4756 nsDisplayListBuilder
* aBuilder
) override
{
4757 return new nsDisplayThemedBackgroundGeometry(this, aBuilder
);
4760 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4761 const nsDisplayItemGeometry
* aGeometry
,
4762 nsRegion
* aInvalidRegion
) const override
;
4764 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4767 nsRect
GetBoundsInternal();
4769 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4770 const nsRect
& aBounds
, nsRect
* aClipRect
);
4772 nsRect mBackgroundRect
;
4774 nsITheme::Transparency mThemeTransparency
;
4775 mozilla::StyleAppearance mAppearance
;
4778 class nsDisplayTableThemedBackground
: public nsDisplayThemedBackground
{
4780 nsDisplayTableThemedBackground(nsDisplayListBuilder
* aBuilder
,
4782 const nsRect
& aBackgroundRect
,
4783 nsIFrame
* aAncestorFrame
)
4784 : nsDisplayThemedBackground(aBuilder
, aFrame
, aBackgroundRect
),
4785 mAncestorFrame(aAncestorFrame
) {
4786 if (aBuilder
->IsRetainingDisplayList()) {
4787 mAncestorFrame
->AddDisplayItem(this);
4791 ~nsDisplayTableThemedBackground() override
{
4792 if (mAncestorFrame
) {
4793 mAncestorFrame
->RemoveDisplayItem(this);
4797 NS_DISPLAY_DECL_NAME("TableThemedBackground",
4798 TYPE_TABLE_THEMED_BACKGROUND_IMAGE
)
4800 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4802 void RemoveFrame(nsIFrame
* aFrame
) override
{
4803 if (aFrame
== mAncestorFrame
) {
4804 mAncestorFrame
= nullptr;
4807 nsDisplayThemedBackground::RemoveFrame(aFrame
);
4811 nsIFrame
* StyleFrame() const override
{ return mAncestorFrame
; }
4812 nsIFrame
* mAncestorFrame
;
4815 class nsDisplayBackgroundColor
: public nsPaintedDisplayItem
{
4816 typedef mozilla::gfx::sRGBColor sRGBColor
;
4819 nsDisplayBackgroundColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4820 const nsRect
& aBackgroundRect
,
4821 const mozilla::ComputedStyle
* aBackgroundStyle
,
4822 const nscolor
& aColor
)
4823 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4824 mBackgroundRect(aBackgroundRect
),
4825 mHasStyle(aBackgroundStyle
),
4826 mDependentFrame(nullptr),
4827 mColor(sRGBColor::FromABGR(aColor
)) {
4828 mState
.mColor
= mColor
;
4832 aBackgroundStyle
->StyleBackground()->BottomLayer().mClip
;
4834 MOZ_ASSERT(aBuilder
->IsForEventDelivery());
4838 ~nsDisplayBackgroundColor() override
{
4839 if (mDependentFrame
) {
4840 mDependentFrame
->RemoveDisplayItem(this);
4844 NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR
)
4846 bool RestoreState() override
{
4847 if (!nsPaintedDisplayItem::RestoreState() && mColor
== mState
.mColor
) {
4851 mColor
= mState
.mColor
;
4855 bool HasBackgroundClipText() const {
4856 MOZ_ASSERT(mHasStyle
);
4857 return mBottomLayerClip
== mozilla::StyleGeometryBox::Text
;
4860 LayerState
GetLayerState(
4861 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4862 const ContainerLayerParameters
& aParameters
) override
;
4863 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4864 void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4865 const DisplayItemClip
& aClip
) override
;
4866 already_AddRefed
<Layer
> BuildLayer(
4867 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4868 const ContainerLayerParameters
& aContainerParameters
) override
;
4869 bool CreateWebRenderCommands(
4870 mozilla::wr::DisplayListBuilder
& aBuilder
,
4871 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4872 const StackingContextHelper
& aSc
,
4873 mozilla::layers::RenderRootStateManager
* aManager
,
4874 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4875 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4876 bool* aSnap
) const override
;
4877 mozilla::Maybe
<nscolor
> IsUniform(
4878 nsDisplayListBuilder
* aBuilder
) const override
;
4879 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4880 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4881 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
4882 const DisplayItemClipChain
* aClip
) override
;
4884 bool CanApplyOpacity() const override
;
4886 float GetOpacity() const { return mColor
.a
; }
4888 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
4890 return mBackgroundRect
;
4893 bool CanPaintWithClip(const DisplayItemClip
& aClip
) override
{
4894 if (HasBackgroundClipText()) {
4898 if (aClip
.GetRoundedRectCount() > 1) {
4905 nsDisplayItemGeometry
* AllocateGeometry(
4906 nsDisplayListBuilder
* aBuilder
) override
{
4907 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
.ToABGR());
4910 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4911 const nsDisplayItemGeometry
* aGeometry
,
4912 nsRegion
* aInvalidRegion
) const override
{
4913 const nsDisplaySolidColorGeometry
* geometry
=
4914 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
4916 if (mColor
.ToABGR() != geometry
->mColor
) {
4918 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
4921 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
4924 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4926 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4927 if (!aBuilder
->IsRetainingDisplayList()) {
4930 mDependentFrame
= aFrame
;
4932 mDependentFrame
->AddDisplayItem(this);
4936 void RemoveFrame(nsIFrame
* aFrame
) override
{
4937 if (aFrame
== mDependentFrame
) {
4938 mDependentFrame
= nullptr;
4941 nsPaintedDisplayItem::RemoveFrame(aFrame
);
4944 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4946 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
4949 const nsRect mBackgroundRect
;
4950 const bool mHasStyle
;
4951 mozilla::StyleGeometryBox mBottomLayerClip
;
4952 nsIFrame
* mDependentFrame
;
4953 mozilla::gfx::sRGBColor mColor
;
4956 mozilla::gfx::sRGBColor mColor
;
4960 class nsDisplayTableBackgroundColor
: public nsDisplayBackgroundColor
{
4962 nsDisplayTableBackgroundColor(nsDisplayListBuilder
* aBuilder
,
4963 nsIFrame
* aFrame
, const nsRect
& aBackgroundRect
,
4964 const mozilla::ComputedStyle
* aBackgroundStyle
,
4965 const nscolor
& aColor
, nsIFrame
* aAncestorFrame
)
4966 : nsDisplayBackgroundColor(aBuilder
, aFrame
, aBackgroundRect
,
4967 aBackgroundStyle
, aColor
),
4968 mAncestorFrame(aAncestorFrame
) {
4969 if (aBuilder
->IsRetainingDisplayList()) {
4970 mAncestorFrame
->AddDisplayItem(this);
4974 ~nsDisplayTableBackgroundColor() override
{
4975 if (mAncestorFrame
) {
4976 mAncestorFrame
->RemoveDisplayItem(this);
4980 NS_DISPLAY_DECL_NAME("TableBackgroundColor", TYPE_TABLE_BACKGROUND_COLOR
)
4982 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4984 void RemoveFrame(nsIFrame
* aFrame
) override
{
4985 if (aFrame
== mAncestorFrame
) {
4986 mAncestorFrame
= nullptr;
4989 nsDisplayBackgroundColor::RemoveFrame(aFrame
);
4992 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
{
4997 nsIFrame
* mAncestorFrame
;
5001 * The standard display item to paint the outer CSS box-shadows of a frame.
5003 class nsDisplayBoxShadowOuter final
: public nsPaintedDisplayItem
{
5005 nsDisplayBoxShadowOuter(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5006 : nsPaintedDisplayItem(aBuilder
, aFrame
), mOpacity(1.0f
) {
5007 MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter
);
5008 mBounds
= GetBoundsInternal();
5011 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowOuter
)
5013 NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER
)
5015 bool RestoreState() override
{
5016 if (!nsPaintedDisplayItem::RestoreState() && mOpacity
== 1.0f
&&
5017 mVisibleRegion
.IsEmpty()) {
5021 mVisibleRegion
.SetEmpty();
5026 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5027 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5028 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
5029 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5030 nsRegion
* aVisibleRegion
) override
;
5031 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5032 const nsDisplayItemGeometry
* aGeometry
,
5033 nsRegion
* aInvalidRegion
) const override
;
5035 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
5036 const DisplayItemClipChain
* aClip
) override
{
5037 NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
5038 mOpacity
= aOpacity
;
5039 IntersectClip(aBuilder
, aClip
, false);
5042 bool CanApplyOpacity() const override
{ return true; }
5044 nsDisplayItemGeometry
* AllocateGeometry(
5045 nsDisplayListBuilder
* aBuilder
) override
{
5046 return new nsDisplayBoxShadowOuterGeometry(this, aBuilder
, mOpacity
);
5049 bool CanBuildWebRenderDisplayItems();
5050 bool CreateWebRenderCommands(
5051 mozilla::wr::DisplayListBuilder
& aBuilder
,
5052 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5053 const StackingContextHelper
& aSc
,
5054 mozilla::layers::RenderRootStateManager
* aManager
,
5055 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5056 nsRect
GetBoundsInternal();
5059 nsRegion mVisibleRegion
;
5065 * The standard display item to paint the inner CSS box-shadows of a frame.
5067 class nsDisplayBoxShadowInner
: public nsPaintedDisplayItem
{
5069 nsDisplayBoxShadowInner(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5070 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
5071 MOZ_COUNT_CTOR(nsDisplayBoxShadowInner
);
5074 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowInner
)
5076 NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER
)
5078 bool RestoreState() override
{
5079 if (!nsPaintedDisplayItem::RestoreState() && mVisibleRegion
.IsEmpty()) {
5083 mVisibleRegion
.SetEmpty();
5087 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5088 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5089 nsRegion
* aVisibleRegion
) override
;
5091 nsDisplayItemGeometry
* AllocateGeometry(
5092 nsDisplayListBuilder
* aBuilder
) override
{
5093 return new nsDisplayBoxShadowInnerGeometry(this, aBuilder
);
5096 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5097 const nsDisplayItemGeometry
* aGeometry
,
5098 nsRegion
* aInvalidRegion
) const override
{
5099 const nsDisplayBoxShadowInnerGeometry
* geometry
=
5100 static_cast<const nsDisplayBoxShadowInnerGeometry
*>(aGeometry
);
5101 if (!geometry
->mPaddingRect
.IsEqualInterior(GetPaddingRect())) {
5102 // nsDisplayBoxShadowInner is based around the padding rect, but it can
5103 // touch pixels outside of this. We should invalidate the entire bounds.
5105 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &snap
));
5109 static bool CanCreateWebRenderCommands(nsDisplayListBuilder
* aBuilder
,
5111 const nsPoint
& aReferencePoint
);
5112 static void CreateInsetBoxShadowWebRenderCommands(
5113 mozilla::wr::DisplayListBuilder
& aBuilder
,
5114 const StackingContextHelper
& aSc
, nsRegion
& aVisibleRegion
,
5115 nsIFrame
* aFrame
, const nsRect
& aBorderRect
);
5116 bool CreateWebRenderCommands(
5117 mozilla::wr::DisplayListBuilder
& aBuilder
,
5118 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5119 const StackingContextHelper
& aSc
,
5120 mozilla::layers::RenderRootStateManager
* aManager
,
5121 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5124 nsRegion mVisibleRegion
;
5128 * The standard display item to paint the CSS outline of a frame.
5130 class nsDisplayOutline final
: public nsPaintedDisplayItem
{
5132 nsDisplayOutline(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5133 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
5134 MOZ_COUNT_CTOR(nsDisplayOutline
);
5137 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOutline
)
5139 NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE
)
5141 bool MustPaintOnContentSide() const override
{
5142 MOZ_ASSERT(IsThemedOutline(),
5143 "The only fallback path we have is for themed outlines");
5147 bool CreateWebRenderCommands(
5148 mozilla::wr::DisplayListBuilder
& aBuilder
,
5149 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5150 const StackingContextHelper
& aSc
,
5151 mozilla::layers::RenderRootStateManager
* aManager
,
5152 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5153 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
5154 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5155 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5158 nsRect
GetInnerRect() const;
5159 bool IsThemedOutline() const;
5160 bool HasRadius() const;
5164 * A class that lets you receive events within the frame bounds but never
5167 class nsDisplayEventReceiver final
: public nsDisplayItem
{
5169 nsDisplayEventReceiver(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5170 : nsDisplayItem(aBuilder
, aFrame
) {
5171 MOZ_COUNT_CTOR(nsDisplayEventReceiver
);
5174 MOZ_COUNTED_DTOR_FINAL(nsDisplayEventReceiver
)
5176 NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER
)
5178 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5179 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
;
5183 * Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
5184 * this gets built when we're doing widget painting and we need to send the
5185 * compositor some hit-test info for a frame. This is effectively a dummy item
5186 * whose sole purpose is to carry the hit-test info to the compositor.
5188 class nsDisplayCompositorHitTestInfo final
: public nsDisplayItem
{
5190 nsDisplayCompositorHitTestInfo(nsDisplayListBuilder
* aBuilder
,
5192 : nsDisplayItem(aBuilder
, aFrame
) {
5193 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
5194 mHitTestInfo
.Initialize(aBuilder
, aFrame
);
5195 SetHasHitTestInfo();
5198 nsDisplayCompositorHitTestInfo(
5199 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, const nsRect
& aArea
,
5200 const mozilla::gfx::CompositorHitTestInfo
& aHitTestFlags
)
5201 : nsDisplayItem(aBuilder
, aFrame
) {
5202 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
5203 mHitTestInfo
.SetAreaAndInfo(aArea
, aHitTestFlags
);
5204 mHitTestInfo
.InitializeScrollTarget(aBuilder
);
5205 SetHasHitTestInfo();
5208 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo
)
5210 NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO
)
5212 bool CreateWebRenderCommands(
5213 mozilla::wr::DisplayListBuilder
& aBuilder
,
5214 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5215 const StackingContextHelper
& aSc
,
5216 mozilla::layers::RenderRootStateManager
* aManager
,
5217 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5219 int32_t ZIndex() const override
;
5220 void SetOverrideZIndex(int32_t aZIndex
);
5222 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
5227 const mozilla::HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
5230 mozilla::HitTestInfo mHitTestInfo
;
5231 mozilla::Maybe
<int32_t> mOverrideZIndex
;
5235 * A class that lets you wrap a display list as a display item.
5237 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
5238 * list has many items, it's not clear which one has the 'underlying frame'.
5239 * Thus we force the creator to specify what the underlying frame is. The
5240 * underlying frame should be the root of a stacking context, because sorting
5241 * a list containing this item will not get at the children.
5243 * In some cases (e.g., clipping) we want to wrap a list but we don't have a
5244 * particular underlying frame that is a stacking context root. In that case
5245 * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
5246 * detect and handle this case.
5248 class nsDisplayWrapList
: public nsPaintedDisplayItem
{
5251 * Takes all the items from aList and puts them in our list.
5253 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5254 nsDisplayList
* aList
);
5256 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5257 nsDisplayItem
* aItem
);
5259 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5260 nsDisplayList
* aList
,
5261 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5262 bool aClearClipChain
= false);
5264 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5265 : nsPaintedDisplayItem(aBuilder
, aFrame
),
5266 mFrameActiveScrolledRoot(aBuilder
->CurrentActiveScrolledRoot()),
5268 mHasZIndexOverride(false) {
5269 MOZ_COUNT_CTOR(nsDisplayWrapList
);
5270 mBaseBuildingRect
= GetBuildingRect();
5274 nsDisplayWrapList() = delete;
5277 * A custom copy-constructor that does not copy mList, as this would mutate
5280 nsDisplayWrapList(const nsDisplayWrapList
& aOther
) = delete;
5281 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
,
5282 const nsDisplayWrapList
& aOther
)
5283 : nsPaintedDisplayItem(aBuilder
, aOther
),
5285 mFrameActiveScrolledRoot(aOther
.mFrameActiveScrolledRoot
),
5286 mMergedFrames(aOther
.mMergedFrames
.Clone()),
5287 mBounds(aOther
.mBounds
),
5288 mBaseBuildingRect(aOther
.mBaseBuildingRect
),
5289 mOverrideZIndex(aOther
.mOverrideZIndex
),
5290 mHasZIndexOverride(aOther
.mHasZIndexOverride
),
5291 mClearingClipChain(aOther
.mClearingClipChain
) {
5292 MOZ_COUNT_CTOR(nsDisplayWrapList
);
5295 ~nsDisplayWrapList() override
;
5297 const nsDisplayWrapList
* AsDisplayWrapList() const final
{ return this; }
5298 nsDisplayWrapList
* AsDisplayWrapList() final
{ return this; }
5300 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
5301 mList
.DeleteAll(aBuilder
);
5302 nsPaintedDisplayItem::Destroy(aBuilder
);
5306 * Creates a new nsDisplayWrapList that holds a pointer to the display list
5307 * owned by the given nsDisplayItem. The new nsDisplayWrapList will be added
5308 * to the bottom of this item's contents.
5310 void MergeDisplayListFromItem(nsDisplayListBuilder
* aBuilder
,
5311 const nsDisplayWrapList
* aItem
);
5314 * Call this if the wrapped list is changed.
5316 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
{
5317 // Clear the clip chain up to the asr, but don't store it, so that we'll
5318 // recover it when we reuse the item.
5319 if (mClearingClipChain
) {
5320 const DisplayItemClipChain
* clip
= mState
.mClipChain
;
5321 while (clip
&& ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(),
5323 clip
= clip
->mParent
;
5325 SetClipChain(clip
, false);
5328 nsRect buildingRect
;
5329 mBounds
= mListPtr
->GetClippedBoundsWithRespectToASR(
5330 aBuilder
, mActiveScrolledRoot
, &buildingRect
);
5331 // The display list may contain content that's visible outside the visible
5332 // rect (i.e. the current dirty rect) passed in when the item was created.
5333 // This happens when the dirty rect has been restricted to the visual
5334 // overflow rect of a frame for some reason (e.g. when setting up dirty
5335 // rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
5336 // frame contains placeholders for out-of-flows that aren't descendants of
5338 buildingRect
.UnionRect(mBaseBuildingRect
, buildingRect
);
5339 SetBuildingRect(buildingRect
);
5342 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5343 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5344 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5345 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5346 bool* aSnap
) const override
;
5347 mozilla::Maybe
<nscolor
> IsUniform(
5348 nsDisplayListBuilder
* aBuilder
) const override
;
5349 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5350 nsRegion
* aVisibleRegion
) override
;
5353 * Checks if the given display item can be merged with this item.
5354 * @return true if the merging is possible, otherwise false.
5356 virtual bool CanMerge(const nsDisplayItem
* aItem
) const { return false; }
5359 * Try to merge with the other item (which is below us in the display
5360 * list). This gets used by nsDisplayClip to coalesce clipping operations
5361 * (optimization), by nsDisplayOpacity to merge rendering for the same
5362 * content element into a single opacity group (correctness), and will be
5363 * used by nsDisplayOutline to merge multiple outlines for the same element
5364 * (also for correctness).
5366 virtual void Merge(const nsDisplayItem
* aItem
) {
5367 MOZ_ASSERT(CanMerge(aItem
));
5368 MOZ_ASSERT(Frame() != aItem
->Frame());
5369 MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList
*>(aItem
));
5373 * Returns the underlying frames of all display items that have been
5374 * merged into this one (excluding this item's own underlying frame)
5377 const nsTArray
<nsIFrame
*>& GetMergedFrames() const { return mMergedFrames
; }
5379 bool HasMergedFrames() const { return !mMergedFrames
.IsEmpty(); }
5381 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5385 bool IsInvalid(nsRect
& aRect
) const override
{
5386 if (mFrame
->IsInvalid(aRect
) && aRect
.IsEmpty()) {
5390 for (uint32_t i
= 0; i
< mMergedFrames
.Length(); i
++) {
5391 if (mMergedFrames
[i
]->IsInvalid(temp
) && temp
.IsEmpty()) {
5395 aRect
= aRect
.Union(temp
);
5397 aRect
+= ToReferenceFrame();
5398 return !aRect
.IsEmpty();
5401 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
5403 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
5405 mListPtr
->IsEmpty() || !ReferenceFrame() ||
5406 !mListPtr
->GetBottom()->ReferenceFrame() ||
5407 mListPtr
->GetBottom()->ReferenceFrame() == ReferenceFrame(),
5408 "Children must have same reference frame");
5412 RetainedDisplayList
* GetChildren() const override
{ return mListPtr
; }
5414 int32_t ZIndex() const override
{
5415 return (mHasZIndexOverride
) ? mOverrideZIndex
5416 : nsPaintedDisplayItem::ZIndex();
5419 void SetOverrideZIndex(int32_t aZIndex
) {
5420 mHasZIndexOverride
= true;
5421 mOverrideZIndex
= aZIndex
;
5425 * This creates a copy of this item, but wrapping aItem instead of
5426 * our existing list. Only gets called if this item returned nullptr
5427 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
5428 * GetUnderlyingFrame().
5430 nsDisplayWrapList
* WrapWithClone(nsDisplayListBuilder
* aBuilder
,
5431 nsDisplayItem
* aItem
) {
5432 MOZ_ASSERT_UNREACHABLE("We never returned nullptr for GetUnderlyingFrame!");
5436 bool CreateWebRenderCommands(
5437 mozilla::wr::DisplayListBuilder
& aBuilder
,
5438 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5439 const StackingContextHelper
& aSc
,
5440 mozilla::layers::RenderRootStateManager
* aManager
,
5441 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5443 const ActiveScrolledRoot
* GetFrameActiveScrolledRoot() {
5444 return mFrameActiveScrolledRoot
;
5448 void MergeFromTrackingMergedFrames(const nsDisplayWrapList
* aOther
) {
5449 mBounds
.UnionRect(mBounds
, aOther
->mBounds
);
5450 nsRect buildingRect
;
5451 buildingRect
.UnionRect(GetBuildingRect(), aOther
->GetBuildingRect());
5452 SetBuildingRect(buildingRect
);
5453 mMergedFrames
.AppendElement(aOther
->mFrame
);
5454 mMergedFrames
.AppendElements(aOther
->mMergedFrames
.Clone());
5457 RetainedDisplayList mList
;
5458 RetainedDisplayList
* mListPtr
;
5459 // The active scrolled root for the frame that created this
5461 RefPtr
<const ActiveScrolledRoot
> mFrameActiveScrolledRoot
;
5462 // The frames from items that have been merged into this item, excluding
5463 // this item's own frame.
5464 nsTArray
<nsIFrame
*> mMergedFrames
;
5466 // Displaylist building rect contributed by this display item itself.
5467 // Our mBuildingRect may include the visible areas of children.
5468 nsRect mBaseBuildingRect
;
5469 int32_t mOverrideZIndex
;
5470 bool mHasZIndexOverride
;
5471 bool mClearingClipChain
= false;
5474 class nsDisplayWrapper
: public nsDisplayWrapList
{
5476 NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST
)
5478 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5479 nsDisplayList
* aList
,
5480 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5481 bool aClearClipChain
= false)
5482 : nsDisplayWrapList(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5485 nsDisplayWrapper(const nsDisplayWrapper
& aOther
) = delete;
5486 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
,
5487 const nsDisplayWrapList
& aOther
)
5488 : nsDisplayWrapList(aBuilder
, aOther
) {}
5490 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5493 NS_DISPLAY_ALLOW_CLONING()
5494 friend class nsDisplayListBuilder
;
5495 friend class nsDisplayWrapList
;
5499 * We call WrapDisplayList on the in-flow lists: BorderBackground(),
5500 * BlockBorderBackgrounds() and Content().
5501 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
5502 * and Floats(). This is done to support special wrapping processing for frames
5503 * that may not be in-flow descendants of the current frame.
5505 class nsDisplayItemWrapper
{
5507 // This is never instantiated directly (it has pure virtual methods), so no
5508 // need to count constructors and destructors.
5510 bool WrapBorderBackground() { return true; }
5511 virtual nsDisplayItem
* WrapList(nsDisplayListBuilder
* aBuilder
,
5512 nsIFrame
* aFrame
, nsDisplayList
* aList
) = 0;
5513 virtual nsDisplayItem
* WrapItem(nsDisplayListBuilder
* aBuilder
,
5514 nsDisplayItem
* aItem
) = 0;
5516 nsresult
WrapLists(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5517 const nsDisplayListSet
& aIn
, const nsDisplayListSet
& aOut
);
5518 nsresult
WrapListsInPlace(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5519 const nsDisplayListSet
& aLists
);
5522 nsDisplayItemWrapper() = default;
5526 * The standard display item to paint a stacking context with translucency
5527 * set by the stacking context root frame's 'opacity' style.
5529 class nsDisplayOpacity
: public nsDisplayWrapList
{
5531 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5532 nsDisplayList
* aList
,
5533 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5534 bool aForEventsOnly
, bool aNeedsActiveLayer
);
5536 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
,
5537 const nsDisplayOpacity
& aOther
)
5538 : nsDisplayWrapList(aBuilder
, aOther
),
5539 mOpacity(aOther
.mOpacity
),
5540 mForEventsOnly(aOther
.mForEventsOnly
),
5541 mNeedsActiveLayer(aOther
.mNeedsActiveLayer
),
5542 mChildOpacityState(ChildOpacityState::Unknown
) {
5543 MOZ_COUNT_CTOR(nsDisplayOpacity
);
5544 // We should not try to merge flattened opacities.
5545 MOZ_ASSERT(aOther
.mChildOpacityState
!= ChildOpacityState::Applied
);
5548 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5549 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5551 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOpacity
)
5553 NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY
)
5555 bool RestoreState() override
{
5556 if (!nsDisplayWrapList::RestoreState() && mOpacity
== mState
.mOpacity
) {
5560 mOpacity
= mState
.mOpacity
;
5564 void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) override
{
5565 mChildOpacityState
= ChildOpacityState::Unknown
;
5568 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5569 bool* aSnap
) const override
;
5570 already_AddRefed
<Layer
> BuildLayer(
5571 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5572 const ContainerLayerParameters
& aContainerParameters
) override
;
5573 LayerState
GetLayerState(
5574 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5575 const ContainerLayerParameters
& aParameters
) override
;
5576 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5577 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5578 nsRegion
* aVisibleRegion
) override
;
5580 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5581 // items for the same content element should be merged into a single
5582 // compositing group
5583 // aItem->GetUnderlyingFrame() returns non-null because it's
5585 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5586 HasSameContent(aItem
);
5589 nsDisplayItemGeometry
* AllocateGeometry(
5590 nsDisplayListBuilder
* aBuilder
) override
{
5591 return new nsDisplayOpacityGeometry(this, aBuilder
, mOpacity
);
5594 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5595 const nsDisplayItemGeometry
* aGeometry
,
5596 nsRegion
* aInvalidRegion
) const override
;
5598 bool IsInvalid(nsRect
& aRect
) const override
{
5599 if (mForEventsOnly
) {
5602 return nsDisplayWrapList::IsInvalid(aRect
);
5604 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
5605 const DisplayItemClipChain
* aClip
) override
;
5606 bool CanApplyOpacity() const override
;
5607 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
5609 bool NeedsGeometryUpdates() const override
{
5610 // For flattened nsDisplayOpacity items, ComputeInvalidationRegion() only
5611 // handles invalidation for changed |mOpacity|. In order to keep track of
5612 // the current bounds of the item for invalidation, nsDisplayOpacityGeometry
5613 // for the corresponding DisplayItemData needs to be updated, even if the
5614 // reported invalidation region is empty.
5615 return mChildOpacityState
== ChildOpacityState::Deferred
;
5619 * Returns true if ShouldFlattenAway() applied opacity to children.
5621 bool OpacityAppliedToChildren() const {
5622 return mChildOpacityState
== ChildOpacityState::Applied
;
5625 static bool NeedsActiveLayer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5626 bool aEnforceMinimumSize
= true);
5627 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5628 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
5629 bool CreateWebRenderCommands(
5630 mozilla::wr::DisplayListBuilder
& aBuilder
,
5631 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5632 const StackingContextHelper
& aSc
,
5633 mozilla::layers::RenderRootStateManager
* aManager
,
5634 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5636 float GetOpacity() const { return mOpacity
; }
5639 NS_DISPLAY_ALLOW_CLONING()
5641 bool ApplyToChildren(nsDisplayListBuilder
* aBuilder
);
5642 bool ApplyToFilterOrMask(const bool aUsingLayers
);
5645 bool mForEventsOnly
: 1;
5646 enum class ChildOpacityState
: uint8_t {
5647 // Our child list has changed since the last time ApplyToChildren was
5650 // Our children defer opacity handling to us.
5652 // Opacity is applied to our children.
5655 bool mNeedsActiveLayer
: 1;
5657 ChildOpacityState mChildOpacityState
: 2;
5659 ChildOpacityState mChildOpacityState
;
5667 class nsDisplayBlendMode
: public nsDisplayWrapList
{
5669 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5670 nsDisplayList
* aList
, mozilla::StyleBlend aBlendMode
,
5671 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5672 const bool aIsForBackground
);
5673 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
,
5674 const nsDisplayBlendMode
& aOther
)
5675 : nsDisplayWrapList(aBuilder
, aOther
),
5676 mBlendMode(aOther
.mBlendMode
),
5677 mIsForBackground(aOther
.mIsForBackground
) {
5678 MOZ_COUNT_CTOR(nsDisplayBlendMode
);
5681 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendMode
)
5683 NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE
)
5685 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5686 bool* aSnap
) const override
;
5687 already_AddRefed
<Layer
> BuildLayer(
5688 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5689 const ContainerLayerParameters
& aContainerParameters
) override
;
5690 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5691 const nsDisplayItemGeometry
* aGeometry
,
5692 nsRegion
* aInvalidRegion
) const override
{
5693 // We don't need to compute an invalidation region since we have
5694 // LayerTreeInvalidation
5697 LayerState
GetLayerState(
5698 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5699 const ContainerLayerParameters
& aParameters
) override
;
5700 bool CreateWebRenderCommands(
5701 mozilla::wr::DisplayListBuilder
& aBuilder
,
5702 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5703 const StackingContextHelper
& aSc
,
5704 mozilla::layers::RenderRootStateManager
* aManager
,
5705 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5706 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5707 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5708 nsRegion
* aVisibleRegion
) override
;
5710 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
5712 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5716 mozilla::gfx::CompositionOp
BlendMode();
5719 mozilla::StyleBlend mBlendMode
;
5720 bool mIsForBackground
;
5723 NS_DISPLAY_ALLOW_CLONING()
5726 class nsDisplayTableBlendMode
: public nsDisplayBlendMode
{
5728 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5729 nsDisplayList
* aList
, mozilla::StyleBlend aBlendMode
,
5730 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5731 nsIFrame
* aAncestorFrame
, const bool aIsForBackground
)
5732 : nsDisplayBlendMode(aBuilder
, aFrame
, aList
, aBlendMode
,
5733 aActiveScrolledRoot
, aIsForBackground
),
5734 mAncestorFrame(aAncestorFrame
) {
5735 if (aBuilder
->IsRetainingDisplayList()) {
5736 mAncestorFrame
->AddDisplayItem(this);
5740 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
,
5741 const nsDisplayTableBlendMode
& aOther
)
5742 : nsDisplayBlendMode(aBuilder
, aOther
),
5743 mAncestorFrame(aOther
.mAncestorFrame
) {
5744 if (aBuilder
->IsRetainingDisplayList()) {
5745 mAncestorFrame
->AddDisplayItem(this);
5749 ~nsDisplayTableBlendMode() override
{
5750 if (mAncestorFrame
) {
5751 mAncestorFrame
->RemoveDisplayItem(this);
5755 NS_DISPLAY_DECL_NAME("TableBlendMode", TYPE_TABLE_BLEND_MODE
)
5757 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5759 void RemoveFrame(nsIFrame
* aFrame
) override
{
5760 if (aFrame
== mAncestorFrame
) {
5761 mAncestorFrame
= nullptr;
5764 nsDisplayBlendMode::RemoveFrame(aFrame
);
5768 nsIFrame
* mAncestorFrame
;
5771 NS_DISPLAY_ALLOW_CLONING()
5774 class nsDisplayBlendContainer
: public nsDisplayWrapList
{
5776 static nsDisplayBlendContainer
* CreateForMixBlendMode(
5777 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5778 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5780 static nsDisplayBlendContainer
* CreateForBackgroundBlendMode(
5781 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5782 nsIFrame
* aSecondaryFrame
, nsDisplayList
* aList
,
5783 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5785 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendContainer
)
5787 NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER
)
5789 already_AddRefed
<Layer
> BuildLayer(
5790 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5791 const ContainerLayerParameters
& aContainerParameters
) override
;
5792 LayerState
GetLayerState(
5793 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5794 const ContainerLayerParameters
& aParameters
) override
;
5795 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5796 bool CreateWebRenderCommands(
5797 mozilla::wr::DisplayListBuilder
& aBuilder
,
5798 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5799 const StackingContextHelper
& aSc
,
5800 mozilla::layers::RenderRootStateManager
* aManager
,
5801 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5803 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5804 // Items for the same content element should be merged into a single
5805 // compositing group.
5806 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5807 HasSameContent(aItem
) &&
5809 static_cast<const nsDisplayBlendContainer
*>(aItem
)
5813 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5818 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5819 nsDisplayList
* aList
,
5820 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5821 bool aIsForBackground
);
5822 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
,
5823 const nsDisplayBlendContainer
& aOther
)
5824 : nsDisplayWrapList(aBuilder
, aOther
),
5825 mIsForBackground(aOther
.mIsForBackground
) {
5826 MOZ_COUNT_CTOR(nsDisplayBlendContainer
);
5829 // Used to distinguish containers created at building stacking
5830 // context or appending background.
5831 bool mIsForBackground
;
5834 NS_DISPLAY_ALLOW_CLONING()
5837 class nsDisplayTableBlendContainer
: public nsDisplayBlendContainer
{
5839 NS_DISPLAY_DECL_NAME("TableBlendContainer", TYPE_TABLE_BLEND_CONTAINER
)
5841 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5843 void RemoveFrame(nsIFrame
* aFrame
) override
{
5844 if (aFrame
== mAncestorFrame
) {
5845 mAncestorFrame
= nullptr;
5848 nsDisplayBlendContainer::RemoveFrame(aFrame
);
5852 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5853 nsDisplayList
* aList
,
5854 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5855 bool aIsForBackground
, nsIFrame
* aAncestorFrame
)
5856 : nsDisplayBlendContainer(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5858 mAncestorFrame(aAncestorFrame
) {
5859 if (aBuilder
->IsRetainingDisplayList()) {
5860 mAncestorFrame
->AddDisplayItem(this);
5864 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
,
5865 const nsDisplayTableBlendContainer
& aOther
)
5866 : nsDisplayBlendContainer(aBuilder
, aOther
),
5867 mAncestorFrame(aOther
.mAncestorFrame
) {}
5869 ~nsDisplayTableBlendContainer() override
{
5870 if (mAncestorFrame
) {
5871 mAncestorFrame
->RemoveDisplayItem(this);
5875 nsIFrame
* mAncestorFrame
;
5878 NS_DISPLAY_ALLOW_CLONING()
5882 * nsDisplayOwnLayer constructor flags. If we nest this class inside
5883 * nsDisplayOwnLayer then we can't forward-declare it up at the top of this
5884 * file and that makes it hard to use in all the places that we need to use it.
5886 enum class nsDisplayOwnLayerFlags
{
5888 GenerateSubdocInvalidations
= 1 << 0,
5889 GenerateScrollableLayer
= 1 << 1,
5892 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags
)
5895 * A display item that has no purpose but to ensure its contents get
5898 class nsDisplayOwnLayer
: public nsDisplayWrapList
{
5900 typedef mozilla::layers::ScrollbarData ScrollbarData
;
5903 OwnLayerForTransformWithRoundedClip
,
5904 OwnLayerForStackingContext
,
5905 OwnLayerForImageBoxFrame
,
5906 OwnLayerForScrollbar
,
5907 OwnLayerForScrollThumb
,
5913 * @param aFlags eGenerateSubdocInvalidations :
5914 * Add UserData to the created ContainerLayer, so that invalidations
5915 * for this layer are send to our nsPresContext.
5916 * eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and
5917 * subclasses), indicates this layer is to be a scrollable layer, so call
5918 * ComputeFrameMetrics, etc.
5919 * @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar
5920 * is set in the flags, this parameter should be the ViewID of the
5921 * scrollable content this scrollbar is for.
5924 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5925 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5926 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
,
5927 const ScrollbarData
& aScrollbarData
= ScrollbarData
{},
5928 bool aForceActive
= true, bool aClearClipChain
= false);
5930 nsDisplayOwnLayer(nsDisplayListBuilder
* aBuilder
,
5931 const nsDisplayOwnLayer
& aOther
)
5932 : nsDisplayWrapList(aBuilder
, aOther
),
5933 mFlags(aOther
.mFlags
),
5934 mScrollbarData(aOther
.mScrollbarData
),
5935 mForceActive(aOther
.mForceActive
),
5936 mWrAnimationId(aOther
.mWrAnimationId
) {
5937 MOZ_COUNT_CTOR(nsDisplayOwnLayer
);
5940 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOwnLayer
)
5942 NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER
)
5944 already_AddRefed
<Layer
> BuildLayer(
5945 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5946 const ContainerLayerParameters
& aContainerParameters
) override
;
5947 bool CreateWebRenderCommands(
5948 mozilla::wr::DisplayListBuilder
& aBuilder
,
5949 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5950 const StackingContextHelper
& aSc
,
5951 mozilla::layers::RenderRootStateManager
* aManager
,
5952 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5953 bool UpdateScrollData(
5954 mozilla::layers::WebRenderScrollData
* aData
,
5955 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
5956 LayerState
GetLayerState(
5957 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5958 const ContainerLayerParameters
& aParameters
) override
;
5959 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5960 GetChildren()->Paint(aBuilder
, aCtx
,
5961 mFrame
->PresContext()->AppUnitsPerDevPixel());
5964 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5965 // Don't allow merging, each sublist must have its own layer
5969 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5973 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5974 nsDisplayOwnLayerFlags
GetFlags() { return mFlags
; }
5975 bool IsScrollThumbLayer() const;
5976 bool IsScrollbarContainer() const;
5977 bool IsRootScrollbarContainer() const;
5978 bool IsZoomingLayer() const;
5979 bool IsFixedPositionLayer() const;
5980 bool IsStickyPositionLayer() const;
5981 bool HasDynamicToolbar() const;
5984 nsDisplayOwnLayerFlags mFlags
;
5987 * If this nsDisplayOwnLayer represents a scroll thumb layer or a
5988 * scrollbar container layer, mScrollbarData stores information
5989 * about the scrollbar. Otherwise, mScrollbarData will be
5990 * default-constructed (in particular with mDirection == Nothing())
5991 * and can be ignored.
5993 ScrollbarData mScrollbarData
;
5995 uint64_t mWrAnimationId
;
5999 * A display item for subdocuments. This is more or less the same as
6000 * nsDisplayOwnLayer, except that it always populates the FrameMetrics instance
6001 * on the ContainerLayer it builds.
6003 class nsDisplaySubDocument
: public nsDisplayOwnLayer
{
6005 nsDisplaySubDocument(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6006 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
6007 nsDisplayOwnLayerFlags aFlags
);
6008 ~nsDisplaySubDocument() override
;
6010 NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT
)
6012 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6014 virtual nsSubDocumentFrame
* SubDocumentFrame() { return mSubDocFrame
; }
6016 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6017 nsRegion
* aVisibleRegion
) override
;
6018 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6019 return mShouldFlatten
;
6022 void SetShouldFlattenAway(bool aShouldFlatten
) {
6023 mShouldFlatten
= aShouldFlatten
;
6026 LayerState
GetLayerState(
6027 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6028 const ContainerLayerParameters
& aParameters
) override
{
6029 if (mShouldFlatten
) {
6030 return mozilla::LayerState::LAYER_NONE
;
6032 return nsDisplayOwnLayer::GetLayerState(aBuilder
, aManager
, aParameters
);
6035 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6036 bool* aSnap
) const override
;
6038 nsIFrame
* FrameForInvalidation() const override
;
6039 void RemoveFrame(nsIFrame
* aFrame
) override
;
6044 ViewID mScrollParentId
;
6045 bool mForceDispatchToContentRegion
;
6046 bool mShouldFlatten
;
6047 nsSubDocumentFrame
* mSubDocFrame
;
6051 * A display item used to represent sticky position elements. The contents
6052 * gets its own layer and creates a stacking context, and the layer will have
6053 * position-related metadata set on it.
6055 class nsDisplayStickyPosition
: public nsDisplayOwnLayer
{
6057 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6058 nsDisplayList
* aList
,
6059 const ActiveScrolledRoot
* aActiveScrolledRoot
,
6060 const ActiveScrolledRoot
* aContainerASR
,
6061 bool aClippedToDisplayPort
);
6062 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
,
6063 const nsDisplayStickyPosition
& aOther
)
6064 : nsDisplayOwnLayer(aBuilder
, aOther
),
6065 mContainerASR(aOther
.mContainerASR
),
6066 mClippedToDisplayPort(aOther
.mClippedToDisplayPort
) {
6067 MOZ_COUNT_CTOR(nsDisplayStickyPosition
);
6070 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayStickyPosition
)
6072 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
6073 bool aStore
) override
;
6074 bool IsClippedToDisplayPort() const { return mClippedToDisplayPort
; }
6076 already_AddRefed
<Layer
> BuildLayer(
6077 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6078 const ContainerLayerParameters
& aContainerParameters
) override
;
6079 NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION
)
6080 LayerState
GetLayerState(
6081 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6082 const ContainerLayerParameters
& aParameters
) override
{
6083 return mozilla::LayerState::LAYER_ACTIVE
;
6085 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6086 GetChildren()->Paint(aBuilder
, aCtx
,
6087 mFrame
->PresContext()->AppUnitsPerDevPixel());
6090 bool CreateWebRenderCommands(
6091 mozilla::wr::DisplayListBuilder
& aBuilder
,
6092 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6093 const StackingContextHelper
& aSc
,
6094 mozilla::layers::RenderRootStateManager
* aManager
,
6095 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6097 bool UpdateScrollData(
6098 mozilla::layers::WebRenderScrollData
* aData
,
6099 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6101 const ActiveScrolledRoot
* GetContainerASR() const { return mContainerASR
; }
6104 NS_DISPLAY_ALLOW_CLONING()
6106 void CalculateLayerScrollRanges(
6107 mozilla::StickyScrollContainer
* aStickyScrollContainer
,
6108 float aAppUnitsPerDevPixel
, float aScaleX
, float aScaleY
,
6109 mozilla::LayerRectAbsolute
& aStickyOuter
,
6110 mozilla::LayerRectAbsolute
& aStickyInner
);
6112 mozilla::StickyScrollContainer
* GetStickyScrollContainer();
6114 // This stores the ASR that this sticky container item would have assuming it
6115 // has no fixed descendants. This may be the same as the ASR returned by
6116 // GetActiveScrolledRoot(), or it may be a descendant of that.
6117 RefPtr
<const ActiveScrolledRoot
> mContainerASR
;
6118 // This flag tracks if this sticky item is just clipped to the enclosing
6119 // scrollframe's displayport, or if there are additional clips in play. In
6120 // the former case, we can skip setting the displayport clip as the scrolled-
6121 // clip of the corresponding layer. This allows sticky items to remain
6122 // unclipped when the enclosing scrollframe is scrolled past the displayport.
6123 // i.e. when the rest of the scrollframe checkerboards, the sticky item will
6124 // not. This makes sense to do because the sticky item has abnormal scrolling
6125 // behavior and may still be visible even if the rest of the scrollframe is
6126 // checkerboarded. Note that the sticky item will still be subject to the
6128 bool mClippedToDisplayPort
;
6131 class nsDisplayFixedPosition
: public nsDisplayOwnLayer
{
6133 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6134 nsDisplayList
* aList
,
6135 const ActiveScrolledRoot
* aActiveScrolledRoot
,
6136 const ActiveScrolledRoot
* aContainerASR
);
6137 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
,
6138 const nsDisplayFixedPosition
& aOther
)
6139 : nsDisplayOwnLayer(aBuilder
, aOther
),
6140 mAnimatedGeometryRootForScrollMetadata(
6141 aOther
.mAnimatedGeometryRootForScrollMetadata
),
6142 mContainerASR(aOther
.mContainerASR
),
6143 mIsFixedBackground(aOther
.mIsFixedBackground
) {
6144 MOZ_COUNT_CTOR(nsDisplayFixedPosition
);
6147 static nsDisplayFixedPosition
* CreateForFixedBackground(
6148 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6149 nsIFrame
* aSecondaryFrame
, nsDisplayBackgroundImage
* aImage
,
6150 const uint16_t aIndex
);
6152 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFixedPosition
)
6154 NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION
)
6156 already_AddRefed
<Layer
> BuildLayer(
6157 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6158 const ContainerLayerParameters
& aContainerParameters
) override
;
6160 LayerState
GetLayerState(
6161 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6162 const ContainerLayerParameters
& aParameters
) override
{
6163 return mozilla::LayerState::LAYER_ACTIVE_FORCE
;
6165 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6166 GetChildren()->Paint(aBuilder
, aCtx
,
6167 mFrame
->PresContext()->AppUnitsPerDevPixel());
6170 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
6171 return mIsFixedBackground
;
6174 AnimatedGeometryRoot
* AnimatedGeometryRootForScrollMetadata() const override
{
6175 return mAnimatedGeometryRootForScrollMetadata
;
6178 bool CreateWebRenderCommands(
6179 mozilla::wr::DisplayListBuilder
& aBuilder
,
6180 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6181 const StackingContextHelper
& aSc
,
6182 mozilla::layers::RenderRootStateManager
* aManager
,
6183 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6184 bool UpdateScrollData(
6185 mozilla::layers::WebRenderScrollData
* aData
,
6186 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6187 void WriteDebugInfo(std::stringstream
& aStream
) override
;
6190 // For background-attachment:fixed
6191 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6192 nsDisplayList
* aList
);
6193 void Init(nsDisplayListBuilder
* aBuilder
);
6194 ViewID
GetScrollTargetId();
6196 RefPtr
<AnimatedGeometryRoot
> mAnimatedGeometryRootForScrollMetadata
;
6197 RefPtr
<const ActiveScrolledRoot
> mContainerASR
;
6198 bool mIsFixedBackground
;
6201 NS_DISPLAY_ALLOW_CLONING()
6204 class nsDisplayTableFixedPosition
: public nsDisplayFixedPosition
{
6206 NS_DISPLAY_DECL_NAME("TableFixedPosition", TYPE_TABLE_FIXED_POSITION
)
6208 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
6210 void RemoveFrame(nsIFrame
* aFrame
) override
{
6211 if (aFrame
== mAncestorFrame
) {
6212 mAncestorFrame
= nullptr;
6215 nsDisplayFixedPosition::RemoveFrame(aFrame
);
6219 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6220 nsDisplayList
* aList
, nsIFrame
* aAncestorFrame
);
6222 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
,
6223 const nsDisplayTableFixedPosition
& aOther
)
6224 : nsDisplayFixedPosition(aBuilder
, aOther
),
6225 mAncestorFrame(aOther
.mAncestorFrame
) {}
6227 ~nsDisplayTableFixedPosition() override
{
6228 if (mAncestorFrame
) {
6229 mAncestorFrame
->RemoveDisplayItem(this);
6233 nsIFrame
* mAncestorFrame
;
6236 NS_DISPLAY_ALLOW_CLONING()
6240 * This creates an empty scrollable layer. It has no child layers.
6241 * It is used to record the existence of a scrollable frame in the layer
6244 class nsDisplayScrollInfoLayer
: public nsDisplayWrapList
{
6246 nsDisplayScrollInfoLayer(nsDisplayListBuilder
* aBuilder
,
6247 nsIFrame
* aScrolledFrame
, nsIFrame
* aScrollFrame
,
6248 const CompositorHitTestInfo
& aHitInfo
,
6249 const nsRect
& aHitArea
);
6251 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayScrollInfoLayer
)
6253 NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER
)
6255 already_AddRefed
<Layer
> BuildLayer(
6256 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6257 const ContainerLayerParameters
& aContainerParameters
) override
;
6259 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6260 bool* aSnap
) const override
{
6265 LayerState
GetLayerState(
6266 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6267 const ContainerLayerParameters
& aParameters
) override
;
6268 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6272 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6276 void WriteDebugInfo(std::stringstream
& aStream
) override
;
6277 mozilla::UniquePtr
<ScrollMetadata
> ComputeScrollMetadata(
6278 nsDisplayListBuilder
* aBuilder
, LayerManager
* aLayerManager
,
6279 const ContainerLayerParameters
& aContainerParameters
);
6280 bool UpdateScrollData(
6281 mozilla::layers::WebRenderScrollData
* aData
,
6282 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6283 bool CreateWebRenderCommands(
6284 mozilla::wr::DisplayListBuilder
& aBuilder
,
6285 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6286 const StackingContextHelper
& aSc
,
6287 mozilla::layers::RenderRootStateManager
* aManager
,
6288 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6291 nsIFrame
* mScrollFrame
;
6292 nsIFrame
* mScrolledFrame
;
6293 ViewID mScrollParentId
;
6294 CompositorHitTestInfo mHitInfo
;
6299 * nsDisplayZoom is used for subdocuments that have a different full zoom than
6300 * their parent documents. This item creates a container layer.
6302 class nsDisplayZoom
: public nsDisplaySubDocument
{
6305 * @param aFrame is the root frame of the subdocument.
6306 * @param aList contains the display items for the subdocument.
6307 * @param aAPD is the app units per dev pixel ratio of the subdocument.
6308 * @param aParentAPD is the app units per dev pixel ratio of the parent
6310 * @param aFlags eGenerateSubdocInvalidations :
6311 * Add UserData to the created ContainerLayer, so that invalidations
6312 * for this layer are send to our nsPresContext.
6314 nsDisplayZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6315 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
6316 int32_t aAPD
, int32_t aParentAPD
,
6317 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
);
6319 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayZoom
)
6321 NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM
)
6323 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6324 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6325 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6326 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6327 nsRegion
* aVisibleRegion
) override
;
6328 LayerState
GetLayerState(
6329 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6330 const ContainerLayerParameters
& aParameters
) override
{
6331 return mozilla::LayerState::LAYER_ACTIVE
;
6334 // Get the app units per dev pixel ratio of the child document.
6335 int32_t GetChildAppUnitsPerDevPixel() { return mAPD
; }
6336 // Get the app units per dev pixel ratio of the parent document.
6337 int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD
; }
6340 int32_t mAPD
, mParentAPD
;
6344 * nsDisplayAsyncZoom is used for APZ zooming. It wraps the contents of the
6345 * root content document's scroll frame, including fixed position content. It
6346 * does not contain the scroll frame's scrollbars. It is clipped to the scroll
6347 * frame's scroll port clip. It is not scrolled; only its non-fixed contents
6348 * are scrolled. This item creates a container layer.
6350 class nsDisplayAsyncZoom
: public nsDisplayOwnLayer
{
6352 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6353 nsDisplayList
* aList
,
6354 const ActiveScrolledRoot
* aActiveScrolledRoot
,
6355 mozilla::layers::FrameMetrics::ViewID aViewID
);
6356 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
,
6357 const nsDisplayAsyncZoom
& aOther
)
6358 : nsDisplayOwnLayer(aBuilder
, aOther
), mViewID(aOther
.mViewID
) {
6359 MOZ_COUNT_CTOR(nsDisplayAsyncZoom
);
6362 #ifdef NS_BUILD_REFCNT_LOGGING
6363 virtual ~nsDisplayAsyncZoom();
6366 NS_DISPLAY_DECL_NAME("AsyncZoom", TYPE_ASYNC_ZOOM
)
6368 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6369 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6370 already_AddRefed
<Layer
> BuildLayer(
6371 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6372 const ContainerLayerParameters
& aContainerParameters
) override
;
6373 LayerState
GetLayerState(
6374 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6375 const ContainerLayerParameters
& aParameters
) override
{
6376 return mozilla::LayerState::LAYER_ACTIVE_FORCE
;
6378 bool UpdateScrollData(
6379 mozilla::layers::WebRenderScrollData
* aData
,
6380 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6383 mozilla::layers::FrameMetrics::ViewID mViewID
;
6387 * A base class for different effects types.
6389 class nsDisplayEffectsBase
: public nsDisplayWrapList
{
6391 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6392 nsDisplayList
* aList
,
6393 const ActiveScrolledRoot
* aActiveScrolledRoot
,
6394 bool aClearClipChain
= false);
6395 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6396 nsDisplayList
* aList
);
6398 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
,
6399 const nsDisplayEffectsBase
& aOther
)
6400 : nsDisplayWrapList(aBuilder
, aOther
),
6401 mEffectsBounds(aOther
.mEffectsBounds
),
6402 mHandleOpacity(aOther
.mHandleOpacity
) {
6403 MOZ_COUNT_CTOR(nsDisplayEffectsBase
);
6406 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayEffectsBase
)
6408 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6409 bool* aSnap
) const override
;
6410 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6411 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6413 bool RestoreState() override
{
6414 if (!nsDisplayWrapList::RestoreState() && !mHandleOpacity
) {
6418 mHandleOpacity
= false;
6422 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6426 virtual void SelectOpacityOptimization(const bool /* aUsingLayers */) {
6430 bool ShouldHandleOpacity() const { return mHandleOpacity
; }
6432 gfxRect
BBoxInUserSpace() const;
6433 gfxPoint
UserSpaceOffset() const;
6435 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6436 const nsDisplayItemGeometry
* aGeometry
,
6437 nsRegion
* aInvalidRegion
) const override
;
6440 void SetHandleOpacity() { mHandleOpacity
= true; }
6441 bool ValidateSVGFrame();
6443 // relative to mFrame
6444 nsRect mEffectsBounds
;
6445 // True if we need to handle css opacity in this display item.
6446 bool mHandleOpacity
;
6450 * A display item to paint a stacking context with 'mask' and 'clip-path'
6451 * effects set by the stacking context root frame's style. The 'mask' and
6452 * 'clip-path' properties may both contain multiple masks and clip paths,
6455 * Note that 'mask' and 'clip-path' may just contain CSS simple-images and CSS
6456 * basic shapes, respectively. That is, they don't necessarily reference
6457 * resources such as SVG 'mask' and 'clipPath' elements.
6459 class nsDisplayMasksAndClipPaths
: public nsDisplayEffectsBase
{
6461 typedef mozilla::layers::ImageLayer ImageLayer
;
6463 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6464 nsDisplayList
* aList
,
6465 const ActiveScrolledRoot
* aActiveScrolledRoot
);
6466 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
,
6467 const nsDisplayMasksAndClipPaths
& aOther
)
6468 : nsDisplayEffectsBase(aBuilder
, aOther
),
6469 mDestRects(aOther
.mDestRects
.Clone()) {
6470 MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths
);
6473 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayMasksAndClipPaths
)
6475 NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK
)
6477 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
6479 void Merge(const nsDisplayItem
* aItem
) override
{
6480 nsDisplayWrapList::Merge(aItem
);
6482 const nsDisplayMasksAndClipPaths
* other
=
6483 static_cast<const nsDisplayMasksAndClipPaths
*>(aItem
);
6484 mEffectsBounds
.UnionRect(
6486 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
6489 already_AddRefed
<Layer
> BuildLayer(
6490 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6491 const ContainerLayerParameters
& aContainerParameters
) override
;
6492 LayerState
GetLayerState(
6493 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6494 const ContainerLayerParameters
& aParameters
) override
;
6495 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6496 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6497 nsRegion
* aVisibleRegion
) override
;
6499 nsDisplayItemGeometry
* AllocateGeometry(
6500 nsDisplayListBuilder
* aBuilder
) override
{
6501 return new nsDisplayMasksAndClipPathsGeometry(this, aBuilder
);
6504 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6505 const nsDisplayItemGeometry
* aGeometry
,
6506 nsRegion
* aInvalidRegion
) const override
;
6507 #ifdef MOZ_DUMP_PAINTING
6508 void PrintEffects(nsACString
& aTo
);
6513 void PaintAsLayer(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6514 LayerManager
* aManager
);
6516 void PaintWithContentsPaintCallback(
6517 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6518 const std::function
<void()>& aPaintChildren
);
6521 * Paint mask onto aMaskContext in mFrame's coordinate space and
6522 * return whether the mask layer was painted successfully.
6524 bool PaintMask(nsDisplayListBuilder
* aBuilder
, gfxContext
* aMaskContext
,
6525 bool* aMaskPainted
= nullptr);
6527 const nsTArray
<nsRect
>& GetDestRects() { return mDestRects
; }
6529 void SelectOpacityOptimization(const bool aUsingLayers
) override
;
6531 bool CreateWebRenderCommands(
6532 mozilla::wr::DisplayListBuilder
& aBuilder
,
6533 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6534 const StackingContextHelper
& aSc
,
6535 mozilla::layers::RenderRootStateManager
* aManager
,
6536 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6538 mozilla::Maybe
<nsRect
> GetClipWithRespectToASR(
6539 nsDisplayListBuilder
* aBuilder
,
6540 const ActiveScrolledRoot
* aASR
) const override
;
6543 NS_DISPLAY_ALLOW_CLONING()
6545 // According to mask property and the capability of aManager, determine
6546 // whether we can paint the mask onto a dedicate mask layer.
6547 bool CanPaintOnMaskLayer(LayerManager
* aManager
);
6549 nsTArray
<nsRect
> mDestRects
;
6550 bool mApplyOpacityWithSimpleClipPath
;
6553 class nsDisplayBackdropRootContainer
: public nsDisplayWrapList
{
6555 nsDisplayBackdropRootContainer(nsDisplayListBuilder
* aBuilder
,
6556 nsIFrame
* aFrame
, nsDisplayList
* aList
,
6557 const ActiveScrolledRoot
* aActiveScrolledRoot
)
6558 : nsDisplayWrapList(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
, true) {
6559 MOZ_COUNT_CTOR(nsDisplayBackdropRootContainer
);
6562 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropRootContainer
)
6564 NS_DISPLAY_DECL_NAME("BackdropRootContainer", TYPE_BACKDROP_ROOT_CONTAINER
)
6566 already_AddRefed
<Layer
> BuildLayer(
6567 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6568 const ContainerLayerParameters
& aContainerParameters
) override
;
6569 LayerState
GetLayerState(
6570 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6571 const ContainerLayerParameters
& aParameters
) override
;
6572 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6574 bool CreateWebRenderCommands(
6575 mozilla::wr::DisplayListBuilder
& aBuilder
,
6576 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6577 const StackingContextHelper
& aSc
,
6578 mozilla::layers::RenderRootStateManager
* aManager
,
6579 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6581 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6582 return !aBuilder
->IsPaintingForWebRender();
6586 class nsDisplayBackdropFilters
: public nsDisplayWrapList
{
6588 nsDisplayBackdropFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6589 nsDisplayList
* aList
, const nsRect
& aBackdropRect
)
6590 : nsDisplayWrapList(aBuilder
, aFrame
, aList
),
6591 mBackdropRect(aBackdropRect
) {
6592 MOZ_COUNT_CTOR(nsDisplayBackdropFilters
);
6595 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropFilters
)
6597 NS_DISPLAY_DECL_NAME("BackdropFilter", TYPE_BACKDROP_FILTER
)
6599 bool CreateWebRenderCommands(
6600 mozilla::wr::DisplayListBuilder
& aBuilder
,
6601 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6602 const StackingContextHelper
& aSc
,
6603 mozilla::layers::RenderRootStateManager
* aManager
,
6604 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6605 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6607 static bool CanCreateWebRenderCommands(nsDisplayListBuilder
* aBuilder
,
6610 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6611 return !aBuilder
->IsPaintingForWebRender();
6615 nsRect mBackdropRect
;
6619 * A display item to paint a stacking context with filter effects set by the
6620 * stacking context root frame's style.
6622 * Note that the filters may just be simple CSS filter functions. That is,
6623 * they won't necessarily be references to SVG 'filter' elements.
6625 class nsDisplayFilters
: public nsDisplayEffectsBase
{
6627 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6628 nsDisplayList
* aList
);
6630 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
,
6631 const nsDisplayFilters
& aOther
)
6632 : nsDisplayEffectsBase(aBuilder
, aOther
),
6633 mEffectsBounds(aOther
.mEffectsBounds
) {
6634 MOZ_COUNT_CTOR(nsDisplayFilters
);
6637 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFilters
)
6639 NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER
)
6641 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
6642 // Items for the same content element should be merged into a single
6643 // compositing group.
6644 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
6645 HasSameContent(aItem
);
6648 void Merge(const nsDisplayItem
* aItem
) override
{
6649 nsDisplayWrapList::Merge(aItem
);
6651 const nsDisplayFilters
* other
= static_cast<const nsDisplayFilters
*>(aItem
);
6652 mEffectsBounds
.UnionRect(
6654 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
6657 already_AddRefed
<Layer
> BuildLayer(
6658 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6659 const ContainerLayerParameters
& aContainerParameters
) override
;
6660 LayerState
GetLayerState(
6661 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6662 const ContainerLayerParameters
& aParameters
) override
;
6663 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6665 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
6667 return mEffectsBounds
+ ToReferenceFrame();
6670 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6671 nsRegion
* aVisibleRegion
) override
;
6673 nsDisplayItemGeometry
* AllocateGeometry(
6674 nsDisplayListBuilder
* aBuilder
) override
{
6675 return new nsDisplayFiltersGeometry(this, aBuilder
);
6678 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6679 const nsDisplayItemGeometry
* aGeometry
,
6680 nsRegion
* aInvalidRegion
) const override
;
6681 #ifdef MOZ_DUMP_PAINTING
6682 void PrintEffects(nsACString
& aTo
);
6685 void PaintAsLayer(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6686 LayerManager
* aManager
);
6688 void PaintWithContentsPaintCallback(
6689 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6690 const std::function
<void(gfxContext
* aContext
)>& aPaintChildren
);
6692 bool CreateWebRenderCommands(
6693 mozilla::wr::DisplayListBuilder
& aBuilder
,
6694 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6695 const StackingContextHelper
& aSc
,
6696 mozilla::layers::RenderRootStateManager
* aManager
,
6697 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6698 bool CanCreateWebRenderCommands();
6701 NS_DISPLAY_ALLOW_CLONING()
6703 // relative to mFrame
6704 nsRect mEffectsBounds
;
6707 /* A display item that applies a transformation to all of its descendant
6708 * elements. This wrapper should only be used if there is a transform applied
6709 * to the root element.
6711 * The reason that a "bounds" rect is involved in transform calculations is
6712 * because CSS-transforms allow percentage values for the x and y components
6713 * of <translation-value>s, where percentages are percentages of the element's
6716 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
6718 * INVARIANT: The wrapped frame is non-null.
6720 class nsDisplayTransform
: public nsPaintedDisplayItem
{
6721 using Matrix4x4
= mozilla::gfx::Matrix4x4
;
6722 using Matrix4x4Flagged
= mozilla::gfx::Matrix4x4Flagged
;
6723 using Point3D
= mozilla::gfx::Point3D
;
6724 using TransformReferenceBox
= nsStyleTransformMatrix::TransformReferenceBox
;
6727 enum class PrerenderDecision
: uint8_t { No
, Full
, Partial
};
6730 WithTransformGetter
,
6733 /* Constructor accepts a display list, empties it, and wraps it up. It also
6734 * ferries the underlying frame to the nsDisplayItem constructor.
6736 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6737 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
);
6739 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6740 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6741 PrerenderDecision aPrerenderDecision
);
6743 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6744 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6745 decltype(WithTransformGetter
));
6747 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayTransform
)
6749 NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM
)
6751 bool RestoreState() override
{
6752 if (!nsPaintedDisplayItem::RestoreState() && !mShouldFlatten
) {
6756 mShouldFlatten
= false;
6760 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
6763 * This function updates bounds for items with a frame establishing
6764 * 3D rendering context.
6766 void UpdateBoundsFor3D(nsDisplayListBuilder
* aBuilder
);
6768 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
;
6770 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
6771 GetChildren()->DeleteAll(aBuilder
);
6772 nsPaintedDisplayItem::Destroy(aBuilder
);
6775 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
6777 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
6779 nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
6780 bool* aSnap
) const override
{
6782 return mChildBounds
;
6785 const nsRect
& GetUntransformedPaintRect() const override
{
6786 return mChildrenBuildingRect
;
6789 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6791 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6792 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6793 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6794 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6795 bool* aSnap
) const override
;
6796 LayerState
GetLayerState(
6797 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6798 const ContainerLayerParameters
& aParameters
) override
;
6799 already_AddRefed
<Layer
> BuildLayer(
6800 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6801 const ContainerLayerParameters
& aContainerParameters
) override
;
6802 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6803 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6804 const mozilla::Maybe
<mozilla::gfx::Polygon
>& aPolygon
);
6805 bool CreateWebRenderCommands(
6806 mozilla::wr::DisplayListBuilder
& aBuilder
,
6807 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6808 const StackingContextHelper
& aSc
,
6809 mozilla::layers::RenderRootStateManager
* aManager
,
6810 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6811 bool UpdateScrollData(
6812 mozilla::layers::WebRenderScrollData
* aData
,
6813 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6814 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6815 nsRegion
* aVisibleRegion
) override
;
6817 nsDisplayItemGeometry
* AllocateGeometry(
6818 nsDisplayListBuilder
* aBuilder
) override
{
6819 return new nsDisplayTransformGeometry(
6820 this, aBuilder
, GetTransformForRendering(),
6821 mFrame
->PresContext()->AppUnitsPerDevPixel());
6824 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6825 const nsDisplayItemGeometry
* aGeometry
,
6826 nsRegion
* aInvalidRegion
) const override
{
6827 const nsDisplayTransformGeometry
* geometry
=
6828 static_cast<const nsDisplayTransformGeometry
*>(aGeometry
);
6830 // This code is only called for flattened, inactive transform items.
6831 // Only check if the transform has changed. The bounds invalidation should
6832 // be handled by the children themselves.
6833 if (!geometry
->mTransform
.FuzzyEqual(GetTransformForRendering())) {
6835 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
6839 bool NeedsGeometryUpdates() const override
{ return mShouldFlatten
; }
6841 const nsIFrame
* ReferenceFrameForChildren() const override
{
6842 // If we were created using a transform-getter, then we don't
6843 // belong to a transformed frame, and aren't a reference frame
6844 // for our children.
6845 if (!mHasTransformGetter
) {
6848 return nsPaintedDisplayItem::ReferenceFrameForChildren();
6851 AnimatedGeometryRoot
* AnimatedGeometryRootForScrollMetadata() const override
{
6852 return mAnimatedGeometryRootForScrollMetadata
;
6855 const nsRect
& GetBuildingRectForChildren() const override
{
6856 return mChildrenBuildingRect
;
6859 enum { INDEX_MAX
= UINT32_MAX
>> TYPE_BITS
};
6862 * We include the perspective matrix from our containing block for the
6863 * purposes of visibility calculations, but we exclude it from the transform
6864 * we set on the layer (for rendering), since there will be an
6865 * nsDisplayPerspective created for that.
6867 const Matrix4x4Flagged
& GetTransform() const;
6868 const Matrix4x4Flagged
& GetInverseTransform() const;
6870 bool ShouldSkipTransform(nsDisplayListBuilder
* aBuilder
) const;
6871 Matrix4x4
GetTransformForRendering(
6872 mozilla::LayoutDevicePoint
* aOutOrigin
= nullptr) const;
6875 * Return the transform that is aggregation of all transform on the
6876 * preserves3d chain.
6878 const Matrix4x4
& GetAccumulatedPreserved3DTransform(
6879 nsDisplayListBuilder
* aBuilder
);
6881 float GetHitDepthAtPoint(nsDisplayListBuilder
* aBuilder
,
6882 const nsPoint
& aPoint
);
6885 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
6886 * space) and returns the smallest rectangle (in aFrame's coordinate space)
6887 * containing the transformed image of that rectangle. That is, it takes
6888 * the four corners of the rectangle, transforms them according to the
6889 * matrix associated with the specified frame, then returns the smallest
6890 * rectangle containing the four transformed points.
6892 * @param untransformedBounds The rectangle (in app units) to transform.
6893 * @param aFrame The frame whose transformation should be applied. This
6894 * function raises an assertion if aFrame is null or doesn't have a
6895 * transform applied to it.
6896 * @param aRefBox the reference box to use, which would usually be just
6897 * TransformReferemceBox(aFrame), but callers may override it if
6900 static nsRect
TransformRect(const nsRect
& aUntransformedBounds
,
6901 const nsIFrame
* aFrame
,
6902 TransformReferenceBox
& aRefBox
);
6904 /* UntransformRect is like TransformRect, except that it inverts the
6907 static bool UntransformRect(const nsRect
& aTransformedBounds
,
6908 const nsRect
& aChildBounds
,
6909 const nsIFrame
* aFrame
, nsRect
* aOutRect
);
6911 bool UntransformRect(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6912 nsRect
* aOutRect
) const;
6914 bool UntransformBuildingRect(nsDisplayListBuilder
* aBuilder
,
6915 nsRect
* aOutRect
) const {
6916 return UntransformRect(aBuilder
, GetBuildingRect(), aOutRect
);
6919 bool UntransformPaintRect(nsDisplayListBuilder
* aBuilder
,
6920 nsRect
* aOutRect
) const {
6921 return UntransformRect(aBuilder
, GetPaintRect(), aOutRect
);
6924 static Point3D
GetDeltaToTransformOrigin(const nsIFrame
* aFrame
,
6925 TransformReferenceBox
&,
6926 float aAppUnitsPerPixel
);
6929 * Returns true if aFrame has perspective applied from its containing
6931 * Returns the matrix to append to apply the persective (taking
6932 * perspective-origin into account), relative to aFrames coordinate
6934 * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
6937 static bool ComputePerspectiveMatrix(const nsIFrame
* aFrame
,
6938 float aAppUnitsPerPixel
,
6939 Matrix4x4
& aOutMatrix
);
6941 struct MOZ_STACK_CLASS FrameTransformProperties
{
6942 FrameTransformProperties(const nsIFrame
* aFrame
,
6943 TransformReferenceBox
& aRefBox
,
6944 float aAppUnitsPerPixel
);
6945 FrameTransformProperties(
6946 const mozilla::StyleTranslate
& aTranslate
,
6947 const mozilla::StyleRotate
& aRotate
, const mozilla::StyleScale
& aScale
,
6948 const mozilla::StyleTransform
& aTransform
,
6949 const mozilla::Maybe
<mozilla::ResolvedMotionPathData
>& aMotion
,
6950 const Point3D
& aToTransformOrigin
)
6952 mTranslate(aTranslate
),
6955 mTransform(aTransform
),
6957 mToTransformOrigin(aToTransformOrigin
) {}
6959 bool HasTransform() const {
6960 return !mTranslate
.IsNone() || !mRotate
.IsNone() || !mScale
.IsNone() ||
6961 !mTransform
.IsNone() || mMotion
.isSome();
6964 const nsIFrame
* mFrame
;
6965 const mozilla::StyleTranslate
& mTranslate
;
6966 const mozilla::StyleRotate
& mRotate
;
6967 const mozilla::StyleScale
& mScale
;
6968 const mozilla::StyleTransform
& mTransform
;
6969 const mozilla::Maybe
<mozilla::ResolvedMotionPathData
> mMotion
;
6970 const Point3D mToTransformOrigin
;
6974 * Given a frame with the transform property or an SVG transform,
6975 * returns the transformation matrix for that frame.
6977 * @param aFrame The frame to get the matrix from.
6978 * @param aOrigin Relative to which point this transform should be applied.
6979 * @param aAppUnitsPerPixel The number of app units per graphics unit.
6980 * @param aBoundsOverride [optional] If this is nullptr (the default), the
6981 * computation will use the value of TransformReferenceBox(aFrame).
6982 * Otherwise, it will use the value of aBoundsOverride. This is
6983 * mostly for internal use and in most cases you will not need to
6985 * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
6986 * by aOrigin. This translation is applied *before* the CSS transform.
6987 * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
6988 * include the transform of any ancestors participating in the same
6989 * 3d rendering context.
6990 * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
6991 * perspective transform from the containing block if applicable.
6994 OFFSET_BY_ORIGIN
= 1 << 0,
6995 INCLUDE_PRESERVE3D_ANCESTORS
= 1 << 1,
6996 INCLUDE_PERSPECTIVE
= 1 << 2,
6998 static Matrix4x4
GetResultingTransformMatrix(const nsIFrame
* aFrame
,
6999 const nsPoint
& aOrigin
,
7000 float aAppUnitsPerPixel
,
7002 static Matrix4x4
GetResultingTransformMatrix(
7003 const FrameTransformProperties
& aProperties
, TransformReferenceBox
&,
7004 float aAppUnitsPerPixel
);
7006 struct PrerenderInfo
{
7007 bool CanUseAsyncAnimations() const {
7008 return mDecision
!= PrerenderDecision::No
&& mHasAnimations
;
7010 PrerenderDecision mDecision
= PrerenderDecision::No
;
7011 bool mHasAnimations
= true;
7014 * Decide whether we should prerender some or all of the contents of the
7015 * transformed frame even when it's not completely visible (yet).
7016 * Return PrerenderDecision::Full if the entire contents should be
7017 * prerendered, PrerenderDecision::Partial if some but not all of the
7018 * contents should be prerendered, or PrerenderDecision::No if only the
7019 * visible area should be rendered.
7020 * |mNoAffectDecisionInPreserve3D| is set if the prerender decision should not
7021 * affect the decision on other frames in the preserve 3d tree.
7022 * |aDirtyRect| is updated to the area that should be prerendered.
7024 static PrerenderInfo
ShouldPrerenderTransformedContent(
7025 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsRect
* aDirtyRect
);
7027 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
7029 bool MayBeAnimated(nsDisplayListBuilder
* aBuilder
,
7030 bool aEnforceMinimumSize
= true) const;
7032 void WriteDebugInfo(std::stringstream
& aStream
) override
;
7035 * This item is an additional item as the boundary between parent
7036 * and child 3D rendering context.
7037 * \see nsIFrame::BuildDisplayListForStackingContext().
7039 bool IsTransformSeparator() const { return mIsTransformSeparator
; }
7041 * This item is the boundary between parent and child 3D rendering
7044 bool IsLeafOf3DContext() const {
7045 return (IsTransformSeparator() ||
7046 (!mFrame
->Extend3DContext() && Combines3DTransformWithAncestors()));
7049 * The backing frame of this item participates a 3D rendering
7052 bool IsParticipating3DContext() const {
7053 return mFrame
->Extend3DContext() || Combines3DTransformWithAncestors();
7056 bool IsPartialPrerender() const {
7057 return mPrerenderDecision
== PrerenderDecision::Partial
;
7060 void AddSizeOfExcludingThis(nsWindowSizes
&) const override
;
7063 void ComputeBounds(nsDisplayListBuilder
* aBuilder
);
7064 nsRect
TransformUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
7065 const Matrix4x4Flagged
& aMatrix
) const;
7066 void UpdateUntransformedBounds(nsDisplayListBuilder
* aBuilder
);
7068 void SetReferenceFrameToAncestor(nsDisplayListBuilder
* aBuilder
);
7069 void Init(nsDisplayListBuilder
* aBuilder
, nsDisplayList
* aChildren
);
7071 static Matrix4x4
GetResultingTransformMatrixInternal(
7072 const FrameTransformProperties
& aProperties
,
7073 TransformReferenceBox
& aRefBox
, const nsPoint
& aOrigin
,
7074 float aAppUnitsPerPixel
, uint32_t aFlags
);
7076 void Collect3DTransformLeaves(nsTArray
<nsDisplayTransform
*>& aLeaves
);
7077 using TransformPolygon
= mozilla::layers::BSPPolygon
<nsDisplayTransform
>;
7078 void CollectSorted3DTransformLeaves(nsDisplayListBuilder
* aBuilder
,
7079 nsTArray
<TransformPolygon
>& aLeaves
);
7081 mutable mozilla::Maybe
<Matrix4x4Flagged
> mTransform
;
7082 mutable mozilla::Maybe
<Matrix4x4Flagged
> mInverseTransform
;
7083 // Accumulated transform of ancestors on the preserves-3d chain.
7084 mozilla::UniquePtr
<Matrix4x4
> mTransformPreserves3D
;
7085 RefPtr
<AnimatedGeometryRoot
> mAnimatedGeometryRootForChildren
;
7086 RefPtr
<AnimatedGeometryRoot
> mAnimatedGeometryRootForScrollMetadata
;
7087 nsRect mChildrenBuildingRect
;
7088 mutable RetainedDisplayList mChildren
;
7090 // The untransformed bounds of |mChildren|.
7091 nsRect mChildBounds
;
7092 // The transformed bounds of this display item.
7094 PrerenderDecision mPrerenderDecision
: 8;
7095 // This item is a separator between 3D rendering contexts, and
7096 // mTransform have been presetted by the constructor.
7097 // This also forces us not to extend the 3D context. Since we don't create a
7098 // transform item, a container layer, for every frame in a preserves3d
7099 // context, the transform items of a child preserves3d context may extend the
7100 // parent context unintendedly if the root of the child preserves3d context
7101 // doesn't create a transform item.
7102 bool mIsTransformSeparator
: 1;
7103 // True if this nsDisplayTransform should get flattened
7104 bool mShouldFlatten
: 1;
7105 // True if we have a transform getter.
7106 bool mHasTransformGetter
: 1;
7109 /* A display item that applies a perspective transformation to a single
7110 * nsDisplayTransform child item. We keep this as a separate item since the
7111 * perspective-origin is relative to an ancestor of the transformed frame, and
7112 * APZ can scroll the child separately.
7114 class nsDisplayPerspective
: public nsPaintedDisplayItem
{
7115 typedef mozilla::gfx::Point3D Point3D
;
7118 nsDisplayPerspective(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
7119 nsDisplayList
* aList
);
7120 ~nsDisplayPerspective() override
= default;
7122 NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE
)
7124 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
7125 mList
.DeleteAll(aBuilder
);
7126 nsPaintedDisplayItem::Destroy(aBuilder
);
7129 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
7130 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
{
7131 return GetChildren()->HitTest(aBuilder
, aRect
, aState
, aOutFrames
);
7134 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
7136 return GetChildren()->GetClippedBoundsWithRespectToASR(aBuilder
,
7137 mActiveScrolledRoot
);
7140 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
7141 nsRegion
* aVisibleRegion
) override
;
7143 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
7144 const nsDisplayItemGeometry
* aGeometry
,
7145 nsRegion
* aInvalidRegion
) const override
{}
7147 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
7148 bool* aSnap
) const override
;
7150 LayerState
GetLayerState(
7151 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7152 const ContainerLayerParameters
& aParameters
) override
;
7153 bool CreateWebRenderCommands(
7154 mozilla::wr::DisplayListBuilder
& aBuilder
,
7155 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
7156 const StackingContextHelper
& aSc
,
7157 mozilla::layers::RenderRootStateManager
* aManager
,
7158 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
7160 already_AddRefed
<Layer
> BuildLayer(
7161 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7162 const ContainerLayerParameters
& aContainerParameters
) override
;
7163 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
7165 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
7169 RetainedDisplayList
* GetChildren() const override
{ return &mList
; }
7171 nsRect
GetComponentAlphaBounds(
7172 nsDisplayListBuilder
* aBuilder
) const override
{
7173 return GetChildren()->GetComponentAlphaBounds(aBuilder
);
7176 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
{
7177 if (GetChildren()->GetTop()) {
7178 static_cast<nsDisplayTransform
*>(GetChildren()->GetTop())
7179 ->DoUpdateBoundsPreserves3D(aBuilder
);
7184 mutable RetainedDisplayList mList
;
7188 * This class adds basic support for limiting the rendering (in the inline axis
7189 * of the writing mode) to the part inside the specified edges.
7190 * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
7191 * of the frame's scrollable overflow rectangle and are the amount to suppress
7194 * Setting none, both or only one edge is allowed.
7195 * The values must be non-negative.
7196 * The default value for both edges is zero, which means everything is painted.
7198 class nsDisplayText final
: public nsPaintedDisplayItem
{
7200 nsDisplayText(nsDisplayListBuilder
* aBuilder
, nsTextFrame
* aFrame
);
7201 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayText
)
7203 NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT
)
7205 bool RestoreState() final
{
7206 if (!nsPaintedDisplayItem::RestoreState() && mOpacity
== 1.0f
) {
7214 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const final
{
7219 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
7220 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
{
7221 if (nsRect(ToReferenceFrame(), mFrame
->GetSize()).Intersects(aRect
)) {
7222 aOutFrames
->AppendElement(mFrame
);
7226 bool CreateWebRenderCommands(
7227 mozilla::wr::DisplayListBuilder
& aBuilder
,
7228 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
7229 const StackingContextHelper
& aSc
,
7230 mozilla::layers::RenderRootStateManager
* aManager
,
7231 nsDisplayListBuilder
* aDisplayListBuilder
) final
;
7232 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) final
;
7234 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const final
{
7235 if (gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()) {
7236 // On OS X, web authors can turn off subpixel text rendering using the
7237 // CSS property -moz-osx-font-smoothing. If they do that, we don't need
7238 // to use component alpha layers for the affected text.
7239 if (mFrame
->StyleFont()->mFont
.smoothing
== NS_FONT_SMOOTHING_GRAYSCALE
) {
7244 return GetBounds(aBuilder
, &snap
);
7247 nsDisplayItemGeometry
* AllocateGeometry(nsDisplayListBuilder
* aBuilder
) final
;
7249 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
7250 const nsDisplayItemGeometry
* aGeometry
,
7251 nsRegion
* aInvalidRegion
) const final
;
7253 void RenderToContext(gfxContext
* aCtx
, nsDisplayListBuilder
* aBuilder
,
7254 bool aIsRecording
= false);
7256 bool CanApplyOpacity() const final
;
7258 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
7259 const DisplayItemClipChain
* aClip
) final
{
7260 NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
7261 mOpacity
= aOpacity
;
7262 IntersectClip(aBuilder
, aClip
, false);
7265 void WriteDebugInfo(std::stringstream
& aStream
) final
;
7267 static nsDisplayText
* CheckCast(nsDisplayItem
* aItem
) {
7268 return (aItem
->GetType() == DisplayItemType::TYPE_TEXT
)
7269 ? static_cast<nsDisplayText
*>(aItem
)
7274 ClipEdges(const nsIFrame
* aFrame
, const nsPoint
& aToReferenceFrame
,
7275 nscoord aVisIStartEdge
, nscoord aVisIEndEdge
) {
7276 nsRect r
= aFrame
->ScrollableOverflowRect() + aToReferenceFrame
;
7277 if (aFrame
->GetWritingMode().IsVertical()) {
7278 mVisIStart
= aVisIStartEdge
> 0 ? r
.y
+ aVisIStartEdge
: nscoord_MIN
;
7279 mVisIEnd
= aVisIEndEdge
> 0
7280 ? std::max(r
.YMost() - aVisIEndEdge
, mVisIStart
)
7283 mVisIStart
= aVisIStartEdge
> 0 ? r
.x
+ aVisIStartEdge
: nscoord_MIN
;
7284 mVisIEnd
= aVisIEndEdge
> 0
7285 ? std::max(r
.XMost() - aVisIEndEdge
, mVisIStart
)
7290 void Intersect(nscoord
* aVisIStart
, nscoord
* aVisISize
) const {
7291 nscoord end
= *aVisIStart
+ *aVisISize
;
7292 *aVisIStart
= std::max(*aVisIStart
, mVisIStart
);
7293 *aVisISize
= std::max(std::min(end
, mVisIEnd
) - *aVisIStart
, 0);
7300 nscoord
& VisIStartEdge() { return mVisIStartEdge
; }
7301 nscoord
& VisIEndEdge() { return mVisIEndEdge
; }
7302 float Opacity() const { return mOpacity
; }
7308 // Lengths measured from the visual inline start and end sides
7309 // (i.e. left and right respectively in horizontal writing modes,
7310 // regardless of bidi directionality; top and bottom in vertical modes).
7311 nscoord mVisIStartEdge
;
7312 nscoord mVisIEndEdge
;
7316 * A display item that for webrender to handle SVG
7318 class nsDisplaySVGWrapper
: public nsDisplayWrapList
{
7320 nsDisplaySVGWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
7321 nsDisplayList
* aList
);
7323 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySVGWrapper
)
7325 NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER
)
7327 already_AddRefed
<Layer
> BuildLayer(
7328 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7329 const ContainerLayerParameters
& aContainerParameters
) override
;
7330 LayerState
GetLayerState(
7331 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7332 const ContainerLayerParameters
& aParameters
) override
;
7333 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
7334 GetChildren()->Paint(aBuilder
, aCtx
,
7335 mFrame
->PresContext()->AppUnitsPerDevPixel());
7337 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
7338 bool CreateWebRenderCommands(
7339 mozilla::wr::DisplayListBuilder
& aBuilder
,
7340 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
7341 const StackingContextHelper
& aSc
,
7342 mozilla::layers::RenderRootStateManager
* aManager
,
7343 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
7347 * A display item for webrender to handle SVG foreign object
7349 class nsDisplayForeignObject
: public nsDisplayWrapList
{
7351 nsDisplayForeignObject(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
7352 nsDisplayList
* aList
);
7353 #ifdef NS_BUILD_REFCNT_LOGGING
7354 virtual ~nsDisplayForeignObject();
7357 NS_DISPLAY_DECL_NAME("ForeignObject", TYPE_FOREIGN_OBJECT
)
7359 virtual already_AddRefed
<Layer
> BuildLayer(
7360 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7361 const ContainerLayerParameters
& aContainerParameters
) override
;
7362 virtual LayerState
GetLayerState(
7363 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7364 const ContainerLayerParameters
& aParameters
) override
;
7365 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
7366 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
7367 GetChildren()->Paint(aBuilder
, aCtx
,
7368 mFrame
->PresContext()->AppUnitsPerDevPixel());
7371 bool CreateWebRenderCommands(
7372 mozilla::wr::DisplayListBuilder
& aBuilder
,
7373 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
7374 const StackingContextHelper
& aSc
,
7375 mozilla::layers::RenderRootStateManager
* aManager
,
7376 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
7380 * A display item to represent a hyperlink.
7382 class nsDisplayLink
: public nsPaintedDisplayItem
{
7384 nsDisplayLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
7385 const char* aLinkSpec
, const nsRect
& aRect
)
7386 : nsPaintedDisplayItem(aBuilder
, aFrame
),
7387 mLinkSpec(aLinkSpec
),
7390 NS_DISPLAY_DECL_NAME("Link", TYPE_LINK
)
7392 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
7395 nsCString mLinkSpec
;
7399 class FlattenedDisplayListIterator
{
7401 FlattenedDisplayListIterator(nsDisplayListBuilder
* aBuilder
,
7402 nsDisplayList
* aList
)
7403 : FlattenedDisplayListIterator(aBuilder
, aList
, true) {}
7405 virtual bool HasNext() const { return mNext
|| !mStack
.IsEmpty(); }
7407 nsDisplayItem
* GetNextItem() {
7410 nsDisplayItem
* next
= mNext
;
7411 mNext
= next
->GetAbove();
7413 if (mNext
&& next
->HasChildren() && mNext
->HasChildren()) {
7414 // Since |next| and |mNext| are container items in the same list,
7415 // merging them might be possible.
7416 next
= TryMergingFrom(next
);
7419 ResolveFlattening();
7424 nsDisplayItem
* PeekNext() { return mNext
; }
7427 FlattenedDisplayListIterator(nsDisplayListBuilder
* aBuilder
,
7428 nsDisplayList
* aList
,
7429 const bool aResolveFlattening
)
7430 : mBuilder(aBuilder
), mNext(aList
->GetBottom()) {
7431 if (aResolveFlattening
) {
7432 // This is done conditionally in case subclass overrides
7433 // ShouldFlattenNextItem().
7434 ResolveFlattening();
7438 virtual void EnterChildList(nsDisplayItem
* aContainerItem
) {}
7439 virtual void ExitChildList() {}
7441 bool AtEndOfNestedList() const { return !mNext
&& mStack
.Length() > 0; }
7443 virtual bool ShouldFlattenNextItem() {
7444 return mNext
&& mNext
->ShouldFlattenAway(mBuilder
);
7447 void ResolveFlattening() {
7448 // Handle the case where we reach the end of a nested list, or the current
7449 // item should start a new nested list. Repeat this until we find an actual
7450 // item, or the very end of the outer list.
7451 while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
7452 if (AtEndOfNestedList()) {
7455 // We reached the end of the list, pop the next item from the stack.
7456 mNext
= mStack
.PopLastElement();
7458 EnterChildList(mNext
);
7460 // This item wants to be flattened. Store the next item on the stack,
7461 // and use the first item in the child list instead.
7462 mStack
.AppendElement(mNext
->GetAbove());
7463 mNext
= mNext
->GetChildren()->GetBottom();
7469 * Tries to merge display items starting from |aCurrent|.
7470 * Updates the internal pointer to the next display item.
7472 nsDisplayItem
* TryMergingFrom(nsDisplayItem
* aCurrent
) {
7473 MOZ_ASSERT(aCurrent
);
7474 MOZ_ASSERT(aCurrent
->GetAbove());
7476 nsDisplayWrapList
* current
= aCurrent
->AsDisplayWrapList();
7477 nsDisplayWrapList
* next
= mNext
->AsDisplayWrapList();
7479 if (!current
|| !next
) {
7480 // Either the current or the next item do not support merging.
7484 // Attempt to merge |next| with |current|.
7485 if (current
->CanMerge(next
)) {
7486 // Merging is possible, collect all the successive mergeable items.
7487 AutoTArray
<nsDisplayWrapList
*, 2> willMerge
{current
};
7490 willMerge
.AppendElement(next
);
7491 mNext
= next
->GetAbove();
7492 next
= mNext
? mNext
->AsDisplayWrapList() : nullptr;
7493 } while (next
&& current
->CanMerge(next
));
7495 current
= mBuilder
->MergeItems(willMerge
);
7498 // Here |mNext| will be either the first item that could not be merged with
7499 // |current|, or nullptr.
7504 nsDisplayListBuilder
* mBuilder
;
7505 nsDisplayItem
* mNext
;
7506 AutoTArray
<nsDisplayItem
*, 16> mStack
;
7511 class PaintTelemetry
{
7513 class AutoRecordPaint
{
7519 mozilla::TimeStamp mStart
;
7523 static uint32_t sPaintLevel
;
7526 } // namespace mozilla
7528 #endif /*NSDISPLAYLIST_H_*/