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 bool RestoreState() override
{
4513 bool superChanged
= nsDisplayImageContainer::RestoreState();
4514 bool opacityChanged
= (mOpacity
!= 1.0f
);
4516 return (superChanged
|| opacityChanged
);
4519 NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND
)
4522 * This will create and append new items for all the layers of the
4523 * background. Returns the type of background that was appended.
4524 * aAllowWillPaintBorderOptimization should usually be left at true, unless
4525 * aFrame has special border drawing that causes opaque borders to not
4526 * actually be opaque.
4528 static AppendedBackgroundType
AppendBackgroundItemsToTop(
4529 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4530 const nsRect
& aBackgroundRect
, nsDisplayList
* aList
,
4531 bool aAllowWillPaintBorderOptimization
= true,
4532 mozilla::ComputedStyle
* aComputedStyle
= nullptr,
4533 const nsRect
& aBackgroundOriginRect
= nsRect(),
4534 nsIFrame
* aSecondaryReferenceFrame
= nullptr,
4535 mozilla::Maybe
<nsDisplayListBuilder::AutoBuildingDisplayList
>*
4536 aAutoBuildingDisplayList
= nullptr);
4538 LayerState
GetLayerState(
4539 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4540 const ContainerLayerParameters
& aParameters
) override
;
4541 already_AddRefed
<Layer
> BuildLayer(
4542 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4543 const ContainerLayerParameters
& aContainerParameters
) override
;
4544 bool CreateWebRenderCommands(
4545 mozilla::wr::DisplayListBuilder
& aBuilder
,
4546 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4547 const StackingContextHelper
& aSc
,
4548 mozilla::layers::RenderRootStateManager
* aManager
,
4549 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4550 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4551 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4552 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
4553 nsRegion
* aVisibleRegion
) override
;
4554 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4555 bool* aSnap
) const override
;
4556 mozilla::Maybe
<nscolor
> IsUniform(
4557 nsDisplayListBuilder
* aBuilder
) const override
;
4559 bool CanApplyOpacity() const override
{ return true; }
4561 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
4562 const DisplayItemClipChain
* aClip
) override
{
4563 mOpacity
= aOpacity
;
4567 * GetBounds() returns the background painting area.
4569 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4571 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4574 * Return the background positioning area.
4575 * (GetBounds() returns the background painting area.)
4576 * Can be called only when mBackgroundStyle is non-null.
4578 nsRect
GetPositioningArea() const;
4581 * Returns true if existing rendered pixels of this display item may need
4582 * to be redrawn if the positioning area size changes but its position does
4584 * If false, only the changed painting area needs to be redrawn when the
4585 * positioning area size changes but its position does not.
4587 bool RenderingMightDependOnPositioningAreaSizeChange() const;
4589 nsDisplayItemGeometry
* AllocateGeometry(
4590 nsDisplayListBuilder
* aBuilder
) override
{
4591 return new nsDisplayBackgroundGeometry(this, aBuilder
);
4594 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4595 const nsDisplayItemGeometry
* aGeometry
,
4596 nsRegion
* aInvalidRegion
) const override
;
4597 bool CanOptimizeToImageLayer(LayerManager
* aManager
,
4598 nsDisplayListBuilder
* aBuilder
) override
;
4599 already_AddRefed
<imgIContainer
> GetImage() override
;
4600 nsRect
GetDestRect() const override
;
4602 void UpdateDrawResult(mozilla::image::ImgDrawResult aResult
) override
{
4603 nsDisplayBackgroundGeometry::UpdateDrawResult(this, aResult
);
4606 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
4607 return mShouldFixToViewport
;
4610 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4612 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4613 if (!aBuilder
->IsRetainingDisplayList()) {
4616 mDependentFrame
= aFrame
;
4618 mDependentFrame
->AddDisplayItem(this);
4622 void RemoveFrame(nsIFrame
* aFrame
) override
{
4623 if (aFrame
== mDependentFrame
) {
4624 mDependentFrame
= nullptr;
4626 nsDisplayImageContainer::RemoveFrame(aFrame
);
4629 // Match https://w3c.github.io/paint-timing/#contentful-image
4630 bool IsContentful() const override
{
4631 const auto& styleImage
=
4632 mBackgroundStyle
->StyleBackground()->mImage
.mLayers
[mLayer
].mImage
;
4634 return styleImage
.IsSizeAvailable() && styleImage
.FinalImage().IsUrl();
4638 typedef class mozilla::layers::ImageContainer ImageContainer
;
4639 typedef class mozilla::layers::ImageLayer ImageLayer
;
4641 bool CanBuildWebRenderDisplayItems(LayerManager
* aManager
,
4642 nsDisplayListBuilder
* aBuilder
);
4643 nsRect
GetBoundsInternal(nsDisplayListBuilder
* aBuilder
,
4644 nsIFrame
* aFrameForBounds
= nullptr);
4646 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4647 const nsRect
& aBounds
, nsRect
* aClipRect
);
4649 // Determine whether we want to be separated into our own layer, independent
4650 // of whether this item can actually be layerized.
4651 enum ImageLayerization
{
4656 ImageLayerization
ShouldCreateOwnLayer(nsDisplayListBuilder
* aBuilder
,
4657 LayerManager
* aManager
);
4659 // Cache the result of nsCSSRendering::FindBackground. Always null if
4660 // mIsThemed is true or if FindBackground returned false.
4661 RefPtr
<mozilla::ComputedStyle
> mBackgroundStyle
;
4662 nsCOMPtr
<imgIContainer
> mImage
;
4663 nsIFrame
* mDependentFrame
;
4664 nsRect mBackgroundRect
; // relative to the reference frame
4667 /* Bounds of this display item */
4670 bool mIsRasterImage
;
4671 /* Whether the image should be treated as fixed to the viewport. */
4672 bool mShouldFixToViewport
;
4673 uint32_t mImageFlags
;
4678 * A display item to paint background image for table. For table parts, such
4679 * as row, row group, col, col group, when drawing its background, we'll
4680 * create separate background image display item for its containning cell.
4681 * Those background image display items will reference to same DisplayItemData
4682 * if we keep the mFrame point to cell's ancestor frame. We don't want to this
4683 * happened bacause share same DisplatItemData will cause many bugs. So that
4684 * we let mFrame point to cell frame and store the table type of the ancestor
4685 * frame. And use mFrame and table type as key to generate DisplayItemData to
4686 * avoid sharing DisplayItemData.
4688 * Also store ancestor frame as mStyleFrame for all rendering informations.
4690 class nsDisplayTableBackgroundImage
: public nsDisplayBackgroundImage
{
4692 nsDisplayTableBackgroundImage(nsDisplayListBuilder
* aBuilder
,
4693 nsIFrame
* aFrame
, const InitData
& aInitData
,
4694 nsIFrame
* aCellFrame
);
4695 ~nsDisplayTableBackgroundImage() override
;
4697 NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE
)
4699 bool IsInvalid(nsRect
& aRect
) const override
;
4701 nsIFrame
* FrameForInvalidation() const override
{ return mStyleFrame
; }
4703 void RemoveFrame(nsIFrame
* aFrame
) override
{
4704 if (aFrame
== mStyleFrame
) {
4705 mStyleFrame
= nullptr;
4708 nsDisplayBackgroundImage::RemoveFrame(aFrame
);
4712 nsIFrame
* StyleFrame() const override
{ return mStyleFrame
; }
4713 nsIFrame
* mStyleFrame
;
4717 * A display item to paint the native theme background for a frame.
4719 class nsDisplayThemedBackground
: public nsPaintedDisplayItem
{
4721 nsDisplayThemedBackground(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4722 const nsRect
& aBackgroundRect
);
4724 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayThemedBackground
)
4726 NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND
)
4728 void Init(nsDisplayListBuilder
* aBuilder
);
4730 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
4731 aBuilder
->UnregisterThemeGeometry(this);
4732 nsPaintedDisplayItem::Destroy(aBuilder
);
4735 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4736 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4737 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4738 bool* aSnap
) const override
;
4739 mozilla::Maybe
<nscolor
> IsUniform(
4740 nsDisplayListBuilder
* aBuilder
) const override
;
4741 bool CreateWebRenderCommands(
4742 mozilla::wr::DisplayListBuilder
& aBuilder
,
4743 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4744 const StackingContextHelper
& aSc
,
4745 mozilla::layers::RenderRootStateManager
* aManager
,
4746 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4748 bool MustPaintOnContentSide() const override
{ return true; }
4751 * GetBounds() returns the background painting area.
4753 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
4755 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4758 * Return the background positioning area.
4759 * (GetBounds() returns the background painting area.)
4760 * Can be called only when mBackgroundStyle is non-null.
4762 nsRect
GetPositioningArea() const;
4765 * Return whether our frame's document does not have the state
4766 * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
4768 bool IsWindowActive() const;
4770 nsDisplayItemGeometry
* AllocateGeometry(
4771 nsDisplayListBuilder
* aBuilder
) override
{
4772 return new nsDisplayThemedBackgroundGeometry(this, aBuilder
);
4775 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4776 const nsDisplayItemGeometry
* aGeometry
,
4777 nsRegion
* aInvalidRegion
) const override
;
4779 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4782 nsRect
GetBoundsInternal();
4784 void PaintInternal(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4785 const nsRect
& aBounds
, nsRect
* aClipRect
);
4787 nsRect mBackgroundRect
;
4789 nsITheme::Transparency mThemeTransparency
;
4790 mozilla::StyleAppearance mAppearance
;
4793 class nsDisplayTableThemedBackground
: public nsDisplayThemedBackground
{
4795 nsDisplayTableThemedBackground(nsDisplayListBuilder
* aBuilder
,
4797 const nsRect
& aBackgroundRect
,
4798 nsIFrame
* aAncestorFrame
)
4799 : nsDisplayThemedBackground(aBuilder
, aFrame
, aBackgroundRect
),
4800 mAncestorFrame(aAncestorFrame
) {
4801 if (aBuilder
->IsRetainingDisplayList()) {
4802 mAncestorFrame
->AddDisplayItem(this);
4806 ~nsDisplayTableThemedBackground() override
{
4807 if (mAncestorFrame
) {
4808 mAncestorFrame
->RemoveDisplayItem(this);
4812 NS_DISPLAY_DECL_NAME("TableThemedBackground",
4813 TYPE_TABLE_THEMED_BACKGROUND_IMAGE
)
4815 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4817 void RemoveFrame(nsIFrame
* aFrame
) override
{
4818 if (aFrame
== mAncestorFrame
) {
4819 mAncestorFrame
= nullptr;
4822 nsDisplayThemedBackground::RemoveFrame(aFrame
);
4826 nsIFrame
* StyleFrame() const override
{ return mAncestorFrame
; }
4827 nsIFrame
* mAncestorFrame
;
4830 class nsDisplayBackgroundColor
: public nsPaintedDisplayItem
{
4831 typedef mozilla::gfx::sRGBColor sRGBColor
;
4834 nsDisplayBackgroundColor(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
4835 const nsRect
& aBackgroundRect
,
4836 const mozilla::ComputedStyle
* aBackgroundStyle
,
4837 const nscolor
& aColor
)
4838 : nsPaintedDisplayItem(aBuilder
, aFrame
),
4839 mBackgroundRect(aBackgroundRect
),
4840 mHasStyle(aBackgroundStyle
),
4841 mDependentFrame(nullptr),
4842 mColor(sRGBColor::FromABGR(aColor
)) {
4843 mState
.mColor
= mColor
;
4847 aBackgroundStyle
->StyleBackground()->BottomLayer().mClip
;
4849 MOZ_ASSERT(aBuilder
->IsForEventDelivery());
4853 ~nsDisplayBackgroundColor() override
{
4854 if (mDependentFrame
) {
4855 mDependentFrame
->RemoveDisplayItem(this);
4859 NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR
)
4861 bool RestoreState() override
{
4862 if (!nsPaintedDisplayItem::RestoreState() && mColor
== mState
.mColor
) {
4866 mColor
= mState
.mColor
;
4870 bool HasBackgroundClipText() const {
4871 MOZ_ASSERT(mHasStyle
);
4872 return mBottomLayerClip
== mozilla::StyleGeometryBox::Text
;
4875 LayerState
GetLayerState(
4876 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4877 const ContainerLayerParameters
& aParameters
) override
;
4878 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
4879 void PaintWithClip(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
4880 const DisplayItemClip
& aClip
) override
;
4881 already_AddRefed
<Layer
> BuildLayer(
4882 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
4883 const ContainerLayerParameters
& aContainerParameters
) override
;
4884 bool CreateWebRenderCommands(
4885 mozilla::wr::DisplayListBuilder
& aBuilder
,
4886 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
4887 const StackingContextHelper
& aSc
,
4888 mozilla::layers::RenderRootStateManager
* aManager
,
4889 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
4890 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
4891 bool* aSnap
) const override
;
4892 mozilla::Maybe
<nscolor
> IsUniform(
4893 nsDisplayListBuilder
* aBuilder
) const override
;
4894 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
4895 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
4896 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
4897 const DisplayItemClipChain
* aClip
) override
;
4899 bool CanApplyOpacity() const override
;
4901 float GetOpacity() const { return mColor
.a
; }
4903 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
4905 return mBackgroundRect
;
4908 bool CanPaintWithClip(const DisplayItemClip
& aClip
) override
{
4909 if (HasBackgroundClipText()) {
4913 if (aClip
.GetRoundedRectCount() > 1) {
4920 nsDisplayItemGeometry
* AllocateGeometry(
4921 nsDisplayListBuilder
* aBuilder
) override
{
4922 return new nsDisplaySolidColorGeometry(this, aBuilder
, mColor
.ToABGR());
4925 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
4926 const nsDisplayItemGeometry
* aGeometry
,
4927 nsRegion
* aInvalidRegion
) const override
{
4928 const nsDisplaySolidColorGeometry
* geometry
=
4929 static_cast<const nsDisplaySolidColorGeometry
*>(aGeometry
);
4931 if (mColor
.ToABGR() != geometry
->mColor
) {
4933 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &dummy
));
4936 ComputeInvalidationRegionDifference(aBuilder
, geometry
, aInvalidRegion
);
4939 nsIFrame
* GetDependentFrame() override
{ return mDependentFrame
; }
4941 void SetDependentFrame(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
) {
4942 if (!aBuilder
->IsRetainingDisplayList()) {
4945 mDependentFrame
= aFrame
;
4947 mDependentFrame
->AddDisplayItem(this);
4951 void RemoveFrame(nsIFrame
* aFrame
) override
{
4952 if (aFrame
== mDependentFrame
) {
4953 mDependentFrame
= nullptr;
4956 nsPaintedDisplayItem::RemoveFrame(aFrame
);
4959 void WriteDebugInfo(std::stringstream
& aStream
) override
;
4961 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
4964 const nsRect mBackgroundRect
;
4965 const bool mHasStyle
;
4966 mozilla::StyleGeometryBox mBottomLayerClip
;
4967 nsIFrame
* mDependentFrame
;
4968 mozilla::gfx::sRGBColor mColor
;
4971 mozilla::gfx::sRGBColor mColor
;
4975 class nsDisplayTableBackgroundColor
: public nsDisplayBackgroundColor
{
4977 nsDisplayTableBackgroundColor(nsDisplayListBuilder
* aBuilder
,
4978 nsIFrame
* aFrame
, const nsRect
& aBackgroundRect
,
4979 const mozilla::ComputedStyle
* aBackgroundStyle
,
4980 const nscolor
& aColor
, nsIFrame
* aAncestorFrame
)
4981 : nsDisplayBackgroundColor(aBuilder
, aFrame
, aBackgroundRect
,
4982 aBackgroundStyle
, aColor
),
4983 mAncestorFrame(aAncestorFrame
) {
4984 if (aBuilder
->IsRetainingDisplayList()) {
4985 mAncestorFrame
->AddDisplayItem(this);
4989 ~nsDisplayTableBackgroundColor() override
{
4990 if (mAncestorFrame
) {
4991 mAncestorFrame
->RemoveDisplayItem(this);
4995 NS_DISPLAY_DECL_NAME("TableBackgroundColor", TYPE_TABLE_BACKGROUND_COLOR
)
4997 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
4999 void RemoveFrame(nsIFrame
* aFrame
) override
{
5000 if (aFrame
== mAncestorFrame
) {
5001 mAncestorFrame
= nullptr;
5004 nsDisplayBackgroundColor::RemoveFrame(aFrame
);
5007 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
{
5012 nsIFrame
* mAncestorFrame
;
5016 * The standard display item to paint the outer CSS box-shadows of a frame.
5018 class nsDisplayBoxShadowOuter final
: public nsPaintedDisplayItem
{
5020 nsDisplayBoxShadowOuter(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5021 : nsPaintedDisplayItem(aBuilder
, aFrame
), mOpacity(1.0f
) {
5022 MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter
);
5023 mBounds
= GetBoundsInternal();
5026 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowOuter
)
5028 NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER
)
5030 bool RestoreState() override
{
5031 if (!nsPaintedDisplayItem::RestoreState() && mOpacity
== 1.0f
&&
5032 mVisibleRegion
.IsEmpty()) {
5036 mVisibleRegion
.SetEmpty();
5041 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5042 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5043 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
5044 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5045 nsRegion
* aVisibleRegion
) override
;
5046 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5047 const nsDisplayItemGeometry
* aGeometry
,
5048 nsRegion
* aInvalidRegion
) const override
;
5050 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
5051 const DisplayItemClipChain
* aClip
) override
{
5052 NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
5053 mOpacity
= aOpacity
;
5054 IntersectClip(aBuilder
, aClip
, false);
5057 bool CanApplyOpacity() const override
{ return true; }
5059 nsDisplayItemGeometry
* AllocateGeometry(
5060 nsDisplayListBuilder
* aBuilder
) override
{
5061 return new nsDisplayBoxShadowOuterGeometry(this, aBuilder
, mOpacity
);
5064 bool CanBuildWebRenderDisplayItems();
5065 bool CreateWebRenderCommands(
5066 mozilla::wr::DisplayListBuilder
& aBuilder
,
5067 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5068 const StackingContextHelper
& aSc
,
5069 mozilla::layers::RenderRootStateManager
* aManager
,
5070 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5071 nsRect
GetBoundsInternal();
5074 nsRegion mVisibleRegion
;
5080 * The standard display item to paint the inner CSS box-shadows of a frame.
5082 class nsDisplayBoxShadowInner
: public nsPaintedDisplayItem
{
5084 nsDisplayBoxShadowInner(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5085 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
5086 MOZ_COUNT_CTOR(nsDisplayBoxShadowInner
);
5089 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowInner
)
5091 NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER
)
5093 bool RestoreState() override
{
5094 if (!nsPaintedDisplayItem::RestoreState() && mVisibleRegion
.IsEmpty()) {
5098 mVisibleRegion
.SetEmpty();
5102 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5103 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5104 nsRegion
* aVisibleRegion
) override
;
5106 nsDisplayItemGeometry
* AllocateGeometry(
5107 nsDisplayListBuilder
* aBuilder
) override
{
5108 return new nsDisplayBoxShadowInnerGeometry(this, aBuilder
);
5111 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5112 const nsDisplayItemGeometry
* aGeometry
,
5113 nsRegion
* aInvalidRegion
) const override
{
5114 const nsDisplayBoxShadowInnerGeometry
* geometry
=
5115 static_cast<const nsDisplayBoxShadowInnerGeometry
*>(aGeometry
);
5116 if (!geometry
->mPaddingRect
.IsEqualInterior(GetPaddingRect())) {
5117 // nsDisplayBoxShadowInner is based around the padding rect, but it can
5118 // touch pixels outside of this. We should invalidate the entire bounds.
5120 aInvalidRegion
->Or(geometry
->mBounds
, GetBounds(aBuilder
, &snap
));
5124 static bool CanCreateWebRenderCommands(nsDisplayListBuilder
* aBuilder
,
5126 const nsPoint
& aReferencePoint
);
5127 static void CreateInsetBoxShadowWebRenderCommands(
5128 mozilla::wr::DisplayListBuilder
& aBuilder
,
5129 const StackingContextHelper
& aSc
, nsRegion
& aVisibleRegion
,
5130 nsIFrame
* aFrame
, const nsRect
& aBorderRect
);
5131 bool CreateWebRenderCommands(
5132 mozilla::wr::DisplayListBuilder
& aBuilder
,
5133 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5134 const StackingContextHelper
& aSc
,
5135 mozilla::layers::RenderRootStateManager
* aManager
,
5136 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5139 nsRegion mVisibleRegion
;
5143 * The standard display item to paint the CSS outline of a frame.
5145 class nsDisplayOutline final
: public nsPaintedDisplayItem
{
5147 nsDisplayOutline(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5148 : nsPaintedDisplayItem(aBuilder
, aFrame
) {
5149 MOZ_COUNT_CTOR(nsDisplayOutline
);
5152 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOutline
)
5154 NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE
)
5156 bool MustPaintOnContentSide() const override
{
5157 MOZ_ASSERT(IsThemedOutline(),
5158 "The only fallback path we have is for themed outlines");
5162 bool CreateWebRenderCommands(
5163 mozilla::wr::DisplayListBuilder
& aBuilder
,
5164 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5165 const StackingContextHelper
& aSc
,
5166 mozilla::layers::RenderRootStateManager
* aManager
,
5167 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5168 bool IsInvisibleInRect(const nsRect
& aRect
) const override
;
5169 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5170 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5173 nsRect
GetInnerRect() const;
5174 bool IsThemedOutline() const;
5175 bool HasRadius() const;
5179 * A class that lets you receive events within the frame bounds but never
5182 class nsDisplayEventReceiver final
: public nsDisplayItem
{
5184 nsDisplayEventReceiver(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5185 : nsDisplayItem(aBuilder
, aFrame
) {
5186 MOZ_COUNT_CTOR(nsDisplayEventReceiver
);
5189 MOZ_COUNTED_DTOR_FINAL(nsDisplayEventReceiver
)
5191 NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER
)
5193 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5194 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
;
5198 * Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
5199 * this gets built when we're doing widget painting and we need to send the
5200 * compositor some hit-test info for a frame. This is effectively a dummy item
5201 * whose sole purpose is to carry the hit-test info to the compositor.
5203 class nsDisplayCompositorHitTestInfo final
: public nsDisplayItem
{
5205 nsDisplayCompositorHitTestInfo(nsDisplayListBuilder
* aBuilder
,
5207 : nsDisplayItem(aBuilder
, aFrame
) {
5208 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
5209 mHitTestInfo
.Initialize(aBuilder
, aFrame
);
5210 SetHasHitTestInfo();
5213 nsDisplayCompositorHitTestInfo(
5214 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, const nsRect
& aArea
,
5215 const mozilla::gfx::CompositorHitTestInfo
& aHitTestFlags
)
5216 : nsDisplayItem(aBuilder
, aFrame
) {
5217 MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo
);
5218 mHitTestInfo
.SetAreaAndInfo(aArea
, aHitTestFlags
);
5219 mHitTestInfo
.InitializeScrollTarget(aBuilder
);
5220 SetHasHitTestInfo();
5223 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo
)
5225 NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO
)
5227 bool CreateWebRenderCommands(
5228 mozilla::wr::DisplayListBuilder
& aBuilder
,
5229 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5230 const StackingContextHelper
& aSc
,
5231 mozilla::layers::RenderRootStateManager
* aManager
,
5232 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5234 int32_t ZIndex() const override
;
5235 void SetOverrideZIndex(int32_t aZIndex
);
5237 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
5242 const mozilla::HitTestInfo
& GetHitTestInfo() final
{ return mHitTestInfo
; }
5245 mozilla::HitTestInfo mHitTestInfo
;
5246 mozilla::Maybe
<int32_t> mOverrideZIndex
;
5250 * A class that lets you wrap a display list as a display item.
5252 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
5253 * list has many items, it's not clear which one has the 'underlying frame'.
5254 * Thus we force the creator to specify what the underlying frame is. The
5255 * underlying frame should be the root of a stacking context, because sorting
5256 * a list containing this item will not get at the children.
5258 * In some cases (e.g., clipping) we want to wrap a list but we don't have a
5259 * particular underlying frame that is a stacking context root. In that case
5260 * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
5261 * detect and handle this case.
5263 class nsDisplayWrapList
: public nsPaintedDisplayItem
{
5266 * Takes all the items from aList and puts them in our list.
5268 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5269 nsDisplayList
* aList
);
5271 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5272 nsDisplayItem
* aItem
);
5274 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5275 nsDisplayList
* aList
,
5276 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5277 bool aClearClipChain
= false);
5279 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
5280 : nsPaintedDisplayItem(aBuilder
, aFrame
),
5281 mFrameActiveScrolledRoot(aBuilder
->CurrentActiveScrolledRoot()),
5283 mHasZIndexOverride(false) {
5284 MOZ_COUNT_CTOR(nsDisplayWrapList
);
5285 mBaseBuildingRect
= GetBuildingRect();
5289 nsDisplayWrapList() = delete;
5292 * A custom copy-constructor that does not copy mList, as this would mutate
5295 nsDisplayWrapList(const nsDisplayWrapList
& aOther
) = delete;
5296 nsDisplayWrapList(nsDisplayListBuilder
* aBuilder
,
5297 const nsDisplayWrapList
& aOther
)
5298 : nsPaintedDisplayItem(aBuilder
, aOther
),
5300 mFrameActiveScrolledRoot(aOther
.mFrameActiveScrolledRoot
),
5301 mMergedFrames(aOther
.mMergedFrames
.Clone()),
5302 mBounds(aOther
.mBounds
),
5303 mBaseBuildingRect(aOther
.mBaseBuildingRect
),
5304 mOverrideZIndex(aOther
.mOverrideZIndex
),
5305 mHasZIndexOverride(aOther
.mHasZIndexOverride
),
5306 mClearingClipChain(aOther
.mClearingClipChain
) {
5307 MOZ_COUNT_CTOR(nsDisplayWrapList
);
5310 ~nsDisplayWrapList() override
;
5312 const nsDisplayWrapList
* AsDisplayWrapList() const final
{ return this; }
5313 nsDisplayWrapList
* AsDisplayWrapList() final
{ return this; }
5315 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
5316 mList
.DeleteAll(aBuilder
);
5317 nsPaintedDisplayItem::Destroy(aBuilder
);
5321 * Creates a new nsDisplayWrapList that holds a pointer to the display list
5322 * owned by the given nsDisplayItem. The new nsDisplayWrapList will be added
5323 * to the bottom of this item's contents.
5325 void MergeDisplayListFromItem(nsDisplayListBuilder
* aBuilder
,
5326 const nsDisplayWrapList
* aItem
);
5329 * Call this if the wrapped list is changed.
5331 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
{
5332 // Clear the clip chain up to the asr, but don't store it, so that we'll
5333 // recover it when we reuse the item.
5334 if (mClearingClipChain
) {
5335 const DisplayItemClipChain
* clip
= mState
.mClipChain
;
5336 while (clip
&& ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(),
5338 clip
= clip
->mParent
;
5340 SetClipChain(clip
, false);
5343 nsRect buildingRect
;
5344 mBounds
= mListPtr
->GetClippedBoundsWithRespectToASR(
5345 aBuilder
, mActiveScrolledRoot
, &buildingRect
);
5346 // The display list may contain content that's visible outside the visible
5347 // rect (i.e. the current dirty rect) passed in when the item was created.
5348 // This happens when the dirty rect has been restricted to the visual
5349 // overflow rect of a frame for some reason (e.g. when setting up dirty
5350 // rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
5351 // frame contains placeholders for out-of-flows that aren't descendants of
5353 buildingRect
.UnionRect(mBaseBuildingRect
, buildingRect
);
5354 SetBuildingRect(buildingRect
);
5357 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5358 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5359 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
5360 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5361 bool* aSnap
) const override
;
5362 mozilla::Maybe
<nscolor
> IsUniform(
5363 nsDisplayListBuilder
* aBuilder
) const override
;
5364 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5365 nsRegion
* aVisibleRegion
) override
;
5368 * Checks if the given display item can be merged with this item.
5369 * @return true if the merging is possible, otherwise false.
5371 virtual bool CanMerge(const nsDisplayItem
* aItem
) const { return false; }
5374 * Try to merge with the other item (which is below us in the display
5375 * list). This gets used by nsDisplayClip to coalesce clipping operations
5376 * (optimization), by nsDisplayOpacity to merge rendering for the same
5377 * content element into a single opacity group (correctness), and will be
5378 * used by nsDisplayOutline to merge multiple outlines for the same element
5379 * (also for correctness).
5381 virtual void Merge(const nsDisplayItem
* aItem
) {
5382 MOZ_ASSERT(CanMerge(aItem
));
5383 MOZ_ASSERT(Frame() != aItem
->Frame());
5384 MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList
*>(aItem
));
5388 * Returns the underlying frames of all display items that have been
5389 * merged into this one (excluding this item's own underlying frame)
5392 const nsTArray
<nsIFrame
*>& GetMergedFrames() const { return mMergedFrames
; }
5394 bool HasMergedFrames() const { return !mMergedFrames
.IsEmpty(); }
5396 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5400 bool IsInvalid(nsRect
& aRect
) const override
{
5401 if (mFrame
->IsInvalid(aRect
) && aRect
.IsEmpty()) {
5405 for (uint32_t i
= 0; i
< mMergedFrames
.Length(); i
++) {
5406 if (mMergedFrames
[i
]->IsInvalid(temp
) && temp
.IsEmpty()) {
5410 aRect
= aRect
.Union(temp
);
5412 aRect
+= ToReferenceFrame();
5413 return !aRect
.IsEmpty();
5416 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
5418 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
5420 mListPtr
->IsEmpty() || !ReferenceFrame() ||
5421 !mListPtr
->GetBottom()->ReferenceFrame() ||
5422 mListPtr
->GetBottom()->ReferenceFrame() == ReferenceFrame(),
5423 "Children must have same reference frame");
5427 RetainedDisplayList
* GetChildren() const override
{ return mListPtr
; }
5429 int32_t ZIndex() const override
{
5430 return (mHasZIndexOverride
) ? mOverrideZIndex
5431 : nsPaintedDisplayItem::ZIndex();
5434 void SetOverrideZIndex(int32_t aZIndex
) {
5435 mHasZIndexOverride
= true;
5436 mOverrideZIndex
= aZIndex
;
5440 * This creates a copy of this item, but wrapping aItem instead of
5441 * our existing list. Only gets called if this item returned nullptr
5442 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
5443 * GetUnderlyingFrame().
5445 nsDisplayWrapList
* WrapWithClone(nsDisplayListBuilder
* aBuilder
,
5446 nsDisplayItem
* aItem
) {
5447 MOZ_ASSERT_UNREACHABLE("We never returned nullptr for GetUnderlyingFrame!");
5451 bool CreateWebRenderCommands(
5452 mozilla::wr::DisplayListBuilder
& aBuilder
,
5453 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5454 const StackingContextHelper
& aSc
,
5455 mozilla::layers::RenderRootStateManager
* aManager
,
5456 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5458 const ActiveScrolledRoot
* GetFrameActiveScrolledRoot() {
5459 return mFrameActiveScrolledRoot
;
5463 void MergeFromTrackingMergedFrames(const nsDisplayWrapList
* aOther
) {
5464 mBounds
.UnionRect(mBounds
, aOther
->mBounds
);
5465 nsRect buildingRect
;
5466 buildingRect
.UnionRect(GetBuildingRect(), aOther
->GetBuildingRect());
5467 SetBuildingRect(buildingRect
);
5468 mMergedFrames
.AppendElement(aOther
->mFrame
);
5469 mMergedFrames
.AppendElements(aOther
->mMergedFrames
.Clone());
5472 RetainedDisplayList mList
;
5473 RetainedDisplayList
* mListPtr
;
5474 // The active scrolled root for the frame that created this
5476 RefPtr
<const ActiveScrolledRoot
> mFrameActiveScrolledRoot
;
5477 // The frames from items that have been merged into this item, excluding
5478 // this item's own frame.
5479 nsTArray
<nsIFrame
*> mMergedFrames
;
5481 // Displaylist building rect contributed by this display item itself.
5482 // Our mBuildingRect may include the visible areas of children.
5483 nsRect mBaseBuildingRect
;
5484 int32_t mOverrideZIndex
;
5485 bool mHasZIndexOverride
;
5486 bool mClearingClipChain
= false;
5489 class nsDisplayWrapper
: public nsDisplayWrapList
{
5491 NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST
)
5493 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5494 nsDisplayList
* aList
,
5495 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5496 bool aClearClipChain
= false)
5497 : nsDisplayWrapList(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5500 nsDisplayWrapper(const nsDisplayWrapper
& aOther
) = delete;
5501 nsDisplayWrapper(nsDisplayListBuilder
* aBuilder
,
5502 const nsDisplayWrapList
& aOther
)
5503 : nsDisplayWrapList(aBuilder
, aOther
) {}
5505 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5508 NS_DISPLAY_ALLOW_CLONING()
5509 friend class nsDisplayListBuilder
;
5510 friend class nsDisplayWrapList
;
5514 * We call WrapDisplayList on the in-flow lists: BorderBackground(),
5515 * BlockBorderBackgrounds() and Content().
5516 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
5517 * and Floats(). This is done to support special wrapping processing for frames
5518 * that may not be in-flow descendants of the current frame.
5520 class nsDisplayItemWrapper
{
5522 // This is never instantiated directly (it has pure virtual methods), so no
5523 // need to count constructors and destructors.
5525 bool WrapBorderBackground() { return true; }
5526 virtual nsDisplayItem
* WrapList(nsDisplayListBuilder
* aBuilder
,
5527 nsIFrame
* aFrame
, nsDisplayList
* aList
) = 0;
5528 virtual nsDisplayItem
* WrapItem(nsDisplayListBuilder
* aBuilder
,
5529 nsDisplayItem
* aItem
) = 0;
5531 nsresult
WrapLists(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5532 const nsDisplayListSet
& aIn
, const nsDisplayListSet
& aOut
);
5533 nsresult
WrapListsInPlace(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5534 const nsDisplayListSet
& aLists
);
5537 nsDisplayItemWrapper() = default;
5541 * The standard display item to paint a stacking context with translucency
5542 * set by the stacking context root frame's 'opacity' style.
5544 class nsDisplayOpacity
: public nsDisplayWrapList
{
5546 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5547 nsDisplayList
* aList
,
5548 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5549 bool aForEventsOnly
, bool aNeedsActiveLayer
);
5551 nsDisplayOpacity(nsDisplayListBuilder
* aBuilder
,
5552 const nsDisplayOpacity
& aOther
)
5553 : nsDisplayWrapList(aBuilder
, aOther
),
5554 mOpacity(aOther
.mOpacity
),
5555 mForEventsOnly(aOther
.mForEventsOnly
),
5556 mNeedsActiveLayer(aOther
.mNeedsActiveLayer
),
5557 mChildOpacityState(ChildOpacityState::Unknown
) {
5558 MOZ_COUNT_CTOR(nsDisplayOpacity
);
5559 // We should not try to merge flattened opacities.
5560 MOZ_ASSERT(aOther
.mChildOpacityState
!= ChildOpacityState::Applied
);
5563 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
5564 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
5566 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOpacity
)
5568 NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY
)
5570 bool RestoreState() override
{
5571 if (!nsDisplayWrapList::RestoreState() && mOpacity
== mState
.mOpacity
) {
5575 mOpacity
= mState
.mOpacity
;
5579 void InvalidateCachedChildInfo(nsDisplayListBuilder
* aBuilder
) override
{
5580 mChildOpacityState
= ChildOpacityState::Unknown
;
5583 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5584 bool* aSnap
) const override
;
5585 already_AddRefed
<Layer
> BuildLayer(
5586 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5587 const ContainerLayerParameters
& aContainerParameters
) override
;
5588 LayerState
GetLayerState(
5589 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5590 const ContainerLayerParameters
& aParameters
) override
;
5591 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5592 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5593 nsRegion
* aVisibleRegion
) override
;
5595 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5596 // items for the same content element should be merged into a single
5597 // compositing group
5598 // aItem->GetUnderlyingFrame() returns non-null because it's
5600 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5601 HasSameContent(aItem
);
5604 nsDisplayItemGeometry
* AllocateGeometry(
5605 nsDisplayListBuilder
* aBuilder
) override
{
5606 return new nsDisplayOpacityGeometry(this, aBuilder
, mOpacity
);
5609 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5610 const nsDisplayItemGeometry
* aGeometry
,
5611 nsRegion
* aInvalidRegion
) const override
;
5613 bool IsInvalid(nsRect
& aRect
) const override
{
5614 if (mForEventsOnly
) {
5617 return nsDisplayWrapList::IsInvalid(aRect
);
5619 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
5620 const DisplayItemClipChain
* aClip
) override
;
5621 bool CanApplyOpacity() const override
;
5622 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
5624 bool NeedsGeometryUpdates() const override
{
5625 // For flattened nsDisplayOpacity items, ComputeInvalidationRegion() only
5626 // handles invalidation for changed |mOpacity|. In order to keep track of
5627 // the current bounds of the item for invalidation, nsDisplayOpacityGeometry
5628 // for the corresponding DisplayItemData needs to be updated, even if the
5629 // reported invalidation region is empty.
5630 return mChildOpacityState
== ChildOpacityState::Deferred
;
5634 * Returns true if ShouldFlattenAway() applied opacity to children.
5636 bool OpacityAppliedToChildren() const {
5637 return mChildOpacityState
== ChildOpacityState::Applied
;
5640 static bool NeedsActiveLayer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5641 bool aEnforceMinimumSize
= true);
5642 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5643 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
5644 bool CreateWebRenderCommands(
5645 mozilla::wr::DisplayListBuilder
& aBuilder
,
5646 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5647 const StackingContextHelper
& aSc
,
5648 mozilla::layers::RenderRootStateManager
* aManager
,
5649 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5651 float GetOpacity() const { return mOpacity
; }
5654 NS_DISPLAY_ALLOW_CLONING()
5656 bool ApplyToChildren(nsDisplayListBuilder
* aBuilder
);
5657 bool ApplyToFilterOrMask(const bool aUsingLayers
);
5660 bool mForEventsOnly
: 1;
5661 enum class ChildOpacityState
: uint8_t {
5662 // Our child list has changed since the last time ApplyToChildren was
5665 // Our children defer opacity handling to us.
5667 // Opacity is applied to our children.
5670 bool mNeedsActiveLayer
: 1;
5672 ChildOpacityState mChildOpacityState
: 2;
5674 ChildOpacityState mChildOpacityState
;
5682 class nsDisplayBlendMode
: public nsDisplayWrapList
{
5684 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5685 nsDisplayList
* aList
, mozilla::StyleBlend aBlendMode
,
5686 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5687 const bool aIsForBackground
);
5688 nsDisplayBlendMode(nsDisplayListBuilder
* aBuilder
,
5689 const nsDisplayBlendMode
& aOther
)
5690 : nsDisplayWrapList(aBuilder
, aOther
),
5691 mBlendMode(aOther
.mBlendMode
),
5692 mIsForBackground(aOther
.mIsForBackground
) {
5693 MOZ_COUNT_CTOR(nsDisplayBlendMode
);
5696 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendMode
)
5698 NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE
)
5700 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
5701 bool* aSnap
) const override
;
5702 already_AddRefed
<Layer
> BuildLayer(
5703 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5704 const ContainerLayerParameters
& aContainerParameters
) override
;
5705 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
5706 const nsDisplayItemGeometry
* aGeometry
,
5707 nsRegion
* aInvalidRegion
) const override
{
5708 // We don't need to compute an invalidation region since we have
5709 // LayerTreeInvalidation
5712 LayerState
GetLayerState(
5713 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5714 const ContainerLayerParameters
& aParameters
) override
;
5715 bool CreateWebRenderCommands(
5716 mozilla::wr::DisplayListBuilder
& aBuilder
,
5717 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5718 const StackingContextHelper
& aSc
,
5719 mozilla::layers::RenderRootStateManager
* aManager
,
5720 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5721 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5722 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
5723 nsRegion
* aVisibleRegion
) override
;
5725 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
5727 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5731 mozilla::gfx::CompositionOp
BlendMode();
5734 mozilla::StyleBlend mBlendMode
;
5735 bool mIsForBackground
;
5738 NS_DISPLAY_ALLOW_CLONING()
5741 class nsDisplayTableBlendMode
: public nsDisplayBlendMode
{
5743 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5744 nsDisplayList
* aList
, mozilla::StyleBlend aBlendMode
,
5745 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5746 nsIFrame
* aAncestorFrame
, const bool aIsForBackground
)
5747 : nsDisplayBlendMode(aBuilder
, aFrame
, aList
, aBlendMode
,
5748 aActiveScrolledRoot
, aIsForBackground
),
5749 mAncestorFrame(aAncestorFrame
) {
5750 if (aBuilder
->IsRetainingDisplayList()) {
5751 mAncestorFrame
->AddDisplayItem(this);
5755 nsDisplayTableBlendMode(nsDisplayListBuilder
* aBuilder
,
5756 const nsDisplayTableBlendMode
& aOther
)
5757 : nsDisplayBlendMode(aBuilder
, aOther
),
5758 mAncestorFrame(aOther
.mAncestorFrame
) {
5759 if (aBuilder
->IsRetainingDisplayList()) {
5760 mAncestorFrame
->AddDisplayItem(this);
5764 ~nsDisplayTableBlendMode() override
{
5765 if (mAncestorFrame
) {
5766 mAncestorFrame
->RemoveDisplayItem(this);
5770 NS_DISPLAY_DECL_NAME("TableBlendMode", TYPE_TABLE_BLEND_MODE
)
5772 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5774 void RemoveFrame(nsIFrame
* aFrame
) override
{
5775 if (aFrame
== mAncestorFrame
) {
5776 mAncestorFrame
= nullptr;
5779 nsDisplayBlendMode::RemoveFrame(aFrame
);
5783 nsIFrame
* mAncestorFrame
;
5786 NS_DISPLAY_ALLOW_CLONING()
5789 class nsDisplayBlendContainer
: public nsDisplayWrapList
{
5791 static nsDisplayBlendContainer
* CreateForMixBlendMode(
5792 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5793 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5795 static nsDisplayBlendContainer
* CreateForBackgroundBlendMode(
5796 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5797 nsIFrame
* aSecondaryFrame
, nsDisplayList
* aList
,
5798 const ActiveScrolledRoot
* aActiveScrolledRoot
);
5800 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendContainer
)
5802 NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER
)
5804 already_AddRefed
<Layer
> BuildLayer(
5805 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5806 const ContainerLayerParameters
& aContainerParameters
) override
;
5807 LayerState
GetLayerState(
5808 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5809 const ContainerLayerParameters
& aParameters
) override
;
5810 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
5811 bool CreateWebRenderCommands(
5812 mozilla::wr::DisplayListBuilder
& aBuilder
,
5813 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5814 const StackingContextHelper
& aSc
,
5815 mozilla::layers::RenderRootStateManager
* aManager
,
5816 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5818 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5819 // Items for the same content element should be merged into a single
5820 // compositing group.
5821 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
5822 HasSameContent(aItem
) &&
5824 static_cast<const nsDisplayBlendContainer
*>(aItem
)
5828 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5833 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5834 nsDisplayList
* aList
,
5835 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5836 bool aIsForBackground
);
5837 nsDisplayBlendContainer(nsDisplayListBuilder
* aBuilder
,
5838 const nsDisplayBlendContainer
& aOther
)
5839 : nsDisplayWrapList(aBuilder
, aOther
),
5840 mIsForBackground(aOther
.mIsForBackground
) {
5841 MOZ_COUNT_CTOR(nsDisplayBlendContainer
);
5844 // Used to distinguish containers created at building stacking
5845 // context or appending background.
5846 bool mIsForBackground
;
5849 NS_DISPLAY_ALLOW_CLONING()
5852 class nsDisplayTableBlendContainer
: public nsDisplayBlendContainer
{
5854 NS_DISPLAY_DECL_NAME("TableBlendContainer", TYPE_TABLE_BLEND_CONTAINER
)
5856 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
5858 void RemoveFrame(nsIFrame
* aFrame
) override
{
5859 if (aFrame
== mAncestorFrame
) {
5860 mAncestorFrame
= nullptr;
5863 nsDisplayBlendContainer::RemoveFrame(aFrame
);
5867 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
5868 nsDisplayList
* aList
,
5869 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5870 bool aIsForBackground
, nsIFrame
* aAncestorFrame
)
5871 : nsDisplayBlendContainer(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
,
5873 mAncestorFrame(aAncestorFrame
) {
5874 if (aBuilder
->IsRetainingDisplayList()) {
5875 mAncestorFrame
->AddDisplayItem(this);
5879 nsDisplayTableBlendContainer(nsDisplayListBuilder
* aBuilder
,
5880 const nsDisplayTableBlendContainer
& aOther
)
5881 : nsDisplayBlendContainer(aBuilder
, aOther
),
5882 mAncestorFrame(aOther
.mAncestorFrame
) {}
5884 ~nsDisplayTableBlendContainer() override
{
5885 if (mAncestorFrame
) {
5886 mAncestorFrame
->RemoveDisplayItem(this);
5890 nsIFrame
* mAncestorFrame
;
5893 NS_DISPLAY_ALLOW_CLONING()
5897 * nsDisplayOwnLayer constructor flags. If we nest this class inside
5898 * nsDisplayOwnLayer then we can't forward-declare it up at the top of this
5899 * file and that makes it hard to use in all the places that we need to use it.
5901 enum class nsDisplayOwnLayerFlags
{
5903 GenerateSubdocInvalidations
= 1 << 0,
5904 GenerateScrollableLayer
= 1 << 1,
5907 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags
)
5910 * A display item that has no purpose but to ensure its contents get
5913 class nsDisplayOwnLayer
: public nsDisplayWrapList
{
5915 typedef mozilla::layers::ScrollbarData ScrollbarData
;
5918 OwnLayerForTransformWithRoundedClip
,
5919 OwnLayerForStackingContext
,
5920 OwnLayerForImageBoxFrame
,
5921 OwnLayerForScrollbar
,
5922 OwnLayerForScrollThumb
,
5928 * @param aFlags eGenerateSubdocInvalidations :
5929 * Add UserData to the created ContainerLayer, so that invalidations
5930 * for this layer are send to our nsPresContext.
5931 * eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and
5932 * subclasses), indicates this layer is to be a scrollable layer, so call
5933 * ComputeFrameMetrics, etc.
5934 * @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar
5935 * is set in the flags, this parameter should be the ViewID of the
5936 * scrollable content this scrollbar is for.
5939 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsDisplayList
* aList
,
5940 const ActiveScrolledRoot
* aActiveScrolledRoot
,
5941 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
,
5942 const ScrollbarData
& aScrollbarData
= ScrollbarData
{},
5943 bool aForceActive
= true, bool aClearClipChain
= false);
5945 nsDisplayOwnLayer(nsDisplayListBuilder
* aBuilder
,
5946 const nsDisplayOwnLayer
& aOther
)
5947 : nsDisplayWrapList(aBuilder
, aOther
),
5948 mFlags(aOther
.mFlags
),
5949 mScrollbarData(aOther
.mScrollbarData
),
5950 mForceActive(aOther
.mForceActive
),
5951 mWrAnimationId(aOther
.mWrAnimationId
) {
5952 MOZ_COUNT_CTOR(nsDisplayOwnLayer
);
5955 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOwnLayer
)
5957 NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER
)
5959 already_AddRefed
<Layer
> BuildLayer(
5960 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5961 const ContainerLayerParameters
& aContainerParameters
) override
;
5962 bool CreateWebRenderCommands(
5963 mozilla::wr::DisplayListBuilder
& aBuilder
,
5964 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
5965 const StackingContextHelper
& aSc
,
5966 mozilla::layers::RenderRootStateManager
* aManager
,
5967 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
5968 bool UpdateScrollData(
5969 mozilla::layers::WebRenderScrollData
* aData
,
5970 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
5971 LayerState
GetLayerState(
5972 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
5973 const ContainerLayerParameters
& aParameters
) override
;
5974 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
5975 GetChildren()->Paint(aBuilder
, aCtx
,
5976 mFrame
->PresContext()->AppUnitsPerDevPixel());
5979 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
5980 // Don't allow merging, each sublist must have its own layer
5984 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
5988 void WriteDebugInfo(std::stringstream
& aStream
) override
;
5989 nsDisplayOwnLayerFlags
GetFlags() { return mFlags
; }
5990 bool IsScrollThumbLayer() const;
5991 bool IsScrollbarContainer() const;
5992 bool IsRootScrollbarContainer() const;
5993 bool IsZoomingLayer() const;
5994 bool IsFixedPositionLayer() const;
5995 bool IsStickyPositionLayer() const;
5996 bool HasDynamicToolbar() const;
5999 nsDisplayOwnLayerFlags mFlags
;
6002 * If this nsDisplayOwnLayer represents a scroll thumb layer or a
6003 * scrollbar container layer, mScrollbarData stores information
6004 * about the scrollbar. Otherwise, mScrollbarData will be
6005 * default-constructed (in particular with mDirection == Nothing())
6006 * and can be ignored.
6008 ScrollbarData mScrollbarData
;
6010 uint64_t mWrAnimationId
;
6014 * A display item for subdocuments. This is more or less the same as
6015 * nsDisplayOwnLayer, except that it always populates the FrameMetrics instance
6016 * on the ContainerLayer it builds.
6018 class nsDisplaySubDocument
: public nsDisplayOwnLayer
{
6020 nsDisplaySubDocument(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6021 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
6022 nsDisplayOwnLayerFlags aFlags
);
6023 ~nsDisplaySubDocument() override
;
6025 NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT
)
6027 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6029 virtual nsSubDocumentFrame
* SubDocumentFrame() { return mSubDocFrame
; }
6031 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6032 nsRegion
* aVisibleRegion
) override
;
6033 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6034 return mShouldFlatten
;
6037 void SetShouldFlattenAway(bool aShouldFlatten
) {
6038 mShouldFlatten
= aShouldFlatten
;
6041 LayerState
GetLayerState(
6042 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6043 const ContainerLayerParameters
& aParameters
) override
{
6044 if (mShouldFlatten
) {
6045 return mozilla::LayerState::LAYER_NONE
;
6047 return nsDisplayOwnLayer::GetLayerState(aBuilder
, aManager
, aParameters
);
6050 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6051 bool* aSnap
) const override
;
6053 nsIFrame
* FrameForInvalidation() const override
;
6054 void RemoveFrame(nsIFrame
* aFrame
) override
;
6059 ViewID mScrollParentId
;
6060 bool mForceDispatchToContentRegion
;
6061 bool mShouldFlatten
;
6062 nsSubDocumentFrame
* mSubDocFrame
;
6066 * A display item used to represent sticky position elements. The contents
6067 * gets its own layer and creates a stacking context, and the layer will have
6068 * position-related metadata set on it.
6070 class nsDisplayStickyPosition
: public nsDisplayOwnLayer
{
6072 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6073 nsDisplayList
* aList
,
6074 const ActiveScrolledRoot
* aActiveScrolledRoot
,
6075 const ActiveScrolledRoot
* aContainerASR
,
6076 bool aClippedToDisplayPort
);
6077 nsDisplayStickyPosition(nsDisplayListBuilder
* aBuilder
,
6078 const nsDisplayStickyPosition
& aOther
)
6079 : nsDisplayOwnLayer(aBuilder
, aOther
),
6080 mContainerASR(aOther
.mContainerASR
),
6081 mClippedToDisplayPort(aOther
.mClippedToDisplayPort
) {
6082 MOZ_COUNT_CTOR(nsDisplayStickyPosition
);
6085 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayStickyPosition
)
6087 void SetClipChain(const DisplayItemClipChain
* aClipChain
,
6088 bool aStore
) override
;
6089 bool IsClippedToDisplayPort() const { return mClippedToDisplayPort
; }
6091 already_AddRefed
<Layer
> BuildLayer(
6092 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6093 const ContainerLayerParameters
& aContainerParameters
) override
;
6094 NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION
)
6095 LayerState
GetLayerState(
6096 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6097 const ContainerLayerParameters
& aParameters
) override
{
6098 return mozilla::LayerState::LAYER_ACTIVE
;
6100 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6101 GetChildren()->Paint(aBuilder
, aCtx
,
6102 mFrame
->PresContext()->AppUnitsPerDevPixel());
6105 bool CreateWebRenderCommands(
6106 mozilla::wr::DisplayListBuilder
& aBuilder
,
6107 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6108 const StackingContextHelper
& aSc
,
6109 mozilla::layers::RenderRootStateManager
* aManager
,
6110 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6112 bool UpdateScrollData(
6113 mozilla::layers::WebRenderScrollData
* aData
,
6114 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6116 const ActiveScrolledRoot
* GetContainerASR() const { return mContainerASR
; }
6119 NS_DISPLAY_ALLOW_CLONING()
6121 void CalculateLayerScrollRanges(
6122 mozilla::StickyScrollContainer
* aStickyScrollContainer
,
6123 float aAppUnitsPerDevPixel
, float aScaleX
, float aScaleY
,
6124 mozilla::LayerRectAbsolute
& aStickyOuter
,
6125 mozilla::LayerRectAbsolute
& aStickyInner
);
6127 mozilla::StickyScrollContainer
* GetStickyScrollContainer();
6129 // This stores the ASR that this sticky container item would have assuming it
6130 // has no fixed descendants. This may be the same as the ASR returned by
6131 // GetActiveScrolledRoot(), or it may be a descendant of that.
6132 RefPtr
<const ActiveScrolledRoot
> mContainerASR
;
6133 // This flag tracks if this sticky item is just clipped to the enclosing
6134 // scrollframe's displayport, or if there are additional clips in play. In
6135 // the former case, we can skip setting the displayport clip as the scrolled-
6136 // clip of the corresponding layer. This allows sticky items to remain
6137 // unclipped when the enclosing scrollframe is scrolled past the displayport.
6138 // i.e. when the rest of the scrollframe checkerboards, the sticky item will
6139 // not. This makes sense to do because the sticky item has abnormal scrolling
6140 // behavior and may still be visible even if the rest of the scrollframe is
6141 // checkerboarded. Note that the sticky item will still be subject to the
6143 bool mClippedToDisplayPort
;
6146 class nsDisplayFixedPosition
: public nsDisplayOwnLayer
{
6148 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6149 nsDisplayList
* aList
,
6150 const ActiveScrolledRoot
* aActiveScrolledRoot
,
6151 const ActiveScrolledRoot
* aContainerASR
);
6152 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
,
6153 const nsDisplayFixedPosition
& aOther
)
6154 : nsDisplayOwnLayer(aBuilder
, aOther
),
6155 mAnimatedGeometryRootForScrollMetadata(
6156 aOther
.mAnimatedGeometryRootForScrollMetadata
),
6157 mContainerASR(aOther
.mContainerASR
),
6158 mIsFixedBackground(aOther
.mIsFixedBackground
) {
6159 MOZ_COUNT_CTOR(nsDisplayFixedPosition
);
6162 static nsDisplayFixedPosition
* CreateForFixedBackground(
6163 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6164 nsIFrame
* aSecondaryFrame
, nsDisplayBackgroundImage
* aImage
,
6165 const uint16_t aIndex
);
6167 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFixedPosition
)
6169 NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION
)
6171 already_AddRefed
<Layer
> BuildLayer(
6172 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6173 const ContainerLayerParameters
& aContainerParameters
) override
;
6175 LayerState
GetLayerState(
6176 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6177 const ContainerLayerParameters
& aParameters
) override
{
6178 return mozilla::LayerState::LAYER_ACTIVE_FORCE
;
6180 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6181 GetChildren()->Paint(aBuilder
, aCtx
,
6182 mFrame
->PresContext()->AppUnitsPerDevPixel());
6185 bool ShouldFixToViewport(nsDisplayListBuilder
* aBuilder
) const override
{
6186 return mIsFixedBackground
;
6189 AnimatedGeometryRoot
* AnimatedGeometryRootForScrollMetadata() const override
{
6190 return mAnimatedGeometryRootForScrollMetadata
;
6193 bool CreateWebRenderCommands(
6194 mozilla::wr::DisplayListBuilder
& aBuilder
,
6195 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6196 const StackingContextHelper
& aSc
,
6197 mozilla::layers::RenderRootStateManager
* aManager
,
6198 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6199 bool UpdateScrollData(
6200 mozilla::layers::WebRenderScrollData
* aData
,
6201 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6202 void WriteDebugInfo(std::stringstream
& aStream
) override
;
6205 // For background-attachment:fixed
6206 nsDisplayFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6207 nsDisplayList
* aList
);
6208 void Init(nsDisplayListBuilder
* aBuilder
);
6209 ViewID
GetScrollTargetId();
6211 RefPtr
<AnimatedGeometryRoot
> mAnimatedGeometryRootForScrollMetadata
;
6212 RefPtr
<const ActiveScrolledRoot
> mContainerASR
;
6213 bool mIsFixedBackground
;
6216 NS_DISPLAY_ALLOW_CLONING()
6219 class nsDisplayTableFixedPosition
: public nsDisplayFixedPosition
{
6221 NS_DISPLAY_DECL_NAME("TableFixedPosition", TYPE_TABLE_FIXED_POSITION
)
6223 nsIFrame
* FrameForInvalidation() const override
{ return mAncestorFrame
; }
6225 void RemoveFrame(nsIFrame
* aFrame
) override
{
6226 if (aFrame
== mAncestorFrame
) {
6227 mAncestorFrame
= nullptr;
6230 nsDisplayFixedPosition::RemoveFrame(aFrame
);
6234 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6235 nsDisplayList
* aList
, nsIFrame
* aAncestorFrame
);
6237 nsDisplayTableFixedPosition(nsDisplayListBuilder
* aBuilder
,
6238 const nsDisplayTableFixedPosition
& aOther
)
6239 : nsDisplayFixedPosition(aBuilder
, aOther
),
6240 mAncestorFrame(aOther
.mAncestorFrame
) {}
6242 ~nsDisplayTableFixedPosition() override
{
6243 if (mAncestorFrame
) {
6244 mAncestorFrame
->RemoveDisplayItem(this);
6248 nsIFrame
* mAncestorFrame
;
6251 NS_DISPLAY_ALLOW_CLONING()
6255 * This creates an empty scrollable layer. It has no child layers.
6256 * It is used to record the existence of a scrollable frame in the layer
6259 class nsDisplayScrollInfoLayer
: public nsDisplayWrapList
{
6261 nsDisplayScrollInfoLayer(nsDisplayListBuilder
* aBuilder
,
6262 nsIFrame
* aScrolledFrame
, nsIFrame
* aScrollFrame
,
6263 const CompositorHitTestInfo
& aHitInfo
,
6264 const nsRect
& aHitArea
);
6266 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayScrollInfoLayer
)
6268 NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER
)
6270 already_AddRefed
<Layer
> BuildLayer(
6271 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6272 const ContainerLayerParameters
& aContainerParameters
) override
;
6274 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6275 bool* aSnap
) const override
{
6280 LayerState
GetLayerState(
6281 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6282 const ContainerLayerParameters
& aParameters
) override
;
6283 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
6287 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6291 void WriteDebugInfo(std::stringstream
& aStream
) override
;
6292 mozilla::UniquePtr
<ScrollMetadata
> ComputeScrollMetadata(
6293 nsDisplayListBuilder
* aBuilder
, LayerManager
* aLayerManager
,
6294 const ContainerLayerParameters
& aContainerParameters
);
6295 bool UpdateScrollData(
6296 mozilla::layers::WebRenderScrollData
* aData
,
6297 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6298 bool CreateWebRenderCommands(
6299 mozilla::wr::DisplayListBuilder
& aBuilder
,
6300 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6301 const StackingContextHelper
& aSc
,
6302 mozilla::layers::RenderRootStateManager
* aManager
,
6303 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6306 nsIFrame
* mScrollFrame
;
6307 nsIFrame
* mScrolledFrame
;
6308 ViewID mScrollParentId
;
6309 CompositorHitTestInfo mHitInfo
;
6314 * nsDisplayZoom is used for subdocuments that have a different full zoom than
6315 * their parent documents. This item creates a container layer.
6317 class nsDisplayZoom
: public nsDisplaySubDocument
{
6320 * @param aFrame is the root frame of the subdocument.
6321 * @param aList contains the display items for the subdocument.
6322 * @param aAPD is the app units per dev pixel ratio of the subdocument.
6323 * @param aParentAPD is the app units per dev pixel ratio of the parent
6325 * @param aFlags eGenerateSubdocInvalidations :
6326 * Add UserData to the created ContainerLayer, so that invalidations
6327 * for this layer are send to our nsPresContext.
6329 nsDisplayZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6330 nsSubDocumentFrame
* aSubDocFrame
, nsDisplayList
* aList
,
6331 int32_t aAPD
, int32_t aParentAPD
,
6332 nsDisplayOwnLayerFlags aFlags
= nsDisplayOwnLayerFlags::None
);
6334 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayZoom
)
6336 NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM
)
6338 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6339 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6340 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6341 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6342 nsRegion
* aVisibleRegion
) override
;
6343 LayerState
GetLayerState(
6344 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6345 const ContainerLayerParameters
& aParameters
) override
{
6346 return mozilla::LayerState::LAYER_ACTIVE
;
6349 // Get the app units per dev pixel ratio of the child document.
6350 int32_t GetChildAppUnitsPerDevPixel() { return mAPD
; }
6351 // Get the app units per dev pixel ratio of the parent document.
6352 int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD
; }
6355 int32_t mAPD
, mParentAPD
;
6359 * nsDisplayAsyncZoom is used for APZ zooming. It wraps the contents of the
6360 * root content document's scroll frame, including fixed position content. It
6361 * does not contain the scroll frame's scrollbars. It is clipped to the scroll
6362 * frame's scroll port clip. It is not scrolled; only its non-fixed contents
6363 * are scrolled. This item creates a container layer.
6365 class nsDisplayAsyncZoom
: public nsDisplayOwnLayer
{
6367 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6368 nsDisplayList
* aList
,
6369 const ActiveScrolledRoot
* aActiveScrolledRoot
,
6370 mozilla::layers::FrameMetrics::ViewID aViewID
);
6371 nsDisplayAsyncZoom(nsDisplayListBuilder
* aBuilder
,
6372 const nsDisplayAsyncZoom
& aOther
)
6373 : nsDisplayOwnLayer(aBuilder
, aOther
), mViewID(aOther
.mViewID
) {
6374 MOZ_COUNT_CTOR(nsDisplayAsyncZoom
);
6377 #ifdef NS_BUILD_REFCNT_LOGGING
6378 virtual ~nsDisplayAsyncZoom();
6381 NS_DISPLAY_DECL_NAME("AsyncZoom", TYPE_ASYNC_ZOOM
)
6383 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6384 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6385 already_AddRefed
<Layer
> BuildLayer(
6386 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6387 const ContainerLayerParameters
& aContainerParameters
) override
;
6388 LayerState
GetLayerState(
6389 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6390 const ContainerLayerParameters
& aParameters
) override
{
6391 return mozilla::LayerState::LAYER_ACTIVE_FORCE
;
6393 bool UpdateScrollData(
6394 mozilla::layers::WebRenderScrollData
* aData
,
6395 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6398 mozilla::layers::FrameMetrics::ViewID mViewID
;
6402 * A base class for different effects types.
6404 class nsDisplayEffectsBase
: public nsDisplayWrapList
{
6406 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6407 nsDisplayList
* aList
,
6408 const ActiveScrolledRoot
* aActiveScrolledRoot
,
6409 bool aClearClipChain
= false);
6410 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6411 nsDisplayList
* aList
);
6413 nsDisplayEffectsBase(nsDisplayListBuilder
* aBuilder
,
6414 const nsDisplayEffectsBase
& aOther
)
6415 : nsDisplayWrapList(aBuilder
, aOther
),
6416 mEffectsBounds(aOther
.mEffectsBounds
),
6417 mHandleOpacity(aOther
.mHandleOpacity
) {
6418 MOZ_COUNT_CTOR(nsDisplayEffectsBase
);
6421 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayEffectsBase
)
6423 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6424 bool* aSnap
) const override
;
6425 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6426 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6428 bool RestoreState() override
{
6429 if (!nsDisplayWrapList::RestoreState() && !mHandleOpacity
) {
6433 mHandleOpacity
= false;
6437 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6441 virtual void SelectOpacityOptimization(const bool /* aUsingLayers */) {
6445 bool ShouldHandleOpacity() const { return mHandleOpacity
; }
6447 gfxRect
BBoxInUserSpace() const;
6448 gfxPoint
UserSpaceOffset() const;
6450 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6451 const nsDisplayItemGeometry
* aGeometry
,
6452 nsRegion
* aInvalidRegion
) const override
;
6455 void SetHandleOpacity() { mHandleOpacity
= true; }
6456 bool ValidateSVGFrame();
6458 // relative to mFrame
6459 nsRect mEffectsBounds
;
6460 // True if we need to handle css opacity in this display item.
6461 bool mHandleOpacity
;
6465 * A display item to paint a stacking context with 'mask' and 'clip-path'
6466 * effects set by the stacking context root frame's style. The 'mask' and
6467 * 'clip-path' properties may both contain multiple masks and clip paths,
6470 * Note that 'mask' and 'clip-path' may just contain CSS simple-images and CSS
6471 * basic shapes, respectively. That is, they don't necessarily reference
6472 * resources such as SVG 'mask' and 'clipPath' elements.
6474 class nsDisplayMasksAndClipPaths
: public nsDisplayEffectsBase
{
6476 typedef mozilla::layers::ImageLayer ImageLayer
;
6478 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6479 nsDisplayList
* aList
,
6480 const ActiveScrolledRoot
* aActiveScrolledRoot
);
6481 nsDisplayMasksAndClipPaths(nsDisplayListBuilder
* aBuilder
,
6482 const nsDisplayMasksAndClipPaths
& aOther
)
6483 : nsDisplayEffectsBase(aBuilder
, aOther
),
6484 mDestRects(aOther
.mDestRects
.Clone()) {
6485 MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths
);
6488 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayMasksAndClipPaths
)
6490 NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK
)
6492 bool CanMerge(const nsDisplayItem
* aItem
) const override
;
6494 void Merge(const nsDisplayItem
* aItem
) override
{
6495 nsDisplayWrapList::Merge(aItem
);
6497 const nsDisplayMasksAndClipPaths
* other
=
6498 static_cast<const nsDisplayMasksAndClipPaths
*>(aItem
);
6499 mEffectsBounds
.UnionRect(
6501 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
6504 already_AddRefed
<Layer
> BuildLayer(
6505 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6506 const ContainerLayerParameters
& aContainerParameters
) override
;
6507 LayerState
GetLayerState(
6508 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6509 const ContainerLayerParameters
& aParameters
) override
;
6510 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6511 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6512 nsRegion
* aVisibleRegion
) override
;
6514 nsDisplayItemGeometry
* AllocateGeometry(
6515 nsDisplayListBuilder
* aBuilder
) override
{
6516 return new nsDisplayMasksAndClipPathsGeometry(this, aBuilder
);
6519 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6520 const nsDisplayItemGeometry
* aGeometry
,
6521 nsRegion
* aInvalidRegion
) const override
;
6522 #ifdef MOZ_DUMP_PAINTING
6523 void PrintEffects(nsACString
& aTo
);
6528 void PaintAsLayer(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6529 LayerManager
* aManager
);
6531 void PaintWithContentsPaintCallback(
6532 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6533 const std::function
<void()>& aPaintChildren
);
6536 * Paint mask onto aMaskContext in mFrame's coordinate space and
6537 * return whether the mask layer was painted successfully.
6539 bool PaintMask(nsDisplayListBuilder
* aBuilder
, gfxContext
* aMaskContext
,
6540 bool* aMaskPainted
= nullptr);
6542 const nsTArray
<nsRect
>& GetDestRects() { return mDestRects
; }
6544 void SelectOpacityOptimization(const bool aUsingLayers
) override
;
6546 bool CreateWebRenderCommands(
6547 mozilla::wr::DisplayListBuilder
& aBuilder
,
6548 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6549 const StackingContextHelper
& aSc
,
6550 mozilla::layers::RenderRootStateManager
* aManager
,
6551 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6553 mozilla::Maybe
<nsRect
> GetClipWithRespectToASR(
6554 nsDisplayListBuilder
* aBuilder
,
6555 const ActiveScrolledRoot
* aASR
) const override
;
6558 NS_DISPLAY_ALLOW_CLONING()
6560 // According to mask property and the capability of aManager, determine
6561 // whether we can paint the mask onto a dedicate mask layer.
6562 bool CanPaintOnMaskLayer(LayerManager
* aManager
);
6564 nsTArray
<nsRect
> mDestRects
;
6565 bool mApplyOpacityWithSimpleClipPath
;
6568 class nsDisplayBackdropRootContainer
: public nsDisplayWrapList
{
6570 nsDisplayBackdropRootContainer(nsDisplayListBuilder
* aBuilder
,
6571 nsIFrame
* aFrame
, nsDisplayList
* aList
,
6572 const ActiveScrolledRoot
* aActiveScrolledRoot
)
6573 : nsDisplayWrapList(aBuilder
, aFrame
, aList
, aActiveScrolledRoot
, true) {
6574 MOZ_COUNT_CTOR(nsDisplayBackdropRootContainer
);
6577 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropRootContainer
)
6579 NS_DISPLAY_DECL_NAME("BackdropRootContainer", TYPE_BACKDROP_ROOT_CONTAINER
)
6581 already_AddRefed
<Layer
> BuildLayer(
6582 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6583 const ContainerLayerParameters
& aContainerParameters
) override
;
6584 LayerState
GetLayerState(
6585 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6586 const ContainerLayerParameters
& aParameters
) override
;
6587 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6589 bool CreateWebRenderCommands(
6590 mozilla::wr::DisplayListBuilder
& aBuilder
,
6591 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6592 const StackingContextHelper
& aSc
,
6593 mozilla::layers::RenderRootStateManager
* aManager
,
6594 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6596 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6597 return !aBuilder
->IsPaintingForWebRender();
6601 class nsDisplayBackdropFilters
: public nsDisplayWrapList
{
6603 nsDisplayBackdropFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6604 nsDisplayList
* aList
, const nsRect
& aBackdropRect
)
6605 : nsDisplayWrapList(aBuilder
, aFrame
, aList
),
6606 mBackdropRect(aBackdropRect
) {
6607 MOZ_COUNT_CTOR(nsDisplayBackdropFilters
);
6610 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropFilters
)
6612 NS_DISPLAY_DECL_NAME("BackdropFilter", TYPE_BACKDROP_FILTER
)
6614 bool CreateWebRenderCommands(
6615 mozilla::wr::DisplayListBuilder
& aBuilder
,
6616 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6617 const StackingContextHelper
& aSc
,
6618 mozilla::layers::RenderRootStateManager
* aManager
,
6619 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6620 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6622 static bool CanCreateWebRenderCommands(nsDisplayListBuilder
* aBuilder
,
6625 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
{
6626 return !aBuilder
->IsPaintingForWebRender();
6630 nsRect mBackdropRect
;
6634 * A display item to paint a stacking context with filter effects set by the
6635 * stacking context root frame's style.
6637 * Note that the filters may just be simple CSS filter functions. That is,
6638 * they won't necessarily be references to SVG 'filter' elements.
6640 class nsDisplayFilters
: public nsDisplayEffectsBase
{
6642 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6643 nsDisplayList
* aList
);
6645 nsDisplayFilters(nsDisplayListBuilder
* aBuilder
,
6646 const nsDisplayFilters
& aOther
)
6647 : nsDisplayEffectsBase(aBuilder
, aOther
),
6648 mEffectsBounds(aOther
.mEffectsBounds
) {
6649 MOZ_COUNT_CTOR(nsDisplayFilters
);
6652 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFilters
)
6654 NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER
)
6656 bool CanMerge(const nsDisplayItem
* aItem
) const override
{
6657 // Items for the same content element should be merged into a single
6658 // compositing group.
6659 return HasDifferentFrame(aItem
) && HasSameTypeAndClip(aItem
) &&
6660 HasSameContent(aItem
);
6663 void Merge(const nsDisplayItem
* aItem
) override
{
6664 nsDisplayWrapList::Merge(aItem
);
6666 const nsDisplayFilters
* other
= static_cast<const nsDisplayFilters
*>(aItem
);
6667 mEffectsBounds
.UnionRect(
6669 other
->mEffectsBounds
+ other
->mFrame
->GetOffsetTo(mFrame
));
6672 already_AddRefed
<Layer
> BuildLayer(
6673 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6674 const ContainerLayerParameters
& aContainerParameters
) override
;
6675 LayerState
GetLayerState(
6676 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6677 const ContainerLayerParameters
& aParameters
) override
;
6678 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6680 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
6682 return mEffectsBounds
+ ToReferenceFrame();
6685 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6686 nsRegion
* aVisibleRegion
) override
;
6688 nsDisplayItemGeometry
* AllocateGeometry(
6689 nsDisplayListBuilder
* aBuilder
) override
{
6690 return new nsDisplayFiltersGeometry(this, aBuilder
);
6693 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6694 const nsDisplayItemGeometry
* aGeometry
,
6695 nsRegion
* aInvalidRegion
) const override
;
6696 #ifdef MOZ_DUMP_PAINTING
6697 void PrintEffects(nsACString
& aTo
);
6700 void PaintAsLayer(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6701 LayerManager
* aManager
);
6703 void PaintWithContentsPaintCallback(
6704 nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6705 const std::function
<void(gfxContext
* aContext
)>& aPaintChildren
);
6707 bool CreateWebRenderCommands(
6708 mozilla::wr::DisplayListBuilder
& aBuilder
,
6709 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6710 const StackingContextHelper
& aSc
,
6711 mozilla::layers::RenderRootStateManager
* aManager
,
6712 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6713 bool CanCreateWebRenderCommands();
6716 NS_DISPLAY_ALLOW_CLONING()
6718 // relative to mFrame
6719 nsRect mEffectsBounds
;
6722 /* A display item that applies a transformation to all of its descendant
6723 * elements. This wrapper should only be used if there is a transform applied
6724 * to the root element.
6726 * The reason that a "bounds" rect is involved in transform calculations is
6727 * because CSS-transforms allow percentage values for the x and y components
6728 * of <translation-value>s, where percentages are percentages of the element's
6731 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
6733 * INVARIANT: The wrapped frame is non-null.
6735 class nsDisplayTransform
: public nsPaintedDisplayItem
{
6736 using Matrix4x4
= mozilla::gfx::Matrix4x4
;
6737 using Matrix4x4Flagged
= mozilla::gfx::Matrix4x4Flagged
;
6738 using Point3D
= mozilla::gfx::Point3D
;
6739 using TransformReferenceBox
= nsStyleTransformMatrix::TransformReferenceBox
;
6742 enum class PrerenderDecision
: uint8_t { No
, Full
, Partial
};
6745 WithTransformGetter
,
6748 /* Constructor accepts a display list, empties it, and wraps it up. It also
6749 * ferries the underlying frame to the nsDisplayItem constructor.
6751 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6752 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
);
6754 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6755 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6756 PrerenderDecision aPrerenderDecision
);
6758 nsDisplayTransform(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
6759 nsDisplayList
* aList
, const nsRect
& aChildrenBuildingRect
,
6760 decltype(WithTransformGetter
));
6762 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayTransform
)
6764 NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM
)
6766 bool RestoreState() override
{
6767 if (!nsPaintedDisplayItem::RestoreState() && !mShouldFlatten
) {
6771 mShouldFlatten
= false;
6775 void UpdateBounds(nsDisplayListBuilder
* aBuilder
) override
;
6778 * This function updates bounds for items with a frame establishing
6779 * 3D rendering context.
6781 void UpdateBoundsFor3D(nsDisplayListBuilder
* aBuilder
);
6783 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
;
6785 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
6786 GetChildren()->DeleteAll(aBuilder
);
6787 nsPaintedDisplayItem::Destroy(aBuilder
);
6790 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const override
;
6792 RetainedDisplayList
* GetChildren() const override
{ return &mChildren
; }
6794 nsRect
GetUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
6795 bool* aSnap
) const override
{
6797 return mChildBounds
;
6800 const nsRect
& GetUntransformedPaintRect() const override
{
6801 return mChildrenBuildingRect
;
6804 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
6806 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6807 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
;
6808 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
;
6809 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
6810 bool* aSnap
) const override
;
6811 LayerState
GetLayerState(
6812 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6813 const ContainerLayerParameters
& aParameters
) override
;
6814 already_AddRefed
<Layer
> BuildLayer(
6815 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
6816 const ContainerLayerParameters
& aContainerParameters
) override
;
6817 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
6818 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
,
6819 const mozilla::Maybe
<mozilla::gfx::Polygon
>& aPolygon
);
6820 bool CreateWebRenderCommands(
6821 mozilla::wr::DisplayListBuilder
& aBuilder
,
6822 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
6823 const StackingContextHelper
& aSc
,
6824 mozilla::layers::RenderRootStateManager
* aManager
,
6825 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
6826 bool UpdateScrollData(
6827 mozilla::layers::WebRenderScrollData
* aData
,
6828 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) override
;
6829 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
6830 nsRegion
* aVisibleRegion
) override
;
6832 nsDisplayItemGeometry
* AllocateGeometry(
6833 nsDisplayListBuilder
* aBuilder
) override
{
6834 return new nsDisplayTransformGeometry(
6835 this, aBuilder
, GetTransformForRendering(),
6836 mFrame
->PresContext()->AppUnitsPerDevPixel());
6839 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
6840 const nsDisplayItemGeometry
* aGeometry
,
6841 nsRegion
* aInvalidRegion
) const override
{
6842 const nsDisplayTransformGeometry
* geometry
=
6843 static_cast<const nsDisplayTransformGeometry
*>(aGeometry
);
6845 // This code is only called for flattened, inactive transform items.
6846 // Only check if the transform has changed. The bounds invalidation should
6847 // be handled by the children themselves.
6848 if (!geometry
->mTransform
.FuzzyEqual(GetTransformForRendering())) {
6850 aInvalidRegion
->Or(GetBounds(aBuilder
, &snap
), geometry
->mBounds
);
6854 bool NeedsGeometryUpdates() const override
{ return mShouldFlatten
; }
6856 const nsIFrame
* ReferenceFrameForChildren() const override
{
6857 // If we were created using a transform-getter, then we don't
6858 // belong to a transformed frame, and aren't a reference frame
6859 // for our children.
6860 if (!mHasTransformGetter
) {
6863 return nsPaintedDisplayItem::ReferenceFrameForChildren();
6866 AnimatedGeometryRoot
* AnimatedGeometryRootForScrollMetadata() const override
{
6867 return mAnimatedGeometryRootForScrollMetadata
;
6870 const nsRect
& GetBuildingRectForChildren() const override
{
6871 return mChildrenBuildingRect
;
6874 enum { INDEX_MAX
= UINT32_MAX
>> TYPE_BITS
};
6877 * We include the perspective matrix from our containing block for the
6878 * purposes of visibility calculations, but we exclude it from the transform
6879 * we set on the layer (for rendering), since there will be an
6880 * nsDisplayPerspective created for that.
6882 const Matrix4x4Flagged
& GetTransform() const;
6883 const Matrix4x4Flagged
& GetInverseTransform() const;
6885 bool ShouldSkipTransform(nsDisplayListBuilder
* aBuilder
) const;
6886 Matrix4x4
GetTransformForRendering(
6887 mozilla::LayoutDevicePoint
* aOutOrigin
= nullptr) const;
6890 * Return the transform that is aggregation of all transform on the
6891 * preserves3d chain.
6893 const Matrix4x4
& GetAccumulatedPreserved3DTransform(
6894 nsDisplayListBuilder
* aBuilder
);
6896 float GetHitDepthAtPoint(nsDisplayListBuilder
* aBuilder
,
6897 const nsPoint
& aPoint
);
6900 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
6901 * space) and returns the smallest rectangle (in aFrame's coordinate space)
6902 * containing the transformed image of that rectangle. That is, it takes
6903 * the four corners of the rectangle, transforms them according to the
6904 * matrix associated with the specified frame, then returns the smallest
6905 * rectangle containing the four transformed points.
6907 * @param untransformedBounds The rectangle (in app units) to transform.
6908 * @param aFrame The frame whose transformation should be applied. This
6909 * function raises an assertion if aFrame is null or doesn't have a
6910 * transform applied to it.
6911 * @param aRefBox the reference box to use, which would usually be just
6912 * TransformReferemceBox(aFrame), but callers may override it if
6915 static nsRect
TransformRect(const nsRect
& aUntransformedBounds
,
6916 const nsIFrame
* aFrame
,
6917 TransformReferenceBox
& aRefBox
);
6919 /* UntransformRect is like TransformRect, except that it inverts the
6922 static bool UntransformRect(const nsRect
& aTransformedBounds
,
6923 const nsRect
& aChildBounds
,
6924 const nsIFrame
* aFrame
, nsRect
* aOutRect
);
6926 bool UntransformRect(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
6927 nsRect
* aOutRect
) const;
6929 bool UntransformBuildingRect(nsDisplayListBuilder
* aBuilder
,
6930 nsRect
* aOutRect
) const {
6931 return UntransformRect(aBuilder
, GetBuildingRect(), aOutRect
);
6934 bool UntransformPaintRect(nsDisplayListBuilder
* aBuilder
,
6935 nsRect
* aOutRect
) const {
6936 return UntransformRect(aBuilder
, GetPaintRect(), aOutRect
);
6939 static Point3D
GetDeltaToTransformOrigin(const nsIFrame
* aFrame
,
6940 TransformReferenceBox
&,
6941 float aAppUnitsPerPixel
);
6944 * Returns true if aFrame has perspective applied from its containing
6946 * Returns the matrix to append to apply the persective (taking
6947 * perspective-origin into account), relative to aFrames coordinate
6949 * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
6952 static bool ComputePerspectiveMatrix(const nsIFrame
* aFrame
,
6953 float aAppUnitsPerPixel
,
6954 Matrix4x4
& aOutMatrix
);
6956 struct MOZ_STACK_CLASS FrameTransformProperties
{
6957 FrameTransformProperties(const nsIFrame
* aFrame
,
6958 TransformReferenceBox
& aRefBox
,
6959 float aAppUnitsPerPixel
);
6960 FrameTransformProperties(
6961 const mozilla::StyleTranslate
& aTranslate
,
6962 const mozilla::StyleRotate
& aRotate
, const mozilla::StyleScale
& aScale
,
6963 const mozilla::StyleTransform
& aTransform
,
6964 const mozilla::Maybe
<mozilla::ResolvedMotionPathData
>& aMotion
,
6965 const Point3D
& aToTransformOrigin
)
6967 mTranslate(aTranslate
),
6970 mTransform(aTransform
),
6972 mToTransformOrigin(aToTransformOrigin
) {}
6974 bool HasTransform() const {
6975 return !mTranslate
.IsNone() || !mRotate
.IsNone() || !mScale
.IsNone() ||
6976 !mTransform
.IsNone() || mMotion
.isSome();
6979 const nsIFrame
* mFrame
;
6980 const mozilla::StyleTranslate
& mTranslate
;
6981 const mozilla::StyleRotate
& mRotate
;
6982 const mozilla::StyleScale
& mScale
;
6983 const mozilla::StyleTransform
& mTransform
;
6984 const mozilla::Maybe
<mozilla::ResolvedMotionPathData
> mMotion
;
6985 const Point3D mToTransformOrigin
;
6989 * Given a frame with the transform property or an SVG transform,
6990 * returns the transformation matrix for that frame.
6992 * @param aFrame The frame to get the matrix from.
6993 * @param aOrigin Relative to which point this transform should be applied.
6994 * @param aAppUnitsPerPixel The number of app units per graphics unit.
6995 * @param aBoundsOverride [optional] If this is nullptr (the default), the
6996 * computation will use the value of TransformReferenceBox(aFrame).
6997 * Otherwise, it will use the value of aBoundsOverride. This is
6998 * mostly for internal use and in most cases you will not need to
7000 * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
7001 * by aOrigin. This translation is applied *before* the CSS transform.
7002 * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
7003 * include the transform of any ancestors participating in the same
7004 * 3d rendering context.
7005 * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
7006 * perspective transform from the containing block if applicable.
7009 OFFSET_BY_ORIGIN
= 1 << 0,
7010 INCLUDE_PRESERVE3D_ANCESTORS
= 1 << 1,
7011 INCLUDE_PERSPECTIVE
= 1 << 2,
7013 static Matrix4x4
GetResultingTransformMatrix(const nsIFrame
* aFrame
,
7014 const nsPoint
& aOrigin
,
7015 float aAppUnitsPerPixel
,
7017 static Matrix4x4
GetResultingTransformMatrix(
7018 const FrameTransformProperties
& aProperties
, TransformReferenceBox
&,
7019 float aAppUnitsPerPixel
);
7021 struct PrerenderInfo
{
7022 bool CanUseAsyncAnimations() const {
7023 return mDecision
!= PrerenderDecision::No
&& mHasAnimations
;
7025 PrerenderDecision mDecision
= PrerenderDecision::No
;
7026 bool mHasAnimations
= true;
7029 * Decide whether we should prerender some or all of the contents of the
7030 * transformed frame even when it's not completely visible (yet).
7031 * Return PrerenderDecision::Full if the entire contents should be
7032 * prerendered, PrerenderDecision::Partial if some but not all of the
7033 * contents should be prerendered, or PrerenderDecision::No if only the
7034 * visible area should be rendered.
7035 * |mNoAffectDecisionInPreserve3D| is set if the prerender decision should not
7036 * affect the decision on other frames in the preserve 3d tree.
7037 * |aDirtyRect| is updated to the area that should be prerendered.
7039 static PrerenderInfo
ShouldPrerenderTransformedContent(
7040 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, nsRect
* aDirtyRect
);
7042 bool CanUseAsyncAnimations(nsDisplayListBuilder
* aBuilder
) override
;
7044 bool MayBeAnimated(nsDisplayListBuilder
* aBuilder
,
7045 bool aEnforceMinimumSize
= true) const;
7047 void WriteDebugInfo(std::stringstream
& aStream
) override
;
7050 * This item is an additional item as the boundary between parent
7051 * and child 3D rendering context.
7052 * \see nsIFrame::BuildDisplayListForStackingContext().
7054 bool IsTransformSeparator() const { return mIsTransformSeparator
; }
7056 * This item is the boundary between parent and child 3D rendering
7059 bool IsLeafOf3DContext() const {
7060 return (IsTransformSeparator() ||
7061 (!mFrame
->Extend3DContext() && Combines3DTransformWithAncestors()));
7064 * The backing frame of this item participates a 3D rendering
7067 bool IsParticipating3DContext() const {
7068 return mFrame
->Extend3DContext() || Combines3DTransformWithAncestors();
7071 bool IsPartialPrerender() const {
7072 return mPrerenderDecision
== PrerenderDecision::Partial
;
7075 void AddSizeOfExcludingThis(nsWindowSizes
&) const override
;
7078 void ComputeBounds(nsDisplayListBuilder
* aBuilder
);
7079 nsRect
TransformUntransformedBounds(nsDisplayListBuilder
* aBuilder
,
7080 const Matrix4x4Flagged
& aMatrix
) const;
7081 void UpdateUntransformedBounds(nsDisplayListBuilder
* aBuilder
);
7083 void SetReferenceFrameToAncestor(nsDisplayListBuilder
* aBuilder
);
7084 void Init(nsDisplayListBuilder
* aBuilder
, nsDisplayList
* aChildren
);
7086 static Matrix4x4
GetResultingTransformMatrixInternal(
7087 const FrameTransformProperties
& aProperties
,
7088 TransformReferenceBox
& aRefBox
, const nsPoint
& aOrigin
,
7089 float aAppUnitsPerPixel
, uint32_t aFlags
);
7091 void Collect3DTransformLeaves(nsTArray
<nsDisplayTransform
*>& aLeaves
);
7092 using TransformPolygon
= mozilla::layers::BSPPolygon
<nsDisplayTransform
>;
7093 void CollectSorted3DTransformLeaves(nsDisplayListBuilder
* aBuilder
,
7094 nsTArray
<TransformPolygon
>& aLeaves
);
7096 mutable mozilla::Maybe
<Matrix4x4Flagged
> mTransform
;
7097 mutable mozilla::Maybe
<Matrix4x4Flagged
> mInverseTransform
;
7098 // Accumulated transform of ancestors on the preserves-3d chain.
7099 mozilla::UniquePtr
<Matrix4x4
> mTransformPreserves3D
;
7100 RefPtr
<AnimatedGeometryRoot
> mAnimatedGeometryRootForChildren
;
7101 RefPtr
<AnimatedGeometryRoot
> mAnimatedGeometryRootForScrollMetadata
;
7102 nsRect mChildrenBuildingRect
;
7103 mutable RetainedDisplayList mChildren
;
7105 // The untransformed bounds of |mChildren|.
7106 nsRect mChildBounds
;
7107 // The transformed bounds of this display item.
7109 PrerenderDecision mPrerenderDecision
: 8;
7110 // This item is a separator between 3D rendering contexts, and
7111 // mTransform have been presetted by the constructor.
7112 // This also forces us not to extend the 3D context. Since we don't create a
7113 // transform item, a container layer, for every frame in a preserves3d
7114 // context, the transform items of a child preserves3d context may extend the
7115 // parent context unintendedly if the root of the child preserves3d context
7116 // doesn't create a transform item.
7117 bool mIsTransformSeparator
: 1;
7118 // True if this nsDisplayTransform should get flattened
7119 bool mShouldFlatten
: 1;
7120 // True if we have a transform getter.
7121 bool mHasTransformGetter
: 1;
7124 /* A display item that applies a perspective transformation to a single
7125 * nsDisplayTransform child item. We keep this as a separate item since the
7126 * perspective-origin is relative to an ancestor of the transformed frame, and
7127 * APZ can scroll the child separately.
7129 class nsDisplayPerspective
: public nsPaintedDisplayItem
{
7130 typedef mozilla::gfx::Point3D Point3D
;
7133 nsDisplayPerspective(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
7134 nsDisplayList
* aList
);
7135 ~nsDisplayPerspective() override
= default;
7137 NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE
)
7139 void Destroy(nsDisplayListBuilder
* aBuilder
) override
{
7140 mList
.DeleteAll(aBuilder
);
7141 nsPaintedDisplayItem::Destroy(aBuilder
);
7144 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
7145 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) override
{
7146 return GetChildren()->HitTest(aBuilder
, aRect
, aState
, aOutFrames
);
7149 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const override
{
7151 return GetChildren()->GetClippedBoundsWithRespectToASR(aBuilder
,
7152 mActiveScrolledRoot
);
7155 bool ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
7156 nsRegion
* aVisibleRegion
) override
;
7158 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
7159 const nsDisplayItemGeometry
* aGeometry
,
7160 nsRegion
* aInvalidRegion
) const override
{}
7162 nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
7163 bool* aSnap
) const override
;
7165 LayerState
GetLayerState(
7166 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7167 const ContainerLayerParameters
& aParameters
) override
;
7168 bool CreateWebRenderCommands(
7169 mozilla::wr::DisplayListBuilder
& aBuilder
,
7170 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
7171 const StackingContextHelper
& aSc
,
7172 mozilla::layers::RenderRootStateManager
* aManager
,
7173 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
7175 already_AddRefed
<Layer
> BuildLayer(
7176 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7177 const ContainerLayerParameters
& aContainerParameters
) override
;
7178 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
7180 RetainedDisplayList
* GetSameCoordinateSystemChildren() const override
{
7184 RetainedDisplayList
* GetChildren() const override
{ return &mList
; }
7186 nsRect
GetComponentAlphaBounds(
7187 nsDisplayListBuilder
* aBuilder
) const override
{
7188 return GetChildren()->GetComponentAlphaBounds(aBuilder
);
7191 void DoUpdateBoundsPreserves3D(nsDisplayListBuilder
* aBuilder
) override
{
7192 if (GetChildren()->GetTop()) {
7193 static_cast<nsDisplayTransform
*>(GetChildren()->GetTop())
7194 ->DoUpdateBoundsPreserves3D(aBuilder
);
7199 mutable RetainedDisplayList mList
;
7203 * This class adds basic support for limiting the rendering (in the inline axis
7204 * of the writing mode) to the part inside the specified edges.
7205 * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
7206 * of the frame's scrollable overflow rectangle and are the amount to suppress
7209 * Setting none, both or only one edge is allowed.
7210 * The values must be non-negative.
7211 * The default value for both edges is zero, which means everything is painted.
7213 class nsDisplayText final
: public nsPaintedDisplayItem
{
7215 nsDisplayText(nsDisplayListBuilder
* aBuilder
, nsTextFrame
* aFrame
);
7216 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayText
)
7218 NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT
)
7220 bool RestoreState() final
{
7221 if (!nsPaintedDisplayItem::RestoreState() && mOpacity
== 1.0f
) {
7229 nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
) const final
{
7234 void HitTest(nsDisplayListBuilder
* aBuilder
, const nsRect
& aRect
,
7235 HitTestState
* aState
, nsTArray
<nsIFrame
*>* aOutFrames
) final
{
7236 if (nsRect(ToReferenceFrame(), mFrame
->GetSize()).Intersects(aRect
)) {
7237 aOutFrames
->AppendElement(mFrame
);
7241 bool CreateWebRenderCommands(
7242 mozilla::wr::DisplayListBuilder
& aBuilder
,
7243 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
7244 const StackingContextHelper
& aSc
,
7245 mozilla::layers::RenderRootStateManager
* aManager
,
7246 nsDisplayListBuilder
* aDisplayListBuilder
) final
;
7247 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) final
;
7249 nsRect
GetComponentAlphaBounds(nsDisplayListBuilder
* aBuilder
) const final
{
7250 if (gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()) {
7251 // On OS X, web authors can turn off subpixel text rendering using the
7252 // CSS property -moz-osx-font-smoothing. If they do that, we don't need
7253 // to use component alpha layers for the affected text.
7254 if (mFrame
->StyleFont()->mFont
.smoothing
== NS_FONT_SMOOTHING_GRAYSCALE
) {
7259 return GetBounds(aBuilder
, &snap
);
7262 nsDisplayItemGeometry
* AllocateGeometry(nsDisplayListBuilder
* aBuilder
) final
;
7264 void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
7265 const nsDisplayItemGeometry
* aGeometry
,
7266 nsRegion
* aInvalidRegion
) const final
;
7268 void RenderToContext(gfxContext
* aCtx
, nsDisplayListBuilder
* aBuilder
,
7269 bool aIsRecording
= false);
7271 bool CanApplyOpacity() const final
;
7273 void ApplyOpacity(nsDisplayListBuilder
* aBuilder
, float aOpacity
,
7274 const DisplayItemClipChain
* aClip
) final
{
7275 NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
7276 mOpacity
= aOpacity
;
7277 IntersectClip(aBuilder
, aClip
, false);
7280 void WriteDebugInfo(std::stringstream
& aStream
) final
;
7282 static nsDisplayText
* CheckCast(nsDisplayItem
* aItem
) {
7283 return (aItem
->GetType() == DisplayItemType::TYPE_TEXT
)
7284 ? static_cast<nsDisplayText
*>(aItem
)
7289 ClipEdges(const nsIFrame
* aFrame
, const nsPoint
& aToReferenceFrame
,
7290 nscoord aVisIStartEdge
, nscoord aVisIEndEdge
) {
7291 nsRect r
= aFrame
->ScrollableOverflowRect() + aToReferenceFrame
;
7292 if (aFrame
->GetWritingMode().IsVertical()) {
7293 mVisIStart
= aVisIStartEdge
> 0 ? r
.y
+ aVisIStartEdge
: nscoord_MIN
;
7294 mVisIEnd
= aVisIEndEdge
> 0
7295 ? std::max(r
.YMost() - aVisIEndEdge
, mVisIStart
)
7298 mVisIStart
= aVisIStartEdge
> 0 ? r
.x
+ aVisIStartEdge
: nscoord_MIN
;
7299 mVisIEnd
= aVisIEndEdge
> 0
7300 ? std::max(r
.XMost() - aVisIEndEdge
, mVisIStart
)
7305 void Intersect(nscoord
* aVisIStart
, nscoord
* aVisISize
) const {
7306 nscoord end
= *aVisIStart
+ *aVisISize
;
7307 *aVisIStart
= std::max(*aVisIStart
, mVisIStart
);
7308 *aVisISize
= std::max(std::min(end
, mVisIEnd
) - *aVisIStart
, 0);
7315 nscoord
& VisIStartEdge() { return mVisIStartEdge
; }
7316 nscoord
& VisIEndEdge() { return mVisIEndEdge
; }
7317 float Opacity() const { return mOpacity
; }
7323 // Lengths measured from the visual inline start and end sides
7324 // (i.e. left and right respectively in horizontal writing modes,
7325 // regardless of bidi directionality; top and bottom in vertical modes).
7326 nscoord mVisIStartEdge
;
7327 nscoord mVisIEndEdge
;
7331 * A display item that for webrender to handle SVG
7333 class nsDisplaySVGWrapper
: public nsDisplayWrapList
{
7335 nsDisplaySVGWrapper(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
7336 nsDisplayList
* aList
);
7338 MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySVGWrapper
)
7340 NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER
)
7342 already_AddRefed
<Layer
> BuildLayer(
7343 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7344 const ContainerLayerParameters
& aContainerParameters
) override
;
7345 LayerState
GetLayerState(
7346 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7347 const ContainerLayerParameters
& aParameters
) override
;
7348 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
7349 GetChildren()->Paint(aBuilder
, aCtx
,
7350 mFrame
->PresContext()->AppUnitsPerDevPixel());
7352 bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
7353 bool CreateWebRenderCommands(
7354 mozilla::wr::DisplayListBuilder
& aBuilder
,
7355 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
7356 const StackingContextHelper
& aSc
,
7357 mozilla::layers::RenderRootStateManager
* aManager
,
7358 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
7362 * A display item for webrender to handle SVG foreign object
7364 class nsDisplayForeignObject
: public nsDisplayWrapList
{
7366 nsDisplayForeignObject(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
7367 nsDisplayList
* aList
);
7368 #ifdef NS_BUILD_REFCNT_LOGGING
7369 virtual ~nsDisplayForeignObject();
7372 NS_DISPLAY_DECL_NAME("ForeignObject", TYPE_FOREIGN_OBJECT
)
7374 virtual already_AddRefed
<Layer
> BuildLayer(
7375 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7376 const ContainerLayerParameters
& aContainerParameters
) override
;
7377 virtual LayerState
GetLayerState(
7378 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
7379 const ContainerLayerParameters
& aParameters
) override
;
7380 virtual bool ShouldFlattenAway(nsDisplayListBuilder
* aBuilder
) override
;
7381 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
{
7382 GetChildren()->Paint(aBuilder
, aCtx
,
7383 mFrame
->PresContext()->AppUnitsPerDevPixel());
7386 bool CreateWebRenderCommands(
7387 mozilla::wr::DisplayListBuilder
& aBuilder
,
7388 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
7389 const StackingContextHelper
& aSc
,
7390 mozilla::layers::RenderRootStateManager
* aManager
,
7391 nsDisplayListBuilder
* aDisplayListBuilder
) override
;
7395 * A display item to represent a hyperlink.
7397 class nsDisplayLink
: public nsPaintedDisplayItem
{
7399 nsDisplayLink(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
7400 const char* aLinkSpec
, const nsRect
& aRect
)
7401 : nsPaintedDisplayItem(aBuilder
, aFrame
),
7402 mLinkSpec(aLinkSpec
),
7405 NS_DISPLAY_DECL_NAME("Link", TYPE_LINK
)
7407 void Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) override
;
7410 nsCString mLinkSpec
;
7414 class FlattenedDisplayListIterator
{
7416 FlattenedDisplayListIterator(nsDisplayListBuilder
* aBuilder
,
7417 nsDisplayList
* aList
)
7418 : FlattenedDisplayListIterator(aBuilder
, aList
, true) {}
7420 virtual bool HasNext() const { return mNext
|| !mStack
.IsEmpty(); }
7422 nsDisplayItem
* GetNextItem() {
7425 nsDisplayItem
* next
= mNext
;
7426 mNext
= next
->GetAbove();
7428 if (mNext
&& next
->HasChildren() && mNext
->HasChildren()) {
7429 // Since |next| and |mNext| are container items in the same list,
7430 // merging them might be possible.
7431 next
= TryMergingFrom(next
);
7434 ResolveFlattening();
7439 nsDisplayItem
* PeekNext() { return mNext
; }
7442 FlattenedDisplayListIterator(nsDisplayListBuilder
* aBuilder
,
7443 nsDisplayList
* aList
,
7444 const bool aResolveFlattening
)
7445 : mBuilder(aBuilder
), mNext(aList
->GetBottom()) {
7446 if (aResolveFlattening
) {
7447 // This is done conditionally in case subclass overrides
7448 // ShouldFlattenNextItem().
7449 ResolveFlattening();
7453 virtual void EnterChildList(nsDisplayItem
* aContainerItem
) {}
7454 virtual void ExitChildList() {}
7456 bool AtEndOfNestedList() const { return !mNext
&& mStack
.Length() > 0; }
7458 virtual bool ShouldFlattenNextItem() {
7459 return mNext
&& mNext
->ShouldFlattenAway(mBuilder
);
7462 void ResolveFlattening() {
7463 // Handle the case where we reach the end of a nested list, or the current
7464 // item should start a new nested list. Repeat this until we find an actual
7465 // item, or the very end of the outer list.
7466 while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
7467 if (AtEndOfNestedList()) {
7470 // We reached the end of the list, pop the next item from the stack.
7471 mNext
= mStack
.PopLastElement();
7473 EnterChildList(mNext
);
7475 // This item wants to be flattened. Store the next item on the stack,
7476 // and use the first item in the child list instead.
7477 mStack
.AppendElement(mNext
->GetAbove());
7478 mNext
= mNext
->GetChildren()->GetBottom();
7484 * Tries to merge display items starting from |aCurrent|.
7485 * Updates the internal pointer to the next display item.
7487 nsDisplayItem
* TryMergingFrom(nsDisplayItem
* aCurrent
) {
7488 MOZ_ASSERT(aCurrent
);
7489 MOZ_ASSERT(aCurrent
->GetAbove());
7491 nsDisplayWrapList
* current
= aCurrent
->AsDisplayWrapList();
7492 nsDisplayWrapList
* next
= mNext
->AsDisplayWrapList();
7494 if (!current
|| !next
) {
7495 // Either the current or the next item do not support merging.
7499 // Attempt to merge |next| with |current|.
7500 if (current
->CanMerge(next
)) {
7501 // Merging is possible, collect all the successive mergeable items.
7502 AutoTArray
<nsDisplayWrapList
*, 2> willMerge
{current
};
7505 willMerge
.AppendElement(next
);
7506 mNext
= next
->GetAbove();
7507 next
= mNext
? mNext
->AsDisplayWrapList() : nullptr;
7508 } while (next
&& current
->CanMerge(next
));
7510 current
= mBuilder
->MergeItems(willMerge
);
7513 // Here |mNext| will be either the first item that could not be merged with
7514 // |current|, or nullptr.
7519 nsDisplayListBuilder
* mBuilder
;
7520 nsDisplayItem
* mNext
;
7521 AutoTArray
<nsDisplayItem
*, 16> mStack
;
7526 class PaintTelemetry
{
7528 class AutoRecordPaint
{
7534 mozilla::TimeStamp mStart
;
7538 static uint32_t sPaintLevel
;
7541 } // namespace mozilla
7543 #endif /*NSDISPLAYLIST_H_*/