Bug 1687263: part 4) Defer and in some cases avoid removing spellchecking-ranges...
[gecko.git] / layout / painting / nsDisplayList.h
blob6d69c5e7036a2ce1a1c1c10eab615b56721158b9
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
8 /*
9 * structures that represent things to be painted (ordered in z-order),
10 * used during painting and hit testing
13 #ifndef NSDISPLAYLIST_H_
14 #define NSDISPLAYLIST_H_
16 #include "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
27 #include "nsCOMPtr.h"
28 #include "nsContainerFrame.h"
29 #include "nsPoint.h"
30 #include "nsRect.h"
31 #include "nsRegion.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"
55 #include "Units.h"
57 #include <stdint.h>
58 #include "nsClassHashtable.h"
59 #include "nsTHashSet.h"
60 #include "nsTHashMap.h"
62 #include <stdlib.h>
63 #include <algorithm>
64 #include <unordered_set>
66 // XXX Includes that could be avoided by moving function implementations to the
67 // cpp file.
68 #include "gfxPlatform.h"
70 class gfxContext;
71 class nsIContent;
72 class nsDisplayList;
73 class nsDisplayTableItem;
74 class nsIScrollableFrame;
75 class nsSubDocumentFrame;
76 class nsDisplayCompositorHitTestInfo;
77 class nsDisplayScrollInfoLayer;
78 class nsDisplayTableBackgroundSet;
79 class nsCaret;
80 enum class nsDisplayOwnLayerFlags;
81 struct WrFiltersHolder;
83 namespace nsStyleTransformMatrix {
84 class TransformReferenceBox;
87 namespace mozilla {
88 class FrameLayerBuilder;
89 class PresShell;
90 class StickyScrollContainer;
91 namespace layers {
92 struct FrameMetrics;
93 class RenderRootStateManager;
94 class Layer;
95 class ImageLayer;
96 class ImageContainer;
97 class StackingContextHelper;
98 class WebRenderCommand;
99 class WebRenderScrollData;
100 class WebRenderLayerScrollData;
101 } // namespace layers
102 namespace wr {
103 class DisplayListBuilder;
104 } // namespace wr
105 namespace dom {
106 class Selection;
107 } // namespace dom
109 enum class DisplayListArenaObjectId {
110 #define DISPLAY_LIST_ARENA_OBJECT(name_) name_,
111 #include "nsDisplayListArenaTypes.h"
112 #undef DISPLAY_LIST_ARENA_OBJECT
113 COUNT
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
154 * the subdocuments.
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
178 * geometry root.
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
182 * for a given frame.
184 struct AnimatedGeometryRoot {
185 static already_AddRefed<AnimatedGeometryRoot> CreateAGRForFrame(
186 nsIFrame* aFrame, AnimatedGeometryRoot* aParent, bool aIsAsync,
187 bool aIsRetained) {
188 RefPtr<AnimatedGeometryRoot> result;
189 if (aIsRetained) {
190 result = aFrame->GetProperty(AnimatedGeometryRootCache());
193 if (result) {
194 result->mParentAGR = aParent;
195 result->mIsAsync = aIsAsync;
196 } else {
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;
211 return agr;
214 NS_INLINE_DECL_REFCOUNTING(AnimatedGeometryRoot)
216 nsIFrame* mFrame;
217 RefPtr<AnimatedGeometryRoot> mParentAGR;
218 bool mIsAsync;
219 bool mIsRetained;
221 protected:
222 static void DetachAGR(AnimatedGeometryRoot* aAGR) {
223 aAGR->mFrame = nullptr;
224 aAGR->mParentAGR = nullptr;
225 NS_RELEASE(aAGR);
228 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnimatedGeometryRootCache,
229 AnimatedGeometryRoot, DetachAGR)
231 AnimatedGeometryRoot(nsIFrame* aFrame, AnimatedGeometryRoot* aParent,
232 bool aIsAsync, bool aIsRetained)
233 : mFrame(aFrame),
234 mParentAGR(aParent),
235 mIsAsync(aIsAsync),
236 mIsRetained(aIsRetained) {
237 MOZ_ASSERT(mParentAGR || mIsAsync,
238 "The root AGR should always be treated as an async AGR.");
239 if (mIsRetained) {
240 NS_ADDREF(this);
241 aFrame->SetProperty(AnimatedGeometryRootCache(), this);
245 ~AnimatedGeometryRoot() {
246 if (mFrame && mIsRetained) {
247 mFrame->RemoveProperty(AnimatedGeometryRootCache());
252 namespace mozilla {
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
269 * is on the stack.
271 struct ActiveScrolledRoot {
272 static already_AddRefed<ActiveScrolledRoot> CreateASRForFrame(
273 const ActiveScrolledRoot* aParent, nsIScrollableFrame* aScrollableFrame,
274 bool aIsRetained);
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());
305 return *mViewId;
308 RefPtr<const ActiveScrolledRoot> mParent;
309 nsIScrollableFrame* mScrollableFrame;
311 NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot)
313 private:
314 ActiveScrolledRoot()
315 : mScrollableFrame(nullptr), mDepth(0), mRetained(false) {}
317 ~ActiveScrolledRoot();
319 static void DetachASR(ActiveScrolledRoot* aASR) {
320 aASR->mParent = nullptr;
321 aASR->mScrollableFrame = nullptr;
322 NS_RELEASE(aASR);
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
335 // needed.
336 mutable Maybe<mozilla::layers::ScrollableLayerGuid::ViewID> mViewId;
338 uint32_t mDepth;
339 bool mRetained;
341 } // namespace mozilla
343 enum class nsDisplayListBuilderMode : uint8_t {
344 Painting,
345 PaintForPrinting,
346 EventDelivery,
347 FrameVisibility,
348 TransformComputation,
349 GenerateGlyph,
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,
383 * StartRoot.
385 class Preserves3DContext {
386 public:
387 typedef mozilla::gfx::Matrix4x4 Matrix4x4;
389 Preserves3DContext()
390 : mAccumulatedRectLevels(0), mAllowAsyncAnimation(true) {}
392 Preserves3DContext(const Preserves3DContext& aOther)
393 : mAccumulatedTransform(),
394 mAccumulatedRect(),
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;
405 nsRect mVisibleRect;
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 };
417 public:
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();
449 void BeginFrame();
450 void EndFrame();
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
486 * visibility.
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 {
538 nsPoint result;
539 FindReferenceFrameFor(aFrame, &result);
540 return 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
585 * layerized.
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
599 * selected.
601 void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
602 bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
604 * @return Returns true if we should include the caret in any display lists
605 * that we make.
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
622 * suppressed.
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;
742 return temp;
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);
753 return true;
755 return false;
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.
769 nsCaret* GetCaret();
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
824 * nested presshell.
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;
865 return old;
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
909 * destroyed.
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
923 * visible.
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);
948 return geometries;
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) {
968 return;
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()
998 const {
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),
1019 "");
1020 #define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) \
1021 static_assert(size_t(DisplayItemType::TYPE_##name_) == \
1022 size_t(mozilla::DisplayListArenaObjectId::name_), \
1023 "");
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,
1091 nsIFrame* aFrame,
1092 DisplayItemType aType);
1095 * Merges the display items in |aMergedItems| and returns a new temporary
1096 * display item.
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 {
1107 public:
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;
1154 private:
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 {
1174 public:
1175 AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
1176 : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
1177 aBuilder->mInTransform = aInTransform;
1180 ~AutoInTransformSetter() { mBuilder->mInTransform = mOldValue; }
1182 private:
1183 nsDisplayListBuilder* mBuilder;
1184 bool mOldValue;
1187 class AutoInEventsOnly {
1188 public:
1189 AutoInEventsOnly(nsDisplayListBuilder* aBuilder, bool aInEventsOnly)
1190 : mBuilder(aBuilder), mOldValue(aBuilder->mInEventsOnly) {
1191 aBuilder->mInEventsOnly |= aInEventsOnly;
1194 ~AutoInEventsOnly() { mBuilder->mInEventsOnly = mOldValue; }
1196 private:
1197 nsDisplayListBuilder* mBuilder;
1198 bool mOldValue;
1202 * A helper class to temporarily set the value of mFilterASR and
1203 * mInFilter.
1205 class AutoEnterFilter {
1206 public:
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;
1222 private:
1223 nsDisplayListBuilder* mBuilder;
1224 const ActiveScrolledRoot* mOldValue;
1225 bool mOldInFilter;
1229 * A helper class to temporarily set the value of mCurrentScrollParentId.
1231 class AutoCurrentScrollParentIdSetter {
1232 public:
1233 AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder,
1234 ViewID aScrollId)
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
1252 // layerize
1253 return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent;
1256 bool GetContainsNonMinimalDisplayPort() const {
1257 // Only for scrollframes participating in scroll handoff can we return
1258 // true.
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;
1269 } else {
1270 // Otherwise we need to keep propagating the force-layerization flag
1271 // upwards to the next ancestor scrollframe that does participate in
1272 // scroll handoff.
1273 mBuilder->mForceLayerForScrollParent |= mOldForceLayer;
1275 mBuilder->mContainsNonMinimalDisplayPort |=
1276 mOldContainsNonMinimalDisplayPort;
1279 private:
1280 nsDisplayListBuilder* mBuilder;
1281 ViewID mOldValue;
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 {
1292 public:
1293 explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder* aBuilder)
1294 : mBuilder(aBuilder),
1295 mSavedActiveScrolledRoot(aBuilder->mCurrentActiveScrolledRoot),
1296 mContentClipASR(aBuilder->ClipState().GetContentClipASR()),
1297 mDescendantsStartIndex(aBuilder->mActiveScrolledRoots.Length()),
1298 mUsed(false) {}
1300 ~AutoCurrentActiveScrolledRootSetter() {
1301 mBuilder->mCurrentActiveScrolledRoot = mSavedActiveScrolledRoot;
1304 void SetCurrentActiveScrolledRoot(
1305 const ActiveScrolledRoot* aActiveScrolledRoot);
1307 void EnterScrollFrame(nsIScrollableFrame* aScrollableFrame) {
1308 MOZ_ASSERT(!mUsed);
1309 ActiveScrolledRoot* asr = mBuilder->AllocateActiveScrolledRoot(
1310 mBuilder->mCurrentActiveScrolledRoot, aScrollableFrame);
1311 mBuilder->mCurrentActiveScrolledRoot = asr;
1312 mUsed = true;
1315 void InsertScrollFrame(nsIScrollableFrame* aScrollableFrame);
1317 private:
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
1340 * class.
1342 bool mUsed;
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 {
1353 public:
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);
1371 private:
1372 nsDisplayListBuilder* mBuilder;
1373 const ActiveScrolledRoot* mSavedContainerASR;
1377 * A helper class to temporarily set the value of mCurrentScrollbarTarget
1378 * and mCurrentScrollbarFlags.
1380 class AutoCurrentScrollbarInfoSetter {
1381 public:
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;
1400 private:
1401 nsDisplayListBuilder* mBuilder;
1405 * A helper class to temporarily set mBuildingExtraPagesForPageNum.
1407 class MOZ_RAII AutoPageNumberSetter {
1408 public:
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);
1418 private:
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 {
1433 public:
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;
1453 void StartRoot() {
1454 mBuilder->mPreserves3DCtx.mAccumulatedTransform = Matrix4x4();
1457 private:
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
1469 * transform.
1471 class AutoAccumulateRect {
1472 public:
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--;
1485 private:
1486 nsDisplayListBuilder* mBuilder;
1487 nsRect mSavedRect;
1490 void AccumulateRect(const nsRect& aRect) {
1491 mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect,
1492 aRect);
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;
1530 nsRect mDirtyRect;
1532 static nsRect ComputeVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
1533 nsIFrame* aFrame,
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;
1550 nsRect mDirtyRect;
1552 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect,
1553 DisplayListBuildingData)
1555 NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect,
1556 nsRect)
1558 static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame) {
1559 if (!aFrame->GetParent()) {
1560 return nullptr;
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
1575 * Windows.
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);
1604 return;
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 {
1702 public:
1703 explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder)
1704 : mBuilder(aBuilder), mSavedCtx(aBuilder->mPreserves3DCtx) {}
1706 ~AutoPreserves3DContext() { mBuilder->mPreserves3DCtx = mSavedCtx; }
1708 private:
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
1742 * are unified.
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;
1783 void* mFrame;
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)) {
1793 return;
1796 mFrameSet.Insert(aFrame);
1797 mFrames.AppendElement(WeakFrameWrapper(aFrame));
1798 mRects.AppendElement(nsRegion::RectToBox(aRect));
1801 void Clear() {
1802 mFrameSet.Clear();
1803 mFrames.Clear();
1804 mRects.Clear();
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.
1825 class Linkifier {
1826 public:
1827 Linkifier(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
1829 ~Linkifier() {
1830 if (mBuilderToReset) {
1831 mBuilderToReset->mLinkSpec.Truncate(0);
1835 void MaybeAppendLink(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1836 nsDisplayList* aList);
1838 private:
1839 nsDisplayListBuilder* mBuilderToReset = nullptr;
1842 private:
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
1881 * returned here.
1883 bool AddToAGRBudget(nsIFrame* aFrame);
1885 struct PresShellState {
1886 mozilla::PresShell* mPresShell;
1887 #ifdef DEBUG
1888 mozilla::Maybe<nsAutoLayoutPhase> mAutoLayoutPhase;
1889 #endif
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;
1917 uint32_t mUsage;
1920 nsIFrame* const mReferenceFrame;
1921 nsIFrame* mIgnoreScrollFrame;
1923 using Arena = nsPresArena<32768, mozilla::DisplayListArenaObjectId,
1924 size_t(mozilla::DisplayListArenaObjectId::COUNT)>;
1925 Arena mPool;
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>>
1932 mThemeGeometries;
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;
1971 nsRect mDirtyRect;
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
1991 // list builds.
1992 bool mHasGlassItemDuringPartial;
1994 nsIFrame* mCaretFrame;
1995 nsRect mCaretRect;
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>
2006 mClipDeduplicator;
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;
2024 bool mBuildCaret;
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
2034 bool mInTransform;
2035 bool mInEventsOnly;
2036 bool mInFilter;
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;
2055 bool mIsBuilding;
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; } \
2082 private: \
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, \
2090 Args&&... aArgs); \
2092 public:
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());
2108 return item;
2111 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2112 void AssertUniqueItem(nsDisplayItem* aItem);
2113 #endif
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,
2131 Args&&... aArgs) {
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.
2140 return nullptr;
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();
2153 if (paintedItem) {
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.");
2178 #endif
2180 return item;
2183 template <typename T, typename F, typename... Args>
2184 MOZ_ALWAYS_INLINE T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, F* aFrame,
2185 Args&&... aArgs) {
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
2197 // destructors.
2198 protected:
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 {
2221 public:
2222 nsDisplayItemBase() = delete;
2225 * Downcasts this item to nsPaintedDisplayItem, if possible.
2227 virtual nsPaintedDisplayItem* AsPaintedDisplayItem() { return nullptr; }
2228 virtual const nsPaintedDisplayItem* AsPaintedDisplayItem() const {
2229 return nullptr;
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 {
2242 return nullptr;
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!");
2261 return mFrame;
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) {
2269 MOZ_ASSERT(aFrame);
2271 if (mFrame && aFrame == mFrame) {
2272 mFrame = nullptr;
2273 SetDeletedFrame();
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!");
2301 return mType;
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) {
2327 if (aReused) {
2328 mItemFlags += ItemBaseFlag::ReusedItem;
2329 } else {
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
2360 * within that list.
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;
2368 #endif
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);
2381 #endif
2382 return false;
2384 *aOutIndex = mOldListIndex;
2385 return true;
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) {
2400 return false;
2403 protected:
2404 nsDisplayItemBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
2405 : mFrame(aFrame), mType(DisplayItemType::TYPE_ZERO) {
2406 MOZ_COUNT_CTOR(nsDisplayItemBase);
2407 MOZ_ASSERT(mFrame);
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);
2426 if (mFrame) {
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
2448 private:
2449 enum class ItemBaseFlag : uint8_t {
2450 CantBeReused,
2451 CantBeCached,
2452 DeletedFrame,
2453 ModifiedFrame,
2454 ReusedItem,
2455 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2456 MergedItem,
2457 PreProcessedItem,
2458 #endif
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
2469 public:
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) {
2479 if (aMerged) {
2480 mItemFlags += ItemBaseFlag::MergedItem;
2481 } else {
2482 mItemFlags -= ItemBaseFlag::MergedItem;
2485 if (aPreProcessed) {
2486 mItemFlags += ItemBaseFlag::PreProcessedItem;
2487 } else {
2488 mItemFlags -= ItemBaseFlag::PreProcessedItem;
2492 uint32_t mOldListKey = 0;
2493 uint32_t mOldNestingDepth = 0;
2494 #endif
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 {
2503 public:
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;
2522 protected:
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;
2562 public:
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)) {
2575 return false;
2578 mClipChain = mState.mClipChain;
2579 mClip = mState.mClip;
2580 mItemFlags -= ItemFlag::DisableSubpixelAA;
2581 return true;
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
2590 * method.
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;
2602 ~HitTestState() {
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 {
2659 *aSnap = false;
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 {
2673 *aSnap = false;
2674 return nsRegion();
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
2686 * account.
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();
2709 return result;
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
2740 * changes.
2742 * @param aGeometry The geometry of the matching display item from the
2743 * previous paint.
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);
2752 bool snap;
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 {
2767 bool snap;
2768 nsRect bounds = GetBounds(aBuilder, &snap);
2770 if (!aGeometry->mBounds.IsEqualInterior(bounds)) {
2771 nscoord radii[8];
2772 if (aGeometry->mHasRoundedCorners || Frame()->GetBorderRadii(radii)) {
2773 aInvalidRegion->Or(aGeometry->mBounds, bounds);
2774 } else {
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
2795 * culling.
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 {
2802 *aSnap = false;
2803 return nsRegion();
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 {
2819 return false;
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; }
2868 #endif
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
2877 * not active.
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) {
2887 return false;
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) {
2908 return false;
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
2926 * is visible.
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),
2947 * return the list.
2949 virtual RetainedDisplayList* GetSameCoordinateSystemChildren() const {
2950 return nullptr;
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.
2980 return;
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
3010 * does per-item:
3011 * -- Intersects GetBounds with aVisibleRegion and puts the result
3012 * in mVisibleRect
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()
3045 const {
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
3053 * in the item does.
3055 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const {
3056 return nsRect();
3060 * Disable usage of component alpha. Currently only relevant for items that
3061 * have text.
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) {
3073 return false;
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,
3093 bool aStore);
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();
3152 protected:
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;
3163 struct {
3164 RefPtr<const DisplayItemClipChain> mClipChain;
3165 const DisplayItemClip* mClip;
3166 } mState;
3168 // Result of ToReferenceFrame(mFrame), if mFrame is non-null
3169 nsPoint mToReferenceFrame;
3171 private:
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().
3180 nsRect mPaintRect;
3182 enum class ItemFlag : uint8_t {
3183 BackfaceHidden,
3184 Combines3DTransformWithAncestors,
3185 DisableSubpixelAA,
3186 ForceNotVisible,
3187 HasHitTestInfo,
3188 IsGlassItem,
3189 PaintRectValid,
3190 #ifdef MOZ_DUMP_PAINTING
3191 // True if this frame has been painted.
3192 Painted,
3193 #endif
3196 mozilla::EnumSet<ItemFlag, uint8_t> mItemFlags;
3199 class nsPaintedDisplayItem : public nsDisplayItem {
3200 public:
3201 nsPaintedDisplayItem* AsPaintedDisplayItem() final { return this; }
3202 const nsPaintedDisplayItem* AsPaintedDisplayItem() const final {
3203 return this;
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
3219 * instead.
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
3227 * constructed.
3229 virtual already_AddRefed<Layer> BuildLayer(
3230 nsDisplayListBuilder* aBuilder, LayerManager* aManager,
3231 const ContainerLayerParameters& aContainerParameters) {
3232 return nullptr;
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
3244 * clip.
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();
3282 protected:
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) {}
3295 protected:
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
3306 * two pointers.
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 {
3316 public:
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>
3323 class Iterator {
3324 public:
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;
3335 return *this;
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; }
3348 private:
3349 T* mItem;
3352 using DisplayItemIterator = Iterator<nsDisplayItem>;
3354 DisplayItemIterator begin() const { return DisplayItemIterator(this); }
3355 DisplayItemIterator end() const { return DisplayItemIterator(); }
3358 * Create an empty list.
3360 nsDisplayList()
3361 : mLength(0), mIsOpaque(false), mForceTransparentSurface(false) {
3362 mTop = &mSentinel;
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);
3376 } else {
3377 mTop = &mSentinel;
3378 mLength = 0;
3382 nsDisplayList& operator=(nsDisplayList&& aOther) {
3383 if (this != &aOther) {
3384 if (aOther.mSentinel.mAbove) {
3385 nsDisplayList tmp;
3386 tmp.AppendToTop(&aOther);
3387 aOther.AppendToTop(this);
3388 AppendToTop(&tmp);
3389 } else {
3390 mTop = &mSentinel;
3391 mLength = 0;
3393 mIsOpaque = aOther.mIsOpaque;
3394 mForceTransparentSurface = aOther.mForceTransparentSurface;
3396 return *this;
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) {
3407 if (!aItem) {
3408 return;
3410 MOZ_ASSERT(!aItem->mAbove, "Already in a list!");
3411 mTop->mAbove = aItem;
3412 mTop = aItem;
3413 mLength++;
3416 template <typename T, typename F, typename... Args>
3417 void AppendNewToTop(nsDisplayListBuilder* aBuilder, F* aFrame,
3418 Args&&... aArgs) {
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)...);
3429 if (item) {
3430 AppendToTop(item);
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) {
3439 if (!aItem) {
3440 return;
3442 MOZ_ASSERT(!aItem->mAbove, "Already in a list!");
3443 aItem->mAbove = mSentinel.mAbove;
3444 mSentinel.mAbove = aItem;
3445 if (mTop == &mSentinel) {
3446 mTop = aItem;
3448 mLength++;
3451 template <typename T, typename F, typename... Args>
3452 void AppendNewToBottom(nsDisplayListBuilder* aBuilder, F* aFrame,
3453 Args&&... aArgs) {
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)...);
3464 if (item) {
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;
3475 mTop = aList->mTop;
3476 aList->mTop = &aList->mSentinel;
3477 aList->mSentinel.mAbove = nullptr;
3478 mLength += aList->mLength;
3479 aList->mLength = 0;
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) {
3491 mTop = aList->mTop;
3494 aList->mTop = &aList->mSentinel;
3495 aList->mSentinel.mAbove = nullptr;
3496 mLength += aList->mLength;
3497 aList->mLength = 0;
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
3547 * before item2.
3548 * We sort the items into increasing order.
3550 template <typename Item, typename Comparator>
3551 void Sort(const Comparator& aComparator) {
3552 if (Count() < 2) {
3553 // Only sort lists with more than one item.
3554 return;
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
3559 // here.
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) {
3569 AppendToTop(item);
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
3629 * not be null.
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
3639 * tree.
3641 * We return the layer manager used for painting --- mainly so that
3642 * callers can dump its layer tree if necessary.
3644 enum {
3645 PAINT_DEFAULT = 0,
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,
3658 uint32_t aFlags,
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
3682 * twice.
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) {
3692 nsRegion result;
3693 bool snap;
3694 for (nsDisplayItem* item : *this) {
3695 result.OrWith(item->GetOpaqueRegion(aBuilder, &snap));
3697 return result;
3701 * Returns the bounds of the area that needs component alpha.
3703 nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const {
3704 nsRect bounds;
3705 for (nsDisplayItem* item : *this) {
3706 bounds.UnionRect(bounds, item->GetComponentAlphaBounds(aBuilder));
3708 return bounds;
3712 * Find the topmost display item that returns a non-null frame, and return
3713 * the frame.
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() {
3729 mIsOpaque = false;
3730 mForceTransparentSurface = false;
3733 private:
3734 nsDisplayItemLink mSentinel;
3735 nsDisplayItemLink* mTop;
3737 uint32_t mLength;
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).
3742 bool mIsOpaque;
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 {
3756 public:
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),
3806 mFloats(aFloats),
3807 mContent(aContent),
3808 mPositioned(aPositionedDescendants),
3809 mOutlines(aOutlines) {}
3812 * A copy constructor that lets the caller override the BorderBackground
3813 * list.
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
3826 * the destination.
3828 void MoveTo(const nsDisplayListSet& aDestination) const;
3830 private:
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);
3835 protected:
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);
3876 private:
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
3891 * order correctly.
3893 class RetainedDisplayList : public nsDisplayList {
3894 public:
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);
3911 return *this;
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");
3923 mOldItems.Clear();
3924 mDAG.Clear();
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 {
3938 public:
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 {
3987 return true;
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;
3997 private:
3998 mutable RetainedDisplayList mChildren;
3999 nsRect mBounds;
4002 class nsDisplayImageContainer : public nsPaintedDisplayItem {
4003 public:
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
4035 * border-rect.
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 {
4043 public:
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),
4055 mPaint(aPaint),
4056 mOldPaint(nullptr),
4057 mName(aName) {
4058 MOZ_COUNT_CTOR(nsDisplayGeneric);
4059 SetType(aType);
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),
4067 mPaint(nullptr),
4068 mOldPaint(aOldPaint),
4069 mName(aName) {
4070 MOZ_COUNT_CTOR(nsDisplayGeneric);
4071 SetType(aType);
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);
4082 if (mPaint) {
4083 mPaint(mFrame, aCtx->GetDrawTarget(), GetPaintRect(), ToReferenceFrame());
4084 } else {
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);
4098 protected:
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,
4106 Args&&... aArgs);
4108 PaintCallback mPaint;
4109 OldPaintCallback mOldPaint; // XXX: should be removed eventually
4110 const char* mName;
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 {
4127 public:
4128 nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4129 const char* aFrameName, uint32_t aColor = 0)
4130 : nsPaintedDisplayItem(aBuilder, aFrame),
4131 mFrameName(aFrameName),
4132 mColor(aColor) {
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;
4142 protected:
4143 const char* mFrameName;
4144 nscolor mColor;
4147 # define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
4148 PR_BEGIN_MACRO \
4149 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
4150 PresShell()->IsPaintingFrameCounts()) { \
4151 aLists.Outlines()->AppendNewToTop<nsDisplayReflowCount>(aBuilder, this, \
4152 _name); \
4154 PR_END_MACRO
4156 # define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
4157 PR_BEGIN_MACRO \
4158 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
4159 PresShell()->IsPaintingFrameCounts()) { \
4160 aLists.Outlines()->AppendNewToTop<nsDisplayReflowCount>(aBuilder, this, \
4161 _name, _color); \
4163 PR_END_MACRO
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 {
4185 public:
4186 nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame);
4188 #ifdef NS_BUILD_REFCNT_LOGGING
4189 ~nsDisplayCaret() override;
4190 #endif
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;
4203 protected:
4204 RefPtr<nsCaret> mCaret;
4205 nsRect mBounds;
4209 * The standard display item to paint the CSS borders of a frame.
4211 class nsDisplayBorder : public nsPaintedDisplayItem {
4212 public:
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 {
4239 *aSnap = true;
4240 return CalculateBounds<nsRegion>(*mFrame->StyleBorder());
4243 protected:
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();
4253 T result;
4254 if (border.top > 0) {
4255 result = nsRect(borderBounds.X(), borderBounds.Y(), borderBounds.Width(),
4256 border.top);
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()));
4273 nscoord radii[8];
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]);
4283 result.OrWith(
4284 nsRect(borderBounds.TopRight() - nsPoint(cornerSize.width, 0),
4285 cornerSize));
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),
4292 cornerSize));
4294 if (border.bottom > 0 || border.left > 0) {
4295 nsSize cornerSize(radii[mozilla::eCornerBottomLeftX],
4296 radii[mozilla::eCornerBottomLeftY]);
4297 result.OrWith(
4298 nsRect(borderBounds.BottomLeft() - nsPoint(0, cornerSize.height),
4299 cornerSize));
4302 return result;
4305 nsRect mBounds;
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 {
4320 public:
4321 nsDisplaySolidColorBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4322 nscolor aColor)
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) {
4336 bool dummy;
4337 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
4338 return;
4340 ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
4343 nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4344 bool* aSnap) const override {
4345 *aSnap = false;
4346 nsRegion result;
4347 if (NS_GET_A(mColor) == 255) {
4348 result = GetBounds(aBuilder, aSnap);
4350 return result;
4353 mozilla::Maybe<nscolor> IsUniform(
4354 nsDisplayListBuilder* aBuilder) const override {
4355 return mozilla::Some(mColor);
4358 protected:
4359 nscolor mColor;
4362 class nsDisplaySolidColor : public nsDisplaySolidColorBase {
4363 public:
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) {
4372 SetCantBeReused();
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);
4407 private:
4408 nsRect mBounds;
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;
4420 public:
4421 nsDisplaySolidColorRegion(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4422 const nsRegion& aRegion, nscolor aColor)
4423 : nsPaintedDisplayItem(aBuilder, aFrame),
4424 mRegion(aRegion),
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,
4438 mColor);
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);
4448 } else {
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;
4460 protected:
4461 nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
4462 void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4463 void WriteDebugInfo(std::stringstream& aStream) override;
4465 private:
4466 nsRegion mRegion;
4467 sRGBColor mColor;
4470 enum class AppendedBackgroundType : uint8_t {
4471 None,
4472 Background,
4473 ThemedBackground,
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 {
4481 public:
4482 typedef mozilla::StyleGeometryBox StyleGeometryBox;
4484 struct InitData {
4485 nsDisplayListBuilder* builder;
4486 mozilla::ComputedStyle* backgroundStyle;
4487 nsCOMPtr<imgIContainer> image;
4488 nsRect backgroundRect;
4489 nsRect fillArea;
4490 nsRect destArea;
4491 uint32_t layer;
4492 bool isRasterImage;
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);
4515 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
4583 * not.
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()) {
4614 return;
4616 mDependentFrame = aFrame;
4617 if (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();
4637 protected:
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 {
4652 WHENEVER_POSSIBLE,
4653 ONLY_FOR_SCALING,
4654 NO_LAYER_NEEDED
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
4665 nsRect mFillRect;
4666 nsRect mDestRect;
4667 /* Bounds of this display item */
4668 nsRect mBounds;
4669 uint16_t mLayer;
4670 bool mIsRasterImage;
4671 /* Whether the image should be treated as fixed to the viewport. */
4672 bool mShouldFixToViewport;
4673 uint32_t mImageFlags;
4674 float mOpacity;
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 {
4691 public:
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;
4706 SetDeletedFrame();
4708 nsDisplayBackgroundImage::RemoveFrame(aFrame);
4711 protected:
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 {
4720 public:
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;
4781 protected:
4782 nsRect GetBoundsInternal();
4784 void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
4785 const nsRect& aBounds, nsRect* aClipRect);
4787 nsRect mBackgroundRect;
4788 nsRect mBounds;
4789 nsITheme::Transparency mThemeTransparency;
4790 mozilla::StyleAppearance mAppearance;
4793 class nsDisplayTableThemedBackground : public nsDisplayThemedBackground {
4794 public:
4795 nsDisplayTableThemedBackground(nsDisplayListBuilder* aBuilder,
4796 nsIFrame* aFrame,
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;
4820 SetDeletedFrame();
4822 nsDisplayThemedBackground::RemoveFrame(aFrame);
4825 protected:
4826 nsIFrame* StyleFrame() const override { return mAncestorFrame; }
4827 nsIFrame* mAncestorFrame;
4830 class nsDisplayBackgroundColor : public nsPaintedDisplayItem {
4831 typedef mozilla::gfx::sRGBColor sRGBColor;
4833 public:
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;
4845 if (mHasStyle) {
4846 mBottomLayerClip =
4847 aBackgroundStyle->StyleBackground()->BottomLayer().mClip;
4848 } else {
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) {
4863 return false;
4866 mColor = mState.mColor;
4867 return true;
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 {
4904 *aSnap = true;
4905 return mBackgroundRect;
4908 bool CanPaintWithClip(const DisplayItemClip& aClip) override {
4909 if (HasBackgroundClipText()) {
4910 return false;
4913 if (aClip.GetRoundedRectCount() > 1) {
4914 return false;
4917 return true;
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) {
4932 bool dummy;
4933 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
4934 return;
4936 ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
4939 nsIFrame* GetDependentFrame() override { return mDependentFrame; }
4941 void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) {
4942 if (!aBuilder->IsRetainingDisplayList()) {
4943 return;
4945 mDependentFrame = aFrame;
4946 if (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;
4963 protected:
4964 const nsRect mBackgroundRect;
4965 const bool mHasStyle;
4966 mozilla::StyleGeometryBox mBottomLayerClip;
4967 nsIFrame* mDependentFrame;
4968 mozilla::gfx::sRGBColor mColor;
4970 struct {
4971 mozilla::gfx::sRGBColor mColor;
4972 } mState;
4975 class nsDisplayTableBackgroundColor : public nsDisplayBackgroundColor {
4976 public:
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;
5002 SetDeletedFrame();
5004 nsDisplayBackgroundColor::RemoveFrame(aFrame);
5007 bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override {
5008 return false;
5011 protected:
5012 nsIFrame* mAncestorFrame;
5016 * The standard display item to paint the outer CSS box-shadows of a frame.
5018 class nsDisplayBoxShadowOuter final : public nsPaintedDisplayItem {
5019 public:
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()) {
5033 return false;
5036 mVisibleRegion.SetEmpty();
5037 mOpacity = 1.0f;
5038 return true;
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();
5073 private:
5074 nsRegion mVisibleRegion;
5075 nsRect mBounds;
5076 float mOpacity;
5080 * The standard display item to paint the inner CSS box-shadows of a frame.
5082 class nsDisplayBoxShadowInner : public nsPaintedDisplayItem {
5083 public:
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()) {
5095 return false;
5098 mVisibleRegion.SetEmpty();
5099 return true;
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.
5119 bool snap;
5120 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
5124 static bool CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder,
5125 nsIFrame* aFrame,
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;
5138 private:
5139 nsRegion mVisibleRegion;
5143 * The standard display item to paint the CSS outline of a frame.
5145 class nsDisplayOutline final : public nsPaintedDisplayItem {
5146 public:
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");
5159 return true;
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;
5172 private:
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
5180 * paints.
5182 class nsDisplayEventReceiver final : public nsDisplayItem {
5183 public:
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 {
5204 public:
5205 nsDisplayCompositorHitTestInfo(nsDisplayListBuilder* aBuilder,
5206 nsIFrame* aFrame)
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 {
5238 *aSnap = false;
5239 return nsRect();
5242 const mozilla::HitTestInfo& GetHitTestInfo() final { return mHitTestInfo; }
5244 private:
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 {
5264 public:
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()),
5282 mOverrideZIndex(0),
5283 mHasZIndexOverride(false) {
5284 MOZ_COUNT_CTOR(nsDisplayWrapList);
5285 mBaseBuildingRect = GetBuildingRect();
5286 mListPtr = &mList;
5289 nsDisplayWrapList() = delete;
5292 * A custom copy-constructor that does not copy mList, as this would mutate
5293 * the other item.
5295 nsDisplayWrapList(const nsDisplayWrapList& aOther) = delete;
5296 nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
5297 const nsDisplayWrapList& aOther)
5298 : nsPaintedDisplayItem(aBuilder, aOther),
5299 mListPtr(&mList),
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(),
5337 clip->mASR)) {
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
5352 // the frame.
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)
5390 * to aFrames.
5392 const nsTArray<nsIFrame*>& GetMergedFrames() const { return mMergedFrames; }
5394 bool HasMergedFrames() const { return !mMergedFrames.IsEmpty(); }
5396 bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5397 return true;
5400 bool IsInvalid(nsRect& aRect) const override {
5401 if (mFrame->IsInvalid(aRect) && aRect.IsEmpty()) {
5402 return true;
5404 nsRect temp;
5405 for (uint32_t i = 0; i < mMergedFrames.Length(); i++) {
5406 if (mMergedFrames[i]->IsInvalid(temp) && temp.IsEmpty()) {
5407 aRect.SetEmpty();
5408 return true;
5410 aRect = aRect.Union(temp);
5412 aRect += ToReferenceFrame();
5413 return !aRect.IsEmpty();
5416 nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override;
5418 RetainedDisplayList* GetSameCoordinateSystemChildren() const override {
5419 NS_ASSERTION(
5420 mListPtr->IsEmpty() || !ReferenceFrame() ||
5421 !mListPtr->GetBottom()->ReferenceFrame() ||
5422 mListPtr->GetBottom()->ReferenceFrame() == ReferenceFrame(),
5423 "Children must have same reference frame");
5424 return mListPtr;
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!");
5448 return nullptr;
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;
5462 protected:
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
5475 // wrap list.
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;
5480 nsRect mBounds;
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 {
5490 public:
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,
5498 aClearClipChain) {}
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;
5507 private:
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 {
5521 public:
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);
5536 protected:
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 {
5545 public:
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) {
5572 return false;
5575 mOpacity = mState.mOpacity;
5576 return true;
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
5599 // nsDisplayOpacity
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) {
5615 return false;
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; }
5653 private:
5654 NS_DISPLAY_ALLOW_CLONING()
5656 bool ApplyToChildren(nsDisplayListBuilder* aBuilder);
5657 bool ApplyToFilterOrMask(const bool aUsingLayers);
5659 float mOpacity;
5660 bool mForEventsOnly : 1;
5661 enum class ChildOpacityState : uint8_t {
5662 // Our child list has changed since the last time ApplyToChildren was
5663 // called.
5664 Unknown,
5665 // Our children defer opacity handling to us.
5666 Deferred,
5667 // Opacity is applied to our children.
5668 Applied
5670 bool mNeedsActiveLayer : 1;
5671 #ifndef __GNUC__
5672 ChildOpacityState mChildOpacityState : 2;
5673 #else
5674 ChildOpacityState mChildOpacityState;
5675 #endif
5677 struct {
5678 float mOpacity;
5679 } mState;
5682 class nsDisplayBlendMode : public nsDisplayWrapList {
5683 public:
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 {
5728 return false;
5731 mozilla::gfx::CompositionOp BlendMode();
5733 protected:
5734 mozilla::StyleBlend mBlendMode;
5735 bool mIsForBackground;
5737 private:
5738 NS_DISPLAY_ALLOW_CLONING()
5741 class nsDisplayTableBlendMode : public nsDisplayBlendMode {
5742 public:
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;
5777 SetDeletedFrame();
5779 nsDisplayBlendMode::RemoveFrame(aFrame);
5782 protected:
5783 nsIFrame* mAncestorFrame;
5785 private:
5786 NS_DISPLAY_ALLOW_CLONING()
5789 class nsDisplayBlendContainer : public nsDisplayWrapList {
5790 public:
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) &&
5823 mIsForBackground ==
5824 static_cast<const nsDisplayBlendContainer*>(aItem)
5825 ->mIsForBackground;
5828 bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5829 return false;
5832 protected:
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;
5848 private:
5849 NS_DISPLAY_ALLOW_CLONING()
5852 class nsDisplayTableBlendContainer : public nsDisplayBlendContainer {
5853 public:
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;
5861 SetDeletedFrame();
5863 nsDisplayBlendContainer::RemoveFrame(aFrame);
5866 protected:
5867 nsDisplayTableBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5868 nsDisplayList* aList,
5869 const ActiveScrolledRoot* aActiveScrolledRoot,
5870 bool aIsForBackground, nsIFrame* aAncestorFrame)
5871 : nsDisplayBlendContainer(aBuilder, aFrame, aList, aActiveScrolledRoot,
5872 aIsForBackground),
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;
5892 private:
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 {
5902 None = 0,
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
5911 * their own layer.
5913 class nsDisplayOwnLayer : public nsDisplayWrapList {
5914 public:
5915 typedef mozilla::layers::ScrollbarData ScrollbarData;
5917 enum OwnLayerType {
5918 OwnLayerForTransformWithRoundedClip,
5919 OwnLayerForStackingContext,
5920 OwnLayerForImageBoxFrame,
5921 OwnLayerForScrollbar,
5922 OwnLayerForScrollThumb,
5923 OwnLayerForSubdoc,
5924 OwnLayerForBoxFrame
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.
5938 nsDisplayOwnLayer(
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
5981 return false;
5984 bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5985 return false;
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;
5998 protected:
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;
6009 bool mForceActive;
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 {
6019 public:
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;
6056 void Disown();
6058 protected:
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 {
6071 public:
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; }
6118 private:
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
6142 // scrollport clip.
6143 bool mClippedToDisplayPort;
6146 class nsDisplayFixedPosition : public nsDisplayOwnLayer {
6147 public:
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;
6204 protected:
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;
6215 private:
6216 NS_DISPLAY_ALLOW_CLONING()
6219 class nsDisplayTableFixedPosition : public nsDisplayFixedPosition {
6220 public:
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;
6228 SetDeletedFrame();
6230 nsDisplayFixedPosition::RemoveFrame(aFrame);
6233 protected:
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;
6250 private:
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
6257 * tree.
6259 class nsDisplayScrollInfoLayer : public nsDisplayWrapList {
6260 public:
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 {
6276 *aSnap = false;
6277 return nsRegion();
6280 LayerState GetLayerState(
6281 nsDisplayListBuilder* aBuilder, LayerManager* aManager,
6282 const ContainerLayerParameters& aParameters) override;
6283 void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
6284 return;
6287 bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
6288 return false;
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;
6305 protected:
6306 nsIFrame* mScrollFrame;
6307 nsIFrame* mScrolledFrame;
6308 ViewID mScrollParentId;
6309 CompositorHitTestInfo mHitInfo;
6310 nsRect mHitArea;
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 {
6318 public:
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
6324 * document.
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; }
6354 private:
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 {
6366 public:
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();
6379 #endif
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;
6397 protected:
6398 mozilla::layers::FrameMetrics::ViewID mViewID;
6402 * A base class for different effects types.
6404 class nsDisplayEffectsBase : public nsDisplayWrapList {
6405 public:
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) {
6430 return false;
6433 mHandleOpacity = false;
6434 return true;
6437 bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
6438 return false;
6441 virtual void SelectOpacityOptimization(const bool /* aUsingLayers */) {
6442 SetHandleOpacity();
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;
6454 protected:
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,
6468 * respectively.
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 {
6475 public:
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(
6500 mEffectsBounds,
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);
6524 #endif
6526 bool IsValidMask();
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;
6557 private:
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 {
6569 public:
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 {
6602 public:
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,
6623 nsIFrame* aFrame);
6625 bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
6626 return !aBuilder->IsPaintingForWebRender();
6629 private:
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 {
6641 public:
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(
6668 mEffectsBounds,
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 {
6681 *aSnap = false;
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);
6698 #endif
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();
6715 private:
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
6729 * border box.
6731 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
6732 * function.
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;
6741 public:
6742 enum class PrerenderDecision : uint8_t { No, Full, Partial };
6744 enum {
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) {
6768 return false;
6771 mShouldFlatten = false;
6772 return true;
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 {
6796 *aSnap = false;
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())) {
6849 bool snap;
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) {
6861 return mFrame;
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
6913 * needed.
6915 static nsRect TransformRect(const nsRect& aUntransformedBounds,
6916 const nsIFrame* aFrame,
6917 TransformReferenceBox& aRefBox);
6919 /* UntransformRect is like TransformRect, except that it inverts the
6920 * transform.
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
6945 * block.
6946 * Returns the matrix to append to apply the persective (taking
6947 * perspective-origin into account), relative to aFrames coordinate
6948 * space).
6949 * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
6950 * cleared.
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)
6966 : mFrame(nullptr),
6967 mTranslate(aTranslate),
6968 mRotate(aRotate),
6969 mScale(aScale),
6970 mTransform(aTransform),
6971 mMotion(aMotion),
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
6999 * specify a value.
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.
7008 enum {
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,
7016 uint32_t aFlags);
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
7057 * context.
7059 bool IsLeafOf3DContext() const {
7060 return (IsTransformSeparator() ||
7061 (!mFrame->Extend3DContext() && Combines3DTransformWithAncestors()));
7064 * The backing frame of this item participates a 3D rendering
7065 * context.
7067 bool IsParticipating3DContext() const {
7068 return mFrame->Extend3DContext() || Combines3DTransformWithAncestors();
7071 bool IsPartialPrerender() const {
7072 return mPrerenderDecision == PrerenderDecision::Partial;
7075 void AddSizeOfExcludingThis(nsWindowSizes&) const override;
7077 private:
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.
7108 nsRect mBounds;
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;
7132 public:
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 {
7150 *aSnap = false;
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 {
7181 return &mList;
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);
7198 private:
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
7207 * on each side.
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 {
7214 public:
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) {
7222 return false;
7225 mOpacity = 1.0f;
7226 return true;
7229 nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const final {
7230 *aSnap = false;
7231 return mBounds;
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) {
7255 return nsRect();
7258 bool snap;
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)
7285 : nullptr;
7288 struct ClipEdges {
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)
7296 : nscoord_MAX;
7297 } else {
7298 mVisIStart = aVisIStartEdge > 0 ? r.x + aVisIStartEdge : nscoord_MIN;
7299 mVisIEnd = aVisIEndEdge > 0
7300 ? std::max(r.XMost() - aVisIEndEdge, mVisIStart)
7301 : nscoord_MAX;
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);
7311 nscoord mVisIStart;
7312 nscoord mVisIEnd;
7315 nscoord& VisIStartEdge() { return mVisIStartEdge; }
7316 nscoord& VisIEndEdge() { return mVisIEndEdge; }
7317 float Opacity() const { return mOpacity; }
7319 private:
7320 nsRect mBounds;
7321 float 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 {
7334 public:
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 {
7365 public:
7366 nsDisplayForeignObject(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
7367 nsDisplayList* aList);
7368 #ifdef NS_BUILD_REFCNT_LOGGING
7369 virtual ~nsDisplayForeignObject();
7370 #endif
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 {
7398 public:
7399 nsDisplayLink(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
7400 const char* aLinkSpec, const nsRect& aRect)
7401 : nsPaintedDisplayItem(aBuilder, aFrame),
7402 mLinkSpec(aLinkSpec),
7403 mRect(aRect) {}
7405 NS_DISPLAY_DECL_NAME("Link", TYPE_LINK)
7407 void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
7409 private:
7410 nsCString mLinkSpec;
7411 nsRect mRect;
7414 class FlattenedDisplayListIterator {
7415 public:
7416 FlattenedDisplayListIterator(nsDisplayListBuilder* aBuilder,
7417 nsDisplayList* aList)
7418 : FlattenedDisplayListIterator(aBuilder, aList, true) {}
7420 virtual bool HasNext() const { return mNext || !mStack.IsEmpty(); }
7422 nsDisplayItem* GetNextItem() {
7423 MOZ_ASSERT(mNext);
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();
7436 return next;
7439 nsDisplayItem* PeekNext() { return mNext; }
7441 protected:
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()) {
7468 ExitChildList();
7470 // We reached the end of the list, pop the next item from the stack.
7471 mNext = mStack.PopLastElement();
7472 } else {
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.
7496 return aCurrent;
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};
7504 do {
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.
7515 return current;
7518 private:
7519 nsDisplayListBuilder* mBuilder;
7520 nsDisplayItem* mNext;
7521 AutoTArray<nsDisplayItem*, 16> mStack;
7524 namespace mozilla {
7526 class PaintTelemetry {
7527 public:
7528 class AutoRecordPaint {
7529 public:
7530 AutoRecordPaint();
7531 ~AutoRecordPaint();
7533 private:
7534 mozilla::TimeStamp mStart;
7537 private:
7538 static uint32_t sPaintLevel;
7541 } // namespace mozilla
7543 #endif /*NSDISPLAYLIST_H_*/