Line data Source code
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 : */
7 :
8 : /*
9 : * structures that represent things to be painted (ordered in z-order),
10 : * used during painting and hit testing
11 : */
12 :
13 : #ifndef NSDISPLAYLIST_H_
14 : #define NSDISPLAYLIST_H_
15 :
16 : #include "mozilla/Attributes.h"
17 : #include "gfxContext.h"
18 : #include "mozilla/ArenaAllocator.h"
19 : #include "mozilla/Assertions.h"
20 : #include "mozilla/Attributes.h"
21 : #include "mozilla/Array.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 "ImgDrawResult.h"
38 : #include "mozilla/EffectCompositor.h"
39 : #include "mozilla/EnumeratedArray.h"
40 : #include "mozilla/Maybe.h"
41 : #include "mozilla/UniquePtr.h"
42 : #include "mozilla/TimeStamp.h"
43 : #include "mozilla/gfx/UserData.h"
44 : #include "mozilla/layers/LayerAttributes.h"
45 : #include "nsCSSRenderingBorders.h"
46 : #include "nsPresArena.h"
47 : #include "nsAutoLayoutPhase.h"
48 : #include "nsDisplayItemTypes.h"
49 : #include "RetainedDisplayListHelpers.h"
50 :
51 : #include <stdint.h>
52 : #include "nsTHashtable.h"
53 :
54 : #include <stdlib.h>
55 : #include <algorithm>
56 : #include <unordered_set>
57 :
58 : class gfxContext;
59 : class nsIContent;
60 : class nsDisplayList;
61 : class nsDisplayTableItem;
62 : class nsIScrollableFrame;
63 : class nsSubDocumentFrame;
64 : class nsDisplayCompositorHitTestInfo;
65 : class nsDisplayScrollInfoLayer;
66 : class nsCaret;
67 : enum class nsDisplayOwnLayerFlags;
68 :
69 : namespace mozilla {
70 : class FrameLayerBuilder;
71 : namespace layers {
72 : class Layer;
73 : class ImageLayer;
74 : class ImageContainer;
75 : class StackingContextHelper;
76 : class WebRenderCommand;
77 : class WebRenderScrollData;
78 : class WebRenderLayerScrollData;
79 : } // namespace layers
80 : namespace wr {
81 : class DisplayListBuilder;
82 : } // namespace wr
83 : namespace dom {
84 : class Selection;
85 : } // namespace dom
86 : } // namespace mozilla
87 :
88 : // A set of blend modes, that never includes OP_OVER (since it's
89 : // considered the default, rather than a specific blend mode).
90 : typedef mozilla::EnumSet<mozilla::gfx::CompositionOp> BlendModeSet;
91 :
92 : /*
93 : * An nsIFrame can have many different visual parts. For example an image frame
94 : * can have a background, border, and outline, the image itself, and a
95 : * translucent selection overlay. In general these parts can be drawn at
96 : * discontiguous z-levels; see CSS2.1 appendix E:
97 : * http://www.w3.org/TR/CSS21/zindex.html
98 : *
99 : * We construct a display list for a frame tree that contains one item
100 : * for each visual part. The display list is itself a tree since some items
101 : * are containers for other items; however, its structure does not match
102 : * the structure of its source frame tree. The display list items are sorted
103 : * by z-order. A display list can be used to paint the frames, to determine
104 : * which frame is the target of a mouse event, and to determine what areas
105 : * need to be repainted when scrolling. The display lists built for each task
106 : * may be different for efficiency; in particular some frames need special
107 : * display list items only for event handling, and do not create these items
108 : * when the display list will be used for painting (the common case). For
109 : * example, when painting we avoid creating nsDisplayBackground items for
110 : * frames that don't display a visible background, but for event handling
111 : * we need those backgrounds because they are not transparent to events.
112 : *
113 : * We could avoid constructing an explicit display list by traversing the
114 : * frame tree multiple times in clever ways. However, reifying the display list
115 : * reduces code complexity and reduces the number of times each frame must be
116 : * traversed to one, which seems to be good for performance. It also means
117 : * we can share code for painting, event handling and scroll analysis.
118 : *
119 : * Display lists are short-lived; content and frame trees cannot change
120 : * between a display list being created and destroyed. Display lists should
121 : * not be created during reflow because the frame tree may be in an
122 : * inconsistent state (e.g., a frame's stored overflow-area may not include
123 : * the bounds of all its children). However, it should be fine to create
124 : * a display list while a reflow is pending, before it starts.
125 : *
126 : * A display list covers the "extended" frame tree; the display list for a frame
127 : * tree containing FRAME/IFRAME elements can include frames from the subdocuments.
128 : *
129 : * Display item's coordinates are relative to their nearest reference frame ancestor.
130 : * Both the display root and any frame with a transform act as a reference frame
131 : * for their frame subtrees.
132 : */
133 :
134 : // All types are defined in nsDisplayItemTypes.h
135 : #define NS_DISPLAY_DECL_NAME(n, e) \
136 : virtual const char* Name() const override { return n; } \
137 : virtual DisplayItemType GetType() const override { return DisplayItemType::e; } \
138 : private: \
139 : void* operator new(size_t aSize, \
140 : nsDisplayListBuilder* aBuilder) { \
141 : return aBuilder->Allocate(aSize, DisplayItemType::e); \
142 : } \
143 : template<typename T, typename... Args> \
144 : friend T* ::MakeDisplayItem(nsDisplayListBuilder* aBuilder, Args&&... aArgs); \
145 : public:
146 :
147 :
148 : /**
149 : * Represents a frame that is considered to have (or will have) "animated geometry"
150 : * for itself and descendant frames.
151 : *
152 : * For example the scrolled frames of scrollframes which are actively being scrolled
153 : * fall into this category. Frames with certain CSS properties that are being animated
154 : * (e.g. 'left'/'top' etc) are also placed in this category. Frames with different
155 : * active geometry roots are in different PaintedLayers, so that we can animate the
156 : * geometry root by changing its transform (either on the main thread or in the
157 : * compositor).
158 : *
159 : * nsDisplayListBuilder constructs a tree of these (for fast traversals) and assigns
160 : * one for each display item.
161 : *
162 : * The animated geometry root for a display item is required to be a descendant (or
163 : * equal to) the item's ReferenceFrame(), which means that we will fall back to
164 : * returning aItem->ReferenceFrame() when we can't find another animated geometry root.
165 : *
166 : * The animated geometry root isn't strongly defined for a frame as transforms and
167 : * background-attachment:fixed can cause it to vary between display items for a given
168 : * frame.
169 : */
170 : struct AnimatedGeometryRoot
171 : {
172 : static already_AddRefed<AnimatedGeometryRoot>
173 : CreateAGRForFrame(nsIFrame* aFrame, AnimatedGeometryRoot* aParent, bool aIsAsync, bool aIsRetained)
174 : {
175 : RefPtr<AnimatedGeometryRoot> result;
176 : if (aIsRetained) {
177 : result = aFrame->GetProperty(AnimatedGeometryRootCache());
178 : }
179 :
180 : if (result) {
181 : result->mParentAGR = aParent;
182 : result->mIsAsync = aIsAsync;
183 : } else {
184 : result = new AnimatedGeometryRoot(aFrame, aParent, aIsAsync, aIsRetained);
185 : }
186 : return result.forget();
187 : }
188 :
189 : operator nsIFrame*() { return mFrame; }
190 :
191 : nsIFrame* operator ->() const { return mFrame; }
192 :
193 : AnimatedGeometryRoot* GetAsyncAGR() {
194 : AnimatedGeometryRoot* agr = this;
195 : while (!agr->mIsAsync && agr->mParentAGR) {
196 : agr = agr->mParentAGR;
197 : }
198 : return agr;
199 : }
200 :
201 0 : NS_INLINE_DECL_REFCOUNTING(AnimatedGeometryRoot)
202 :
203 : nsIFrame* mFrame;
204 : RefPtr<AnimatedGeometryRoot> mParentAGR;
205 : bool mIsAsync;
206 : bool mIsRetained;
207 :
208 : protected:
209 0 : static void DetachAGR(AnimatedGeometryRoot* aAGR) {
210 0 : aAGR->mFrame = nullptr;
211 0 : aAGR->mParentAGR = nullptr;
212 0 : NS_RELEASE(aAGR);
213 0 : }
214 : NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnimatedGeometryRootCache, AnimatedGeometryRoot, DetachAGR)
215 :
216 : AnimatedGeometryRoot(nsIFrame* aFrame, AnimatedGeometryRoot* aParent, bool aIsAsync, bool aIsRetained)
217 : : mFrame(aFrame)
218 : , mParentAGR(aParent)
219 : , mIsAsync(aIsAsync)
220 : , mIsRetained(aIsRetained)
221 : {
222 : MOZ_ASSERT(mParentAGR || mIsAsync, "The root AGR should always be treated as an async AGR.");
223 : if (mIsRetained) {
224 : NS_ADDREF(this);
225 : aFrame->SetProperty(AnimatedGeometryRootCache(), this);
226 : }
227 : }
228 :
229 0 : ~AnimatedGeometryRoot()
230 0 : {
231 0 : if (mFrame && mIsRetained) {
232 0 : mFrame->DeleteProperty(AnimatedGeometryRootCache());
233 : }
234 0 : }
235 : };
236 :
237 : namespace mozilla {
238 :
239 : /**
240 : * An active scrolled root (ASR) is similar to an animated geometry root (AGR).
241 : * The differences are:
242 : * - ASRs are only created for async-scrollable scroll frames. This is a
243 : * (hopefully) temporary restriction. In the future we will want to create
244 : * ASRs for all the things that are currently creating AGRs, and then
245 : * replace AGRs with ASRs and rename them from "active scrolled root" to
246 : * "animated geometry root".
247 : * - ASR objects are created during display list construction by the nsIFrames
248 : * that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter.
249 : * The current ASR is returned by nsDisplayListBuilder::CurrentActiveScrolledRoot().
250 : * - There is no way to go from an nsIFrame pointer to the ASR of that frame.
251 : * If you need to look up an ASR after display list construction, you need
252 : * to store it while the AutoCurrentActiveScrolledRootSetter that creates it
253 : * is on the stack.
254 : */
255 : struct ActiveScrolledRoot {
256 : static already_AddRefed<ActiveScrolledRoot>
257 : CreateASRForFrame(const ActiveScrolledRoot* aParent,
258 : nsIScrollableFrame* aScrollableFrame,
259 : bool aIsRetained)
260 : {
261 : nsIFrame* f = do_QueryFrame(aScrollableFrame);
262 :
263 : RefPtr<ActiveScrolledRoot> asr;
264 : if (aIsRetained) {
265 : asr = f->GetProperty(ActiveScrolledRootCache());
266 : }
267 :
268 : if (!asr) {
269 : asr = new ActiveScrolledRoot();
270 :
271 : if (aIsRetained) {
272 : RefPtr<ActiveScrolledRoot> ref = asr;
273 : f->SetProperty(ActiveScrolledRootCache(), ref.forget().take());
274 : }
275 : }
276 : asr->mParent = aParent;
277 : asr->mScrollableFrame = aScrollableFrame;
278 : asr->mViewId = Nothing();
279 : asr->mDepth = aParent ? aParent->mDepth + 1 : 1;
280 : asr->mRetained = aIsRetained;
281 :
282 : return asr.forget();
283 : }
284 :
285 : static const ActiveScrolledRoot* PickAncestor(const ActiveScrolledRoot* aOne,
286 : const ActiveScrolledRoot* aTwo)
287 : {
288 : MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
289 : return Depth(aOne) <= Depth(aTwo) ? aOne : aTwo;
290 : }
291 :
292 2 : static const ActiveScrolledRoot* PickDescendant(const ActiveScrolledRoot* aOne,
293 : const ActiveScrolledRoot* aTwo)
294 : {
295 2 : MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
296 2 : return Depth(aOne) >= Depth(aTwo) ? aOne : aTwo;
297 : }
298 :
299 : static bool IsAncestor(const ActiveScrolledRoot* aAncestor,
300 : const ActiveScrolledRoot* aDescendant);
301 :
302 : static nsCString ToString(const mozilla::ActiveScrolledRoot* aActiveScrolledRoot);
303 :
304 : // Call this when inserting an ancestor.
305 : void IncrementDepth() { mDepth++; }
306 :
307 : /**
308 : * Find the view ID (or generate a new one) for the content element
309 : * corresponding to the ASR.
310 : */
311 0 : mozilla::layers::FrameMetrics::ViewID GetViewId() const {
312 0 : if (!mViewId.isSome()) {
313 0 : nsIContent* content = mScrollableFrame->GetScrolledFrame()->GetContent();
314 0 : mViewId = Some(nsLayoutUtils::FindOrCreateIDFor(content));
315 : }
316 0 : return *mViewId;
317 : }
318 :
319 : RefPtr<const ActiveScrolledRoot> mParent;
320 : nsIScrollableFrame* mScrollableFrame;
321 :
322 0 : NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot)
323 :
324 : private:
325 : ActiveScrolledRoot()
326 : : mScrollableFrame(nullptr)
327 : , mDepth(0)
328 : , mRetained(false)
329 0 : {
330 0 : }
331 0 :
332 0 : ~ActiveScrolledRoot()
333 0 : {
334 : if (mScrollableFrame && mRetained) {
335 0 : nsIFrame* f = do_QueryFrame(mScrollableFrame);
336 : f->DeleteProperty(ActiveScrolledRootCache());
337 0 : }
338 0 : }
339 0 :
340 0 : static void DetachASR(ActiveScrolledRoot* aASR) {
341 0 : aASR->mParent = nullptr;
342 : aASR->mScrollableFrame = nullptr;
343 : NS_RELEASE(aASR);
344 : }
345 0 : NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache, ActiveScrolledRoot, DetachASR)
346 :
347 : static uint32_t Depth(const ActiveScrolledRoot* aActiveScrolledRoot) {
348 : return aActiveScrolledRoot ? aActiveScrolledRoot->mDepth : 0;
349 : }
350 :
351 : // This field is lazily populated in GetViewId(). We don't want to do the
352 : // work of populating if webrender is disabled, because it is often not
353 : // needed.
354 : mutable Maybe<mozilla::layers::FrameMetrics::ViewID> mViewId;
355 :
356 : uint32_t mDepth;
357 : bool mRetained;
358 : };
359 :
360 : }
361 :
362 : enum class nsDisplayListBuilderMode : uint8_t {
363 : PAINTING,
364 : EVENT_DELIVERY,
365 : PLUGIN_GEOMETRY,
366 : FRAME_VISIBILITY,
367 : TRANSFORM_COMPUTATION,
368 : GENERATE_GLYPH,
369 : PAINTING_SELECTION_BACKGROUND
370 : };
371 :
372 : /**
373 : * This manages a display list and is passed as a parameter to
374 : * nsIFrame::BuildDisplayList.
375 : * It contains the parameters that don't change from frame to frame and manages
376 : * the display list memory using an arena. It also establishes the reference
377 : * coordinate system for all display list items. Some of the parameters are
378 : * available from the prescontext/presshell, but we copy them into the builder
379 : * for faster/more convenient access.
380 : */
381 : class nsDisplayListBuilder {
382 : typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
383 : typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
384 :
385 : /**
386 : * This manages status of a 3d context to collect visible rects of
387 : * descendants and passing a dirty rect.
388 : *
389 : * Since some transforms maybe singular, passing visible rects or
390 : * the dirty rect level by level from parent to children may get a
391 : * wrong result, being different from the result of appling with
392 : * effective transform directly.
393 : *
394 : * nsFrame::BuildDisplayListForStackingContext() uses
395 : * AutoPreserves3DContext to install an instance on the builder.
396 : *
397 : * \see AutoAccumulateTransform, AutoAccumulateRect,
398 : * AutoPreserves3DContext, Accumulate, GetCurrentTransform,
399 : * StartRoot.
400 : */
401 : class Preserves3DContext {
402 : public:
403 : typedef mozilla::gfx::Matrix4x4 Matrix4x4;
404 :
405 : Preserves3DContext()
406 : : mAccumulatedRectLevels(0)
407 : {}
408 : Preserves3DContext(const Preserves3DContext &aOther)
409 : : mAccumulatedTransform()
410 : , mAccumulatedRect()
411 : , mAccumulatedRectLevels(0)
412 : , mVisibleRect(aOther.mVisibleRect) {}
413 :
414 : // Accmulate transforms of ancestors on the preserves-3d chain.
415 : Matrix4x4 mAccumulatedTransform;
416 : // Accmulate visible rect of descendants in the preserves-3d context.
417 : nsRect mAccumulatedRect;
418 : // How far this frame is from the root of the current 3d context.
419 : int mAccumulatedRectLevels;
420 : nsRect mVisibleRect;
421 : };
422 :
423 : /**
424 : * A frame can be in one of three states of AGR.
425 : * AGR_NO means the frame is not an AGR for now.
426 : * AGR_YES means the frame is an AGR for now.
427 : * AGR_MAYBE means the frame is not an AGR for now, but a transition
428 : * to AGR_YES without restyling is possible.
429 : */
430 : enum AGRState { AGR_NO, AGR_YES, AGR_MAYBE };
431 :
432 : public:
433 : typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
434 : typedef mozilla::DisplayItemClip DisplayItemClip;
435 : typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
436 : typedef mozilla::DisplayItemClipChainHasher DisplayItemClipChainHasher;
437 : typedef mozilla::DisplayItemClipChainEqualer DisplayItemClipChainEqualer;
438 : typedef mozilla::DisplayListClipState DisplayListClipState;
439 : typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
440 : typedef nsIWidget::ThemeGeometry ThemeGeometry;
441 : typedef mozilla::layers::Layer Layer;
442 : typedef mozilla::layers::FrameMetrics FrameMetrics;
443 : typedef mozilla::layers::FrameMetrics::ViewID ViewID;
444 : typedef mozilla::gfx::Matrix4x4 Matrix4x4;
445 : typedef mozilla::Maybe<mozilla::layers::ScrollDirection> MaybeScrollDirection;
446 :
447 : /**
448 : * @param aReferenceFrame the frame at the root of the subtree; its origin
449 : * is the origin of the reference coordinate system for this display list
450 : * @param aMode encodes what the builder is being used for.
451 : * @param aBuildCaret whether or not we should include the caret in any
452 : * display lists that we make.
453 : */
454 : nsDisplayListBuilder(nsIFrame* aReferenceFrame,
455 : nsDisplayListBuilderMode aMode,
456 : bool aBuildCaret,
457 : bool aRetainingDisplayList = false);
458 : ~nsDisplayListBuilder();
459 :
460 : void BeginFrame();
461 : void EndFrame();
462 :
463 : void AddTemporaryItem(nsDisplayItem* aItem)
464 : {
465 : mTemporaryItems.AppendElement(aItem);
466 : }
467 :
468 : void SetWillComputePluginGeometry(bool aWillComputePluginGeometry)
469 : {
470 : mWillComputePluginGeometry = aWillComputePluginGeometry;
471 : }
472 : void SetForPluginGeometry(bool aForPlugin)
473 : {
474 : if (aForPlugin) {
475 : NS_ASSERTION(mMode == nsDisplayListBuilderMode::PAINTING, "Can only switch from PAINTING to PLUGIN_GEOMETRY");
476 : NS_ASSERTION(mWillComputePluginGeometry, "Should have signalled this in advance");
477 : mMode = nsDisplayListBuilderMode::PLUGIN_GEOMETRY;
478 : } else {
479 : NS_ASSERTION(mMode == nsDisplayListBuilderMode::PLUGIN_GEOMETRY, "Can only switch from PAINTING to PLUGIN_GEOMETRY");
480 : mMode = nsDisplayListBuilderMode::PAINTING;
481 : }
482 : }
483 :
484 : mozilla::layers::LayerManager* GetWidgetLayerManager(nsView** aView = nullptr);
485 :
486 : /**
487 : * @return true if the display is being built in order to determine which
488 : * frame is under the mouse position.
489 : */
490 : bool IsForEventDelivery()
491 : {
492 : return mMode == nsDisplayListBuilderMode::EVENT_DELIVERY;
493 : }
494 :
495 : /**
496 : * Be careful with this. The display list will be built in PAINTING mode
497 : * first and then switched to PLUGIN_GEOMETRY before a second call to
498 : * ComputeVisibility.
499 : * @return true if the display list is being built to compute geometry
500 : * for plugins.
501 : */
502 : bool IsForPluginGeometry()
503 : {
504 : return mMode == nsDisplayListBuilderMode::PLUGIN_GEOMETRY;
505 : }
506 :
507 : /**
508 : * @return true if the display list is being built for painting.
509 : */
510 : bool IsForPainting()
511 : {
512 : return mMode == nsDisplayListBuilderMode::PAINTING;
513 : }
514 :
515 : /**
516 : * @return true if the display list is being built for determining frame
517 : * visibility.
518 : */
519 : bool IsForFrameVisibility()
520 : {
521 : return mMode == nsDisplayListBuilderMode::FRAME_VISIBILITY;
522 : }
523 :
524 : /**
525 : * @return true if the display list is being built for creating the glyph
526 : * mask from text items.
527 : */
528 : bool IsForGenerateGlyphMask()
529 : {
530 : return mMode == nsDisplayListBuilderMode::GENERATE_GLYPH;
531 : }
532 :
533 : /**
534 : * @return true if the display list is being built for painting selection
535 : * background.
536 : */
537 : bool IsForPaintingSelectionBG()
538 : {
539 : return mMode == nsDisplayListBuilderMode::PAINTING_SELECTION_BACKGROUND;
540 : }
541 :
542 : bool BuildCompositorHitTestInfo()
543 : {
544 : return mBuildCompositorHitTestInfo;
545 : }
546 :
547 : bool WillComputePluginGeometry() { return mWillComputePluginGeometry; }
548 : /**
549 : * @return true if "painting is suppressed" during page load and we
550 : * should paint only the background of the document.
551 : */
552 : bool IsBackgroundOnly() {
553 : NS_ASSERTION(mPresShellStates.Length() > 0,
554 : "don't call this if we're not in a presshell");
555 : return CurrentPresShellState()->mIsBackgroundOnly;
556 : }
557 : /**
558 : * @return true if the currently active BuildDisplayList call is being
559 : * applied to a frame at the root of a pseudo stacking context. A pseudo
560 : * stacking context is either a real stacking context or basically what
561 : * CSS2.1 appendix E refers to with "treat the element as if it created
562 : * a new stacking context
563 : */
564 : bool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; }
565 :
566 : /**
567 : * @return the selection that painting should be restricted to (or nullptr
568 : * in the normal unrestricted case)
569 : */
570 : mozilla::dom::Selection* GetBoundingSelection() { return mBoundingSelection; }
571 :
572 : /**
573 : * @return the root of given frame's (sub)tree, whose origin
574 : * establishes the coordinate system for the child display items.
575 : */
576 : const nsIFrame* FindReferenceFrameFor(const nsIFrame *aFrame,
577 : nsPoint* aOffset = nullptr) const;
578 :
579 : /**
580 : * @return the root of the display list's frame (sub)tree, whose origin
581 : * establishes the coordinate system for the display list
582 : */
583 : nsIFrame* RootReferenceFrame()
584 : {
585 : return mReferenceFrame;
586 : }
587 :
588 : /**
589 : * @return a point pt such that adding pt to a coordinate relative to aFrame
590 : * makes it relative to ReferenceFrame(), i.e., returns
591 0 : * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
592 : * the appunits of aFrame.
593 0 : */
594 0 : const nsPoint ToReferenceFrame(const nsIFrame* aFrame) const
595 0 : {
596 : nsPoint result;
597 : FindReferenceFrameFor(aFrame, &result);
598 : return result;
599 : }
600 : /**
601 : * When building the display list, the scrollframe aFrame will be "ignored"
602 : * for the purposes of clipping, and its scrollbars will be hidden. We use
603 : * this to allow RenderOffscreen to render a whole document without beign
604 : * clipped by the viewport or drawing the viewport scrollbars.
605 : */
606 : void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
607 : /**
608 : * Get the scrollframe to ignore, if any.
609 : */
610 : nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
611 : /**
612 : * Get the ViewID of the nearest scrolling ancestor frame.
613 : */
614 : ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
615 : /**
616 : * Get and set the flag that indicates if scroll parents should have layers
617 : * forcibly created. This flag is set when a deeply nested scrollframe has
618 : * a displayport, and for scroll handoff to work properly the ancestor
619 : * scrollframes should also get their own scrollable layers.
620 : */
621 : void ForceLayerForScrollParent() { mForceLayerForScrollParent = true; }
622 : /**
623 : * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
624 : * which we are building display items at the moment.
625 : */
626 : ViewID GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget; }
627 : MaybeScrollDirection GetCurrentScrollbarDirection() const { return mCurrentScrollbarDirection; }
628 : /**
629 : * Returns true if building a scrollbar, and the scrollbar will not be
630 : * layerized.
631 : */
632 : bool IsBuildingNonLayerizedScrollbar() const {
633 : return mIsBuildingScrollbar && !mCurrentScrollbarWillHaveLayer;
634 : }
635 : /**
636 : * Calling this setter makes us include all out-of-flow descendant
637 : * frames in the display list, wherever they may be positioned (even
638 : * outside the dirty rects).
639 : */
640 : void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
641 : bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
642 : /**
643 : * Calling this setter makes us exclude all leaf frames that aren't
644 : * selected.
645 : */
646 : void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
647 : bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
648 : /**
649 : * Calling this setter makes us compute accurate visible regions at the cost
650 : * of performance if regions get very complex.
651 : */
652 : bool GetAccurateVisibleRegions() { return mMode == nsDisplayListBuilderMode::PLUGIN_GEOMETRY; }
653 : /**
654 : * @return Returns true if we should include the caret in any display lists
655 : * that we make.
656 : */
657 : bool IsBuildingCaret() const { return mBuildCaret; }
658 :
659 : bool IsRetainingDisplayList() const { return mRetainingDisplayList; }
660 :
661 : bool IsPartialUpdate() const { return mPartialUpdate; }
662 : void SetPartialUpdate(bool aPartial) { mPartialUpdate = aPartial; }
663 :
664 : bool IsBuilding() const { return mIsBuilding; }
665 : void SetIsBuilding(bool aIsBuilding)
666 : {
667 : mIsBuilding = aIsBuilding;
668 : for (nsIFrame* f : mModifiedFramesDuringBuilding) {
669 : f->SetFrameIsModified(false);
670 : }
671 : mModifiedFramesDuringBuilding.Clear();
672 : }
673 :
674 : bool InInvalidSubtree() const { return mInInvalidSubtree; }
675 :
676 : /**
677 : * Allows callers to selectively override the regular paint suppression checks,
678 : * so that methods like GetFrameForPoint work when painting is suppressed.
679 : */
680 : void IgnorePaintSuppression() { mIgnoreSuppression = true; }
681 : /**
682 : * @return Returns if this builder will ignore paint suppression.
683 : */
684 : bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
685 : /**
686 : * Call this if we're doing normal painting to the window.
687 : */
688 : void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
689 : bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
690 : /**
691 : * Call this to prevent descending into subdocuments.
692 : */
693 : void SetDescendIntoSubdocuments(bool aDescend) { mDescendIntoSubdocuments = aDescend; }
694 : bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }
695 :
696 : /**
697 : * Get dirty rect relative to current frame (the frame that we're calling
698 : * BuildDisplayList on right now).
699 : */
700 : const nsRect& GetVisibleRect() { return mVisibleRect; }
701 : const nsRect& GetDirtyRect() { return mDirtyRect; }
702 :
703 : void SetVisibleRect(const nsRect& aVisibleRect) { mVisibleRect = aVisibleRect; }
704 : void IntersectVisibleRect(const nsRect& aVisibleRect) { mVisibleRect.IntersectRect(mVisibleRect, aVisibleRect); }
705 : void SetDirtyRect(const nsRect& aDirtyRect) { mDirtyRect = aDirtyRect; }
706 : void IntersectDirtyRect(const nsRect& aDirtyRect) { mDirtyRect.IntersectRect(mDirtyRect, aDirtyRect); }
707 :
708 : const nsIFrame* GetCurrentFrame() { return mCurrentFrame; }
709 : const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; }
710 : const nsPoint& GetCurrentFrameOffsetToReferenceFrame() { return mCurrentOffsetToReferenceFrame; }
711 : AnimatedGeometryRoot* GetCurrentAnimatedGeometryRoot() {
712 : return mCurrentAGR;
713 : }
714 : AnimatedGeometryRoot* GetRootAnimatedGeometryRoot() {
715 : return mRootAGR;
716 : }
717 :
718 : void RecomputeCurrentAnimatedGeometryRoot();
719 :
720 : void Check() {
721 : mPool.Check();
722 : }
723 :
724 : /**
725 : * Returns true if merging and flattening of display lists should be
726 : * performed while computing visibility.
727 : */
728 : bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; }
729 : void SetAllowMergingAndFlattening(bool aAllow) { mAllowMergingAndFlattening = aAllow; }
730 :
731 : /**
732 : * Sets the current compositor hit test info to |aHitTestInfo|.
733 : * This is used during display list building to determine if the parent frame
734 : * hit test info contains the same information that child frame needs.
735 : */
736 : void SetCompositorHitTestInfo(nsDisplayCompositorHitTestInfo* aHitTestInfo)
737 : {
738 : mCompositorHitTestInfo = aHitTestInfo;
739 : }
740 : nsDisplayCompositorHitTestInfo* GetCompositorHitTestInfo() const
741 : {
742 : return mCompositorHitTestInfo;
743 : }
744 :
745 : /**
746 : * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
747 0 : * needed, and adds it to the top of |aList|. If |aBuildNew| is true, the
748 : * previous hit test info will not be reused.
749 0 : */
750 : void BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
751 : nsDisplayList* aList,
752 : const bool aBuildNew);
753 :
754 : bool IsInsidePointerEventsNoneDoc()
755 : {
756 : return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
757 : }
758 :
759 : bool GetAncestorHasApzAwareEventHandler() const { return mAncestorHasApzAwareEventHandler; }
760 : void SetAncestorHasApzAwareEventHandler(bool aValue)
761 : {
762 : mAncestorHasApzAwareEventHandler = aValue;
763 : }
764 :
765 : bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; }
766 : void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; }
767 : void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = false; }
768 :
769 : bool SetIsCompositingCheap(bool aCompositingCheap) {
770 : bool temp = mIsCompositingCheap;
771 : mIsCompositingCheap = aCompositingCheap;
772 : return temp;
773 : }
774 : bool IsCompositingCheap() const { return mIsCompositingCheap; }
775 : /**
776 : * Display the caret if needed.
777 : */
778 : bool DisplayCaret(nsIFrame* aFrame, nsDisplayList* aList)
779 : {
780 : nsIFrame* frame = GetCaretFrame();
781 : if (aFrame == frame) {
782 : frame->DisplayCaret(this, aList);
783 : return true;
784 : }
785 : return false;
786 : }
787 : /**
788 : * Get the frame that the caret is supposed to draw in.
789 : * If the caret is currently invisible, this will be null.
790 : */
791 : nsIFrame* GetCaretFrame() {
792 : return CurrentPresShellState()->mCaretFrame;
793 : }
794 : /**
795 : * Get the rectangle we're supposed to draw the caret into.
796 : */
797 : const nsRect& GetCaretRect() {
798 : return CurrentPresShellState()->mCaretRect;
799 : }
800 : /**
801 : * Get the caret associated with the current presshell.
802 : */
803 : nsCaret* GetCaret();
804 : /**
805 : * Notify the display list builder that we're entering a presshell.
806 : * aReferenceFrame should be a frame in the new presshell.
807 : * aPointerEventsNoneDoc should be set to true if the frame generating this
808 : * document is pointer-events:none.
809 : */
810 : void EnterPresShell(nsIFrame* aReferenceFrame,
811 : bool aPointerEventsNoneDoc = false);
812 : /**
813 : * For print-preview documents, we sometimes need to build display items for
814 : * the same frames multiple times in the same presentation, with different
815 : * clipping. Between each such batch of items, call
816 : * ResetMarkedFramesForDisplayList to make sure that the results of
817 : * MarkFramesForDisplayList do not carry over between batches.
818 : */
819 : void ResetMarkedFramesForDisplayList(nsIFrame* aReferenceFrame);
820 : /**
821 : * Notify the display list builder that we're leaving a presshell.
822 : */
823 : void LeavePresShell(nsIFrame* aReferenceFrame, nsDisplayList* aPaintedContents);
824 :
825 : void IncrementPresShellPaintCount(nsIPresShell* aPresShell);
826 :
827 : /**
828 : * Returns true if we're currently building a display list that's
829 : * directly or indirectly under an nsDisplayTransform.
830 : */
831 : bool IsInTransform() const { return mInTransform; }
832 : /**
833 : * Indicate whether or not we're directly or indirectly under and
834 : * nsDisplayTransform or SVG foreignObject.
835 : */
836 : void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }
837 :
838 : bool IsInPageSequence() const { return mInPageSequence; }
839 : void SetInPageSequence(bool aInPage) { mInPageSequence = aInPage; }
840 :
841 : /**
842 : * Return true if we're currently building a display list for a
843 : * nested presshell.
844 : */
845 : bool IsInSubdocument() { return mPresShellStates.Length() > 1; }
846 :
847 : void SetDisablePartialUpdates(bool aDisable) { mDisablePartialUpdates = aDisable; }
848 : bool DisablePartialUpdates() { return mDisablePartialUpdates; }
849 :
850 : void SetPartialBuildFailed(bool aFailed) { mPartialBuildFailed = aFailed; }
851 : bool PartialBuildFailed() { return mPartialBuildFailed; }
852 :
853 : /**
854 : * Return true if we're currently building a display list for the presshell
855 : * of a chrome document, or if we're building the display list for a popup.
856 : */
857 : bool IsInChromeDocumentOrPopup() {
858 : return mIsInChromePresContext || mIsBuildingForPopup;
859 : }
860 :
861 : /**
862 : * @return true if images have been set to decode synchronously.
863 : */
864 : bool ShouldSyncDecodeImages() { return mSyncDecodeImages; }
865 :
866 : /**
867 : * Indicates whether we should synchronously decode images. If true, we decode
868 : * and draw whatever image data has been loaded. If false, we just draw
869 : * whatever has already been decoded.
870 : */
871 : void SetSyncDecodeImages(bool aSyncDecodeImages) {
872 : mSyncDecodeImages = aSyncDecodeImages;
873 : }
874 :
875 : void FreeClipChains();
876 :
877 : /*
878 : * Frees the temporary display items created during merging.
879 : */
880 : void FreeTemporaryItems();
881 :
882 : /**
883 : * Helper method to generate background painting flags based on the
884 : * information available in the display list builder. Currently only
885 : * accounts for mSyncDecodeImages.
886 : */
887 : uint32_t GetBackgroundPaintFlags();
888 :
889 : /**
890 : * Subtracts aRegion from *aVisibleRegion. We avoid letting
891 : * aVisibleRegion become overcomplex by simplifying it if necessary.
892 : */
893 : void SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
894 : const nsRegion& aRegion);
895 :
896 : /**
897 : * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
898 : * (which is relative to aDirtyFrame). If the frames have placeholders
899 : * that might not be displayed, we mark the placeholders and their ancestors
900 : * to ensure that display list construction descends into them
901 : * anyway. nsDisplayListBuilder will take care of unmarking them when it is
902 : * destroyed.
903 : */
904 : void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
905 : const nsFrameList& aFrames);
906 : void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame);
907 : void MarkFrameForDisplayIfVisible(nsIFrame* aFrame, nsIFrame* aStopAtFrame);
908 : void AddFrameMarkedForDisplayIfVisible(nsIFrame* aFrame);
909 :
910 : void ClearFixedBackgroundDisplayData();
911 : /**
912 : * Mark all child frames that Preserve3D() as needing display.
913 : * Because these frames include transforms set on their parent, dirty rects
914 : * for intermediate frames may be empty, yet child frames could still be visible.
915 : */
916 : void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame);
917 :
918 : /**
919 : * Returns true if we need to descend into this frame when building
920 : * the display list, even though it doesn't intersect the dirty
921 : * rect, because it may have out-of-flows that do so.
922 : */
923 : bool ShouldDescendIntoFrame(nsIFrame* aFrame, bool aVisible) const {
924 : return
925 : (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
926 : (aVisible && aFrame->ForceDescendIntoIfVisible()) ||
927 : GetIncludeAllOutOfFlows();
928 : }
929 :
930 : /**
931 : * Returns the list of registered theme geometries.
932 : */
933 : nsTArray<ThemeGeometry> GetThemeGeometries() const
934 : {
935 : nsTArray<ThemeGeometry> geometries;
936 :
937 : for (auto iter = mThemeGeometries.ConstIter(); !iter.Done(); iter.Next()) {
938 : geometries.AppendElements(*iter.Data());
939 : }
940 :
941 : return geometries;
942 : }
943 :
944 : /**
945 : * Notifies the builder that a particular themed widget exists
946 : * at the given rectangle within the currently built display list.
947 : * For certain appearance values (currently only NS_THEME_TOOLBAR and
948 : * NS_THEME_WINDOW_TITLEBAR) this gets called during every display list
949 : * construction, for every themed widget of the right type within the
950 : * display list, except for themed widgets which are transformed or have
951 : * effects applied to them (e.g. CSS opacity or filters).
952 : *
953 : * @param aWidgetType the -moz-appearance value for the themed widget
954 : * @param aItem the item associated with the theme geometry
955 : * @param aRect the device-pixel rect relative to the widget's displayRoot
956 : * for the themed widget
957 : */
958 : void RegisterThemeGeometry(uint8_t aWidgetType, nsDisplayItem* aItem,
959 : const mozilla::LayoutDeviceIntRect& aRect)
960 : {
961 : if (!mIsPaintingToWindow) {
962 : return;
963 : }
964 :
965 0 : nsTArray<ThemeGeometry>* geometries = mThemeGeometries.LookupOrAdd(aItem);
966 : geometries->AppendElement(ThemeGeometry(aWidgetType, aRect));
967 0 : }
968 0 :
969 : /**
970 : * Removes theme geometries associated with the given display item |aItem|.
971 : */
972 : void UnregisterThemeGeometry(nsDisplayItem* aItem)
973 : {
974 : mThemeGeometries.Remove(aItem);
975 : }
976 :
977 : /**
978 : * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
979 : * -moz-window-dragging value is |drag|, its border box is added to the
980 : * collected dragging region; if the value is |no-drag|, the border box is
981 : * subtracted from the region; if the value is |default|, that frame does
982 : * not influence the window dragging region.
983 : */
984 : void AdjustWindowDraggingRegion(nsIFrame* aFrame);
985 :
986 : LayoutDeviceIntRegion GetWindowDraggingRegion() const;
987 :
988 : void RemoveModifiedWindowRegions();
989 : void ClearRetainedWindowRegions();
990 :
991 : /**
992 : * Allocate memory in our arena. It will only be freed when this display list
993 : * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
994 : * destructors are called as soon as the item is no longer used.
995 : */
996 : void* Allocate(size_t aSize, DisplayItemType aType);
997 :
998 : void Destroy(DisplayItemType aType, void* aPtr);
999 :
1000 : /**
1001 : * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
1002 : * automatically when the arena goes away.
1003 : */
1004 : ActiveScrolledRoot* AllocateActiveScrolledRoot(const ActiveScrolledRoot* aParent,
1005 : nsIScrollableFrame* aScrollableFrame);
1006 :
1007 : /**
1008 : * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
1009 : * up automatically when the arena goes away.
1010 : */
1011 : const DisplayItemClipChain* AllocateDisplayItemClipChain(const DisplayItemClip& aClip,
1012 : const ActiveScrolledRoot* aASR,
1013 : const DisplayItemClipChain* aParent);
1014 :
1015 : /**
1016 : * Intersect two clip chains, allocating the new clip chain items in this
1017 : * builder's arena. The result is parented to aAncestor, and no intersections
1018 : * happen past aAncestor's ASR.
1019 : * That means aAncestor has to be living in this builder's arena already.
1020 : * aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
1021 : * their values are copied into the newly-allocated intersected clip chain
1022 : * and this function does not hold on to any pointers to them.
1023 : */
1024 : const DisplayItemClipChain* CreateClipChainIntersection(const DisplayItemClipChain* aAncestor,
1025 : const DisplayItemClipChain* aLeafClip1,
1026 : const DisplayItemClipChain* aLeafClip2);
1027 :
1028 : /**
1029 : * Clone the supplied clip chain's chain items into this builder's arena.
1030 : */
1031 : const DisplayItemClipChain* CopyWholeChain(const DisplayItemClipChain* aClipChain);
1032 :
1033 : /**
1034 : * Only used for containerful root scrolling. This is a workaround.
1035 : */
1036 : void SetActiveScrolledRootForRootScrollframe(const ActiveScrolledRoot* aASR)
1037 : { mActiveScrolledRootForRootScrollframe = aASR; }
1038 : const ActiveScrolledRoot* ActiveScrolledRootForRootScrollframe() const
1039 : { return mActiveScrolledRootForRootScrollframe; }
1040 :
1041 : /**
1042 : * Transfer off main thread animations to the layer. May be called
1043 : * with aBuilder and aItem both null, but only if the caller has
1044 : * already checked that off main thread animations should be sent to
1045 : * the layer. When they are both null, the animations are added to
1046 : * the layer as pending animations.
1047 : */
1048 : static void AddAnimationsAndTransitionsToLayer(Layer* aLayer,
1049 : nsDisplayListBuilder* aBuilder,
1050 : nsDisplayItem* aItem,
1051 : nsIFrame* aFrame,
1052 : nsCSSPropertyID aProperty);
1053 :
1054 : /**
1055 : * Merges the display items in |aMergedItems| and returns a new temporary
1056 : * display item.
1057 : * The display items in |aMergedItems| have to be mergeable with each other.
1058 : */
1059 : nsDisplayItem* MergeItems(nsTArray<nsDisplayItem*>& aMergedItems);
1060 :
1061 : /**
1062 : * A helper class to temporarily set the value of
1063 : * mIsAtRootOfPseudoStackingContext, and temporarily
1064 : * set mCurrentFrame and related state. Also temporarily sets mDirtyRect.
1065 : * aDirtyRect is relative to aForChild.
1066 : */
1067 : class AutoBuildingDisplayList {
1068 : public:
1069 : AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder,
1070 : nsIFrame* aForChild,
1071 : const nsRect& aVisibleRect,
1072 : const nsRect& aDirtyRect,
1073 : bool aIsRoot)
1074 : : mBuilder(aBuilder),
1075 : mPrevFrame(aBuilder->mCurrentFrame),
1076 : mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame),
1077 : mPrevCompositorHitTestInfo(aBuilder->mCompositorHitTestInfo),
1078 : mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame),
1079 : mPrevVisibleRect(aBuilder->mVisibleRect),
1080 : mPrevDirtyRect(aBuilder->mDirtyRect),
1081 : mPrevAGR(aBuilder->mCurrentAGR),
1082 : mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext),
1083 : mPrevAncestorHasApzAwareEventHandler(aBuilder->mAncestorHasApzAwareEventHandler),
1084 : mPrevBuildingInvisibleItems(aBuilder->mBuildingInvisibleItems),
1085 : mPrevInInvalidSubtree(aBuilder->mInInvalidSubtree)
1086 : {
1087 : if (aForChild->IsTransformed()) {
1088 : aBuilder->mCurrentOffsetToReferenceFrame = nsPoint();
1089 : aBuilder->mCurrentReferenceFrame = aForChild;
1090 : } else if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
1091 : aBuilder->mCurrentOffsetToReferenceFrame += aForChild->GetPosition();
1092 : } else {
1093 : aBuilder->mCurrentReferenceFrame =
1094 : aBuilder->FindReferenceFrameFor(aForChild,
1095 : &aBuilder->mCurrentOffsetToReferenceFrame);
1096 : }
1097 : bool isAsync;
1098 : mCurrentAGRState = aBuilder->IsAnimatedGeometryRoot(aForChild, isAsync);
1099 : if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
1100 : if (mCurrentAGRState == AGR_YES) {
1101 : aBuilder->mCurrentAGR = aBuilder->WrapAGRForFrame(aForChild, isAsync, aBuilder->mCurrentAGR);
1102 : }
1103 : } else if (aForChild != aBuilder->mCurrentFrame) {
1104 : aBuilder->mCurrentAGR = aBuilder->FindAnimatedGeometryRootFor(aForChild);
1105 : }
1106 : MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(), *aBuilder->mCurrentAGR));
1107 : aBuilder->mInInvalidSubtree = aBuilder->mInInvalidSubtree || aForChild->IsFrameModified();
1108 : aBuilder->mCurrentFrame = aForChild;
1109 : aBuilder->mVisibleRect = aVisibleRect;
1110 : aBuilder->mDirtyRect = aBuilder->mInInvalidSubtree ? aVisibleRect : aDirtyRect;
1111 : aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
1112 : }
1113 : void SetReferenceFrameAndCurrentOffset(const nsIFrame* aFrame, const nsPoint& aOffset) {
1114 : mBuilder->mCurrentReferenceFrame = aFrame;
1115 : mBuilder->mCurrentOffsetToReferenceFrame = aOffset;
1116 : }
1117 : bool IsAnimatedGeometryRoot() const {
1118 : return mCurrentAGRState == AGR_YES;
1119 : }
1120 : bool MaybeAnimatedGeometryRoot() const {
1121 : return mCurrentAGRState == AGR_MAYBE;
1122 : }
1123 : void RestoreBuildingInvisibleItemsValue() {
1124 : mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
1125 : }
1126 : ~AutoBuildingDisplayList() {
1127 : mBuilder->mCurrentFrame = mPrevFrame;
1128 : mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
1129 : mBuilder->mCompositorHitTestInfo = mPrevCompositorHitTestInfo;
1130 : mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
1131 : mBuilder->mVisibleRect = mPrevVisibleRect;
1132 : mBuilder->mDirtyRect = mPrevDirtyRect;
1133 : mBuilder->mCurrentAGR = mPrevAGR;
1134 : mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext;
1135 : mBuilder->mAncestorHasApzAwareEventHandler = mPrevAncestorHasApzAwareEventHandler;
1136 : mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
1137 : mBuilder->mInInvalidSubtree = mPrevInInvalidSubtree;
1138 : }
1139 : private:
1140 : nsDisplayListBuilder* mBuilder;
1141 : AGRState mCurrentAGRState;
1142 : const nsIFrame* mPrevFrame;
1143 : const nsIFrame* mPrevReferenceFrame;
1144 : nsDisplayCompositorHitTestInfo* mPrevCompositorHitTestInfo;
1145 : nsPoint mPrevOffset;
1146 : nsRect mPrevVisibleRect;
1147 : nsRect mPrevDirtyRect;
1148 : RefPtr<AnimatedGeometryRoot> mPrevAGR;
1149 : bool mPrevIsAtRootOfPseudoStackingContext;
1150 : bool mPrevAncestorHasApzAwareEventHandler;
1151 : bool mPrevBuildingInvisibleItems;
1152 : bool mPrevInInvalidSubtree;
1153 : };
1154 :
1155 : /**
1156 : * A helper class to temporarily set the value of mInTransform.
1157 : */
1158 : class AutoInTransformSetter {
1159 : public:
1160 : AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
1161 : : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
1162 : aBuilder->mInTransform = aInTransform;
1163 : }
1164 : ~AutoInTransformSetter() {
1165 : mBuilder->mInTransform = mOldValue;
1166 : }
1167 : private:
1168 : nsDisplayListBuilder* mBuilder;
1169 : bool mOldValue;
1170 : };
1171 :
1172 : /**
1173 : * A helper class to temporarily set the value of mFilterASR.
1174 : */
1175 : class AutoFilterASRSetter {
1176 : public:
1177 : AutoFilterASRSetter(nsDisplayListBuilder* aBuilder, bool aUsingFilter)
1178 : : mBuilder(aBuilder), mOldValue(aBuilder->mFilterASR)
1179 : {
1180 : if (!aBuilder->mFilterASR && aUsingFilter) {
1181 : aBuilder->mFilterASR = aBuilder->CurrentActiveScrolledRoot();
1182 : }
1183 : }
1184 : ~AutoFilterASRSetter() {
1185 : mBuilder->mFilterASR = mOldValue;
1186 : }
1187 : private:
1188 : nsDisplayListBuilder* mBuilder;
1189 : const ActiveScrolledRoot* mOldValue;
1190 : };
1191 :
1192 : /**
1193 : * A helper class to temporarily set the value of mCurrentScrollParentId.
1194 : */
1195 : class AutoCurrentScrollParentIdSetter {
1196 : public:
1197 : AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId)
1198 : : mBuilder(aBuilder)
1199 : , mOldValue(aBuilder->mCurrentScrollParentId)
1200 : , mOldForceLayer(aBuilder->mForceLayerForScrollParent) {
1201 : // If this AutoCurrentScrollParentIdSetter has the same scrollId as the
1202 : // previous one on the stack, then that means the scrollframe that
1203 : // created this isn't actually scrollable and cannot participate in
1204 : // scroll handoff. We set mCanBeScrollParent to false to indicate this.
1205 : mCanBeScrollParent = (mOldValue != aScrollId);
1206 : aBuilder->mCurrentScrollParentId = aScrollId;
1207 : aBuilder->mForceLayerForScrollParent = false;
1208 : }
1209 : bool ShouldForceLayerForScrollParent() const {
1210 : // Only scrollframes participating in scroll handoff can be forced to
1211 : // layerize
1212 : return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent;
1213 : };
1214 : ~AutoCurrentScrollParentIdSetter() {
1215 : mBuilder->mCurrentScrollParentId = mOldValue;
1216 : if (mCanBeScrollParent) {
1217 : // If this flag is set, caller code is responsible for having dealt
1218 : // with the current value of mBuilder->mForceLayerForScrollParent, so
1219 : // we can just restore the old value.
1220 : mBuilder->mForceLayerForScrollParent = mOldForceLayer;
1221 : } else {
1222 : // Otherwise we need to keep propagating the force-layerization flag
1223 : // upwards to the next ancestor scrollframe that does participate in
1224 : // scroll handoff.
1225 : mBuilder->mForceLayerForScrollParent |= mOldForceLayer;
1226 : }
1227 : }
1228 : private:
1229 : nsDisplayListBuilder* mBuilder;
1230 : ViewID mOldValue;
1231 : bool mOldForceLayer;
1232 : bool mCanBeScrollParent;
1233 : };
1234 :
1235 : /**
1236 : * Used to update the current active scrolled root on the display list
1237 : * builder, and to create new active scrolled roots.
1238 : */
1239 : class AutoCurrentActiveScrolledRootSetter {
1240 : public:
1241 : explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder* aBuilder)
1242 : : mBuilder(aBuilder)
1243 : , mSavedActiveScrolledRoot(aBuilder->mCurrentActiveScrolledRoot)
1244 : , mContentClipASR(aBuilder->ClipState().GetContentClipASR())
1245 : , mDescendantsStartIndex(aBuilder->mActiveScrolledRoots.Length())
1246 : , mUsed(false)
1247 : {
1248 : }
1249 :
1250 : ~AutoCurrentActiveScrolledRootSetter()
1251 : {
1252 : mBuilder->mCurrentActiveScrolledRoot = mSavedActiveScrolledRoot;
1253 : }
1254 :
1255 : void SetCurrentActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot);
1256 :
1257 : void EnterScrollFrame(nsIScrollableFrame* aScrollableFrame)
1258 : {
1259 : MOZ_ASSERT(!mUsed);
1260 : ActiveScrolledRoot* asr = mBuilder->AllocateActiveScrolledRoot(
1261 : mBuilder->mCurrentActiveScrolledRoot, aScrollableFrame);
1262 : mBuilder->mCurrentActiveScrolledRoot = asr;
1263 : mUsed = true;
1264 : }
1265 :
1266 : void InsertScrollFrame(nsIScrollableFrame* aScrollableFrame);
1267 :
1268 : private:
1269 : nsDisplayListBuilder* mBuilder;
1270 : /**
1271 : * The builder's mCurrentActiveScrolledRoot at construction time which
1272 : * needs to be restored at destruction time.
1273 : */
1274 : const ActiveScrolledRoot* mSavedActiveScrolledRoot;
1275 : /**
1276 : * If there's a content clip on the builder at construction time, then
1277 : * mContentClipASR is that content clip's ASR, otherwise null. The
1278 : * assumption is that the content clip doesn't get relaxed while this
1279 : * object is on the stack.
1280 : */
1281 : const ActiveScrolledRoot* mContentClipASR;
1282 : /**
1283 : * InsertScrollFrame needs to mutate existing ASRs (those that were
1284 : * created while this object was on the stack), and mDescendantsStartIndex
1285 : * makes it easier to skip ASRs that were created in the past.
1286 : */
1287 : size_t mDescendantsStartIndex;
1288 : /**
1289 : * Flag to make sure that only one of SetCurrentActiveScrolledRoot /
1290 : * EnterScrollFrame / InsertScrollFrame is called per instance of this
1291 : * class.
1292 : */
1293 : bool mUsed;
1294 : };
1295 :
1296 : /**
1297 : * Keeps track of the innermost ASR that can be used as the ASR for a
1298 : * container item that wraps all items that were created while this
1299 : * object was on the stack.
1300 : * The rule is: all child items of the container item need to have
1301 : * clipped bounds with respect to the container ASR.
1302 : */
1303 : class AutoContainerASRTracker {
1304 : public:
1305 : explicit AutoContainerASRTracker(nsDisplayListBuilder* aBuilder)
1306 : : mBuilder(aBuilder)
1307 : , mSavedContainerASR(aBuilder->mCurrentContainerASR)
1308 : {
1309 : mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickDescendant(
1310 : mBuilder->ClipState().GetContentClipASR(),
1311 : mBuilder->mCurrentActiveScrolledRoot);
1312 : }
1313 :
1314 : const ActiveScrolledRoot* GetContainerASR()
1315 : {
1316 : return mBuilder->mCurrentContainerASR;
1317 : }
1318 :
1319 : ~AutoContainerASRTracker()
1320 : {
1321 : mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
1322 : mBuilder->mCurrentContainerASR, mSavedContainerASR);
1323 : }
1324 :
1325 : private:
1326 : nsDisplayListBuilder* mBuilder;
1327 : const ActiveScrolledRoot* mSavedContainerASR;
1328 : };
1329 :
1330 : /**
1331 : * A helper class to temporarily set the value of mCurrentScrollbarTarget
1332 : * and mCurrentScrollbarFlags.
1333 : */
1334 : class AutoCurrentScrollbarInfoSetter {
1335 : public:
1336 : AutoCurrentScrollbarInfoSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollTargetID,
1337 : const MaybeScrollDirection& aScrollbarDirection, bool aWillHaveLayer)
1338 : : mBuilder(aBuilder) {
1339 : aBuilder->mIsBuildingScrollbar = true;
1340 : aBuilder->mCurrentScrollbarTarget = aScrollTargetID;
1341 : aBuilder->mCurrentScrollbarDirection = aScrollbarDirection;
1342 : aBuilder->mCurrentScrollbarWillHaveLayer = aWillHaveLayer;
1343 : }
1344 : ~AutoCurrentScrollbarInfoSetter() {
1345 : // No need to restore old values because scrollbars cannot be nested.
1346 : mBuilder->mIsBuildingScrollbar = false;
1347 : mBuilder->mCurrentScrollbarTarget = FrameMetrics::NULL_SCROLL_ID;
1348 : mBuilder->mCurrentScrollbarDirection.reset();
1349 : mBuilder->mCurrentScrollbarWillHaveLayer = false;
1350 : }
1351 : private:
1352 : nsDisplayListBuilder* mBuilder;
1353 : };
1354 :
1355 : /**
1356 : * A helper class to track current effective transform for items.
1357 : *
1358 : * For frames that is Combines3DTransformWithAncestors(), we need to
1359 : * apply all transforms of ancestors on the same preserves3D chain
1360 : * on the bounds of current frame to the coordination of the 3D
1361 0 : * context root. The 3D context root computes it's bounds from
1362 0 : * these transformed bounds.
1363 0 : */
1364 : class AutoAccumulateTransform {
1365 0 : public:
1366 0 : typedef mozilla::gfx::Matrix4x4 Matrix4x4;
1367 0 :
1368 : explicit AutoAccumulateTransform(nsDisplayListBuilder* aBuilder)
1369 : : mBuilder(aBuilder)
1370 : , mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform) {}
1371 :
1372 : ~AutoAccumulateTransform() {
1373 : mBuilder->mPreserves3DCtx.mAccumulatedTransform = mSavedTransform;
1374 : }
1375 :
1376 : void Accumulate(const Matrix4x4& aTransform) {
1377 : mBuilder->mPreserves3DCtx.mAccumulatedTransform =
1378 0 : aTransform * mBuilder->mPreserves3DCtx.mAccumulatedTransform;
1379 0 : }
1380 0 :
1381 : const Matrix4x4& GetCurrentTransform() {
1382 : return mBuilder->mPreserves3DCtx.mAccumulatedTransform;
1383 : }
1384 :
1385 : void StartRoot() {
1386 : mBuilder->mPreserves3DCtx.mAccumulatedTransform = Matrix4x4();
1387 : }
1388 :
1389 : private:
1390 : nsDisplayListBuilder* mBuilder;
1391 : Matrix4x4 mSavedTransform;
1392 : };
1393 :
1394 : /**
1395 : * A helper class to collect bounds rects of descendants.
1396 : *
1397 : * For a 3D context root, it's bounds is computed from the bounds of
1398 0 : * descendants. If we transform bounds frame by frame applying
1399 0 : * transforms, the bounds may turn to empty for any singular
1400 0 : * transform on the path, but it is not empty for the accumulated
1401 0 : * transform.
1402 0 : */
1403 0 : class AutoAccumulateRect {
1404 0 : public:
1405 0 : explicit AutoAccumulateRect(nsDisplayListBuilder* aBuilder)
1406 0 : : mBuilder(aBuilder)
1407 0 : , mSavedRect(aBuilder->mPreserves3DCtx.mAccumulatedRect) {
1408 : aBuilder->mPreserves3DCtx.mAccumulatedRect = nsRect();
1409 : aBuilder->mPreserves3DCtx.mAccumulatedRectLevels++;
1410 : }
1411 : ~AutoAccumulateRect() {
1412 : mBuilder->mPreserves3DCtx.mAccumulatedRect = mSavedRect;
1413 : mBuilder->mPreserves3DCtx.mAccumulatedRectLevels--;
1414 : }
1415 :
1416 : private:
1417 : nsDisplayListBuilder* mBuilder;
1418 : nsRect mSavedRect;
1419 : };
1420 :
1421 : void AccumulateRect(const nsRect& aRect) {
1422 : mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect, aRect);
1423 : }
1424 : const nsRect& GetAccumulatedRect() {
1425 : return mPreserves3DCtx.mAccumulatedRect;
1426 : }
1427 : /**
1428 : * The level is increased by one for items establishing 3D rendering
1429 : * context and starting a new accumulation.
1430 : */
1431 : int GetAccumulatedRectLevels() {
1432 : return mPreserves3DCtx.mAccumulatedRectLevels;
1433 : }
1434 :
1435 : // Helpers for tables
1436 : nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
1437 : void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
1438 :
1439 : struct OutOfFlowDisplayData {
1440 : OutOfFlowDisplayData(const DisplayItemClipChain* aContainingBlockClipChain,
1441 : const DisplayItemClipChain* aCombinedClipChain,
1442 : const ActiveScrolledRoot* aContainingBlockActiveScrolledRoot,
1443 : const nsRect &aVisibleRect,
1444 : const nsRect &aDirtyRect)
1445 : : mContainingBlockClipChain(aContainingBlockClipChain)
1446 : , mCombinedClipChain(aCombinedClipChain)
1447 : , mContainingBlockActiveScrolledRoot(aContainingBlockActiveScrolledRoot)
1448 : , mVisibleRect(aVisibleRect)
1449 : , mDirtyRect(aDirtyRect)
1450 : {}
1451 : const DisplayItemClipChain* mContainingBlockClipChain;
1452 : const DisplayItemClipChain* mCombinedClipChain; // only necessary for the special case of top layer
1453 : const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot;
1454 : nsRect mVisibleRect;
1455 : nsRect mDirtyRect;
1456 :
1457 : static nsRect ComputeVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
1458 : nsIFrame* aFrame,
1459 : const nsRect& aVisibleRect,
1460 : const nsRect& aDirtyRect,
1461 : nsRect* aOutDirtyRect) {
1462 : nsRect visible = aVisibleRect;
1463 : nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect;
1464 :
1465 : if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
1466 : aBuilder->IsPaintingToWindow()) {
1467 : // position: fixed items are reflowed into and only drawn inside the
1468 : // viewport, or the scroll position clamping scrollport size, if one is
1469 : // set.
1470 : nsIPresShell* ps = aFrame->PresShell();
1471 : if (ps->IsScrollPositionClampingScrollPortSizeSet()) {
1472 : dirtyRectRelativeToDirtyFrame =
1473 : nsRect(nsPoint(0, 0), ps->GetScrollPositionClampingScrollPortSize());
1474 : visible = dirtyRectRelativeToDirtyFrame;
1475 : #ifdef MOZ_WIDGET_ANDROID
1476 : } else {
1477 : dirtyRectRelativeToDirtyFrame =
1478 : nsRect(nsPoint(0, 0), aFrame->GetParent()->GetSize());
1479 : visible = dirtyRectRelativeToDirtyFrame;
1480 : #endif
1481 : }
1482 : }
1483 : *aOutDirtyRect = dirtyRectRelativeToDirtyFrame - aFrame->GetPosition();
1484 : visible -= aFrame->GetPosition();
1485 :
1486 : nsRect overflowRect = aFrame->GetVisualOverflowRect();
1487 :
1488 : if (aFrame->IsTransformed() &&
1489 : mozilla::EffectCompositor::HasAnimationsForCompositor(aFrame,
1490 : eCSSProperty_transform)) {
1491 : /**
1492 : * Add a fuzz factor to the overflow rectangle so that elements only just
1493 : * out of view are pulled into the display list, so they can be
1494 : * prerendered if necessary.
1495 : */
1496 : overflowRect.Inflate(nsPresContext::CSSPixelsToAppUnits(32));
1497 : }
1498 :
1499 : visible.IntersectRect(visible, overflowRect);
1500 : aOutDirtyRect->IntersectRect(*aOutDirtyRect, overflowRect);
1501 :
1502 : return visible;
1503 : }
1504 :
1505 : nsRect GetVisibleRectForFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1506 : nsRect* aDirtyRect) {
1507 : return ComputeVisibleRectForFrame(aBuilder, aFrame, mVisibleRect, mDirtyRect, aDirtyRect);
1508 : }
1509 : };
1510 :
1511 : NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty,
1512 : OutOfFlowDisplayData)
1513 :
1514 : struct DisplayListBuildingData {
1515 : RefPtr<AnimatedGeometryRoot> mModifiedAGR = nullptr;
1516 : nsRect mDirtyRect;
1517 : };
1518 : NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect, DisplayListBuildingData)
1519 :
1520 : NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect, nsRect)
1521 :
1522 : static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame)
1523 : {
1524 : if (!aFrame->GetParent()) {
1525 : return nullptr;
1526 : }
1527 : return aFrame->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
1528 : }
1529 :
1530 : nsPresContext* CurrentPresContext() {
1531 : return CurrentPresShellState()->mPresShell->GetPresContext();
1532 : }
1533 :
1534 : OutOfFlowDisplayData* GetCurrentFixedBackgroundDisplayData()
1535 : {
1536 : auto& displayData = CurrentPresShellState()->mFixedBackgroundDisplayData;
1537 : return displayData ? displayData.ptr() : nullptr;
1538 : }
1539 :
1540 : /**
1541 : * Accumulates the bounds of box frames that have moz-appearance
1542 : * -moz-win-exclude-glass style. Used in setting glass margins on
1543 : * Windows.
1544 : *
1545 : * We set the window opaque region (from which glass margins are computed)
1546 : * to the intersection of the glass region specified here and the opaque
1547 : * region computed during painting. So the excluded glass region actually
1548 : * *limits* the extent of the opaque area reported to Windows. We limit it
1549 : * so that changes to the computed opaque region (which can vary based on
1550 : * region optimizations and the placement of UI elements) outside the
1551 : * -moz-win-exclude-glass area don't affect the glass margins reported to
1552 : * Windows; changing those margins willy-nilly can cause the Windows 7 glass
1553 : * haze effect to jump around disconcertingly.
1554 : */
1555 : void AddWindowExcludeGlassRegion(nsIFrame* aFrame, const nsRect& aBounds)
1556 : {
1557 : mWindowExcludeGlassRegion.Add(aFrame, aBounds);
1558 : }
1559 :
1560 : /**
1561 : * Returns the window exclude glass region.
1562 : */
1563 : nsRegion GetWindowExcludeGlassRegion() const
1564 : {
1565 : return mWindowExcludeGlassRegion.ToRegion();
1566 : }
1567 :
1568 : /**
1569 : * Accumulates opaque stuff into the window opaque region.
1570 : */
1571 : void AddWindowOpaqueRegion(const nsRegion& bounds) {
1572 : mWindowOpaqueRegion.Or(mWindowOpaqueRegion, bounds);
1573 : }
1574 : /**
1575 : * Returns the window opaque region built so far. This may be incomplete
1576 : * since the opaque region is built during layer construction.
1577 : */
1578 : const nsRegion& GetWindowOpaqueRegion() {
1579 : return mWindowOpaqueRegion;
1580 : }
1581 :
1582 : /**
1583 : * Clears the window opaque region.
1584 : */
1585 : void ClearWindowOpaqueRegion()
1586 : {
1587 : mWindowOpaqueRegion.SetEmpty();
1588 : }
1589 :
1590 : void SetGlassDisplayItem(nsDisplayItem* aItem) {
1591 : if (mGlassDisplayItem) {
1592 : // Web pages or extensions could trigger this by using
1593 : // -moz-appearance:win-borderless-glass etc on their own elements.
1594 : // Keep the first one, since that will be the background of the root
1595 : // window
1596 : NS_WARNING("Multiple glass backgrounds found?");
1597 : } else {
1598 : mGlassDisplayItem = aItem;
1599 : }
1600 : }
1601 : bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem);
1602 :
1603 : void SetContainsPluginItem() { mContainsPluginItem = true; }
1604 : bool ContainsPluginItem() { return mContainsPluginItem; }
1605 :
1606 : /**
1607 : * mContainsBlendMode is true if we processed a display item that
1608 : * has a blend mode attached. We do this so we can insert a
1609 : * nsDisplayBlendContainer in the parent stacking context.
1610 : */
1611 : void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; }
1612 : bool ContainsBlendMode() const { return mContainsBlendMode; }
1613 :
1614 : DisplayListClipState& ClipState() { return mClipState; }
1615 : const ActiveScrolledRoot* CurrentActiveScrolledRoot() { return mCurrentActiveScrolledRoot; }
1616 : const ActiveScrolledRoot* CurrentAncestorASRStackingContextContents() { return mCurrentContainerASR; }
1617 :
1618 : /**
1619 : * Add the current frame to the will-change budget if possible and
1620 : * remeber the outcome. Subsequent calls to IsInWillChangeBudget
1621 : * will return the same value as return here.
1622 : */
1623 : bool AddToWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
1624 :
1625 : /**
1626 : * This will add the current frame to the will-change budget the first
1627 : * time it is seen. On subsequent calls this will return the same
1628 : * answer. This effectively implements a first-come, first-served
1629 : * allocation of the will-change budget.
1630 : */
1631 : bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
1632 :
1633 : void ClearWillChangeBudget(nsIFrame* aFrame);
1634 :
1635 : void EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage);
1636 : void ExitSVGEffectsContents();
1637 :
1638 : /**
1639 : * Note: if changing the conditions under which scroll info layers
1640 : * are created, make a corresponding change to
1641 : * ScrollFrameWillBuildScrollInfoLayer() in nsSliderFrame.cpp.
1642 : */
1643 : bool ShouldBuildScrollInfoItemsForHoisting() const
1644 : { return mSVGEffectsBuildingDepth > 0; }
1645 :
1646 : void AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem);
1647 :
1648 : /**
1649 : * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
1650 : *
1651 : * mPreserves3DCtx is used by class AutoAccumulateTransform &
1652 : * AutoAccumulateRect to passing data between frames in the 3D
1653 : * context. If a frame create a new 3D context, it should restore
1654 : * the value of mPreserves3DCtx before returning back to the parent.
1655 : * This class do it for the users.
1656 : */
1657 : class AutoPreserves3DContext {
1658 : public:
1659 : explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder)
1660 : : mBuilder(aBuilder)
1661 : , mSavedCtx(aBuilder->mPreserves3DCtx) {}
1662 : ~AutoPreserves3DContext() {
1663 : mBuilder->mPreserves3DCtx = mSavedCtx;
1664 : }
1665 :
1666 : private:
1667 : nsDisplayListBuilder* mBuilder;
1668 : Preserves3DContext mSavedCtx;
1669 : };
1670 :
1671 : const nsRect GetPreserves3DRect() const {
1672 : return mPreserves3DCtx.mVisibleRect;
1673 : }
1674 : void SavePreserves3DRect() {
1675 : mPreserves3DCtx.mVisibleRect = mVisibleRect;
1676 : }
1677 :
1678 : bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems; }
1679 : void SetBuildingInvisibleItems(bool aBuildingInvisibleItems) {
1680 : mBuildingInvisibleItems = aBuildingInvisibleItems;
1681 : }
1682 :
1683 : bool MarkFrameModifiedDuringBuilding(nsIFrame* aFrame)
1684 : {
1685 : if (!aFrame->IsFrameModified()) {
1686 : mModifiedFramesDuringBuilding.AppendElement(aFrame);
1687 : aFrame->SetFrameIsModified(true);
1688 : return true;
1689 : }
1690 : return false;
1691 : }
1692 :
1693 : bool MarkCurrentFrameModifiedDuringBuilding()
1694 : {
1695 : if (MarkFrameModifiedDuringBuilding(const_cast<nsIFrame*>(mCurrentFrame))) {
1696 : mInInvalidSubtree = true;
1697 : mDirtyRect = mVisibleRect;
1698 : return true;
1699 : }
1700 : return false;
1701 : }
1702 :
1703 : void RebuildAllItemsInCurrentSubtree()
1704 : {
1705 : mInInvalidSubtree = true;
1706 : mDirtyRect = mVisibleRect;
1707 : }
1708 :
1709 : /**
1710 : * This is a convenience function to ease the transition until AGRs and ASRs
1711 : * are unified.
1712 : */
1713 : AnimatedGeometryRoot* AnimatedGeometryRootForASR(const ActiveScrolledRoot* aASR);
1714 :
1715 : bool HitTestIsForVisibility() const {
1716 : return mHitTestIsForVisibility;
1717 : }
1718 : void SetHitTestIsForVisibility(bool aHitTestIsForVisibility) {
1719 : mHitTestIsForVisibility = aHitTestIsForVisibility;
1720 : }
1721 :
1722 : /**
1723 : * Represents a region composed of frame/rect pairs.
1724 : * WeakFrames are used to track whether a rect still belongs to the region.
1725 : * Modified frames and rects are removed and re-added to the region if needed.
1726 : */
1727 : struct WeakFrameRegion {
1728 : std::vector<WeakFrame> mFrames;
1729 : nsTArray<pixman_box32_t> mRects;
1730 :
1731 : void Add(nsIFrame* aFrame, const nsRect& aRect)
1732 : {
1733 : mFrames.emplace_back(aFrame);
1734 : mRects.AppendElement(nsRegion::RectToBox(aRect));
1735 : }
1736 :
1737 : void Add(nsIFrame* aFrame, const mozilla::gfx::IntRect& aRect)
1738 : {
1739 : mFrames.emplace_back(aFrame);
1740 : mRects.AppendElement(nsRegion::RectToBox(aRect));
1741 : }
1742 :
1743 : void Clear()
1744 : {
1745 : mFrames.clear();
1746 : mRects.Clear();
1747 : }
1748 :
1749 : typedef mozilla::gfx::ArrayView<pixman_box32_t> BoxArrayView;
1750 :
1751 : nsRegion ToRegion() const
1752 : {
1753 : return nsRegion(BoxArrayView(mRects));
1754 : }
1755 :
1756 : LayoutDeviceIntRegion ToLayoutDeviceIntRegion() const
1757 : {
1758 : return LayoutDeviceIntRegion(BoxArrayView(mRects));
1759 : }
1760 : };
1761 :
1762 : private:
1763 : bool MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame);
1764 :
1765 : /**
1766 : * Returns whether a frame acts as an animated geometry root, optionally
1767 : * returning the next ancestor to check.
1768 : */
1769 : AGRState IsAnimatedGeometryRoot(nsIFrame* aFrame,
1770 : bool& aIsAsync,
1771 : nsIFrame** aParent = nullptr);
1772 :
1773 : /**
1774 : * Returns the nearest ancestor frame to aFrame that is considered to have
1775 : * (or will have) animated geometry. This can return aFrame.
1776 : */
1777 : nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame, bool& aIsAsync);
1778 :
1779 : /**
1780 : * Returns true if nsDisplayCompositorHitTestInfo item should be build for
1781 : * |aFrame|. Otherwise returns false. If |aBuildNew| is true, reusing the
1782 : * previous hit test info will not be considered.
1783 : */
1784 : bool ShouldBuildCompositorHitTestInfo(const nsIFrame* aFrame,
1785 : const mozilla::gfx::CompositorHitTestInfo& aInfo,
1786 : const bool aBuildNew) const;
1787 :
1788 : friend class nsDisplayCanvasBackgroundImage;
1789 : friend class nsDisplayBackgroundImage;
1790 : friend class nsDisplayFixedPosition;
1791 : friend class nsDisplayPerspective;
1792 : AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsDisplayItem* aItem);
1793 :
1794 : friend class nsDisplayItem;
1795 : friend class nsDisplayOwnLayer;
1796 : friend struct RetainedDisplayListBuilder;
1797 : AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsIFrame* aFrame);
1798 :
1799 : AnimatedGeometryRoot* WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
1800 : bool aIsAsync,
1801 : AnimatedGeometryRoot* aParent = nullptr);
1802 :
1803 : nsDataHashtable<nsPtrHashKey<nsIFrame>, RefPtr<AnimatedGeometryRoot>> mFrameToAnimatedGeometryRootMap;
1804 :
1805 : /**
1806 : * Add the current frame to the AGR budget if possible and remember
1807 : * the outcome. Subsequent calls will return the same value as
1808 : * returned here.
1809 : */
1810 : bool AddToAGRBudget(nsIFrame* aFrame);
1811 :
1812 : struct PresShellState {
1813 : nsIPresShell* mPresShell;
1814 : #ifdef DEBUG
1815 : mozilla::Maybe<nsAutoLayoutPhase> mAutoLayoutPhase;
1816 : #endif
1817 : nsIFrame* mCaretFrame;
1818 : nsRect mCaretRect;
1819 : mozilla::Maybe<OutOfFlowDisplayData> mFixedBackgroundDisplayData;
1820 : uint32_t mFirstFrameMarkedForDisplay;
1821 : uint32_t mFirstFrameWithOOFData;
1822 0 : bool mIsBackgroundOnly;
1823 0 : // This is a per-document flag turning off event handling for all content
1824 : // in the document, and is set when we enter a subdocument for a pointer-
1825 0 : // events:none frame.
1826 : bool mInsidePointerEventsNoneDoc;
1827 : };
1828 :
1829 : PresShellState* CurrentPresShellState() {
1830 : NS_ASSERTION(mPresShellStates.Length() > 0,
1831 : "Someone forgot to enter a presshell");
1832 : return &mPresShellStates[mPresShellStates.Length() - 1];
1833 : }
1834 :
1835 : struct DocumentWillChangeBudget {
1836 : DocumentWillChangeBudget()
1837 : : mBudget(0)
1838 : {}
1839 :
1840 : uint32_t mBudget;
1841 : };
1842 :
1843 : struct FrameWillChangeBudget {
1844 : FrameWillChangeBudget(nsIFrame* aFrame, uint32_t aUsage)
1845 : : mFrame(aFrame)
1846 : , mUsage(aUsage)
1847 : {}
1848 :
1849 : nsIFrame* mFrame;
1850 : uint32_t mUsage;
1851 : };
1852 :
1853 : nsIFrame* const mReferenceFrame;
1854 : nsIFrame* mIgnoreScrollFrame;
1855 : nsDisplayCompositorHitTestInfo* mCompositorHitTestInfo;
1856 :
1857 : nsPresArena mPool;
1858 :
1859 : RefPtr<mozilla::dom::Selection> mBoundingSelection;
1860 : AutoTArray<PresShellState,8> mPresShellStates;
1861 : AutoTArray<nsIFrame*,400> mFramesMarkedForDisplay;
1862 : AutoTArray<nsIFrame*,40> mFramesMarkedForDisplayIfVisible;
1863 : AutoTArray<nsIFrame*,20> mFramesWithOOFData;
1864 : nsClassHashtable<nsPtrHashKey<nsDisplayItem>, nsTArray<ThemeGeometry>> mThemeGeometries;
1865 : nsDisplayTableItem* mCurrentTableItem;
1866 : DisplayListClipState mClipState;
1867 : const ActiveScrolledRoot* mCurrentActiveScrolledRoot;
1868 : const ActiveScrolledRoot* mCurrentContainerASR;
1869 : // mCurrentFrame is the frame that we're currently calling (or about to call)
1870 : // BuildDisplayList on.
1871 : const nsIFrame* mCurrentFrame;
1872 : // The reference frame for mCurrentFrame.
1873 : const nsIFrame* mCurrentReferenceFrame;
1874 : // The offset from mCurrentFrame to mCurrentReferenceFrame.
1875 : nsPoint mCurrentOffsetToReferenceFrame;
1876 :
1877 : RefPtr<AnimatedGeometryRoot> mRootAGR;
1878 : RefPtr<AnimatedGeometryRoot> mCurrentAGR;
1879 :
1880 : // will-change budget tracker
1881 : nsDataHashtable<nsPtrHashKey<nsPresContext>, DocumentWillChangeBudget>
1882 : mWillChangeBudget;
1883 :
1884 : // Any frame listed in this set is already counted in the budget
1885 : // and thus is in-budget.
1886 : nsDataHashtable<nsPtrHashKey<nsIFrame>, uint32_t> mWillChangeBudgetSet;
1887 :
1888 : // Area of animated geometry root budget already allocated
1889 : uint32_t mUsedAGRBudget;
1890 : // Set of frames already counted in budget
1891 : nsTHashtable<nsPtrHashKey<nsIFrame> > mAGRBudgetSet;
1892 :
1893 : nsTArray<nsIFrame*> mModifiedFramesDuringBuilding;
1894 :
1895 : // Relative to mCurrentFrame.
1896 : nsRect mVisibleRect;
1897 : nsRect mDirtyRect;
1898 :
1899 : // Tracked regions used for retained display list.
1900 : WeakFrameRegion mWindowExcludeGlassRegion;
1901 : WeakFrameRegion mRetainedWindowDraggingRegion;
1902 : WeakFrameRegion mRetainedWindowNoDraggingRegion;
1903 :
1904 : // Optimized versions for non-retained display list.
1905 : LayoutDeviceIntRegion mWindowDraggingRegion;
1906 : LayoutDeviceIntRegion mWindowNoDraggingRegion;
1907 :
1908 : // Window opaque region is calculated during layer building.
1909 : nsRegion mWindowOpaqueRegion;
1910 :
1911 : // The display item for the Windows window glass background, if any
1912 : nsDisplayItem* mGlassDisplayItem;
1913 : // A temporary list that we append scroll info items to while building
1914 : // display items for the contents of frames with SVG effects.
1915 : // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
1916 : // This is a pointer and not a real nsDisplayList value because the
1917 : // nsDisplayList class is defined below this class, so we can't use it here.
1918 : nsDisplayList* mScrollInfoItemsForHoisting;
1919 : nsTArray<RefPtr<ActiveScrolledRoot>> mActiveScrolledRoots;
1920 : std::unordered_set<
1921 : const DisplayItemClipChain*,
1922 : DisplayItemClipChainHasher,
1923 : DisplayItemClipChainEqualer> mClipDeduplicator;
1924 : std::list<DisplayItemClipChain*> mClipChainsToDestroy;
1925 : nsTArray<nsDisplayItem*> mTemporaryItems;
1926 : const ActiveScrolledRoot* mActiveScrolledRootForRootScrollframe;
1927 : nsDisplayListBuilderMode mMode;
1928 : ViewID mCurrentScrollParentId;
1929 : ViewID mCurrentScrollbarTarget;
1930 : MaybeScrollDirection mCurrentScrollbarDirection;
1931 : Preserves3DContext mPreserves3DCtx;
1932 : int32_t mSVGEffectsBuildingDepth;
1933 : // When we are inside a filter, the current ASR at the time we entered the
1934 : // filter. Otherwise nullptr.
1935 : const ActiveScrolledRoot* mFilterASR;
1936 : bool mContainsBlendMode;
1937 : bool mIsBuildingScrollbar;
1938 : bool mCurrentScrollbarWillHaveLayer;
1939 : bool mBuildCaret;
1940 : bool mRetainingDisplayList;
1941 : bool mPartialUpdate;
1942 : bool mIgnoreSuppression;
1943 : bool mIsAtRootOfPseudoStackingContext;
1944 : bool mIncludeAllOutOfFlows;
1945 : bool mDescendIntoSubdocuments;
1946 : bool mSelectedFramesOnly;
1947 : bool mAllowMergingAndFlattening;
1948 : bool mWillComputePluginGeometry;
1949 : // True when we're building a display list that's directly or indirectly
1950 : // under an nsDisplayTransform
1951 : bool mInTransform;
1952 : bool mInPageSequence;
1953 : bool mIsInChromePresContext;
1954 : bool mSyncDecodeImages;
1955 : bool mIsPaintingToWindow;
1956 : bool mIsCompositingCheap;
1957 : bool mContainsPluginItem;
1958 : bool mAncestorHasApzAwareEventHandler;
1959 : // True when the first async-scrollable scroll frame for which we build a
1960 : // display list has a display port. An async-scrollable scroll frame is one
1961 : // which WantsAsyncScroll().
1962 : bool mHaveScrollableDisplayPort;
1963 : bool mWindowDraggingAllowed;
1964 : bool mIsBuildingForPopup;
1965 : bool mForceLayerForScrollParent;
1966 : bool mAsyncPanZoomEnabled;
1967 : bool mBuildingInvisibleItems;
1968 : bool mHitTestIsForVisibility;
1969 : bool mIsBuilding;
1970 : bool mInInvalidSubtree;
1971 : bool mBuildCompositorHitTestInfo;
1972 : bool mLessEventRegionItems;
1973 : bool mDisablePartialUpdates;
1974 : bool mPartialBuildFailed;
1975 : };
1976 :
1977 : class nsDisplayItem;
1978 : class nsDisplayList;
1979 : class RetainedDisplayList;
1980 : /**
1981 : * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
1982 0 : * nsDisplayItemLink holds the link. The lists are linked from lowest to
1983 : * highest in z-order.
1984 : */
1985 : class nsDisplayItemLink {
1986 : // This is never instantiated directly, so no need to count constructors and
1987 : // destructors.
1988 : protected:
1989 : nsDisplayItemLink() : mAbove(nullptr) {}
1990 : nsDisplayItemLink(const nsDisplayItemLink&) : mAbove(nullptr) {}
1991 : nsDisplayItem* mAbove;
1992 :
1993 : friend class nsDisplayList;
1994 : };
1995 :
1996 : class nsDisplayWrapList;
1997 0 :
1998 : #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1999 0 : void AssertUniqueItem(nsDisplayItem* aItem);
2000 : #endif
2001 :
2002 0 : template<typename T, typename... Args>
2003 0 : MOZ_ALWAYS_INLINE T*
2004 0 : MakeDisplayItem(nsDisplayListBuilder* aBuilder, Args&&... aArgs)
2005 0 : {
2006 0 : T* item = new (aBuilder) T(aBuilder, std::forward<Args>(aArgs)...);
2007 0 :
2008 : const mozilla::SmallPointerArray<mozilla::DisplayItemData>& array =
2009 : item->Frame()->DisplayItemData();
2010 : for (uint32_t i = 0; i < array.Length(); i++) {
2011 : mozilla::DisplayItemData* did = array.ElementAt(i);
2012 : if (did->GetDisplayItemKey() == item->GetPerFrameKey()) {
2013 : if (!did->HasMergedFrames()) {
2014 0 : item->SetDisplayItemData(did);
2015 0 : }
2016 0 : break;
2017 0 : }
2018 : }
2019 :
2020 : #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2021 0 : if (aBuilder->IsRetainingDisplayList() &&
2022 : !aBuilder->IsInPageSequence() &&
2023 : aBuilder->IsBuilding()) {
2024 : AssertUniqueItem(item);
2025 : }
2026 : #endif
2027 :
2028 : return item;
2029 : }
2030 :
2031 : /**
2032 : * This is the unit of rendering and event testing. Each instance of this
2033 : * class represents an entity that can be drawn on the screen, e.g., a
2034 : * frame's CSS background, or a frame's text string.
2035 : *
2036 : * nsDisplayItems can be containers --- i.e., they can perform hit testing
2037 : * and painting by recursively traversing a list of child items.
2038 : *
2039 : * These are arena-allocated during display list construction. A typical
2040 : * subclass would just have a frame pointer, so its object would be just three
2041 : * pointers (vtable, next-item, frame).
2042 : *
2043 : * Display items belong to a list at all times (except temporarily as they
2044 : * move from one list to another).
2045 : */
2046 : class nsDisplayItem : public nsDisplayItemLink {
2047 : public:
2048 : typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
2049 : typedef mozilla::DisplayItemClip DisplayItemClip;
2050 : typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
2051 : typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
2052 : typedef mozilla::layers::FrameMetrics FrameMetrics;
2053 : typedef mozilla::layers::ScrollMetadata ScrollMetadata;
2054 : typedef mozilla::layers::FrameMetrics::ViewID ViewID;
2055 : typedef mozilla::layers::Layer Layer;
2056 : typedef mozilla::layers::LayerManager LayerManager;
2057 : typedef mozilla::layers::StackingContextHelper StackingContextHelper;
2058 : typedef mozilla::layers::WebRenderCommand WebRenderCommand;
2059 : typedef mozilla::layers::WebRenderParentCommand WebRenderParentCommand;
2060 : typedef mozilla::LayerState LayerState;
2061 : typedef mozilla::image::imgDrawingParams imgDrawingParams;
2062 : typedef mozilla::image::ImgDrawResult ImgDrawResult;
2063 : typedef class mozilla::gfx::DrawTarget DrawTarget;
2064 :
2065 : // This is never instantiated directly (it has pure virtual methods), so no
2066 : // need to count constructors and destructors.
2067 : nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
2068 : nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2069 : const ActiveScrolledRoot* aActiveScrolledRoot,
2070 : bool aAnonymous = false);
2071 :
2072 : /**
2073 : * This constructor is only used in rare cases when we need to construct
2074 : * temporary items.
2075 : */
2076 : explicit nsDisplayItem(nsIFrame* aFrame)
2077 : : mFrame(aFrame)
2078 : , mClipChain(nullptr)
2079 : , mClip(nullptr)
2080 : , mActiveScrolledRoot(nullptr)
2081 : , mReferenceFrame(nullptr)
2082 : , mAnimatedGeometryRoot(nullptr)
2083 : , mForceNotVisible(false)
2084 : , mDisableSubpixelAA(false)
2085 : , mReusedItem(false)
2086 : , mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden())
2087 : , mPaintRectValid(false)
2088 : #ifdef MOZ_DUMP_PAINTING
2089 0 : , mPainted(false)
2090 0 : #endif
2091 0 : {
2092 0 : MOZ_COUNT_CTOR(nsDisplayItem);
2093 : }
2094 0 :
2095 : protected:
2096 : virtual ~nsDisplayItem() {
2097 0 : MOZ_COUNT_DTOR(nsDisplayItem);
2098 : if (mFrame) {
2099 0 : mFrame->RemoveDisplayItem(this);
2100 0 : }
2101 0 : }
2102 0 : public:
2103 :
2104 0 : virtual void Destroy(nsDisplayListBuilder* aBuilder)
2105 : {
2106 0 : DisplayItemType type = GetType();
2107 0 : this->~nsDisplayItem();
2108 0 : aBuilder->Destroy(type, this);
2109 0 : }
2110 :
2111 0 : virtual void RestoreState()
2112 : {
2113 0 : mClipChain = mState.mClipChain;
2114 0 : mClip = mState.mClip;
2115 0 : mDisableSubpixelAA = false;
2116 0 : }
2117 :
2118 0 : virtual void RemoveFrame(nsIFrame* aFrame)
2119 : {
2120 : if (mFrame && aFrame == mFrame) {
2121 : MOZ_ASSERT(!mFrame->HasDisplayItem(this));
2122 : mFrame = nullptr;
2123 0 : mDisplayItemData = nullptr;
2124 0 : }
2125 : }
2126 :
2127 : /**
2128 : * Downcasts this item to nsDisplayWrapList, if possible.
2129 0 : */
2130 : virtual const nsDisplayWrapList* AsDisplayWrapList() const { return nullptr; }
2131 0 : virtual nsDisplayWrapList* AsDisplayWrapList() { return nullptr; }
2132 :
2133 : /**
2134 : * Create a clone of this item.
2135 : */
2136 : virtual nsDisplayItem* Clone(nsDisplayListBuilder* aBuilder) const
2137 : {
2138 : return nullptr;
2139 : }
2140 0 :
2141 0 : nsDisplayItem(const nsDisplayItem&) = delete;
2142 : /**
2143 0 : * The custom copy-constructor is implemented to prevent copying the saved
2144 : * state of the item.
2145 0 : * This is currently only used when creating temporary items for merging.
2146 : */
2147 : nsDisplayItem(nsDisplayListBuilder* aBuilder, const nsDisplayItem& aOther)
2148 : : mFrame(aOther.mFrame)
2149 : , mClipChain(aOther.mClipChain)
2150 0 : , mClip(aOther.mClip)
2151 0 : , mActiveScrolledRoot(aOther.mActiveScrolledRoot)
2152 : , mReferenceFrame(aOther.mReferenceFrame)
2153 0 : , mAnimatedGeometryRoot(aOther.mAnimatedGeometryRoot)
2154 : , mToReferenceFrame(aOther.mToReferenceFrame)
2155 : , mBuildingRect(aOther.mBuildingRect)
2156 0 : , mPaintRect(aOther.mPaintRect)
2157 : , mForceNotVisible(aOther.mForceNotVisible)
2158 : , mDisableSubpixelAA(aOther.mDisableSubpixelAA)
2159 0 : , mReusedItem(false)
2160 0 : , mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden())
2161 : , mPaintRectValid(false)
2162 : #ifdef MOZ_DUMP_PAINTING
2163 : , mPainted(false)
2164 : #endif
2165 : {
2166 : MOZ_COUNT_CTOR(nsDisplayItem);
2167 : }
2168 :
2169 :
2170 : struct HitTestState {
2171 : explicit HitTestState() : mInPreserves3D(false) {}
2172 :
2173 : ~HitTestState() {
2174 : NS_ASSERTION(mItemBuffer.Length() == 0,
2175 : "mItemBuffer should have been cleared");
2176 : }
2177 :
2178 : // Handling transform items for preserve 3D frames.
2179 : bool mInPreserves3D;
2180 : AutoTArray<nsDisplayItem*, 100> mItemBuffer;
2181 : };
2182 :
2183 : /**
2184 : * Some consecutive items should be rendered together as a unit, e.g.,
2185 : * outlines for the same element. For this, we need a way for items to
2186 : * identify their type. We use the type for other purposes too.
2187 0 : */
2188 : virtual DisplayItemType GetType() const = 0;
2189 : /**
2190 : * Pairing this with the GetUnderlyingFrame() pointer gives a key that
2191 : * uniquely identifies this display item in the display item tree.
2192 : * XXX check nsOptionEventGrabberWrapper/nsXULEventRedirectorWrapper
2193 : */
2194 : virtual uint32_t GetPerFrameKey() const { return uint32_t(GetType()); }
2195 :
2196 : uint8_t GetFlags() { return GetDisplayItemFlagsForType(GetType()); }
2197 :
2198 : /**
2199 : * This is called after we've constructed a display list for event handling.
2200 : * When this is called, we've already ensured that aRect intersects the
2201 : * item's bounds and that clipping has been taking into account.
2202 : *
2203 : * @param aRect the point or rect being tested, relative to the reference
2204 0 : * frame. If the width and height are both 1 app unit, it indicates we're
2205 0 : * hit testing a point, not a rect.
2206 : * @param aState must point to a HitTestState. If you don't have one,
2207 : * just create one with the default constructor and pass it in.
2208 : * @param aOutFrames each item appends the frame(s) in this display item that
2209 : * the rect is considered over (if any) to aOutFrames.
2210 : */
2211 0 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2212 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {}
2213 0 : /**
2214 0 : * @return the frame that this display item is based on. This is used to sort
2215 : * items by z-index and content order and for some other uses. Never
2216 : * returns null.
2217 : */
2218 : inline nsIFrame* Frame() const
2219 : {
2220 : MOZ_ASSERT(mFrame, "Trying to use display item after deletion!");
2221 0 : return mFrame;
2222 : }
2223 0 :
2224 : /**
2225 : * @return the nsIFrame that provides the style data, and should
2226 0 : * be checked when deciding if this display item can be reused.
2227 : */
2228 0 : virtual nsIFrame* FrameForInvalidation() const
2229 : {
2230 : return mFrame;
2231 : }
2232 :
2233 : virtual bool HasDeletedFrame() const { return !mFrame; }
2234 :
2235 : virtual nsIFrame* StyleFrame() const { return mFrame; }
2236 :
2237 : /**
2238 : * Compute the used z-index of our frame; returns zero for elements to which
2239 : * z-index does not apply, and for z-index:auto.
2240 : * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
2241 : */
2242 : virtual int32_t ZIndex() const;
2243 : /**
2244 : * The default bounds is the frame border rect.
2245 : * @param aSnap *aSnap is set to true if the returned rect will be
2246 : * snapped to nearest device pixel edges during actual drawing.
2247 0 : * It might be set to false and snap anyway, so code computing the set of
2248 : * pixels affected by this display item needs to round outwards to pixel
2249 : * boundaries when *aSnap is set to false.
2250 0 : * This does not take the item's clipping into account.
2251 0 : * @return a rectangle relative to aBuilder->ReferenceFrame() that
2252 : * contains the area drawn by this display item
2253 : */
2254 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
2255 : bool* aSnap) const
2256 : {
2257 0 : *aSnap = false;
2258 0 : return nsRect(ToReferenceFrame(), Frame()->GetSize());
2259 : }
2260 :
2261 : virtual nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder,
2262 : bool* aSnap) const
2263 : {
2264 : *aSnap = false;
2265 0 : return nsRegion();
2266 : }
2267 :
2268 : /**
2269 : * Returns true if nothing will be rendered inside aRect, false if uncertain.
2270 : * aRect is assumed to be contained in this item's bounds.
2271 : */
2272 : virtual bool IsInvisibleInRect(const nsRect& aRect) const { return false; }
2273 :
2274 0 : /**
2275 : * Returns the result of GetBounds intersected with the item's clip.
2276 0 : * The intersection is approximate since rounded corners are not taking into
2277 : * account.
2278 : */
2279 0 : nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder) const;
2280 :
2281 0 : nsRect GetBorderRect() const
2282 : {
2283 : return nsRect(ToReferenceFrame(), Frame()->GetSize());
2284 : }
2285 :
2286 : nsRect GetPaddingRect() const
2287 : {
2288 : return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
2289 : }
2290 :
2291 : nsRect GetContentRect() const
2292 : {
2293 0 : return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
2294 : }
2295 0 :
2296 0 : /**
2297 0 : * Checks if the frame(s) owning this display item have been marked as invalid,
2298 : * and needing repainting.
2299 : */
2300 : virtual bool IsInvalid(nsRect& aRect) const
2301 : {
2302 : bool result = mFrame ? mFrame->IsInvalid(aRect) : false;
2303 : aRect += ToReferenceFrame();
2304 : return result;
2305 : }
2306 :
2307 : /**
2308 : * Creates and initializes an nsDisplayItemGeometry object that retains the current
2309 : * areas covered by this display item. These need to retain enough information
2310 : * such that they can be compared against a future nsDisplayItem of the same type,
2311 : * and determine if repainting needs to happen.
2312 : *
2313 0 : * Subclasses wishing to store more information need to override both this
2314 : * and ComputeInvalidationRegion, as well as implementing an nsDisplayItemGeometry
2315 0 : * subclass.
2316 : *
2317 : * The default implementation tracks both the display item bounds, and the frame's
2318 : * border rect.
2319 : */
2320 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
2321 : {
2322 : return new nsDisplayItemGenericGeometry(this, aBuilder);
2323 : }
2324 :
2325 : /**
2326 : * Compares an nsDisplayItemGeometry object from a previous paint against the
2327 : * current item. Computes if the geometry of the item has changed, and the
2328 : * invalidation area required for correct repainting.
2329 : *
2330 : * The existing geometry will have been created from a display item with a
2331 : * matching GetPerFrameKey()/mFrame pair to the current item.
2332 : *
2333 : * The default implementation compares the display item bounds, and the frame's
2334 0 : * border rect, and invalidates the entire bounds if either rect changes.
2335 : *
2336 : * @param aGeometry The geometry of the matching display item from the
2337 : * previous paint.
2338 0 : * @param aInvalidRegion Output param, the region to invalidate, or
2339 : * unchanged if none.
2340 0 : */
2341 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2342 0 : const nsDisplayItemGeometry* aGeometry,
2343 : nsRegion* aInvalidRegion) const
2344 0 : {
2345 : const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
2346 : bool snap;
2347 : if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
2348 : !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
2349 : aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
2350 0 : }
2351 : }
2352 :
2353 : /**
2354 : * An alternative default implementation of ComputeInvalidationRegion,
2355 0 : * that instead invalidates only the changed area between the two items.
2356 : */
2357 0 : void ComputeInvalidationRegionDifference(nsDisplayListBuilder* aBuilder,
2358 : const nsDisplayItemBoundsGeometry* aGeometry,
2359 0 : nsRegion* aInvalidRegion) const
2360 0 : {
2361 0 : bool snap;
2362 : nsRect bounds = GetBounds(aBuilder, &snap);
2363 0 :
2364 : if (!aGeometry->mBounds.IsEqualInterior(bounds)) {
2365 : nscoord radii[8];
2366 0 : if (aGeometry->mHasRoundedCorners ||
2367 : Frame()->GetBorderRadii(radii)) {
2368 : aInvalidRegion->Or(aGeometry->mBounds, bounds);
2369 : } else {
2370 : aInvalidRegion->Xor(aGeometry->mBounds, bounds);
2371 : }
2372 : }
2373 : }
2374 :
2375 : /**
2376 : * @param aSnap set to true if the edges of the rectangles of the opaque
2377 : * region would be snapped to device pixels when drawing
2378 0 : * @return a region of the item that is opaque --- that is, every pixel
2379 : * that is visible is painted with an opaque
2380 : * color. This is useful for determining when one piece
2381 0 : * of content completely obscures another so that we can do occlusion
2382 0 : * culling.
2383 : * This does not take clipping into account.
2384 : */
2385 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2386 : bool* aSnap) const
2387 : {
2388 0 : *aSnap = false;
2389 : return nsRegion();
2390 0 : }
2391 : /**
2392 : * @return Some(nscolor) if the item is guaranteed to paint every pixel in its
2393 : * bounds with the same (possibly translucent) color
2394 : */
2395 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const
2396 : {
2397 0 : return mozilla::Nothing();
2398 : }
2399 0 :
2400 : /**
2401 : * @return true if the contents of this item are rendered fixed relative
2402 0 : * to the nearest viewport.
2403 : */
2404 0 : virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const
2405 : {
2406 : return false;
2407 : }
2408 :
2409 : virtual bool ClearsBackground() const
2410 : {
2411 : return false;
2412 : }
2413 :
2414 : /**
2415 : * Returns true if all layers that can be active should be forced to be
2416 : * active. Requires setting the pref layers.force-active=true.
2417 : */
2418 : static bool ForceActiveLayers();
2419 :
2420 : /**
2421 : * @return LAYER_NONE if BuildLayer will return null. In this case
2422 : * there is no layer for the item, and Paint should be called instead
2423 : * to paint the content using Thebes.
2424 : * Return LAYER_INACTIVE if there is a layer --- BuildLayer will
2425 : * not return null (unless there's an error) --- but the layer contents
2426 : * are not changing frequently. In this case it makes sense to composite
2427 : * the layer into a PaintedLayer with other content, so we don't have to
2428 : * recomposite it every time we paint.
2429 : * Note: GetLayerState is only allowed to return LAYER_INACTIVE if all
2430 : * descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also,
2431 : * all descendant display item frames must have an active scrolled root
2432 : * that's either the same as this item's frame's active scrolled root, or
2433 : * a descendant of this item's frame. This ensures that the entire
2434 : * set of display items can be collapsed onto a single PaintedLayer.
2435 : * Return LAYER_ACTIVE if the layer is active, that is, its contents are
2436 0 : * changing frequently. In this case it makes sense to keep the layer
2437 : * as a separate buffer in VRAM and composite it into the destination
2438 : * every time we paint.
2439 : *
2440 0 : * Users of GetLayerState should check ForceActiveLayers() and if it returns
2441 : * true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE.
2442 : */
2443 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2444 : LayerManager* aManager,
2445 : const ContainerLayerParameters& aParameters)
2446 : {
2447 0 : return mozilla::LAYER_NONE;
2448 : }
2449 0 :
2450 : /**
2451 : * Return true to indicate the layer should be constructed even if it's
2452 : * completely invisible.
2453 : */
2454 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const
2455 : {
2456 : return false;
2457 0 : }
2458 :
2459 : /**
2460 : * Actually paint this item to some rendering context.
2461 : * Content outside mVisibleRect need not be painted.
2462 : * aCtx must be set up as for nsDisplayList::Paint.
2463 : */
2464 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {}
2465 :
2466 : #ifdef MOZ_DUMP_PAINTING
2467 : /**
2468 : * Mark this display item as being painted via FrameLayerBuilder::DrawPaintedLayer.
2469 : */
2470 : bool Painted() const { return mPainted; }
2471 :
2472 : /**
2473 : * Check if this display item has been painted.
2474 : */
2475 : void SetPainted() { mPainted = true; }
2476 : #endif
2477 :
2478 : /**
2479 : * Get the layer drawn by this display item. Call this only if
2480 : * GetLayerState() returns something other than LAYER_NONE.
2481 : * If GetLayerState returned LAYER_NONE then Paint will be called
2482 : * instead.
2483 : * This is called while aManager is in the construction phase.
2484 : *
2485 0 : * The caller (nsDisplayList) is responsible for setting the visible
2486 : * region of the layer.
2487 : *
2488 : * @param aContainerParameters should be passed to
2489 0 : * FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is
2490 : * constructed.
2491 : */
2492 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2493 : LayerManager* aManager,
2494 : const ContainerLayerParameters& aContainerParameters)
2495 : {
2496 : return nullptr;
2497 : }
2498 :
2499 : /**
2500 0 : * Function to create the WebRenderCommands.
2501 : * We should check if the layer state is
2502 : * active first and have an early return if the layer state is
2503 : * not active.
2504 0 : *
2505 : * @return true if successfully creating webrender commands.
2506 : */
2507 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
2508 : mozilla::wr::IpcResourceUpdateQueue& aResources,
2509 : const StackingContextHelper& aSc,
2510 : mozilla::layers::WebRenderLayerManager* aManager,
2511 : nsDisplayListBuilder* aDisplayListBuilder) { return false; }
2512 :
2513 : /**
2514 : * Updates the provided aLayerData with any APZ-relevant scroll data
2515 : * that is specific to this display item. This is stuff that would normally
2516 : * be put on the layer during BuildLayer, but this is only called in
2517 : * layers-free webrender mode, where we don't have layers.
2518 : *
2519 : * This function returns true if and only if it has APZ-relevant scroll data
2520 : * to provide. Note that the arguments passed in may be nullptr, in which case
2521 0 : * the function should still return true if and only if it has APZ-relevant
2522 : * scroll data, but obviously in this case it can't actually put the
2523 0 : * data onto aLayerData, because there isn't one.
2524 : *
2525 : * This function assumes that aData and aLayerData will either both be null,
2526 : * or will both be non-null. The caller is responsible for enforcing this.
2527 : */
2528 : virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
2529 : mozilla::layers::WebRenderLayerScrollData* aLayerData)
2530 : { return false; }
2531 :
2532 : /**
2533 : * On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
2534 : * which may be visible. If the display item opaquely covers an area, it
2535 : * can remove that area from aVisibleRegion before returning.
2536 : * nsDisplayList::ComputeVisibility automatically subtracts the region
2537 : * returned by GetOpaqueRegion, and automatically removes items whose bounds
2538 : * do not intersect the visible area, so implementations of
2539 : * nsDisplayItem::ComputeVisibility do not need to do these things.
2540 : * nsDisplayList::ComputeVisibility will already have set mVisibleRect on
2541 : * this item to the intersection of *aVisibleRegion and this item's bounds.
2542 : * We rely on that, so this should only be called by
2543 : * nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility.
2544 : * aAllowVisibleRegionExpansion is a rect where we are allowed to
2545 : * expand the visible region and is only used for making sure the
2546 : * background behind a plugin is visible.
2547 : * This method needs to be idempotent.
2548 : *
2549 : * @return true if the item is visible, false if no part of the item
2550 : * is visible.
2551 : */
2552 0 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2553 : nsRegion* aVisibleRegion);
2554 :
2555 : /**
2556 : * Checks if the given display item can be merged with this item.
2557 : * @return true if the merging is possible, otherwise false.
2558 : */
2559 : virtual bool CanMerge(const nsDisplayItem* aItem) const { return false; }
2560 :
2561 : /**
2562 0 : * Try to merge with the other item (which is below us in the display
2563 : * list). This gets used by nsDisplayClip to coalesce clipping operations
2564 : * (optimization), by nsDisplayOpacity to merge rendering for the same
2565 : * content element into a single opacity group (correctness), and will be
2566 : * used by nsDisplayOutline to merge multiple outlines for the same element
2567 0 : * (also for correctness).
2568 0 : */
2569 : virtual void Merge(const nsDisplayItem* aItem) {}
2570 :
2571 : /**
2572 : * Merges the given display list to this item.
2573 : */
2574 : virtual void MergeDisplayListFromItem(nsDisplayListBuilder* aBuilder,
2575 0 : const nsDisplayItem* aItem) {}
2576 :
2577 0 : /**
2578 : * Appends the underlying frames of all display items that have been
2579 : * merged into this one (excluding this item's own underlying frame)
2580 : * to aFrames.
2581 : */
2582 : virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) const {}
2583 :
2584 : virtual bool HasMergedFrames() const { return false; }
2585 0 :
2586 0 : /**
2587 : * During the visibility computation and after TryMerge, display lists may
2588 : * return true here to flatten themselves away, removing them. This
2589 : * flattening is distinctly different from FlattenTo, which occurs before
2590 : * items are merged together.
2591 : */
2592 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
2593 : return false;
2594 0 : }
2595 :
2596 : /**
2597 : * Some items such as those calling into the native themed widget machinery
2598 : * have to be painted on the content process. In this case it is best to avoid
2599 : * allocating layers that serializes and forwards the work to the compositor.
2600 : */
2601 0 : virtual bool MustPaintOnContentSide() const { return false; }
2602 :
2603 0 : /**
2604 : * If this has a child list where the children are in the same coordinate
2605 : * system as this item (i.e., they have the same reference frame),
2606 0 : * return the list.
2607 : */
2608 : virtual nsDisplayList* GetSameCoordinateSystemChildren() const
2609 : {
2610 : return nullptr;
2611 : }
2612 :
2613 : virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) {}
2614 : /**
2615 : * Do UpdateBounds() for items with frames establishing or extending
2616 : * 3D rendering context.
2617 : *
2618 : * This function is called by UpdateBoundsFor3D() of
2619 : * nsDisplayTransform(), and it is called by
2620 : * BuildDisplayListForStackingContext() on transform items
2621 0 : * establishing 3D rendering context.
2622 : *
2623 : * The bounds of a transform item with the frame establishing 3D
2624 : * rendering context should be computed by calling
2625 : * DoUpdateBoundsPreserves3D() on all descendants that participate
2626 : * the same 3d rendering context.
2627 0 : */
2628 : virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) {}
2629 :
2630 : /**
2631 : * If this has a child list, return it, even if the children are in
2632 : * a different coordinate system to this item.
2633 0 : */
2634 : virtual RetainedDisplayList* GetChildren() const { return nullptr; }
2635 0 :
2636 : /**
2637 0 : * Returns the building rectangle used by nsDisplayListBuilder when
2638 0 : * this item was constructed.
2639 : */
2640 : const nsRect& GetBuildingRect() const { return mBuildingRect; }
2641 0 :
2642 0 : void SetBuildingRect(const nsRect& aBuildingRect)
2643 : {
2644 : mPaintRect = mBuildingRect = aBuildingRect;
2645 : }
2646 :
2647 : void SetPaintRect(const nsRect& aPaintRect) {
2648 : mPaintRect = aPaintRect;
2649 : mPaintRectValid = true;
2650 : }
2651 : bool HasPaintRect() const { return mPaintRectValid; }
2652 0 :
2653 : /**
2654 : * Returns the building rect for the children, relative to their
2655 : * reference frame. Can be different from mBuildingRect for nsDisplayTransform,
2656 : * since the reference frame for the children is different from the reference
2657 : * frame for the item itself.
2658 0 : */
2659 : virtual const nsRect& GetBuildingRectForChildren() const { return mBuildingRect; }
2660 :
2661 0 : /**
2662 0 : * Stores the given opacity value to be applied when drawing. It is an error to
2663 : * call this if CanApplyOpacity returned false.
2664 : */
2665 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
2666 : float aOpacity,
2667 0 : const DisplayItemClipChain* aClip) {
2668 : NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity not supported on this type");
2669 : }
2670 : /**
2671 : * Returns true if this display item would return true from ApplyOpacity without
2672 : * actually applying the opacity. Otherwise returns false.
2673 : */
2674 : virtual bool CanApplyOpacity() const { return false; }
2675 :
2676 0 : bool ForceNotVisible() const { return mForceNotVisible; }
2677 :
2678 : /**
2679 : * For debugging and stuff
2680 : */
2681 : virtual const char* Name() const = 0;
2682 :
2683 : virtual void WriteDebugInfo(std::stringstream& aStream) {}
2684 :
2685 : nsDisplayItem* GetAbove() { return mAbove; }
2686 :
2687 : /**
2688 : * Like ComputeVisibility, but does the work that nsDisplayList
2689 : * does per-item:
2690 : * -- Intersects GetBounds with aVisibleRegion and puts the result
2691 : * in mVisibleRect
2692 : * -- Subtracts bounds from aVisibleRegion if the item is opaque
2693 : */
2694 0 : bool RecomputeVisibility(nsDisplayListBuilder* aBuilder,
2695 0 : nsRegion* aVisibleRegion,
2696 0 : bool aUseClipBounds = true);
2697 :
2698 : /**
2699 : * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
2700 : */
2701 : const nsPoint& ToReferenceFrame() const {
2702 : NS_ASSERTION(mFrame, "No frame?");
2703 : return mToReferenceFrame;
2704 : }
2705 : /**
2706 : * @return the root of the display list's frame (sub)tree, whose origin
2707 0 : * establishes the coordinate system for the display list
2708 : */
2709 0 : const nsIFrame* ReferenceFrame() const { return mReferenceFrame; }
2710 0 :
2711 0 : /**
2712 : * Returns the reference frame for display item children of this item.
2713 : */
2714 0 : virtual const nsIFrame* ReferenceFrameForChildren() const { return mReferenceFrame; }
2715 0 :
2716 : AnimatedGeometryRoot* GetAnimatedGeometryRoot() const {
2717 : MOZ_ASSERT(mAnimatedGeometryRoot, "Must have cached AGR before accessing it!");
2718 : return mAnimatedGeometryRoot;
2719 : }
2720 :
2721 : virtual struct AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const {
2722 : return GetAnimatedGeometryRoot();
2723 : }
2724 0 :
2725 : /**
2726 0 : * Checks if this display item (or any children) contains content that might
2727 : * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
2728 : * bounds of the area that needs component alpha, or an empty rect if nothing
2729 : * in the item does.
2730 : */
2731 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const
2732 : {
2733 : return nsRect();
2734 : }
2735 :
2736 : /**
2737 : * Disable usage of component alpha. Currently only relevant for items that have text.
2738 : */
2739 : void DisableComponentAlpha()
2740 : {
2741 : mDisableSubpixelAA = true;
2742 0 : }
2743 0 :
2744 : bool IsSubpixelAADisabled() const { return mDisableSubpixelAA; }
2745 :
2746 0 : /**
2747 : * Check if we can add async animations to the layer for this display item.
2748 0 : */
2749 : virtual bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
2750 0 : return false;
2751 : }
2752 :
2753 : virtual bool SupportsOptimizingToImage() const { return false; }
2754 0 :
2755 0 : const DisplayItemClip& GetClip() const
2756 : {
2757 : return mClip ? *mClip : DisplayItemClip::NoClip();
2758 : }
2759 0 : void IntersectClip(nsDisplayListBuilder* aBuilder, const DisplayItemClipChain* aOther, bool aStore);
2760 :
2761 : virtual void SetActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot) { mActiveScrolledRoot = aActiveScrolledRoot; }
2762 : const ActiveScrolledRoot* GetActiveScrolledRoot() const { return mActiveScrolledRoot; }
2763 :
2764 : virtual void SetClipChain(const DisplayItemClipChain* aClipChain,
2765 : bool aStore);
2766 : const DisplayItemClipChain* GetClipChain() const { return mClipChain; }
2767 :
2768 0 : /**
2769 : * Intersect all clips in our clip chain up to (and including) aASR and set
2770 : * set the intersection as this item's clip.
2771 : */
2772 : void FuseClipChainUpTo(nsDisplayListBuilder* aBuilder,
2773 : const ActiveScrolledRoot* aASR);
2774 :
2775 0 : bool BackfaceIsHidden() const { return mFrame->BackfaceIsHidden(); }
2776 :
2777 0 : bool In3DContextAndBackfaceIsHidden()
2778 0 : {
2779 : return mBackfaceHidden;
2780 : }
2781 0 :
2782 : bool HasSameTypeAndClip(const nsDisplayItem* aOther) const
2783 0 : {
2784 : return GetType() == aOther->GetType() &&
2785 : GetClipChain() == aOther->GetClipChain();
2786 : }
2787 :
2788 : bool HasSameContent(const nsDisplayItem* aOther) const
2789 : {
2790 : return mFrame->GetContent() == aOther->Frame()->GetContent();
2791 : }
2792 :
2793 : bool IsReused() const
2794 : {
2795 : return mReusedItem;
2796 0 : }
2797 :
2798 0 : void SetReused(bool aReused)
2799 : {
2800 0 : mReusedItem = aReused;
2801 : }
2802 :
2803 : virtual bool CanBeReused() const { return true; }
2804 :
2805 : virtual nsIFrame* GetDependentFrame()
2806 : {
2807 : return nullptr;
2808 0 : }
2809 :
2810 : virtual mozilla::Maybe<nsRect> GetClipWithRespectToASR(
2811 : nsDisplayListBuilder* aBuilder,
2812 : const ActiveScrolledRoot* aASR) const;
2813 :
2814 : void SetDisplayItemData(mozilla::DisplayItemData* aDID) {
2815 : mDisplayItemData = aDID;
2816 : }
2817 :
2818 : mozilla::DisplayItemData* GetDisplayItemData() { return mDisplayItemData; }
2819 :
2820 : // Set the nsDisplayList that this item belongs to, and what
2821 : // index it is within that list. Temporary state for merging
2822 : // used by RetainedDisplayListBuilder.
2823 : void SetOldListIndex(nsDisplayList* aList, OldListIndex aIndex, uint32_t aListKey, uint32_t aNestingDepth)
2824 : {
2825 : #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2826 : mOldListKey = aListKey;
2827 : mOldNestingDepth = aNestingDepth;
2828 : #endif
2829 : mOldList = reinterpret_cast<uintptr_t>(aList);
2830 : mOldListIndex = aIndex;
2831 : }
2832 : bool GetOldListIndex(nsDisplayList* aList, uint32_t aListKey, OldListIndex* aOutIndex)
2833 : {
2834 : if (mOldList != reinterpret_cast<uintptr_t>(aList)) {
2835 : #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2836 : MOZ_CRASH_UNSAFE_PRINTF("Item found was in the wrong list! type %d (outer type was %d at depth %d, now is %d)", GetPerFrameKey(), mOldListKey, mOldNestingDepth, aListKey);
2837 : #endif
2838 0 : return false;
2839 : }
2840 : *aOutIndex = mOldListIndex;
2841 : return true;
2842 : }
2843 :
2844 : const nsRect& GetPaintRect() const {
2845 : return mPaintRect;
2846 : }
2847 :
2848 : protected:
2849 : nsDisplayItem() = delete;
2850 :
2851 : typedef bool (*PrefFunc)(void);
2852 : bool ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc) const;
2853 : bool CanUseAdvancedLayer(LayerManager* aManager) const;
2854 :
2855 : nsIFrame* mFrame;
2856 : RefPtr<const DisplayItemClipChain> mClipChain;
2857 : const DisplayItemClip* mClip;
2858 : RefPtr<const ActiveScrolledRoot> mActiveScrolledRoot;
2859 : // Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
2860 : const nsIFrame* mReferenceFrame;
2861 : RefPtr<struct AnimatedGeometryRoot> mAnimatedGeometryRoot;
2862 : // Result of ToReferenceFrame(mFrame), if mFrame is non-null
2863 : nsPoint mToReferenceFrame;
2864 : RefPtr<mozilla::DisplayItemData> mDisplayItemData;
2865 :
2866 : private:
2867 : // This is the rectangle that nsDisplayListBuilder was using as the visible
2868 : // rect to decide which items to construct.
2869 : nsRect mBuildingRect;
2870 :
2871 : // nsDisplayList::ComputeVisibility sets this to the visible region
2872 : // of the item by intersecting the visible region with the bounds
2873 : // of the item. Paint implementations can use this to limit their drawing.
2874 : // Guaranteed to be contained in GetBounds().
2875 : nsRect mPaintRect;
2876 :
2877 : protected:
2878 :
2879 : #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2880 : public:
2881 : uint32_t mOldListKey = 0;
2882 : uint32_t mOldNestingDepth = 0;
2883 : bool mMergedItem = false;
2884 : bool mPreProcessedItem = false;
2885 : protected:
2886 : #endif
2887 : OldListIndex mOldListIndex;
2888 : uintptr_t mOldList = 0;
2889 :
2890 : bool mForceNotVisible;
2891 : bool mDisableSubpixelAA;
2892 : bool mReusedItem;
2893 0 : bool mBackfaceHidden;
2894 : bool mPaintRectValid;
2895 : #ifdef MOZ_DUMP_PAINTING
2896 : // True if this frame has been painted.
2897 : bool mPainted;
2898 : #endif
2899 :
2900 : struct {
2901 : RefPtr<const DisplayItemClipChain> mClipChain;
2902 : const DisplayItemClip* mClip;
2903 : } mState;
2904 : };
2905 :
2906 : /**
2907 : * Manages a singly-linked list of display list items.
2908 : *
2909 : * mSentinel is the sentinel list value, the first value in the null-terminated
2910 : * linked list of items. mTop is the last item in the list (whose 'above'
2911 : * pointer is null). This class has no virtual methods. So list objects are just
2912 : * two pointers.
2913 : *
2914 : * Stepping upward through this list is very fast. Stepping downward is very
2915 : * slow so we don't support it. The methods that need to step downward
2916 : * (HitTest(), ComputeVisibility()) internally build a temporary array of all
2917 : * the items while they do the downward traversal, so overall they're still
2918 : * linear time. We have optimized for efficient AppendToTop() of both
2919 : * items and lists, with minimal codesize. AppendToBottom() is efficient too.
2920 : */
2921 : class nsDisplayList {
2922 : public:
2923 : typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
2924 0 : typedef mozilla::layers::Layer Layer;
2925 0 : typedef mozilla::layers::LayerManager LayerManager;
2926 : typedef mozilla::layers::PaintedLayer PaintedLayer;
2927 0 :
2928 : /**
2929 0 : * Create an empty list.
2930 : */
2931 0 : nsDisplayList()
2932 : : mLength(0)
2933 : , mIsOpaque(false)
2934 : , mForceTransparentSurface(false)
2935 : {
2936 : mTop = &mSentinel;
2937 : mSentinel.mAbove = nullptr;
2938 : }
2939 : ~nsDisplayList() {
2940 : if (mSentinel.mAbove) {
2941 : NS_WARNING("Nonempty list left over?");
2942 0 : }
2943 0 : }
2944 0 :
2945 0 : /**
2946 0 : * Append an item to the top of the list. The item must not currently
2947 0 : * be in a list and cannot be null.
2948 0 : */
2949 : void AppendToTop(nsDisplayItem* aItem) {
2950 : MOZ_ASSERT(aItem, "No item to append!");
2951 : MOZ_ASSERT(!aItem->mAbove, "Already in a list!");
2952 : mTop->mAbove = aItem;
2953 : mTop = aItem;
2954 : mLength++;
2955 : }
2956 :
2957 : /**
2958 : * Append a new item to the bottom of the list. The item must be non-null
2959 : * and not already in a list.
2960 : */
2961 : void AppendToBottom(nsDisplayItem* aItem) {
2962 : MOZ_ASSERT(aItem, "No item to append!");
2963 : MOZ_ASSERT(!aItem->mAbove, "Already in a list!");
2964 : aItem->mAbove = mSentinel.mAbove;
2965 : mSentinel.mAbove = aItem;
2966 : if (mTop == &mSentinel) {
2967 : mTop = aItem;
2968 : }
2969 : mLength++;
2970 : }
2971 :
2972 : /**
2973 : * Removes all items from aList and appends them to the top of this list
2974 : */
2975 : void AppendToTop(nsDisplayList* aList) {
2976 : if (aList->mSentinel.mAbove) {
2977 : mTop->mAbove = aList->mSentinel.mAbove;
2978 : mTop = aList->mTop;
2979 : aList->mTop = &aList->mSentinel;
2980 : aList->mSentinel.mAbove = nullptr;
2981 : mLength += aList->mLength;
2982 : aList->mLength = 0;
2983 : }
2984 : }
2985 :
2986 : /**
2987 : * Removes all items from aList and prepends them to the bottom of this list
2988 : */
2989 : void AppendToBottom(nsDisplayList* aList) {
2990 : if (aList->mSentinel.mAbove) {
2991 : aList->mTop->mAbove = mSentinel.mAbove;
2992 : mSentinel.mAbove = aList->mSentinel.mAbove;
2993 : if (mTop == &mSentinel) {
2994 : mTop = aList->mTop;
2995 : }
2996 :
2997 : aList->mTop = &aList->mSentinel;
2998 : aList->mSentinel.mAbove = nullptr;
2999 : mLength += aList->mLength;
3000 : aList->mLength = 0;
3001 : }
3002 : }
3003 :
3004 : /**
3005 : * Remove an item from the bottom of the list and return it.
3006 : */
3007 : nsDisplayItem* RemoveBottom();
3008 :
3009 : /**
3010 0 : * Remove all items from the list and call their destructors.
3011 0 : */
3012 : void DeleteAll(nsDisplayListBuilder* aBuilder);
3013 :
3014 : /**
3015 : * @return the item at the top of the list, or null if the list is empty
3016 : */
3017 0 : nsDisplayItem* GetTop() const {
3018 : return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nullptr;
3019 : }
3020 : /**
3021 : * @return the item at the bottom of the list, or null if the list is empty
3022 : */
3023 : nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
3024 : bool IsEmpty() const { return mTop == &mSentinel; }
3025 :
3026 : /**
3027 : * @return the number of items in the list
3028 : */
3029 : uint32_t Count() const { return mLength; }
3030 : /**
3031 : * Stable sort the list by the z-order of GetUnderlyingFrame() on
3032 : * each item. 'auto' is counted as zero.
3033 : * It is assumed that the list is already in content document order.
3034 : */
3035 : void SortByZOrder();
3036 : /**
3037 : * Stable sort the list by the tree order of the content of
3038 : * GetUnderlyingFrame() on each item. z-index is ignored.
3039 : * @param aCommonAncestor a common ancestor of all the content elements
3040 : * associated with the display items, for speeding up tree order
3041 : * checks, or nullptr if not known; it's only a hint, if it is not an
3042 : * ancestor of some elements, then we lose performance but not correctness
3043 : */
3044 : void SortByContentOrder(nsIContent* aCommonAncestor);
3045 :
3046 : /**
3047 : * Sort the display list using a stable sort. Take care, because some of the
3048 : * items might be nsDisplayLists themselves.
3049 : * aComparator(Item item1, Item item2) should return true if item1 should go
3050 : * before item2.
3051 : * We sort the items into increasing order.
3052 : */
3053 : template<typename Item, typename Comparator>
3054 : void Sort(const Comparator& aComparator) {
3055 : // Some casual local browsing testing suggests that a local preallocated
3056 : // array of 20 items should be able to avoid a lot of dynamic allocations
3057 : // here.
3058 : AutoTArray<Item, 20> items;
3059 :
3060 : while (nsDisplayItem* item = RemoveBottom()) {
3061 : items.AppendElement(Item(item));
3062 : }
3063 :
3064 : std::stable_sort(items.begin(), items.end(), aComparator);
3065 :
3066 : for (Item& item : items) {
3067 : AppendToTop(item);
3068 : }
3069 : }
3070 :
3071 : /**
3072 : * Compute visiblity for the items in the list.
3073 : * We put this logic here so it can be shared by top-level
3074 : * painting and also display items that maintain child lists.
3075 : * This is also a good place to put ComputeVisibility-related logic
3076 : * that must be applied to every display item. In particular, this
3077 : * sets mVisibleRect on each display item.
3078 : * This sets mIsOpaque if the entire visible area of this list has
3079 : * been removed from aVisibleRegion when we return.
3080 : * This does not remove any items from the list, so we can recompute
3081 : * visiblity with different regions later (see
3082 : * FrameLayerBuilder::DrawPaintedLayer).
3083 : * This method needs to be idempotent.
3084 : *
3085 : * @param aVisibleRegion the area that is visible, relative to the
3086 : * reference frame; on return, this contains the area visible under the list.
3087 : * I.e., opaque contents of this list are subtracted from aVisibleRegion.
3088 : * @param aListVisibleBounds must be equal to the bounds of the intersection
3089 : * of aVisibleRegion and GetBounds() for this list.
3090 : * @return true if any item in the list is visible.
3091 : */
3092 : bool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
3093 : nsRegion* aVisibleRegion,
3094 : const nsRect& aListVisibleBounds);
3095 :
3096 : /**
3097 : * As ComputeVisibilityForSublist, but computes visibility for a root
3098 : * list (a list that does not belong to an nsDisplayItem).
3099 : * This method needs to be idempotent.
3100 : *
3101 : * @param aVisibleRegion the area that is visible
3102 : */
3103 : bool ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
3104 : nsRegion* aVisibleRegion);
3105 :
3106 : /**
3107 : * Returns true if the visible region output from ComputeVisiblity was
3108 : * empty, i.e. everything visible in this list is opaque.
3109 : */
3110 : bool IsOpaque() const {
3111 : return mIsOpaque;
3112 : }
3113 :
3114 : /**
3115 : * Returns true if any display item requires the surface to be transparent.
3116 : */
3117 : bool NeedsTransparentSurface() const {
3118 : return mForceTransparentSurface;
3119 : }
3120 : /**
3121 : * Paint the list to the rendering context. We assume that (0,0) in aCtx
3122 : * corresponds to the origin of the reference frame. For best results,
3123 : * aCtx's current transform should make (0,0) pixel-aligned. The
3124 : * rectangle in aDirtyRect is painted, which *must* be contained in the
3125 : * dirty rect used to construct the display list.
3126 : *
3127 : * If aFlags contains PAINT_USE_WIDGET_LAYERS and
3128 : * ShouldUseWidgetLayerManager() is set, then we will paint using
3129 : * the reference frame's widget's layer manager (and ctx may be null),
3130 : * otherwise we will use a temporary BasicLayerManager and ctx must
3131 : * not be null.
3132 : *
3133 : * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
3134 : * layer manager has already had BeginTransaction() called on it and
3135 : * we should not call it again.
3136 : *
3137 : * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode
3138 : * to avoid short cut optimizations.
3139 : *
3140 : * This must only be called on the root display list of the display list
3141 : * tree.
3142 : *
3143 : * We return the layer manager used for painting --- mainly so that
3144 : * callers can dump its layer tree if necessary.
3145 : */
3146 : enum {
3147 : PAINT_DEFAULT = 0,
3148 : PAINT_USE_WIDGET_LAYERS = 0x01,
3149 : PAINT_EXISTING_TRANSACTION = 0x04,
3150 : PAINT_NO_COMPOSITE = 0x08,
3151 : PAINT_COMPRESSED = 0x10,
3152 : PAINT_IDENTICAL_DISPLAY_LIST = 0x20
3153 : };
3154 : already_AddRefed<LayerManager> PaintRoot(nsDisplayListBuilder* aBuilder,
3155 : gfxContext* aCtx,
3156 : uint32_t aFlags);
3157 :
3158 : mozilla::FrameLayerBuilder* BuildLayers(nsDisplayListBuilder* aBuilder,
3159 : LayerManager* aLayerManager,
3160 : uint32_t aFlags,
3161 : bool aIsWidgetTransaction);
3162 : /**
3163 : * Get the bounds. Takes the union of the bounds of all children.
3164 : * The result is not cached.
3165 : */
3166 : nsRect GetBounds(nsDisplayListBuilder* aBuilder) const;
3167 :
3168 : /**
3169 : * Get this list's bounds, respecting clips relative to aASR. The result is
3170 : * the union of each item's clipped bounds with respect to aASR. That means
3171 : * that if an item can move asynchronously with an ASR that is a descendant
3172 : * of aASR, then the clipped bounds with respect to aASR will be the clip of
3173 : * that item for aASR, because the item can move anywhere inside that clip.
3174 : * If there is an item in this list which is not bounded with respect to
3175 : * aASR (i.e. which does not have "finite bounds" with respect to aASR),
3176 : * then this method trigger an assertion failure.
3177 : * The optional aBuildingRect out argument can be set to non-null if the
3178 : * caller is also interested to know the building rect. This can be used
3179 : * to get the visible rect efficiently without traversing the display list
3180 : * twice.
3181 : */
3182 : nsRect GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
3183 : const ActiveScrolledRoot* aASR,
3184 : nsRect* aBuildingRect = nullptr) const;
3185 :
3186 : /**
3187 : * Find the topmost display item that returns a non-null frame, and return
3188 : * the frame.
3189 : */
3190 : void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
3191 : nsDisplayItem::HitTestState* aState,
3192 : nsTArray<nsIFrame*> *aOutFrames) const;
3193 : /**
3194 : * Compute the union of the visible rects of the items in the list. The
3195 : * result is not cached.
3196 : */
3197 : nsRect GetBuildingRect() const;
3198 :
3199 : void SetIsOpaque()
3200 : {
3201 : mIsOpaque = true;
3202 : }
3203 : void SetNeedsTransparentSurface()
3204 : {
3205 : mForceTransparentSurface = true;
3206 : }
3207 :
3208 : void RestoreState() {
3209 : mIsOpaque = false;
3210 : mForceTransparentSurface = false;
3211 : }
3212 :
3213 : private:
3214 : nsDisplayItemLink mSentinel;
3215 : nsDisplayItemLink* mTop;
3216 :
3217 : uint32_t mLength;
3218 :
3219 : // This is set to true by FrameLayerBuilder if the final visible region
3220 : // is empty (i.e. everything that was visible is covered by some
3221 : // opaque content in this list).
3222 : bool mIsOpaque;
3223 : // This is set to true by FrameLayerBuilder if any display item in this
3224 0 : // list needs to force the surface containing this list to be transparent.
3225 : bool mForceTransparentSurface;
3226 : };
3227 0 :
3228 0 : class FlattenedDisplayItemIterator
3229 : {
3230 0 : public:
3231 : FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder,
3232 : nsDisplayList* aList,
3233 0 : const bool aResolveFlattening = true)
3234 : : mBuilder(aBuilder)
3235 0 : , mNext(aList->GetBottom())
3236 : {
3237 2 : if (aResolveFlattening) {
3238 2 : // This is done conditionally in case subclass overrides
3239 2 : // ShouldFlattenNextItem().
3240 2 : ResolveFlattening();
3241 : }
3242 0 : }
3243 :
3244 0 : virtual ~FlattenedDisplayItemIterator()
3245 : {
3246 : MOZ_ASSERT(!HasNext());
3247 0 : }
3248 0 :
3249 0 : nsDisplayItem* GetNext()
3250 : {
3251 0 : nsDisplayItem* next = mNext;
3252 :
3253 : // Advance mNext to the following item
3254 2 : if (next) {
3255 : mNext = mNext->GetAbove();
3256 0 : ResolveFlattening();
3257 : }
3258 : return next;
3259 : }
3260 :
3261 : bool HasNext() const
3262 : {
3263 : return mNext || !mStack.IsEmpty();
3264 : }
3265 2 :
3266 : nsDisplayItem* PeekNext()
3267 2 : {
3268 : return mNext;
3269 : }
3270 0 :
3271 : protected:
3272 0 : bool AtEndOfNestedList() const
3273 : {
3274 : return !mNext && mStack.Length() > 0;
3275 2 : }
3276 :
3277 : virtual bool ShouldFlattenNextItem()
3278 : {
3279 : return mNext && mNext->ShouldFlattenAway(mBuilder);
3280 2 : }
3281 2 :
3282 : void ResolveFlattening()
3283 2 : {
3284 2 : // Handle the case where we reach the end of a nested list, or the current
3285 2 : // item should start a new nested list. Repeat this until we find an actual
3286 : // item, or the very end of the outer list.
3287 2 : while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
3288 : if (AtEndOfNestedList()) {
3289 : // Pop the last item off the stack.
3290 : mNext = mStack.LastElement();
3291 2 : EndNested(mNext);
3292 2 : mStack.RemoveElementAt(mStack.Length() - 1);
3293 2 : // We stored the item that was flattened, so advance to the next.
3294 2 : mNext = mNext->GetAbove();
3295 : } else {
3296 : // This item wants to be flattened. Store the current item on the stack,
3297 2 : // and use the first item in the child list instead.
3298 : mStack.AppendElement(mNext);
3299 0 : StartNested(mNext);
3300 0 : nsDisplayList* childItems = mNext->GetSameCoordinateSystemChildren();
3301 : mNext = childItems->GetBottom();
3302 : }
3303 : }
3304 : }
3305 :
3306 : virtual void EndNested(nsDisplayItem* aItem) {}
3307 : virtual void StartNested(nsDisplayItem* aItem) {}
3308 :
3309 : nsDisplayListBuilder* mBuilder;
3310 : nsDisplayItem* mNext;
3311 : AutoTArray<nsDisplayItem*, 10> mStack;
3312 : };
3313 :
3314 : /**
3315 : * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
3316 : * will put any generated items onto the appropriate list given here. It's
3317 : * basically just a collection with one list for each separate stacking layer.
3318 : * The lists themselves are external to this object and thus can be shared
3319 : * with others. Some of the list pointers may even refer to the same list.
3320 : */
3321 : class nsDisplayListSet {
3322 : public:
3323 : /**
3324 : * @return a list where one should place the border and/or background for
3325 : * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
3326 : */
3327 : nsDisplayList* BorderBackground() const { return mBorderBackground; }
3328 : /**
3329 : * @return a list where one should place the borders and/or backgrounds for
3330 : * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
3331 : */
3332 : nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; }
3333 : /**
3334 : * @return a list where one should place descendant floats (step 5 of
3335 : * CSS 2.1 appendix E)
3336 : */
3337 : nsDisplayList* Floats() const { return mFloats; }
3338 : /**
3339 : * @return a list where one should place the (pseudo) stacking contexts
3340 : * for descendants of this frame (everything from steps 3, 7 and 8
3341 : * of CSS 2.1 appendix E)
3342 : */
3343 : nsDisplayList* PositionedDescendants() const { return mPositioned; }
3344 : /**
3345 : * @return a list where one should place the outlines
3346 : * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
3347 : */
3348 : nsDisplayList* Outlines() const { return mOutlines; }
3349 : /**
3350 : * @return a list where one should place all other content
3351 : */
3352 : nsDisplayList* Content() const { return mContent; }
3353 :
3354 : void DeleteAll(nsDisplayListBuilder* aBuilder) {
3355 : BorderBackground()->DeleteAll(aBuilder);
3356 : BlockBorderBackgrounds()->DeleteAll(aBuilder);
3357 : Floats()->DeleteAll(aBuilder);
3358 : PositionedDescendants()->DeleteAll(aBuilder);
3359 : Outlines()->DeleteAll(aBuilder);
3360 : Content()->DeleteAll(aBuilder);
3361 : }
3362 :
3363 : nsDisplayListSet(nsDisplayList* aBorderBackground,
3364 : nsDisplayList* aBlockBorderBackgrounds,
3365 : nsDisplayList* aFloats,
3366 : nsDisplayList* aContent,
3367 : nsDisplayList* aPositionedDescendants,
3368 : nsDisplayList* aOutlines) :
3369 : mBorderBackground(aBorderBackground),
3370 : mBlockBorderBackgrounds(aBlockBorderBackgrounds),
3371 : mFloats(aFloats),
3372 : mContent(aContent),
3373 : mPositioned(aPositionedDescendants),
3374 : mOutlines(aOutlines) {
3375 : }
3376 :
3377 : /**
3378 : * A copy constructor that lets the caller override the BorderBackground
3379 : * list.
3380 : */
3381 : nsDisplayListSet(const nsDisplayListSet& aLists,
3382 : nsDisplayList* aBorderBackground) :
3383 : mBorderBackground(aBorderBackground),
3384 : mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
3385 : mFloats(aLists.Floats()),
3386 : mContent(aLists.Content()),
3387 : mPositioned(aLists.PositionedDescendants()),
3388 : mOutlines(aLists.Outlines()) {
3389 : }
3390 :
3391 : /**
3392 : * Move all display items in our lists to top of the corresponding lists in the
3393 : * destination.
3394 : */
3395 : void MoveTo(const nsDisplayListSet& aDestination) const;
3396 :
3397 : private:
3398 : // This class is only used on stack, so we don't have to worry about leaking
3399 : // it. Don't let us be heap-allocated!
3400 : void* operator new(size_t sz) CPP_THROW_NEW;
3401 :
3402 : protected:
3403 : nsDisplayList* mBorderBackground;
3404 : nsDisplayList* mBlockBorderBackgrounds;
3405 : nsDisplayList* mFloats;
3406 : nsDisplayList* mContent;
3407 : nsDisplayList* mPositioned;
3408 : nsDisplayList* mOutlines;
3409 : };
3410 :
3411 : /**
3412 : * A specialization of nsDisplayListSet where the lists are actually internal
3413 : * to the object, and all distinct.
3414 : */
3415 : struct nsDisplayListCollection : public nsDisplayListSet {
3416 : explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder) :
3417 : nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4],
3418 : &mLists[5]) {}
3419 : explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder, nsDisplayList* aBorderBackground) :
3420 : nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4],
3421 : &mLists[5]) {}
3422 :
3423 : /**
3424 : * Sort all lists by content order.
3425 : */
3426 : void SortAllByContentOrder(nsIContent* aCommonAncestor) {
3427 : for (int32_t i = 0; i < 6; ++i) {
3428 : mLists[i].SortByContentOrder(aCommonAncestor);
3429 : }
3430 : }
3431 :
3432 : private:
3433 : // This class is only used on stack, so we don't have to worry about leaking
3434 : // it. Don't let us be heap-allocated!
3435 : void* operator new(size_t sz) CPP_THROW_NEW;
3436 :
3437 : nsDisplayList mLists[6];
3438 : };
3439 :
3440 : /**
3441 : * A display list that also retains the partial build
3442 : * information (in the form of a DAG) used to create it.
3443 : *
3444 0 : * Display lists built from a partial list aren't necessarily
3445 : * in the same order as a full build, and the DAG retains
3446 : * the information needing to interpret the current
3447 : * order correctly.
3448 : */
3449 : class RetainedDisplayList : public nsDisplayList {
3450 : public:
3451 : RetainedDisplayList() {}
3452 : RetainedDisplayList(RetainedDisplayList&& aOther)
3453 : {
3454 : AppendToTop(&aOther);
3455 : mDAG = std::move(aOther.mDAG);
3456 : }
3457 : ~RetainedDisplayList()
3458 : {
3459 : MOZ_ASSERT(mOldItems.IsEmpty(), "Must empty list before destroying");
3460 : }
3461 :
3462 : RetainedDisplayList& operator=(RetainedDisplayList&& aOther)
3463 : {
3464 0 : MOZ_ASSERT(!Count(), "Can only move into an empty list!");
3465 : MOZ_ASSERT(mOldItems.IsEmpty(), "Can only move into an empty list!");
3466 0 : AppendToTop(&aOther);
3467 0 : mDAG = std::move(aOther.mDAG);
3468 0 : return *this;
3469 : }
3470 :
3471 0 : void DeleteAll(nsDisplayListBuilder* aBuilder)
3472 0 : {
3473 0 : for (OldItemInfo& i : mOldItems) {
3474 0 : if (i.mItem) {
3475 : i.mItem->Destroy(aBuilder);
3476 : }
3477 : }
3478 : mOldItems.Clear();
3479 : mDAG.Clear();
3480 : nsDisplayList::DeleteAll(aBuilder);
3481 : }
3482 :
3483 : DirectedAcyclicGraph<MergedListUnits> mDAG;
3484 :
3485 : // Temporary state initialized during the preprocess pass
3486 : // of RetainedDisplayListBuilder and then used during merging.
3487 : nsTArray<OldItemInfo> mOldItems;
3488 : };
3489 :
3490 : class nsDisplayImageContainer : public nsDisplayItem {
3491 : public:
3492 : typedef mozilla::LayerIntPoint LayerIntPoint;
3493 : typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
3494 : typedef mozilla::layers::ImageContainer ImageContainer;
3495 : typedef mozilla::layers::ImageLayer ImageLayer;
3496 :
3497 : nsDisplayImageContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
3498 : : nsDisplayItem(aBuilder, aFrame)
3499 : {}
3500 :
3501 : /**
3502 : * @return true if this display item can be optimized into an image layer.
3503 : * It is an error to call GetContainer() unless you've called
3504 : * CanOptimizeToImageLayer() first and it returned true.
3505 : */
3506 : virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
3507 : nsDisplayListBuilder* aBuilder);
3508 :
3509 : already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
3510 : nsDisplayListBuilder* aBuilder);
3511 : void ConfigureLayer(ImageLayer* aLayer,
3512 : const ContainerLayerParameters& aParameters);
3513 :
3514 : virtual void UpdateDrawResult(mozilla::image::ImgDrawResult aResult) = 0;
3515 :
3516 : virtual already_AddRefed<imgIContainer> GetImage() = 0;
3517 :
3518 : virtual nsRect GetDestRect() const = 0;
3519 :
3520 : virtual bool SupportsOptimizingToImage() const override { return true; }
3521 : };
3522 :
3523 : /**
3524 : * Use this class to implement not-very-frequently-used display items
3525 : * that are not opaque, do not receive events, and are bounded by a frame's
3526 : * border-rect.
3527 : *
3528 : * This should not be used for display items which are created frequently,
3529 : * because each item is one or two pointers bigger than an item from a
3530 : * custom display item class could be, and fractionally slower. However it does
3531 : * save code size. We use this for infrequently-used item types.
3532 : */
3533 : class nsDisplayGeneric : public nsDisplayItem {
3534 : public:
3535 : typedef void (* PaintCallback)(nsIFrame* aFrame, DrawTarget* aDrawTarget,
3536 : const nsRect& aDirtyRect, nsPoint aFramePt);
3537 :
3538 : // XXX: should be removed eventually
3539 : typedef void (* OldPaintCallback)(nsIFrame* aFrame, gfxContext* aCtx,
3540 : const nsRect& aDirtyRect, nsPoint aFramePt);
3541 :
3542 : nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3543 : PaintCallback aPaint, const char* aName, DisplayItemType aType)
3544 : : nsDisplayItem(aBuilder, aFrame)
3545 : , mPaint(aPaint)
3546 : , mOldPaint(nullptr)
3547 : , mName(aName)
3548 : , mType(aType)
3549 : {
3550 : MOZ_COUNT_CTOR(nsDisplayGeneric);
3551 : }
3552 :
3553 : // XXX: should be removed eventually
3554 : nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3555 : OldPaintCallback aOldPaint, const char* aName, DisplayItemType aType)
3556 : : nsDisplayItem(aBuilder, aFrame)
3557 : , mPaint(nullptr)
3558 0 : , mOldPaint(aOldPaint)
3559 0 : , mName(aName)
3560 0 : , mType(aType)
3561 : {
3562 : MOZ_COUNT_CTOR(nsDisplayGeneric);
3563 0 : }
3564 : #ifdef NS_BUILD_REFCNT_LOGGING
3565 0 : virtual ~nsDisplayGeneric() {
3566 0 : MOZ_COUNT_DTOR(nsDisplayGeneric);
3567 0 : }
3568 : #endif
3569 0 :
3570 : virtual void Paint(nsDisplayListBuilder* aBuilder,
3571 0 : gfxContext* aCtx) override {
3572 0 : MOZ_ASSERT(!!mPaint != !!mOldPaint);
3573 0 : if (mPaint) {
3574 : mPaint(mFrame, aCtx->GetDrawTarget(), GetPaintRect(), ToReferenceFrame());
3575 : } else {
3576 : mOldPaint(mFrame, aCtx, GetPaintRect(), ToReferenceFrame());
3577 0 : }
3578 : }
3579 0 : virtual const char* Name() const override { return mName; }
3580 0 : virtual DisplayItemType GetType() const override { return mType; }
3581 0 :
3582 : // This override is needed because GetType() for nsDisplayGeneric subclasses
3583 : // does not match TYPE_GENERIC that was used to allocate the object.
3584 : virtual void Destroy(nsDisplayListBuilder* aBuilder) override
3585 : {
3586 : this->~nsDisplayGeneric();
3587 : aBuilder->Destroy(DisplayItemType::TYPE_GENERIC, this);
3588 : }
3589 :
3590 : protected:
3591 : void* operator new(size_t aSize,
3592 : nsDisplayListBuilder* aBuilder) {
3593 : return aBuilder->Allocate(aSize, DisplayItemType::TYPE_GENERIC);
3594 : }
3595 : template<typename T, typename... Args>
3596 : friend T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, Args&&... aArgs);
3597 :
3598 : PaintCallback mPaint;
3599 : OldPaintCallback mOldPaint; // XXX: should be removed eventually
3600 : const char* mName;
3601 : DisplayItemType mType;
3602 : };
3603 :
3604 : #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
3605 : /**
3606 : * This class implements painting of reflow counts. Ideally, we would simply
3607 : * make all the frame names be those returned by nsFrame::GetFrameName
3608 : * (except that tosses in the content tag name!) and support only one color
3609 : * and eliminate this class altogether in favor of nsDisplayGeneric, but for
3610 : * the time being we can't pass args to a PaintCallback, so just have a
3611 : * separate class to do the right thing. Sadly, this alsmo means we need to
3612 : * hack all leaf frame classes to handle this.
3613 : *
3614 : * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
3615 : * here... I could switch it all to nscolor, but why bother?
3616 : */
3617 : class nsDisplayReflowCount : public nsDisplayItem {
3618 : public:
3619 : nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3620 : const char* aFrameName,
3621 : uint32_t aColor = 0)
3622 0 : : nsDisplayItem(aBuilder, aFrame),
3623 0 : mFrameName(aFrameName),
3624 0 : mColor(aColor)
3625 : {
3626 : MOZ_COUNT_CTOR(nsDisplayReflowCount);
3627 0 : }
3628 0 : #ifdef NS_BUILD_REFCNT_LOGGING
3629 0 : virtual ~nsDisplayReflowCount() {
3630 : MOZ_COUNT_DTOR(nsDisplayReflowCount);
3631 0 : }
3632 0 : #endif
3633 0 :
3634 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
3635 : mFrame->PresShell()->PaintCount(mFrameName, aCtx,
3636 : mFrame->PresContext(),
3637 : mFrame, ToReferenceFrame(),
3638 : mColor);
3639 : }
3640 : NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT)
3641 : protected:
3642 : const char* mFrameName;
3643 : nscolor mColor;
3644 : };
3645 :
3646 : #define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
3647 : PR_BEGIN_MACRO \
3648 : if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3649 : PresShell()->IsPaintingFrameCounts()) { \
3650 : aLists.Outlines()->AppendToTop( \
3651 : MakeDisplayItem<nsDisplayReflowCount>(aBuilder, this, _name)); \
3652 : } \
3653 : PR_END_MACRO
3654 :
3655 : #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
3656 : PR_BEGIN_MACRO \
3657 : if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3658 : PresShell()->IsPaintingFrameCounts()) { \
3659 : aLists.Outlines()->AppendToTop( \
3660 : MakeDisplayItem<nsDisplayReflowCount>(aBuilder, this, _name, _color)); \
3661 : } \
3662 : PR_END_MACRO
3663 :
3664 : /*
3665 : Macro to be used for classes that don't actually implement BuildDisplayList
3666 : */
3667 : #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
3668 : void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
3669 : const nsRect& aDirtyRect, \
3670 : const nsDisplayListSet& aLists) { \
3671 : DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
3672 : _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
3673 : }
3674 :
3675 : #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3676 :
3677 : #define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
3678 : #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
3679 : #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
3680 :
3681 : #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3682 :
3683 : class nsDisplayCaret : public nsDisplayItem {
3684 : public:
3685 : nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame);
3686 0 : #ifdef NS_BUILD_REFCNT_LOGGING
3687 : virtual ~nsDisplayCaret();
3688 : #endif
3689 :
3690 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
3691 : bool* aSnap) const override;
3692 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3693 : NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
3694 :
3695 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3696 : mozilla::wr::IpcResourceUpdateQueue& aResources,
3697 : const StackingContextHelper& aSc,
3698 : mozilla::layers::WebRenderLayerManager* aManager,
3699 : nsDisplayListBuilder* aDisplayListBuilder) override;
3700 :
3701 : protected:
3702 : RefPtr<nsCaret> mCaret;
3703 : nsRect mBounds;
3704 : };
3705 :
3706 : /**
3707 0 : * The standard display item to paint the CSS borders of a frame.
3708 0 : */
3709 0 : class nsDisplayBorder : public nsDisplayItem {
3710 : public:
3711 : nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
3712 :
3713 : #ifdef NS_BUILD_REFCNT_LOGGING
3714 : virtual ~nsDisplayBorder() {
3715 : MOZ_COUNT_DTOR(nsDisplayBorder);
3716 : }
3717 : #endif
3718 :
3719 : virtual bool IsInvisibleInRect(const nsRect& aRect) const override;
3720 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
3721 : bool* aSnap) const override;
3722 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3723 : LayerManager* aManager,
3724 : const ContainerLayerParameters& aParameters) override;
3725 :
3726 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3727 : LayerManager* aManager,
3728 : const ContainerLayerParameters& aContainerParameters) override;
3729 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3730 0 : mozilla::wr::IpcResourceUpdateQueue& aResources,
3731 : const StackingContextHelper& aSc,
3732 : mozilla::layers::WebRenderLayerManager* aManager,
3733 : nsDisplayListBuilder* aDisplayListBuilder) override;
3734 :
3735 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3736 :
3737 : NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
3738 0 :
3739 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
3740 :
3741 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3742 0 : const nsDisplayItemGeometry* aGeometry,
3743 : nsRegion* aInvalidRegion) const override;
3744 :
3745 : virtual nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder,
3746 : bool* aSnap) const override
3747 : {
3748 : *aSnap = true;
3749 : return CalculateBounds<nsRegion>(*mFrame->StyleBorder());
3750 : }
3751 :
3752 0 : protected:
3753 : void CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3754 0 : mozilla::wr::IpcResourceUpdateQueue& aResource,
3755 0 : const StackingContextHelper& aSc,
3756 0 : mozilla::layers::WebRenderLayerManager* aManager,
3757 0 : nsDisplayListBuilder* aDisplayListBuilder);
3758 : template<typename T>
3759 0 : T CalculateBounds(const nsStyleBorder& aStyleBorder) const
3760 0 : {
3761 0 : nsRect borderBounds(ToReferenceFrame(), mFrame->GetSize());
3762 0 : if (aStyleBorder.IsBorderImageLoaded()) {
3763 : borderBounds.Inflate(aStyleBorder.GetImageOutset());
3764 0 : return borderBounds;
3765 0 : } else {
3766 : nsMargin border = aStyleBorder.GetComputedBorder();
3767 0 : T result;
3768 0 : if (border.top > 0) {
3769 : result = nsRect(borderBounds.X(), borderBounds.Y(), borderBounds.Width(), border.top);
3770 0 : }
3771 0 : if (border.right > 0) {
3772 : result.OrWith(nsRect(borderBounds.XMost() - border.right, borderBounds.Y(), border.right, borderBounds.Height()));
3773 : }
3774 : if (border.bottom > 0) {
3775 0 : result.OrWith(nsRect(borderBounds.X(), borderBounds.YMost() - border.bottom, borderBounds.Width(), border.bottom));
3776 0 : }
3777 0 : if (border.left > 0) {
3778 0 : result.OrWith(nsRect(borderBounds.X(), borderBounds.Y(), border.left, borderBounds.Height()));
3779 : }
3780 0 :
3781 0 : nscoord radii[8];
3782 0 : if (mFrame->GetBorderRadii(radii)) {
3783 : if (border.left > 0 || border.top > 0) {
3784 0 : nsSize cornerSize(radii[mozilla::eCornerTopLeftX], radii[mozilla::eCornerTopLeftY]);
3785 0 : result.OrWith(nsRect(borderBounds.TopLeft(), cornerSize));
3786 0 : }
3787 : if (border.top > 0 || border.right > 0) {
3788 0 : nsSize cornerSize(radii[mozilla::eCornerTopRightX], radii[mozilla::eCornerTopRightY]);
3789 0 : result.OrWith(nsRect(borderBounds.TopRight() - nsPoint(cornerSize.width, 0), cornerSize));
3790 0 : }
3791 : if (border.right > 0 || border.bottom > 0) {
3792 : nsSize cornerSize(radii[mozilla::eCornerBottomRightX], radii[mozilla::eCornerBottomRightY]);
3793 0 : result.OrWith(nsRect(borderBounds.BottomRight() - nsPoint(cornerSize.width, cornerSize.height), cornerSize));
3794 : }
3795 : if (border.bottom > 0 || border.left > 0) {
3796 : nsSize cornerSize(radii[mozilla::eCornerBottomLeftX], radii[mozilla::eCornerBottomLeftY]);
3797 : result.OrWith(nsRect(borderBounds.BottomLeft() - nsPoint(0, cornerSize.height), cornerSize));
3798 : }
3799 : }
3800 : return result;
3801 : }
3802 : }
3803 :
3804 : mozilla::Array<mozilla::gfx::Color, 4> mColors;
3805 : mozilla::Array<mozilla::LayerCoord, 4> mWidths;
3806 : mozilla::Array<mozilla::LayerSize, 4> mCorners;
3807 : mozilla::Array<uint8_t, 4> mBorderStyles;
3808 : mozilla::LayerRect mRect;
3809 :
3810 : mozilla::Maybe<nsCSSBorderRenderer> mBorderRenderer;
3811 : mozilla::Maybe<nsCSSBorderImageRenderer> mBorderImageRenderer;
3812 :
3813 : nsRect mBounds;
3814 : bool mBorderIsEmpty;
3815 : };
3816 :
3817 : /**
3818 : * A simple display item that just renders a solid color across the
3819 : * specified bounds. For canvas frames (in the CSS sense) we split off the
3820 : * drawing of the background color into this class (from nsDisplayBackground
3821 0 : * via nsDisplayCanvasBackground). This is done so that we can always draw a
3822 : * background color to avoid ugly flashes of white when we can't draw a full
3823 : * frame tree (ie when a page is loading). The bounds can differ from the
3824 : * frame's bounds -- this is needed when a frame/iframe is loading and there
3825 : * is not yet a frame tree to go in the frame/iframe so we use the subdoc
3826 : * frame of the parent document as a standin.
3827 0 : */
3828 : class nsDisplaySolidColorBase : public nsDisplayItem {
3829 0 : public:
3830 : nsDisplaySolidColorBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nscolor aColor)
3831 : : nsDisplayItem(aBuilder, aFrame), mColor(aColor)
3832 0 : {}
3833 :
3834 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
3835 : {
3836 : return new nsDisplaySolidColorGeometry(this, aBuilder, mColor);
3837 0 : }
3838 0 :
3839 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3840 0 : const nsDisplayItemGeometry* aGeometry,
3841 : nsRegion* aInvalidRegion) const override
3842 : {
3843 0 : const nsDisplaySolidColorGeometry* geometry =
3844 : static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
3845 : if (mColor != geometry->mColor) {
3846 0 : bool dummy;
3847 : aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
3848 : return;
3849 0 : }
3850 0 : ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
3851 0 : }
3852 0 :
3853 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3854 0 : bool* aSnap) const override
3855 : {
3856 : *aSnap = false;
3857 0 : nsRegion result;
3858 : if (NS_GET_A(mColor) == 255) {
3859 0 : result = GetBounds(aBuilder, aSnap);
3860 : }
3861 : return result;
3862 : }
3863 :
3864 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override
3865 : {
3866 : return mozilla::Some(mColor);
3867 : }
3868 :
3869 : protected:
3870 : nscolor mColor;
3871 : };
3872 :
3873 : class nsDisplaySolidColor : public nsDisplaySolidColorBase {
3874 : public:
3875 : nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3876 : const nsRect& aBounds, nscolor aColor, bool aCanBeReused = true)
3877 0 : : nsDisplaySolidColorBase(aBuilder, aFrame, aColor), mBounds(aBounds)
3878 0 : , mCanBeReused(aCanBeReused)
3879 0 : {
3880 : NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
3881 : MOZ_COUNT_CTOR(nsDisplaySolidColor);
3882 : }
3883 : #ifdef NS_BUILD_REFCNT_LOGGING
3884 : virtual ~nsDisplaySolidColor() {
3885 : MOZ_COUNT_DTOR(nsDisplaySolidColor);
3886 : }
3887 : #endif
3888 :
3889 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
3890 : bool* aSnap) const override;
3891 :
3892 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3893 : LayerManager* aManager,
3894 : const ContainerLayerParameters& aParameters) override;
3895 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3896 : LayerManager* aManager,
3897 : const ContainerLayerParameters& aContainerParameters) override;
3898 :
3899 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3900 :
3901 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
3902 0 :
3903 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3904 0 : mozilla::wr::IpcResourceUpdateQueue& aResources,
3905 : const StackingContextHelper& aSc,
3906 0 : mozilla::layers::WebRenderLayerManager* aManager,
3907 : nsDisplayListBuilder* aDisplayListBuilder) override;
3908 0 :
3909 0 : NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
3910 :
3911 0 : virtual bool CanBeReused() const override { return mCanBeReused; }
3912 :
3913 : int32_t ZIndex() const override
3914 : {
3915 : if (mOverrideZIndex) {
3916 : return mOverrideZIndex.value();
3917 : }
3918 : return nsDisplaySolidColorBase::ZIndex();
3919 : }
3920 :
3921 : void SetOverrideZIndex(int32_t aZIndex)
3922 : {
3923 : mOverrideZIndex = mozilla::Some(aZIndex);
3924 : }
3925 :
3926 : private:
3927 : nsRect mBounds;
3928 : bool mCanBeReused;
3929 : mozilla::Maybe<int32_t> mOverrideZIndex;
3930 : };
3931 :
3932 : /**
3933 : * A display item that renders a solid color over a region. This is not
3934 : * exposed through CSS, its only purpose is efficient invalidation of
3935 : * the find bar highlighter dimmer.
3936 : */
3937 : class nsDisplaySolidColorRegion : public nsDisplayItem {
3938 : typedef mozilla::gfx::Color Color;
3939 :
3940 : public:
3941 : nsDisplaySolidColorRegion(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3942 0 : const nsRegion& aRegion, nscolor aColor)
3943 0 : : nsDisplayItem(aBuilder, aFrame), mRegion(aRegion), mColor(Color::FromABGR(aColor))
3944 0 : {
3945 : NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColorRegions!");
3946 : MOZ_COUNT_CTOR(nsDisplaySolidColorRegion);
3947 0 : }
3948 : #ifdef NS_BUILD_REFCNT_LOGGING
3949 0 : virtual ~nsDisplaySolidColorRegion() {
3950 : MOZ_COUNT_DTOR(nsDisplaySolidColorRegion);
3951 : }
3952 0 : #endif
3953 :
3954 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
3955 : {
3956 : return new nsDisplaySolidColorRegionGeometry(this, aBuilder, mRegion, mColor);
3957 0 : }
3958 0 :
3959 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3960 : const nsDisplayItemGeometry* aGeometry,
3961 0 : nsRegion* aInvalidRegion) const override
3962 : {
3963 0 : const nsDisplaySolidColorRegionGeometry* geometry =
3964 : static_cast<const nsDisplaySolidColorRegionGeometry*>(aGeometry);
3965 : if (mColor == geometry->mColor) {
3966 : aInvalidRegion->Xor(geometry->mRegion, mRegion);
3967 : } else {
3968 : aInvalidRegion->Or(geometry->mRegion.GetBounds(), mRegion.GetBounds());
3969 : }
3970 : }
3971 0 :
3972 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3973 : mozilla::wr::IpcResourceUpdateQueue& aResources,
3974 : const StackingContextHelper& aSc,
3975 : mozilla::layers::WebRenderLayerManager* aManager,
3976 : nsDisplayListBuilder* aDisplayListBuilder) override;
3977 :
3978 : NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION)
3979 :
3980 : protected:
3981 :
3982 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
3983 : bool* aSnap) const override;
3984 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3985 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
3986 :
3987 : private:
3988 : nsRegion mRegion;
3989 : Color mColor;
3990 : };
3991 :
3992 : /**
3993 : * A display item to paint one background-image for a frame. Each background
3994 : * image layer gets its own nsDisplayBackgroundImage.
3995 : */
3996 : class nsDisplayBackgroundImage : public nsDisplayImageContainer {
3997 : public:
3998 : typedef mozilla::StyleGeometryBox StyleGeometryBox;
3999 :
4000 : struct InitData {
4001 : nsDisplayListBuilder* builder;
4002 : nsIFrame* frame;
4003 : mozilla::ComputedStyle* backgroundStyle;
4004 : nsCOMPtr<imgIContainer> image;
4005 : nsRect backgroundRect;
4006 : nsRect fillArea;
4007 : nsRect destArea;
4008 : uint32_t layer;
4009 : bool isRasterImage;
4010 : bool shouldFixToViewport;
4011 : };
4012 :
4013 : /**
4014 : * aLayer signifies which background layer this item represents.
4015 : * aIsThemed should be the value of aFrame->IsThemed.
4016 : * aBackgroundStyle should be the result of
4017 : * nsCSSRendering::FindBackground, or null if FindBackground returned false.
4018 : * aBackgroundRect is relative to aFrame.
4019 : */
4020 : static InitData GetInitData(nsDisplayListBuilder* aBuilder,
4021 : nsIFrame* aFrame,
4022 : uint32_t aLayer,
4023 : const nsRect& aBackgroundRect,
4024 : mozilla::ComputedStyle* aBackgroundStyle);
4025 :
4026 : explicit nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder,
4027 : const InitData& aInitData,
4028 : nsIFrame* aFrameForBounds = nullptr);
4029 : virtual ~nsDisplayBackgroundImage();
4030 :
4031 : // This will create and append new items for all the layers of the
4032 : // background. Returns whether we appended a themed background.
4033 : // aAllowWillPaintBorderOptimization should usually be left at true, unless
4034 : // aFrame has special border drawing that causes opaque borders to not
4035 : // actually be opaque.
4036 : static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
4037 : nsIFrame* aFrame,
4038 : const nsRect& aBackgroundRect,
4039 : nsDisplayList* aList,
4040 : bool aAllowWillPaintBorderOptimization = true,
4041 : mozilla::ComputedStyle* aComputedStyle = nullptr,
4042 : const nsRect& aBackgroundOriginRect = nsRect(),
4043 : nsIFrame* aSecondaryReferenceFrame = nullptr);
4044 :
4045 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4046 : LayerManager* aManager,
4047 : const ContainerLayerParameters& aParameters) override;
4048 :
4049 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4050 : LayerManager* aManager,
4051 : const ContainerLayerParameters& aContainerParameters) override;
4052 :
4053 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4054 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4055 : const StackingContextHelper& aSc,
4056 : mozilla::layers::WebRenderLayerManager* aManager,
4057 : nsDisplayListBuilder* aDisplayListBuilder) override;
4058 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4059 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
4060 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4061 : nsRegion* aVisibleRegion) override;
4062 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4063 : bool* aSnap) const override;
4064 0 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
4065 : /**
4066 0 : * GetBounds() returns the background painting area.
4067 : */
4068 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
4069 0 : bool* aSnap) const override;
4070 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4071 : virtual uint32_t GetPerFrameKey() const override
4072 : {
4073 : return (mLayer << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
4074 : }
4075 :
4076 : NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
4077 :
4078 : /**
4079 : * Return the background positioning area.
4080 : * (GetBounds() returns the background painting area.)
4081 : * Can be called only when mBackgroundStyle is non-null.
4082 : */
4083 : nsRect GetPositioningArea() const;
4084 :
4085 : /**
4086 : * Returns true if existing rendered pixels of this display item may need
4087 0 : * to be redrawn if the positioning area size changes but its position does
4088 : * not.
4089 0 : * If false, only the changed painting area needs to be redrawn when the
4090 : * positioning area size changes but its position does not.
4091 : */
4092 : bool RenderingMightDependOnPositioningAreaSizeChange() const;
4093 :
4094 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
4095 : {
4096 : return new nsDisplayBackgroundGeometry(this, aBuilder);
4097 : }
4098 :
4099 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4100 : const nsDisplayItemGeometry* aGeometry,
4101 : nsRegion* aInvalidRegion) const override;
4102 :
4103 : virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
4104 : nsDisplayListBuilder* aBuilder) override;
4105 : virtual already_AddRefed<imgIContainer> GetImage() override;
4106 : virtual nsRect GetDestRect() const override;
4107 :
4108 : virtual void UpdateDrawResult(mozilla::image::ImgDrawResult aResult) override
4109 : {
4110 : nsDisplayBackgroundGeometry::UpdateDrawResult(this, aResult);
4111 : }
4112 :
4113 : static nsRegion GetInsideClipRegion(const nsDisplayItem* aItem,
4114 : StyleGeometryBox aClip,
4115 : const nsRect& aRect,
4116 : const nsRect& aBackgroundRect);
4117 :
4118 : virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const override
4119 : {
4120 : return mShouldFixToViewport;
4121 : }
4122 :
4123 : virtual nsIFrame* GetDependentFrame() override
4124 : {
4125 : return mDependentFrame;
4126 : }
4127 :
4128 : void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4129 : {
4130 : if (!aBuilder->IsRetainingDisplayList()) {
4131 : return;
4132 : }
4133 : mDependentFrame = aFrame;
4134 : if (aFrame) {
4135 : mDependentFrame->AddDisplayItem(this);
4136 : }
4137 : }
4138 :
4139 : virtual void RemoveFrame(nsIFrame* aFrame) override
4140 : {
4141 : if (aFrame == mDependentFrame) {
4142 : mDependentFrame = nullptr;
4143 : }
4144 : nsDisplayItem::RemoveFrame(aFrame);
4145 : }
4146 :
4147 : protected:
4148 : typedef class mozilla::layers::ImageContainer ImageContainer;
4149 : typedef class mozilla::layers::ImageLayer ImageLayer;
4150 :
4151 : bool CanBuildWebRenderDisplayItems(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
4152 : nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder,
4153 : nsIFrame* aFrameForBounds = nullptr);
4154 :
4155 : void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
4156 : const nsRect& aBounds, nsRect* aClipRect);
4157 :
4158 : // Determine whether we want to be separated into our own layer, independent
4159 : // of whether this item can actually be layerized.
4160 : enum ImageLayerization {
4161 : WHENEVER_POSSIBLE,
4162 : ONLY_FOR_SCALING,
4163 : NO_LAYER_NEEDED
4164 : };
4165 : ImageLayerization ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
4166 : LayerManager* aManager);
4167 :
4168 : // Cache the result of nsCSSRendering::FindBackground. Always null if
4169 : // mIsThemed is true or if FindBackground returned false.
4170 : RefPtr<mozilla::ComputedStyle> mBackgroundStyle;
4171 : nsCOMPtr<imgIContainer> mImage;
4172 : nsIFrame* mDependentFrame;
4173 : nsRect mBackgroundRect; // relative to the reference frame
4174 : nsRect mFillRect;
4175 : nsRect mDestRect;
4176 : /* Bounds of this display item */
4177 : nsRect mBounds;
4178 : uint32_t mLayer;
4179 : bool mIsRasterImage;
4180 : /* Whether the image should be treated as fixed to the viewport. */
4181 : bool mShouldFixToViewport;
4182 : uint32_t mImageFlags;
4183 : };
4184 :
4185 : enum class TableType : uint8_t {
4186 : TABLE,
4187 : TABLE_COL,
4188 : TABLE_COL_GROUP,
4189 : TABLE_ROW,
4190 : TABLE_ROW_GROUP,
4191 : TABLE_CELL,
4192 :
4193 : TABLE_TYPE_MAX
4194 : };
4195 :
4196 : enum class TableTypeBits : uint8_t {
4197 : COUNT = 3
4198 : };
4199 :
4200 : static_assert(
4201 : static_cast<uint8_t>(TableType::TABLE_TYPE_MAX) < (1 << (static_cast<uint8_t>(TableTypeBits::COUNT) + 1)),
4202 : "TableType cannot fit with TableTypeBits::COUNT");
4203 : TableType GetTableTypeFromFrame(nsIFrame* aFrame);
4204 :
4205 : /**
4206 : * A display item to paint background image for table. For table parts, such
4207 : * as row, row group, col, col group, when drawing its background, we'll
4208 : * create separate background image display item for its containning cell.
4209 : * Those background image display items will reference to same DisplayItemData
4210 : * if we keep the mFrame point to cell's ancestor frame. We don't want to this
4211 : * happened bacause share same DisplatItemData will cause many bugs. So that
4212 : * we let mFrame point to cell frame and store the table type of the ancestor
4213 : * frame. And use mFrame and table type as key to generate DisplayItemData to
4214 : * avoid sharing DisplayItemData.
4215 : *
4216 0 : * Also store ancestor frame as mStyleFrame for all rendering informations.
4217 0 : */
4218 0 : class nsDisplayTableBackgroundImage : public nsDisplayBackgroundImage {
4219 0 : public:
4220 : nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder, const InitData& aInitData, nsIFrame* aCellFrame);
4221 : ~nsDisplayTableBackgroundImage();
4222 :
4223 : virtual uint32_t GetPerFrameKey() const override {
4224 : return (mLayer << (TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
4225 : (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
4226 : nsDisplayItem::GetPerFrameKey();
4227 : }
4228 :
4229 : virtual bool IsInvalid(nsRect& aRect) const override;
4230 :
4231 : virtual nsIFrame* FrameForInvalidation() const override { return mStyleFrame; }
4232 :
4233 : virtual bool HasDeletedFrame() const override {
4234 : return !mStyleFrame || nsDisplayBackgroundImage::HasDeletedFrame();
4235 : }
4236 :
4237 0 : virtual void RemoveFrame(nsIFrame* aFrame) override {
4238 : if (aFrame == mStyleFrame) {
4239 : mStyleFrame = nullptr;
4240 : }
4241 : nsDisplayBackgroundImage::RemoveFrame(aFrame);
4242 : }
4243 :
4244 : NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE)
4245 : protected:
4246 : virtual nsIFrame* StyleFrame() const override { return mStyleFrame; }
4247 :
4248 : nsIFrame* mStyleFrame;
4249 : TableType mTableType;
4250 : };
4251 :
4252 : /**
4253 : * A display item to paint the native theme background for a frame.
4254 : */
4255 0 : class nsDisplayThemedBackground : public nsDisplayItem {
4256 : public:
4257 0 : nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4258 0 : const nsRect& aBackgroundRect);
4259 0 : virtual ~nsDisplayThemedBackground();
4260 : void Init(nsDisplayListBuilder* aBuilder);
4261 :
4262 : void Destroy(nsDisplayListBuilder* aBuilder) override
4263 : {
4264 : aBuilder->UnregisterThemeGeometry(this);
4265 : nsDisplayItem::Destroy(aBuilder);
4266 : }
4267 :
4268 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4269 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
4270 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4271 0 : bool* aSnap) const override;
4272 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
4273 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4274 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4275 : const StackingContextHelper& aSc,
4276 : mozilla::layers::WebRenderLayerManager* aManager,
4277 : nsDisplayListBuilder* aDisplayListBuilder) override;
4278 : virtual bool MustPaintOnContentSide() const override { return true; }
4279 0 :
4280 : /**
4281 : * GetBounds() returns the background painting area.
4282 : */
4283 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
4284 : bool* aSnap) const override;
4285 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4286 : NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND)
4287 :
4288 : /**
4289 : * Return the background positioning area.
4290 : * (GetBounds() returns the background painting area.)
4291 : * Can be called only when mBackgroundStyle is non-null.
4292 : */
4293 : nsRect GetPositioningArea() const;
4294 0 :
4295 : /**
4296 0 : * Return whether our frame's document does not have the state
4297 : * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
4298 : */
4299 : bool IsWindowActive() const;
4300 :
4301 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
4302 : {
4303 : return new nsDisplayThemedBackgroundGeometry(this, aBuilder);
4304 : }
4305 :
4306 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4307 : const nsDisplayItemGeometry* aGeometry,
4308 : nsRegion* aInvalidRegion) const override;
4309 :
4310 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
4311 : protected:
4312 : nsRect GetBoundsInternal();
4313 :
4314 : void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
4315 : const nsRect& aBounds, nsRect* aClipRect);
4316 :
4317 : nsRect mBackgroundRect;
4318 : nsRect mBounds;
4319 : nsITheme::Transparency mThemeTransparency;
4320 : uint8_t mAppearance;
4321 : };
4322 :
4323 : class nsDisplayTableThemedBackground : public nsDisplayThemedBackground {
4324 : public:
4325 : nsDisplayTableThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4326 : const nsRect& aBackgroundRect,
4327 : nsIFrame* aAncestorFrame)
4328 : : nsDisplayThemedBackground(aBuilder, aFrame, aBackgroundRect)
4329 0 : , mAncestorFrame(aAncestorFrame)
4330 0 : , mTableType(GetTableTypeFromFrame(aAncestorFrame))
4331 0 : {
4332 : if (aBuilder->IsRetainingDisplayList()) {
4333 0 : mAncestorFrame->AddDisplayItem(this);
4334 : }
4335 0 : }
4336 0 : ~nsDisplayTableThemedBackground() {
4337 0 : if (mAncestorFrame) {
4338 : mAncestorFrame->RemoveDisplayItem(this);
4339 : }
4340 0 : }
4341 :
4342 0 : virtual uint32_t GetPerFrameKey() const override {
4343 0 : return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
4344 : nsDisplayItem::GetPerFrameKey();
4345 : }
4346 0 :
4347 0 : virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
4348 0 :
4349 : virtual bool HasDeletedFrame() const override {
4350 0 : return !mAncestorFrame || nsDisplayThemedBackground::HasDeletedFrame();
4351 0 : }
4352 :
4353 0 : virtual void RemoveFrame(nsIFrame* aFrame) override {
4354 : if (aFrame == mAncestorFrame) {
4355 0 : mAncestorFrame = nullptr;
4356 : }
4357 : nsDisplayThemedBackground::RemoveFrame(aFrame);
4358 : }
4359 :
4360 : NS_DISPLAY_DECL_NAME("TableThemedBackground", TYPE_TABLE_THEMED_BACKGROUND_IMAGE)
4361 : protected:
4362 : virtual nsIFrame* StyleFrame() const override { return mAncestorFrame; }
4363 : nsIFrame* mAncestorFrame;
4364 : TableType mTableType;
4365 : };
4366 :
4367 : class nsDisplayBackgroundColor : public nsDisplayItem
4368 : {
4369 : typedef mozilla::gfx::Color Color;
4370 :
4371 : public:
4372 : nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4373 : const nsRect& aBackgroundRect,
4374 : mozilla::ComputedStyle* aBackgroundStyle,
4375 : nscolor aColor)
4376 : : nsDisplayItem(aBuilder, aFrame)
4377 0 : , mBackgroundRect(aBackgroundRect)
4378 0 : , mBackgroundStyle(aBackgroundStyle)
4379 0 : , mDependentFrame(nullptr)
4380 0 : , mColor(Color::FromABGR(aColor))
4381 : {
4382 0 : mState.mColor = mColor;
4383 : }
4384 0 : virtual ~nsDisplayBackgroundColor()
4385 : {
4386 0 : if (mDependentFrame) {
4387 0 : mDependentFrame->RemoveDisplayItem(this);
4388 0 : }
4389 : }
4390 :
4391 : virtual void RestoreState() override
4392 : {
4393 : nsDisplayItem::RestoreState();
4394 : mColor = mState.mColor;
4395 : }
4396 :
4397 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4398 : LayerManager* aManager,
4399 : const ContainerLayerParameters& aParameters) override;
4400 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4401 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4402 : LayerManager* aManager,
4403 : const ContainerLayerParameters& aContainerParameters) override;
4404 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4405 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4406 : const StackingContextHelper& aSc,
4407 : mozilla::layers::WebRenderLayerManager* aManager,
4408 : nsDisplayListBuilder* aDisplayListBuilder) override;
4409 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4410 : bool* aSnap) const override;
4411 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
4412 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4413 0 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
4414 :
4415 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
4416 0 : float aOpacity,
4417 0 : const DisplayItemClipChain* aClip) override;
4418 : virtual bool CanApplyOpacity() const override;
4419 :
4420 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
4421 : bool* aSnap) const override
4422 0 : {
4423 : *aSnap = true;
4424 : return mBackgroundRect;
4425 0 : }
4426 :
4427 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
4428 : {
4429 0 : return new nsDisplaySolidColorGeometry(this, aBuilder, mColor.ToABGR());
4430 0 : }
4431 :
4432 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4433 : const nsDisplayItemGeometry* aGeometry,
4434 : nsRegion* aInvalidRegion) const override
4435 0 : {
4436 : const nsDisplaySolidColorGeometry* geometry = static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
4437 : if (mColor.ToABGR() != geometry->mColor) {
4438 0 : bool dummy;
4439 : aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
4440 0 : return;
4441 : }
4442 : ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
4443 : }
4444 :
4445 : virtual nsIFrame* GetDependentFrame() override
4446 : {
4447 : return mDependentFrame;
4448 : }
4449 :
4450 : void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4451 : {
4452 : if (!aBuilder->IsRetainingDisplayList()) {
4453 : return;
4454 0 : }
4455 : mDependentFrame = aFrame;
4456 0 : if (aFrame) {
4457 0 : mDependentFrame->AddDisplayItem(this);
4458 : }
4459 0 : }
4460 0 :
4461 : virtual void RemoveFrame(nsIFrame* aFrame) override
4462 0 : {
4463 : if (aFrame == mDependentFrame) {
4464 : mDependentFrame = nullptr;
4465 : }
4466 : nsDisplayItem::RemoveFrame(aFrame);
4467 : }
4468 :
4469 : NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
4470 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
4471 :
4472 : protected:
4473 : const nsRect mBackgroundRect;
4474 : RefPtr<mozilla::ComputedStyle> mBackgroundStyle;
4475 : nsIFrame* mDependentFrame;
4476 : mozilla::gfx::Color mColor;
4477 :
4478 : struct {
4479 : mozilla::gfx::Color mColor;
4480 : } mState;
4481 : };
4482 :
4483 : class nsDisplayTableBackgroundColor : public nsDisplayBackgroundColor
4484 : {
4485 : public:
4486 : nsDisplayTableBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4487 : const nsRect& aBackgroundRect,
4488 : mozilla::ComputedStyle* aBackgroundStyle,
4489 : nscolor aColor,
4490 : nsIFrame* aAncestorFrame)
4491 : : nsDisplayBackgroundColor(aBuilder, aFrame, aBackgroundRect, aBackgroundStyle, aColor)
4492 0 : , mAncestorFrame(aAncestorFrame)
4493 0 : , mTableType(GetTableTypeFromFrame(aAncestorFrame))
4494 0 : {
4495 : if (aBuilder->IsRetainingDisplayList()) {
4496 0 : mAncestorFrame->AddDisplayItem(this);
4497 : }
4498 0 : }
4499 : ~nsDisplayTableBackgroundColor() {
4500 0 : if (mAncestorFrame) {
4501 0 : mAncestorFrame->RemoveDisplayItem(this);
4502 : }
4503 : }
4504 0 :
4505 0 : virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
4506 0 :
4507 : virtual bool HasDeletedFrame() const override {
4508 0 : return !mAncestorFrame || nsDisplayBackgroundColor::HasDeletedFrame();
4509 0 : }
4510 :
4511 0 : virtual void RemoveFrame(nsIFrame* aFrame) override {
4512 0 : if (aFrame == mAncestorFrame) {
4513 0 : mAncestorFrame = nullptr;
4514 : }
4515 : nsDisplayBackgroundColor::RemoveFrame(aFrame);
4516 0 : }
4517 :
4518 : virtual uint32_t GetPerFrameKey() const override {
4519 : return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
4520 : nsDisplayItem::GetPerFrameKey();
4521 : }
4522 :
4523 : NS_DISPLAY_DECL_NAME("TableBackgroundColor", TYPE_TABLE_BACKGROUND_COLOR)
4524 : protected:
4525 : nsIFrame* mAncestorFrame;
4526 : TableType mTableType;
4527 : };
4528 :
4529 0 : class nsDisplayClearBackground : public nsDisplayItem
4530 : {
4531 : public:
4532 0 : nsDisplayClearBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4533 0 : : nsDisplayItem(aBuilder, aFrame)
4534 : { }
4535 :
4536 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
4537 : bool* aSnap) const override
4538 0 : {
4539 0 : *aSnap = true;
4540 : return nsRect(ToReferenceFrame(), Frame()->GetSize());
4541 : }
4542 :
4543 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4544 : bool* aSnap) const override {
4545 : *aSnap = false;
4546 : return GetBounds(aBuilder, aSnap);
4547 : }
4548 :
4549 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override
4550 : {
4551 : return mozilla::Some(NS_RGBA(0, 0, 0, 0));
4552 : }
4553 :
4554 : virtual bool ClearsBackground() const override
4555 : {
4556 : return true;
4557 : }
4558 :
4559 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4560 : LayerManager* aManager,
4561 : const ContainerLayerParameters& aParameters) override
4562 : {
4563 : return mozilla::LAYER_ACTIVE_FORCE;
4564 : }
4565 :
4566 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4567 : LayerManager* aManager,
4568 : const ContainerLayerParameters& aContainerParameters) override;
4569 0 :
4570 : bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4571 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4572 : const StackingContextHelper& aSc,
4573 : mozilla::layers::WebRenderLayerManager* aManager,
4574 : nsDisplayListBuilder* aDisplayListBuilder) override;
4575 :
4576 : NS_DISPLAY_DECL_NAME("ClearBackground", TYPE_CLEAR_BACKGROUND)
4577 : };
4578 :
4579 : /**
4580 : * The standard display item to paint the outer CSS box-shadows of a frame.
4581 : */
4582 : class nsDisplayBoxShadowOuter final : public nsDisplayItem {
4583 : public:
4584 : nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4585 0 : : nsDisplayItem(aBuilder, aFrame)
4586 0 : , mOpacity(1.0f)
4587 0 : {
4588 : MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
4589 : mBounds = GetBoundsInternal();
4590 : }
4591 : #ifdef NS_BUILD_REFCNT_LOGGING
4592 : virtual ~nsDisplayBoxShadowOuter() {
4593 : MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter);
4594 : }
4595 : #endif
4596 0 :
4597 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4598 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
4599 : bool* aSnap) const override;
4600 : virtual bool IsInvisibleInRect(const nsRect& aRect) const override;
4601 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4602 0 : nsRegion* aVisibleRegion) override;
4603 : NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
4604 :
4605 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4606 0 : const nsDisplayItemGeometry* aGeometry,
4607 0 : nsRegion* aInvalidRegion) const override;
4608 0 :
4609 0 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
4610 0 : float aOpacity,
4611 : const DisplayItemClipChain* aClip) override
4612 0 : {
4613 : NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
4614 : mOpacity = aOpacity;
4615 0 : IntersectClip(aBuilder, aClip, false);
4616 : }
4617 0 : virtual bool CanApplyOpacity() const override
4618 0 : {
4619 0 : return true;
4620 0 : }
4621 :
4622 0 : virtual void RestoreState() override
4623 : {
4624 0 : nsDisplayItem::RestoreState();
4625 : mVisibleRegion.SetEmpty();
4626 : mOpacity = 1.0f;
4627 : }
4628 :
4629 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
4630 : {
4631 : return new nsDisplayBoxShadowOuterGeometry(this, aBuilder, mOpacity);
4632 : }
4633 :
4634 : bool CanBuildWebRenderDisplayItems();
4635 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4636 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4637 : const StackingContextHelper& aSc,
4638 : mozilla::layers::WebRenderLayerManager* aManager,
4639 : nsDisplayListBuilder* aDisplayListBuilder) override;
4640 : nsRect GetBoundsInternal();
4641 :
4642 : private:
4643 : nsRegion mVisibleRegion;
4644 : nsRect mBounds;
4645 : float mOpacity;
4646 : };
4647 :
4648 : /**
4649 : * The standard display item to paint the inner CSS box-shadows of a frame.
4650 : */
4651 0 : class nsDisplayBoxShadowInner : public nsDisplayItem {
4652 0 : public:
4653 0 : nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4654 : : nsDisplayItem(aBuilder, aFrame) {
4655 : MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
4656 0 : }
4657 : #ifdef NS_BUILD_REFCNT_LOGGING
4658 0 : virtual ~nsDisplayBoxShadowInner() {
4659 0 : MOZ_COUNT_DTOR(nsDisplayBoxShadowInner);
4660 0 : }
4661 : #endif
4662 :
4663 : virtual void RestoreState() override
4664 : {
4665 0 : nsDisplayItem::RestoreState();
4666 : mVisibleRegion.SetEmpty();
4667 0 : }
4668 :
4669 0 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4670 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4671 : nsRegion* aVisibleRegion) override;
4672 0 : NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
4673 :
4674 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
4675 : {
4676 0 : return new nsDisplayBoxShadowInnerGeometry(this, aBuilder);
4677 0 : }
4678 :
4679 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4680 : const nsDisplayItemGeometry* aGeometry,
4681 0 : nsRegion* aInvalidRegion) const override
4682 : {
4683 0 : const nsDisplayBoxShadowInnerGeometry* geometry = static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry);
4684 : if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
4685 : // nsDisplayBoxShadowInner is based around the padding rect, but it can
4686 : // touch pixels outside of this. We should invalidate the entire bounds.
4687 : bool snap;
4688 : aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
4689 : }
4690 : }
4691 :
4692 : static bool CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder,
4693 : nsIFrame* aFrame,
4694 : nsPoint aReferencePoint);
4695 : static void CreateInsetBoxShadowWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4696 : const StackingContextHelper& aSc,
4697 : nsRegion& aVisibleRegion,
4698 : nsIFrame* aFrame,
4699 : const nsRect aBorderRect);
4700 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4701 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4702 : const StackingContextHelper& aSc,
4703 : mozilla::layers::WebRenderLayerManager* aManager,
4704 : nsDisplayListBuilder* aDisplayListBuilder) override;
4705 :
4706 : private:
4707 : nsRegion mVisibleRegion;
4708 : };
4709 :
4710 : /**
4711 : * The standard display item to paint the CSS outline of a frame.
4712 : */
4713 0 : class nsDisplayOutline : public nsDisplayItem {
4714 0 : public:
4715 0 : nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
4716 : nsDisplayItem(aBuilder, aFrame) {
4717 : MOZ_COUNT_CTOR(nsDisplayOutline);
4718 : }
4719 : #ifdef NS_BUILD_REFCNT_LOGGING
4720 : virtual ~nsDisplayOutline() {
4721 : MOZ_COUNT_DTOR(nsDisplayOutline);
4722 : }
4723 : #endif
4724 :
4725 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4726 0 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4727 : const StackingContextHelper& aSc,
4728 : mozilla::layers::WebRenderLayerManager* aManager,
4729 : nsDisplayListBuilder* aDisplayListBuilder) override;
4730 : virtual bool IsInvisibleInRect(const nsRect& aRect) const override;
4731 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
4732 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4733 : NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
4734 : };
4735 :
4736 : /**
4737 : * A class that lets you receive events within the frame bounds but never paints.
4738 : */
4739 0 : class nsDisplayEventReceiver : public nsDisplayItem {
4740 0 : public:
4741 0 : nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4742 : : nsDisplayItem(aBuilder, aFrame) {
4743 : MOZ_COUNT_CTOR(nsDisplayEventReceiver);
4744 : }
4745 : #ifdef NS_BUILD_REFCNT_LOGGING
4746 : virtual ~nsDisplayEventReceiver() {
4747 : MOZ_COUNT_DTOR(nsDisplayEventReceiver);
4748 : }
4749 : #endif
4750 :
4751 : void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4752 0 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
4753 : bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4754 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4755 : const StackingContextHelper& aSc,
4756 : mozilla::layers::WebRenderLayerManager* aManager,
4757 : nsDisplayListBuilder* aDisplayListBuilder) override;
4758 :
4759 : NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
4760 : };
4761 :
4762 : /**
4763 : * Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
4764 : * this gets built when we're doing widget painting and we need to send the
4765 : * compositor some hit-test info for a frame. This is effectively a dummy item
4766 : * whose sole purpose is to carry the hit-test info to the compositor.
4767 : */
4768 : class nsDisplayCompositorHitTestInfo : public nsDisplayEventReceiver {
4769 0 : public:
4770 0 : nsDisplayCompositorHitTestInfo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4771 0 : mozilla::gfx::CompositorHitTestInfo aHitTestInfo,
4772 0 : uint32_t aIndex = 0,
4773 : const mozilla::Maybe<nsRect>& aArea = mozilla::Nothing());
4774 :
4775 : #ifdef NS_BUILD_REFCNT_LOGGING
4776 : virtual ~nsDisplayCompositorHitTestInfo()
4777 : {
4778 : MOZ_COUNT_DTOR(nsDisplayCompositorHitTestInfo);
4779 : }
4780 : #endif
4781 :
4782 : mozilla::gfx::CompositorHitTestInfo HitTestInfo() const { return mHitTestInfo; }
4783 :
4784 : bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4785 : mozilla::wr::IpcResourceUpdateQueue& aResources,
4786 : const StackingContextHelper& aSc,
4787 : mozilla::layers::WebRenderLayerManager* aManager,
4788 : nsDisplayListBuilder* aDisplayListBuilder) override;
4789 : void WriteDebugInfo(std::stringstream& aStream) override;
4790 : uint32_t GetPerFrameKey() const override;
4791 : int32_t ZIndex() const override;
4792 : void SetOverrideZIndex(int32_t aZIndex);
4793 :
4794 : /**
4795 0 : * Returns the hit test area of this item.
4796 0 : */
4797 : const nsRect& Area() const { return mArea; }
4798 :
4799 : /**
4800 : * ApplyOpacity() is overriden for opacity flattening.
4801 0 : */
4802 : void ApplyOpacity(nsDisplayListBuilder* aBuilder, float aOpacity,
4803 0 : const DisplayItemClipChain* aClip) override {}
4804 :
4805 0 : /**
4806 0 : * CanApplyOpacity() is overriden for opacity flattening.
4807 : */
4808 : bool CanApplyOpacity() const override { return true; }
4809 0 :
4810 : nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override
4811 : {
4812 : *aSnap = false;
4813 : return nsRect();
4814 : }
4815 :
4816 : NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO)
4817 :
4818 : private:
4819 : mozilla::gfx::CompositorHitTestInfo mHitTestInfo;
4820 : mozilla::Maybe<mozilla::layers::FrameMetrics::ViewID> mScrollTarget;
4821 : nsRect mArea;
4822 : uint32_t mIndex;
4823 : mozilla::Maybe<int32_t> mOverrideZIndex;
4824 : int32_t mAppUnitsPerDevPixel;
4825 : };
4826 :
4827 : /**
4828 : * A class that lets you wrap a display list as a display item.
4829 : *
4830 : * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
4831 : * list has many items, it's not clear which one has the 'underlying frame'.
4832 : * Thus we force the creator to specify what the underlying frame is. The
4833 : * underlying frame should be the root of a stacking context, because sorting
4834 : * a list containing this item will not get at the children.
4835 : *
4836 : * In some cases (e.g., clipping) we want to wrap a list but we don't have a
4837 : * particular underlying frame that is a stacking context root. In that case
4838 : * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
4839 : * detect and handle this case.
4840 : */
4841 : class nsDisplayWrapList : public nsDisplayItem {
4842 : public:
4843 : /**
4844 : * Takes all the items from aList and puts them in our list.
4845 : */
4846 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4847 : nsDisplayList* aList, bool aAnonymous = false);
4848 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4849 : nsDisplayList* aList,
4850 : const ActiveScrolledRoot* aActiveScrolledRoot,
4851 : bool aClearClipChain = false,
4852 : uint32_t aIndex = 0,
4853 : bool aAnonymous = false);
4854 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4855 : nsDisplayItem* aItem, bool aAnonymous = false);
4856 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4857 : : nsDisplayItem(aBuilder, aFrame)
4858 : , mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot())
4859 : , mOverrideZIndex(0)
4860 : , mIndex(0)
4861 : , mHasZIndexOverride(false)
4862 : {
4863 : MOZ_COUNT_CTOR(nsDisplayWrapList);
4864 : mBaseBuildingRect = GetBuildingRect();
4865 : mListPtr = &mList;
4866 0 : }
4867 0 :
4868 : /**
4869 : * A custom copy-constructor that does not copy mList, as this would mutate
4870 : * the other item.
4871 : */
4872 : nsDisplayWrapList(const nsDisplayWrapList& aOther) = delete;
4873 0 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, const nsDisplayWrapList& aOther)
4874 0 : : nsDisplayItem(aBuilder, aOther)
4875 0 : , mListPtr(&mList)
4876 0 : , mFrameActiveScrolledRoot(aOther.mFrameActiveScrolledRoot)
4877 : , mMergedFrames(aOther.mMergedFrames)
4878 0 : , mBounds(aOther.mBounds)
4879 0 : , mBaseBuildingRect(aOther.mBaseBuildingRect)
4880 : , mOverrideZIndex(aOther.mOverrideZIndex)
4881 : , mIndex(aOther.mIndex)
4882 : , mHasZIndexOverride(aOther.mHasZIndexOverride)
4883 0 : , mClearingClipChain(aOther.mClearingClipChain)
4884 : {
4885 0 : MOZ_COUNT_CTOR(nsDisplayWrapList);
4886 : }
4887 0 :
4888 : virtual ~nsDisplayWrapList();
4889 0 :
4890 : virtual const nsDisplayWrapList* AsDisplayWrapList() const override
4891 : {
4892 0 : return this;
4893 0 : }
4894 0 : virtual nsDisplayWrapList* AsDisplayWrapList() override
4895 0 : {
4896 : return this;
4897 : }
4898 :
4899 : virtual void Destroy(nsDisplayListBuilder* aBuilder) override {
4900 : mList.DeleteAll(aBuilder);
4901 : nsDisplayItem::Destroy(aBuilder);
4902 : }
4903 :
4904 : /**
4905 : * Creates a new nsDisplayWrapList that holds a pointer to the display list
4906 : * owned by the given nsDisplayItem. The new nsDisplayWrapList will be added
4907 : * to the bottom of this item's contents.
4908 0 : */
4909 : virtual void MergeDisplayListFromItem(nsDisplayListBuilder* aBuilder,
4910 : const nsDisplayItem* aItem) override;
4911 :
4912 0 : /**
4913 0 : * Call this if the wrapped list is changed.
4914 0 : */
4915 0 : virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
4916 : {
4917 0 : // Clear the clip chain up to the asr, but don't store it, so that we'll recover
4918 : // it when we reuse the item.
4919 : if (mClearingClipChain) {
4920 0 : const DisplayItemClipChain* clip = mState.mClipChain;
4921 0 : while (clip && ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(), clip->mASR)) {
4922 0 : clip = clip->mParent;
4923 : }
4924 : SetClipChain(clip, false);
4925 : }
4926 :
4927 : nsRect buildingRect;
4928 : mBounds =
4929 : mListPtr->GetClippedBoundsWithRespectToASR(aBuilder, mActiveScrolledRoot, &buildingRect);
4930 0 : // The display list may contain content that's visible outside the visible
4931 0 : // rect (i.e. the current dirty rect) passed in when the item was created.
4932 0 : // This happens when the dirty rect has been restricted to the visual
4933 : // overflow rect of a frame for some reason (e.g. when setting up dirty
4934 : // rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
4935 : // frame contains placeholders for out-of-flows that aren't descendants of
4936 : // the frame.
4937 : buildingRect.UnionRect(mBaseBuildingRect, buildingRect);
4938 : SetBuildingRect(buildingRect);
4939 : }
4940 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4941 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
4942 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
4943 : bool* aSnap) const override;
4944 0 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4945 : bool* aSnap) const override;
4946 0 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
4947 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4948 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4949 0 : nsRegion* aVisibleRegion) override;
4950 :
4951 0 : virtual uint32_t GetPerFrameKey() const override
4952 : {
4953 : return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
4954 0 : }
4955 :
4956 0 : virtual bool CanMerge(const nsDisplayItem* aItem) const override
4957 0 : {
4958 0 : return false;
4959 : }
4960 0 :
4961 : virtual void Merge(const nsDisplayItem* aItem) override
4962 0 : {
4963 0 : MOZ_ASSERT(CanMerge(aItem));
4964 : MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList*>(aItem));
4965 0 : }
4966 :
4967 0 : virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) const override
4968 : {
4969 : aFrames->AppendElements(mMergedFrames);
4970 0 : }
4971 :
4972 0 : virtual bool HasMergedFrames() const override
4973 : {
4974 : return !mMergedFrames.IsEmpty();
4975 0 : }
4976 :
4977 0 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
4978 : {
4979 : return true;
4980 0 : }
4981 0 :
4982 0 : virtual bool IsInvalid(nsRect& aRect) const override
4983 0 : {
4984 0 : if (mFrame->IsInvalid(aRect) && aRect.IsEmpty()) {
4985 : return true;
4986 0 : }
4987 : nsRect temp;
4988 0 : for (uint32_t i = 0; i < mMergedFrames.Length(); i++) {
4989 0 : if (mMergedFrames[i]->IsInvalid(temp) && temp.IsEmpty()) {
4990 : aRect.SetEmpty();
4991 0 : return true;
4992 : }
4993 : aRect = aRect.Union(temp);
4994 : }
4995 0 : aRect += ToReferenceFrame();
4996 : return !aRect.IsEmpty();
4997 0 : }
4998 : NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
4999 :
5000 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override;
5001 0 :
5002 : virtual nsDisplayList* GetSameCoordinateSystemChildren() const override
5003 : {
5004 0 : NS_ASSERTION(mListPtr->IsEmpty() || !ReferenceFrame() ||
5005 : !mListPtr->GetBottom()->ReferenceFrame() ||
5006 0 : mListPtr->GetBottom()->ReferenceFrame() == ReferenceFrame(),
5007 : "Children must have same reference frame");
5008 0 : return mListPtr;
5009 : }
5010 :
5011 : virtual RetainedDisplayList* GetChildren() const override { return mListPtr; }
5012 :
5013 : virtual int32_t ZIndex() const override
5014 : {
5015 : return (mHasZIndexOverride) ? mOverrideZIndex : nsDisplayItem::ZIndex();
5016 : }
5017 :
5018 : void SetOverrideZIndex(int32_t aZIndex)
5019 : {
5020 : mHasZIndexOverride = true;
5021 : mOverrideZIndex = aZIndex;
5022 : }
5023 :
5024 : void SetReferenceFrame(const nsIFrame* aFrame);
5025 0 :
5026 : /**
5027 0 : * This creates a copy of this item, but wrapping aItem instead of
5028 0 : * our existing list. Only gets called if this item returned nullptr
5029 : * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
5030 : * GetUnderlyingFrame().
5031 : */
5032 : virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
5033 : nsDisplayItem* aItem) {
5034 : NS_NOTREACHED("We never returned nullptr for GetUnderlyingFrame!");
5035 : return nullptr;
5036 : }
5037 :
5038 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
5039 : mozilla::wr::IpcResourceUpdateQueue& aResources,
5040 : const StackingContextHelper& aSc,
5041 : mozilla::layers::WebRenderLayerManager* aManager,
5042 0 : nsDisplayListBuilder* aDisplayListBuilder) override;
5043 :
5044 0 : const ActiveScrolledRoot* GetFrameActiveScrolledRoot() { return mFrameActiveScrolledRoot; }
5045 0 :
5046 0 : protected:
5047 0 : nsDisplayWrapList() = delete;
5048 0 :
5049 0 : void MergeFromTrackingMergedFrames(const nsDisplayWrapList* aOther)
5050 0 : {
5051 : mBounds.UnionRect(mBounds, aOther->mBounds);
5052 : nsRect buildingRect;
5053 : buildingRect.UnionRect(GetBuildingRect(), aOther->GetBuildingRect());
5054 : SetBuildingRect(buildingRect);
5055 : mMergedFrames.AppendElement(aOther->mFrame);
5056 : mMergedFrames.AppendElements(aOther->mMergedFrames);
5057 : }
5058 :
5059 : RetainedDisplayList mList;
5060 : RetainedDisplayList* mListPtr;
5061 : // The active scrolled root for the frame that created this
5062 : // wrap list.
5063 : RefPtr<const ActiveScrolledRoot> mFrameActiveScrolledRoot;
5064 : // The frames from items that have been merged into this item, excluding
5065 : // this item's own frame.
5066 : nsTArray<nsIFrame*> mMergedFrames;
5067 : nsRect mBounds;
5068 : // Displaylist building rect contributed by this display item itself.
5069 : // Our mBuildingRect may include the visible areas of children.
5070 : nsRect mBaseBuildingRect;
5071 : int32_t mOverrideZIndex;
5072 : uint32_t mIndex;
5073 : bool mHasZIndexOverride;
5074 : bool mClearingClipChain = false;
5075 : };
5076 :
5077 : /**
5078 : * We call WrapDisplayList on the in-flow lists: BorderBackground(),
5079 : * BlockBorderBackgrounds() and Content().
5080 : * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
5081 : * and Floats(). This is done to support special wrapping processing for frames
5082 : * that may not be in-flow descendants of the current frame.
5083 : */
5084 : class nsDisplayWrapper {
5085 : public:
5086 : // This is never instantiated directly (it has pure virtual methods), so no
5087 : // need to count constructors and destructors.
5088 :
5089 : virtual bool WrapBorderBackground() { return true; }
5090 : virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
5091 : nsIFrame* aFrame, nsDisplayList* aList) = 0;
5092 : virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
5093 : nsDisplayItem* aItem) = 0;
5094 :
5095 : nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5096 : const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
5097 : nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5098 : const nsDisplayListSet& aLists);
5099 : protected:
5100 : nsDisplayWrapper() = default;
5101 : };
5102 :
5103 : /**
5104 : * The standard display item to paint a stacking context with translucency
5105 : * set by the stacking context root frame's 'opacity' style.
5106 : */
5107 : class nsDisplayOpacity : public nsDisplayWrapList {
5108 : public:
5109 : nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5110 : nsDisplayList* aList,
5111 : const ActiveScrolledRoot* aActiveScrolledRoot,
5112 : bool aForEventsAndPluginsOnly);
5113 :
5114 : nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
5115 : const nsDisplayOpacity& aOther)
5116 : : nsDisplayWrapList(aBuilder, aOther)
5117 : , mOpacity(aOther.mOpacity)
5118 : , mForEventsAndPluginsOnly(aOther.mForEventsAndPluginsOnly)
5119 : , mOpacityAppliedToChildren(false)
5120 : {
5121 : // We should not try to merge flattened opacities.
5122 : MOZ_ASSERT(!aOther.mOpacityAppliedToChildren);
5123 : }
5124 :
5125 : #ifdef NS_BUILD_REFCNT_LOGGING
5126 : virtual ~nsDisplayOpacity();
5127 : #endif
5128 :
5129 : virtual void RestoreState() override
5130 : {
5131 : nsDisplayItem::RestoreState();
5132 : mOpacity = mState.mOpacity;
5133 : mOpacityAppliedToChildren = false;
5134 : }
5135 :
5136 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
5137 : {
5138 : MOZ_COUNT_CTOR(nsDisplayOpacity);
5139 : return MakeDisplayItem<nsDisplayOpacity>(aBuilder, *this);
5140 : }
5141 :
5142 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5143 : bool* aSnap) const override;
5144 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
5145 : LayerManager* aManager,
5146 0 : const ContainerLayerParameters& aContainerParameters) override;
5147 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5148 : LayerManager* aManager,
5149 : const ContainerLayerParameters& aParameters) override;
5150 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
5151 0 : nsRegion* aVisibleRegion) override;
5152 :
5153 : virtual bool CanMerge(const nsDisplayItem* aItem) const override
5154 0 : {
5155 : // items for the same content element should be merged into a single
5156 0 : // compositing group
5157 : // aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
5158 : return HasSameTypeAndClip(aItem) && HasSameContent(aItem);
5159 : }
5160 :
5161 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
5162 : {
5163 0 : return new nsDisplayOpacityGeometry(this, aBuilder, mOpacity);
5164 : }
5165 0 :
5166 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
5167 : const nsDisplayItemGeometry* aGeometry,
5168 0 : nsRegion* aInvalidRegion) const override;
5169 :
5170 : virtual bool IsInvalid(nsRect& aRect) const override
5171 : {
5172 : if (mForEventsAndPluginsOnly) {
5173 : return false;
5174 : }
5175 : return nsDisplayWrapList::IsInvalid(aRect);
5176 : }
5177 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
5178 : float aOpacity,
5179 : const DisplayItemClipChain* aClip) override;
5180 : virtual bool CanApplyOpacity() const override;
5181 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
5182 :
5183 0 : /**
5184 : * Returns true if ShouldFlattenAway() applied opacity to children.
5185 : */
5186 : bool OpacityAppliedToChildren() const { return mOpacityAppliedToChildren; }
5187 :
5188 : static bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
5189 : NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
5190 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
5191 :
5192 : bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
5193 :
5194 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
5195 : mozilla::wr::IpcResourceUpdateQueue& aResources,
5196 : const StackingContextHelper& aSc,
5197 : mozilla::layers::WebRenderLayerManager* aManager,
5198 : nsDisplayListBuilder* aDisplayListBuilder) override;
5199 :
5200 : float GetOpacity() { return mOpacity; }
5201 :
5202 : private:
5203 : bool ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder);
5204 :
5205 : float mOpacity;
5206 : bool mForEventsAndPluginsOnly;
5207 : bool mOpacityAppliedToChildren;
5208 :
5209 : struct {
5210 : float mOpacity;
5211 : } mState;
5212 : };
5213 :
5214 0 : class nsDisplayBlendMode : public nsDisplayWrapList {
5215 : public:
5216 0 : nsDisplayBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5217 0 : nsDisplayList* aList, uint8_t aBlendMode,
5218 0 : const ActiveScrolledRoot* aActiveScrolledRoot,
5219 0 : uint32_t aIndex = 0);
5220 : nsDisplayBlendMode(nsDisplayListBuilder* aBuilder,
5221 : const nsDisplayBlendMode& aOther)
5222 : : nsDisplayWrapList(aBuilder, aOther)
5223 : , mBlendMode(aOther.mBlendMode)
5224 0 : , mIndex(aOther.mIndex)
5225 : {}
5226 0 : #ifdef NS_BUILD_REFCNT_LOGGING
5227 0 : virtual ~nsDisplayBlendMode();
5228 : #endif
5229 :
5230 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
5231 : {
5232 : MOZ_COUNT_CTOR(nsDisplayBlendMode);
5233 : return MakeDisplayItem<nsDisplayBlendMode>(aBuilder, *this);
5234 : }
5235 :
5236 0 : nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5237 : bool* aSnap) const override;
5238 :
5239 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
5240 : LayerManager* aManager,
5241 0 : const ContainerLayerParameters& aContainerParameters) override;
5242 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
5243 0 : const nsDisplayItemGeometry* aGeometry,
5244 : nsRegion* aInvalidRegion) const override
5245 : {
5246 : // We don't need to compute an invalidation region since we have LayerTreeInvalidation
5247 : }
5248 : virtual uint32_t GetPerFrameKey() const override {
5249 : return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
5250 : }
5251 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5252 : LayerManager* aManager,
5253 : const ContainerLayerParameters& aParameters) override;
5254 : bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
5255 : mozilla::wr::IpcResourceUpdateQueue& aResources,
5256 : const StackingContextHelper& aSc,
5257 : mozilla::layers::WebRenderLayerManager* aManager,
5258 0 : nsDisplayListBuilder* aDisplayListBuilder) override;
5259 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
5260 0 : nsRegion* aVisibleRegion) override;
5261 :
5262 : virtual bool CanMerge(const nsDisplayItem* aItem) const override;
5263 :
5264 0 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
5265 : {
5266 : return false;
5267 : }
5268 : mozilla::gfx::CompositionOp BlendMode();
5269 :
5270 : NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE)
5271 :
5272 : protected:
5273 : uint8_t mBlendMode;
5274 : uint32_t mIndex;
5275 : };
5276 :
5277 : class nsDisplayTableBlendMode : public nsDisplayBlendMode
5278 : {
5279 : public:
5280 : nsDisplayTableBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5281 : nsDisplayList* aList, uint8_t aBlendMode,
5282 : const ActiveScrolledRoot* aActiveScrolledRoot,
5283 : uint32_t aIndex, nsIFrame* aAncestorFrame)
5284 : : nsDisplayBlendMode(aBuilder, aFrame, aList, aBlendMode, aActiveScrolledRoot, aIndex)
5285 : , mAncestorFrame(aAncestorFrame)
5286 : , mTableType(GetTableTypeFromFrame(aAncestorFrame))
5287 0 : {
5288 : if (aBuilder->IsRetainingDisplayList()) {
5289 0 : mAncestorFrame->AddDisplayItem(this);
5290 0 : }
5291 0 : }
5292 :
5293 0 : nsDisplayTableBlendMode(nsDisplayListBuilder* aBuilder,
5294 0 : const nsDisplayTableBlendMode& aOther)
5295 : : nsDisplayBlendMode(aBuilder, aOther)
5296 0 : , mAncestorFrame(aOther.mAncestorFrame)
5297 0 : , mTableType(aOther.mTableType)
5298 0 : {
5299 0 : if (aBuilder->IsRetainingDisplayList()) {
5300 : mAncestorFrame->AddDisplayItem(this);
5301 0 : }
5302 : }
5303 0 : ~nsDisplayTableBlendMode() {
5304 : if (mAncestorFrame) {
5305 0 : mAncestorFrame->RemoveDisplayItem(this);
5306 : }
5307 : }
5308 0 :
5309 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
5310 0 : {
5311 0 : return MakeDisplayItem<nsDisplayTableBlendMode>(aBuilder, *this);
5312 : }
5313 :
5314 0 : virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
5315 0 :
5316 0 : virtual bool HasDeletedFrame() const override {
5317 : return !mAncestorFrame || nsDisplayBlendMode::HasDeletedFrame();
5318 0 : }
5319 0 :
5320 : virtual void RemoveFrame(nsIFrame* aFrame) override {
5321 0 : if (aFrame == mAncestorFrame) {
5322 0 : mAncestorFrame = nullptr;
5323 0 : }
5324 0 : nsDisplayBlendMode::RemoveFrame(aFrame);
5325 : }
5326 :
5327 0 : virtual uint32_t GetPerFrameKey() const override {
5328 : return (mIndex << (TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
5329 : (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
5330 : nsDisplayItem::GetPerFrameKey();
5331 : }
5332 :
5333 : NS_DISPLAY_DECL_NAME("TableBlendMode", TYPE_TABLE_BLEND_MODE)
5334 :
5335 : protected:
5336 : nsIFrame* mAncestorFrame;
5337 : TableType mTableType;
5338 : };
5339 :
5340 : class nsDisplayBlendContainer : public nsDisplayWrapList {
5341 : public:
5342 : static nsDisplayBlendContainer*
5343 : CreateForMixBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5344 : nsDisplayList* aList,
5345 : const ActiveScrolledRoot* aActiveScrolledRoot);
5346 :
5347 : static nsDisplayBlendContainer*
5348 : CreateForBackgroundBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5349 : nsDisplayList* aList,
5350 0 : const ActiveScrolledRoot* aActiveScrolledRoot);
5351 :
5352 0 : #ifdef NS_BUILD_REFCNT_LOGGING
5353 0 : virtual ~nsDisplayBlendContainer();
5354 : #endif
5355 :
5356 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
5357 : {
5358 : MOZ_COUNT_CTOR(nsDisplayBlendContainer);
5359 : return MakeDisplayItem<nsDisplayBlendContainer>(aBuilder, *this);
5360 : }
5361 :
5362 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
5363 : LayerManager* aManager,
5364 : const ContainerLayerParameters& aContainerParameters) override;
5365 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5366 : LayerManager* aManager,
5367 : const ContainerLayerParameters& aParameters) override;
5368 0 : bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
5369 : mozilla::wr::IpcResourceUpdateQueue& aResources,
5370 : const StackingContextHelper& aSc,
5371 : mozilla::layers::WebRenderLayerManager* aManager,
5372 0 : nsDisplayListBuilder* aDisplayListBuilder) override;
5373 0 :
5374 : virtual bool CanMerge(const nsDisplayItem* aItem) const override
5375 : {
5376 0 : // Items for the same content element should be merged into a single
5377 : // compositing group.
5378 0 : return HasSameTypeAndClip(aItem) && HasSameContent(aItem)
5379 : && mIsForBackground == static_cast<const nsDisplayBlendContainer*>(aItem)->mIsForBackground;
5380 0 : }
5381 0 :
5382 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
5383 0 : {
5384 : return false;
5385 : }
5386 : virtual uint32_t GetPerFrameKey() const override {
5387 : return (mIsForBackground ? 1 << TYPE_BITS : 0) | nsDisplayItem::GetPerFrameKey();
5388 : }
5389 : NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
5390 0 :
5391 : protected:
5392 0 : nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5393 0 : nsDisplayList* aList,
5394 0 : const ActiveScrolledRoot* aActiveScrolledRoot,
5395 : bool aIsForBackground);
5396 : nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
5397 : const nsDisplayBlendContainer& aOther)
5398 : : nsDisplayWrapList(aBuilder, aOther)
5399 : , mIsForBackground(aOther.mIsForBackground)
5400 : {}
5401 :
5402 : // Used to distinguish containers created at building stacking
5403 : // context or appending background.
5404 : bool mIsForBackground;
5405 : };
5406 :
5407 : class nsDisplayTableBlendContainer : public nsDisplayBlendContainer
5408 : {
5409 : public:
5410 0 : static nsDisplayTableBlendContainer*
5411 : CreateForBackgroundBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5412 0 : nsDisplayList* aList,
5413 : const ActiveScrolledRoot* aActiveScrolledRoot,
5414 : nsIFrame* aAncestorFrame);
5415 0 :
5416 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
5417 0 : {
5418 0 : return MakeDisplayItem<nsDisplayTableBlendContainer>(aBuilder, *this);
5419 : }
5420 :
5421 0 : virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
5422 0 :
5423 0 : virtual bool HasDeletedFrame() const override {
5424 : return !mAncestorFrame || nsDisplayBlendContainer::HasDeletedFrame();
5425 0 : }
5426 0 :
5427 : virtual void RemoveFrame(nsIFrame* aFrame) override {
5428 0 : if (aFrame == mAncestorFrame) {
5429 0 : mAncestorFrame = nullptr;
5430 0 : }
5431 : nsDisplayBlendContainer::RemoveFrame(aFrame);
5432 : }
5433 0 :
5434 : virtual uint32_t GetPerFrameKey() const override {
5435 : return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
5436 : nsDisplayItem::GetPerFrameKey();
5437 : }
5438 :
5439 : NS_DISPLAY_DECL_NAME("TableBlendContainer", TYPE_TABLE_BLEND_CONTAINER)
5440 :
5441 : protected:
5442 : nsDisplayTableBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5443 : nsDisplayList* aList,
5444 : const ActiveScrolledRoot* aActiveScrolledRoot,
5445 : bool aIsForBackground, nsIFrame* aAncestorFrame)
5446 : : nsDisplayBlendContainer(aBuilder, aFrame, aList, aActiveScrolledRoot, aIsForBackground)
5447 : , mAncestorFrame(aAncestorFrame)
5448 : , mTableType(GetTableTypeFromFrame(aAncestorFrame))
5449 0 : {
5450 : if (aBuilder->IsRetainingDisplayList()) {
5451 0 : mAncestorFrame->AddDisplayItem(this);
5452 0 : }
5453 0 : }
5454 :
5455 0 : nsDisplayTableBlendContainer(nsDisplayListBuilder* aBuilder,
5456 0 : const nsDisplayTableBlendContainer& aOther)
5457 : : nsDisplayBlendContainer(aBuilder, aOther)
5458 0 : , mAncestorFrame(aOther.mAncestorFrame)
5459 0 : , mTableType(aOther.mTableType)
5460 0 : {
5461 0 : if (aBuilder->IsRetainingDisplayList()) {
5462 : mAncestorFrame->AddDisplayItem(this);
5463 0 : }
5464 : }
5465 : ~nsDisplayTableBlendContainer() {
5466 : if (mAncestorFrame) {
5467 : mAncestorFrame->RemoveDisplayItem(this);
5468 : }
5469 : }
5470 :
5471 : nsIFrame* mAncestorFrame;
5472 : TableType mTableType;
5473 : };
5474 :
5475 :
5476 : /**
5477 : * nsDisplayOwnLayer constructor flags. If we nest this class inside
5478 : * nsDisplayOwnLayer then we can't forward-declare it up at the top of this
5479 : * file and that makes it hard to use in all the places that we need to use it.
5480 : */
5481 : enum class nsDisplayOwnLayerFlags {
5482 : eNone = 0,
5483 : eGenerateSubdocInvalidations = 1 << 0,
5484 : eGenerateScrollableLayer = 1 << 1,
5485 : };
5486 :
5487 : MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags)
5488 :
5489 : /**
5490 : * A display item that has no purpose but to ensure its contents get
5491 : * their own layer.
5492 : */
5493 : class nsDisplayOwnLayer : public nsDisplayWrapList {
5494 : public:
5495 : typedef mozilla::layers::ScrollbarData ScrollbarData;
5496 :
5497 : /**
5498 : * @param aFlags eGenerateSubdocInvalidations :
5499 : * Add UserData to the created ContainerLayer, so that invalidations
5500 : * for this layer are send to our nsPresContext.
5501 : * eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and
5502 : * subclasses), indicates this layer is to be a scrollable layer, so call
5503 : * ComputeFrameMetrics, etc.
5504 : * @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar
5505 : * is set in the flags, this parameter should be the ViewID of the
5506 : * scrollable content this scrollbar is for.
5507 : */
5508 : nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5509 : nsDisplayList* aList,
5510 : const ActiveScrolledRoot* aActiveScrolledRoot,
5511 : nsDisplayOwnLayerFlags aFlags = nsDisplayOwnLayerFlags::eNone,
5512 : const ScrollbarData& aScrollbarData = ScrollbarData{},
5513 : bool aForceActive = true,
5514 0 : bool aClearClipChain = false);
5515 0 :
5516 0 : #ifdef NS_BUILD_REFCNT_LOGGING
5517 : virtual ~nsDisplayOwnLayer();
5518 0 : #endif
5519 0 :
5520 : nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, const nsDisplayOwnLayer& aOther)
5521 0 : : nsDisplayWrapList(aBuilder, aOther)
5522 0 : , mFlags(aOther.mFlags)
5523 : , mScrollbarData(aOther.mScrollbarData)
5524 : , mForceActive(aOther.mForceActive)
5525 : , mWrAnimationId(aOther.mWrAnimationId)
5526 : {
5527 : MOZ_COUNT_CTOR(nsDisplayOwnLayer);
5528 : }
5529 :
5530 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override;
5531 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
5532 : LayerManager* aManager,
5533 : const ContainerLayerParameters& aContainerParameters) override;
5534 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
5535 : mozilla::wr::IpcResourceUpdateQueue& aResources,
5536 : const StackingContextHelper& aSc,
5537 : mozilla::layers::WebRenderLayerManager* aManager,
5538 : nsDisplayListBuilder* aDisplayListBuilder) override;
5539 0 : virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
5540 : mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
5541 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5542 0 : LayerManager* aManager,
5543 : const ContainerLayerParameters& aParameters) override;
5544 :
5545 0 : virtual bool CanMerge(const nsDisplayItem* aItem) const override
5546 : {
5547 0 : // Don't allow merging, each sublist must have its own layer
5548 : return false;
5549 : }
5550 :
5551 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
5552 : {
5553 : return false;
5554 : }
5555 0 :
5556 : void WriteDebugInfo(std::stringstream& aStream) override;
5557 :
5558 : nsDisplayOwnLayerFlags GetFlags() { return mFlags; }
5559 : bool IsScrollThumbLayer() const;
5560 : bool IsScrollbarContainer() const;
5561 : NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
5562 : protected:
5563 : nsDisplayOwnLayerFlags mFlags;
5564 :
5565 : /**
5566 : * If this nsDisplayOwnLayer represents a scroll thumb layer or a
5567 : * scrollbar container layer, mScrollbarData stores information
5568 : * about the scrollbar. Otherwise, mScrollbarData will be
5569 : * default-constructed (in particular with mDirection == Nothing())
5570 : * and can be ignored.
5571 : */
5572 : ScrollbarData mScrollbarData;
5573 : bool mForceActive;
5574 : uint64_t mWrAnimationId;
5575 : };
5576 :
5577 : /**
5578 : * A display item for subdocuments. This is more or less the same as nsDisplayOwnLayer,
5579 : * except that it always populates the FrameMetrics instance on the ContainerLayer it
5580 : * builds.
5581 : */
5582 : class nsDisplaySubDocument : public nsDisplayOwnLayer {
5583 : public:
5584 : nsDisplaySubDocument(nsDisplayListBuilder* aBuilder,
5585 : nsIFrame* aFrame, nsSubDocumentFrame* aSubDocFrame,
5586 : nsDisplayList* aList, nsDisplayOwnLayerFlags aFlags);
5587 : virtual ~nsDisplaySubDocument();
5588 :
5589 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
5590 : bool* aSnap) const override;
5591 :
5592 : virtual nsSubDocumentFrame* SubDocumentFrame() { return mSubDocFrame; }
5593 0 :
5594 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
5595 0 : nsRegion* aVisibleRegion) override;
5596 :
5597 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override;
5598 :
5599 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
5600 : {
5601 : return mShouldFlatten;
5602 : }
5603 :
5604 : void SetShouldFlattenAway(bool aShouldFlatten)
5605 : {
5606 : mShouldFlatten = aShouldFlatten;
5607 : }
5608 :
5609 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5610 : LayerManager* aManager,
5611 : const ContainerLayerParameters& aParameters) override
5612 : {
5613 : if (mShouldFlatten) {
5614 : return mozilla::LAYER_NONE;
5615 : }
5616 0 : return nsDisplayOwnLayer::GetLayerState(aBuilder, aManager, aParameters);
5617 : }
5618 :
5619 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5620 : bool* aSnap) const override;
5621 :
5622 : NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT)
5623 :
5624 : mozilla::UniquePtr<ScrollMetadata> ComputeScrollMetadata(LayerManager* aLayerManager,
5625 : const ContainerLayerParameters& aContainerParameters);
5626 :
5627 : virtual nsIFrame* FrameForInvalidation() const override;
5628 :
5629 : virtual bool HasDeletedFrame() const override;
5630 :
5631 : virtual void RemoveFrame(nsIFrame* aFrame) override;
5632 :
5633 : void Disown();
5634 :
5635 : protected:
5636 : ViewID mScrollParentId;
5637 : bool mForceDispatchToContentRegion;
5638 : bool mShouldFlatten;
5639 : nsSubDocumentFrame* mSubDocFrame;
5640 : };
5641 :
5642 : /**
5643 : * A display item for subdocuments to capture the resolution from the presShell
5644 : * and ensure that it gets applied to all the right elements. This item creates
5645 : * a container layer.
5646 : */
5647 : class nsDisplayResolution : public nsDisplaySubDocument {
5648 : public:
5649 : nsDisplayResolution(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5650 : nsDisplayList* aList, nsDisplayOwnLayerFlags aFlags);
5651 : #ifdef NS_BUILD_REFCNT_LOGGING
5652 : virtual ~nsDisplayResolution();
5653 0 : #endif
5654 : virtual void HitTest(nsDisplayListBuilder* aBuilder,
5655 : const nsRect& aRect,
5656 : HitTestState* aState,
5657 : nsTArray<nsIFrame*> *aOutFrames) override;
5658 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
5659 : LayerManager* aManager,
5660 : const ContainerLayerParameters& aContainerParameters) override;
5661 : NS_DISPLAY_DECL_NAME("Resolution", TYPE_RESOLUTION)
5662 : };
5663 :
5664 : /**
5665 : * A display item used to represent sticky position elements. The contents
5666 : * gets its own layer and creates a stacking context, and the layer will have
5667 : * position-related metadata set on it.
5668 : */
5669 : class nsDisplayStickyPosition : public nsDisplayOwnLayer {
5670 : public:
5671 : nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5672 : nsDisplayList* aList,
5673 : const ActiveScrolledRoot* aActiveScrolledRoot,
5674 : const ActiveScrolledRoot* aContainerASR);
5675 : nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
5676 : const nsDisplayStickyPosition& aOther)
5677 : : nsDisplayOwnLayer(aBuilder, aOther)
5678 : , mContainerASR(aOther.mContainerASR)
5679 : {}
5680 :
5681 : #ifdef NS_BUILD_REFCNT_LOGGING
5682 : virtual ~nsDisplayStickyPosition();
5683 : #endif
5684 :
5685 : void SetClipChain(const DisplayItemClipChain* aClipChain, bool aStore) override;
5686 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
5687 0 : {
5688 : MOZ_COUNT_CTOR(nsDisplayStickyPosition);
5689 : return MakeDisplayItem<nsDisplayStickyPosition>(aBuilder, *this);
5690 : }
5691 :
5692 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
5693 : LayerManager* aManager,
5694 : const ContainerLayerParameters& aContainerParameters) override;
5695 0 : NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION)
5696 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5697 : LayerManager* aManager,
5698 0 : const ContainerLayerParameters& aParameters) override
5699 : {
5700 : return mozilla::LAYER_ACTIVE;
5701 : }
5702 :
5703 : virtual bool CanMerge(const nsDisplayItem* aItem) const override
5704 : {
5705 : // Items with the same fixed position frame can be merged.
5706 : return HasSameTypeAndClip(aItem) && mFrame == aItem->Frame();
5707 : }
5708 :
5709 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
5710 : mozilla::wr::IpcResourceUpdateQueue& aResources,
5711 : const StackingContextHelper& aSc,
5712 : mozilla::layers::WebRenderLayerManager* aManager,
5713 : nsDisplayListBuilder* aDisplayListBuilder) override;
5714 :
5715 : const ActiveScrolledRoot* GetContainerASR() const
5716 : {
5717 : return mContainerASR;
5718 : }
5719 :
5720 : private:
5721 : // This stores the ASR that this sticky container item would have assuming it
5722 : // has no fixed descendants. This may be the same as the ASR returned by
5723 : // GetActiveScrolledRoot(), or it may be a descendant of that.
5724 : RefPtr<const ActiveScrolledRoot> mContainerASR;
5725 0 : };
5726 :
5727 0 : class nsDisplayFixedPosition : public nsDisplayOwnLayer {
5728 : public:
5729 0 : nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5730 0 : nsDisplayList* aList,
5731 : const ActiveScrolledRoot* aActiveScrolledRoot,
5732 0 : const ActiveScrolledRoot* aContainerASR);
5733 0 : nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder,
5734 : const nsDisplayFixedPosition& aOther)
5735 : : nsDisplayOwnLayer(aBuilder, aOther)
5736 : , mAnimatedGeometryRootForScrollMetadata(aOther.mAnimatedGeometryRootForScrollMetadata)
5737 : , mIndex(aOther.mIndex)
5738 : , mIsFixedBackground(aOther.mIsFixedBackground)
5739 : , mContainerASR(aOther.mContainerASR)
5740 : {
5741 : MOZ_COUNT_CTOR(nsDisplayFixedPosition);
5742 : }
5743 :
5744 : static nsDisplayFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
5745 0 : nsIFrame* aFrame,
5746 : nsDisplayBackgroundImage* aImage,
5747 0 : uint32_t aIndex);
5748 :
5749 :
5750 : #ifdef NS_BUILD_REFCNT_LOGGING
5751 : virtual ~nsDisplayFixedPosition();
5752 : #endif
5753 0 :
5754 0 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
5755 : {
5756 : return MakeDisplayItem<nsDisplayFixedPosition>(aBuilder, *this);
5757 : }
5758 0 :
5759 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
5760 : LayerManager* aManager,
5761 0 : const ContainerLayerParameters& aContainerParameters) override;
5762 : NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
5763 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5764 0 : LayerManager* aManager,
5765 : const ContainerLayerParameters& aParameters) override
5766 : {
5767 0 : return mozilla::LAYER_ACTIVE_FORCE;
5768 : }
5769 0 :
5770 : virtual bool CanMerge(const nsDisplayItem* aItem) const override
5771 : {
5772 0 : // Items with the same fixed position frame can be merged.
5773 0 : return HasSameTypeAndClip(aItem) && mFrame == aItem->Frame();
5774 : }
5775 :
5776 0 : virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const override
5777 0 : {
5778 : return mIsFixedBackground;
5779 : }
5780 :
5781 : virtual uint32_t GetPerFrameKey() const override {
5782 : return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
5783 : }
5784 :
5785 : AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const override {
5786 : return mAnimatedGeometryRootForScrollMetadata;
5787 : }
5788 :
5789 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
5790 : mozilla::wr::IpcResourceUpdateQueue& aResources,
5791 : const StackingContextHelper& aSc,
5792 : mozilla::layers::WebRenderLayerManager* aManager,
5793 : nsDisplayListBuilder* aDisplayListBuilder) override;
5794 : virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
5795 : mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
5796 :
5797 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
5798 :
5799 : protected:
5800 : // For background-attachment:fixed
5801 : nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5802 : nsDisplayList* aList, uint32_t aIndex);
5803 : void Init(nsDisplayListBuilder* aBuilder);
5804 : ViewID GetScrollTargetId();
5805 :
5806 : RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForScrollMetadata;
5807 : uint32_t mIndex;
5808 : bool mIsFixedBackground;
5809 : RefPtr<const ActiveScrolledRoot> mContainerASR;
5810 : };
5811 :
5812 0 : class nsDisplayTableFixedPosition : public nsDisplayFixedPosition
5813 : {
5814 0 : public:
5815 : static nsDisplayTableFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
5816 : nsIFrame* aFrame,
5817 0 : nsDisplayBackgroundImage* aImage,
5818 : uint32_t aIndex,
5819 0 : nsIFrame* aAncestorFrame);
5820 0 :
5821 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
5822 : {
5823 0 : return MakeDisplayItem<nsDisplayTableFixedPosition>(aBuilder, *this);
5824 0 : }
5825 0 :
5826 : virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
5827 0 :
5828 0 : virtual bool HasDeletedFrame() const override {
5829 : return !mAncestorFrame || nsDisplayFixedPosition::HasDeletedFrame();
5830 0 : }
5831 0 :
5832 0 : virtual void RemoveFrame(nsIFrame* aFrame) override {
5833 0 : if (aFrame == mAncestorFrame) {
5834 : mAncestorFrame = nullptr;
5835 : }
5836 0 : nsDisplayFixedPosition::RemoveFrame(aFrame);
5837 : }
5838 :
5839 : virtual uint32_t GetPerFrameKey() const override {
5840 : return (mIndex << (TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
5841 : (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
5842 0 : nsDisplayItem::GetPerFrameKey();
5843 : }
5844 0 :
5845 0 : NS_DISPLAY_DECL_NAME("TableFixedPosition", TYPE_TABLE_FIXED_POSITION)
5846 0 : protected:
5847 : nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5848 0 : nsDisplayList* aList, uint32_t aIndex,
5849 0 : nsIFrame* aAncestorFrame);
5850 :
5851 0 : nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder,
5852 0 : const nsDisplayTableFixedPosition& aOther)
5853 0 : : nsDisplayFixedPosition(aBuilder, aOther)
5854 0 : , mAncestorFrame(aOther.mAncestorFrame)
5855 : , mTableType(aOther.mTableType)
5856 0 : {
5857 : if (aBuilder->IsRetainingDisplayList()) {
5858 : mAncestorFrame->AddDisplayItem(this);
5859 : }
5860 : }
5861 : ~nsDisplayTableFixedPosition() {
5862 : if (mAncestorFrame) {
5863 : mAncestorFrame->RemoveDisplayItem(this);
5864 : }
5865 : }
5866 :
5867 : nsIFrame* mAncestorFrame;
5868 : TableType mTableType;
5869 : };
5870 :
5871 : /**
5872 0 : * This creates an empty scrollable layer. It has no child layers.
5873 : * It is used to record the existence of a scrollable frame in the layer
5874 : * tree.
5875 : */
5876 : class nsDisplayScrollInfoLayer : public nsDisplayWrapList
5877 : {
5878 : public:
5879 : nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder,
5880 : nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame);
5881 : NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER)
5882 :
5883 0 :
5884 : #ifdef NS_BUILD_REFCNT_LOGGING
5885 0 : virtual ~nsDisplayScrollInfoLayer();
5886 : #endif
5887 :
5888 0 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
5889 : LayerManager* aManager,
5890 : const ContainerLayerParameters& aContainerParameters) override;
5891 0 :
5892 0 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override
5893 : {
5894 : return true;
5895 : }
5896 :
5897 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5898 : bool* aSnap) const override
5899 0 : {
5900 : *aSnap = false;
5901 0 : return nsRegion();
5902 : }
5903 :
5904 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5905 : LayerManager* aManager,
5906 : const ContainerLayerParameters& aParameters) override;
5907 :
5908 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
5909 : {
5910 : return false;
5911 : }
5912 :
5913 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
5914 :
5915 : mozilla::UniquePtr<ScrollMetadata> ComputeScrollMetadata(LayerManager* aLayerManager,
5916 : const ContainerLayerParameters& aContainerParameters);
5917 :
5918 : virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
5919 : mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
5920 :
5921 : protected:
5922 : nsIFrame* mScrollFrame;
5923 : nsIFrame* mScrolledFrame;
5924 : ViewID mScrollParentId;
5925 : };
5926 :
5927 : /**
5928 : * nsDisplayZoom is used for subdocuments that have a different full zoom than
5929 : * their parent documents. This item creates a container layer.
5930 : */
5931 : class nsDisplayZoom : public nsDisplaySubDocument {
5932 : public:
5933 : /**
5934 : * @param aFrame is the root frame of the subdocument.
5935 : * @param aList contains the display items for the subdocument.
5936 : * @param aAPD is the app units per dev pixel ratio of the subdocument.
5937 : * @param aParentAPD is the app units per dev pixel ratio of the parent
5938 : * document.
5939 : * @param aFlags eGenerateSubdocInvalidations :
5940 : * Add UserData to the created ContainerLayer, so that invalidations
5941 : * for this layer are send to our nsPresContext.
5942 : */
5943 : nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5944 : nsDisplayList* aList,
5945 : int32_t aAPD, int32_t aParentAPD,
5946 : nsDisplayOwnLayerFlags aFlags = nsDisplayOwnLayerFlags::eNone);
5947 : #ifdef NS_BUILD_REFCNT_LOGGING
5948 : virtual ~nsDisplayZoom();
5949 : #endif
5950 :
5951 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
5952 : bool* aSnap) const override;
5953 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
5954 0 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
5955 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
5956 : nsRegion* aVisibleRegion) override;
5957 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
5958 : LayerManager* aManager,
5959 : const ContainerLayerParameters& aParameters) override
5960 : {
5961 : return mozilla::LAYER_ACTIVE;
5962 : }
5963 : NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
5964 :
5965 : // Get the app units per dev pixel ratio of the child document.
5966 : int32_t GetChildAppUnitsPerDevPixel() { return mAPD; }
5967 : // Get the app units per dev pixel ratio of the parent document.
5968 : int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD; }
5969 :
5970 : private:
5971 : int32_t mAPD, mParentAPD;
5972 : };
5973 :
5974 : class nsDisplaySVGEffects: public nsDisplayWrapList {
5975 : public:
5976 : nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5977 : nsDisplayList* aList, bool aHandleOpacity,
5978 : const ActiveScrolledRoot* aActiveScrolledRoot,
5979 : bool aClearClipChain = false);
5980 : nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5981 : nsDisplayList* aList, bool aHandleOpacity);
5982 : #ifdef NS_BUILD_REFCNT_LOGGING
5983 : virtual ~nsDisplaySVGEffects();
5984 : #endif
5985 :
5986 : nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
5987 : const nsDisplaySVGEffects& aOther)
5988 : : nsDisplayWrapList(aBuilder, aOther)
5989 : , mEffectsBounds(aOther.mEffectsBounds)
5990 : , mHandleOpacity(aOther.mHandleOpacity)
5991 : {
5992 0 : MOZ_COUNT_CTOR(nsDisplaySVGEffects);
5993 0 : }
5994 :
5995 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5996 : bool* aSnap) const override;
5997 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
5998 : HitTestState* aState,
5999 : nsTArray<nsIFrame*> *aOutFrames) override;
6000 :
6001 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
6002 : return false;
6003 : }
6004 :
6005 : bool ShouldHandleOpacity() {
6006 : return mHandleOpacity;
6007 : }
6008 :
6009 : gfxRect BBoxInUserSpace() const;
6010 : gfxPoint UserSpaceOffset() const;
6011 :
6012 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6013 : const nsDisplayItemGeometry* aGeometry,
6014 : nsRegion* aInvalidRegion) const override;
6015 : protected:
6016 : bool ValidateSVGFrame();
6017 :
6018 : // relative to mFrame
6019 : nsRect mEffectsBounds;
6020 : // True if we need to handle css opacity in this display item.
6021 : bool mHandleOpacity;
6022 : };
6023 :
6024 : /**
6025 : * A display item to paint a stacking context with mask and clip effects
6026 : * set by the stacking context root frame's style.
6027 : */
6028 : class nsDisplayMask : public nsDisplaySVGEffects {
6029 : public:
6030 : typedef mozilla::layers::ImageLayer ImageLayer;
6031 :
6032 : nsDisplayMask(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6033 : nsDisplayList* aList, bool aHandleOpacity,
6034 : const ActiveScrolledRoot* aActiveScrolledRoot);
6035 : nsDisplayMask(nsDisplayListBuilder* aBuilder,
6036 : const nsDisplayMask& aOther)
6037 : : nsDisplaySVGEffects(aBuilder, aOther)
6038 : , mDestRects(aOther.mDestRects)
6039 : {}
6040 : #ifdef NS_BUILD_REFCNT_LOGGING
6041 0 : virtual ~nsDisplayMask();
6042 : #endif
6043 :
6044 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
6045 : {
6046 : MOZ_COUNT_CTOR(nsDisplayMask);
6047 : return MakeDisplayItem<nsDisplayMask>(aBuilder, *this);
6048 : }
6049 :
6050 : NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK)
6051 :
6052 : virtual bool CanMerge(const nsDisplayItem* aItem) const override;
6053 :
6054 : virtual void Merge(const nsDisplayItem* aItem) override
6055 : {
6056 : nsDisplayWrapList::Merge(aItem);
6057 :
6058 : const nsDisplayMask* other = static_cast<const nsDisplayMask*>(aItem);
6059 : mEffectsBounds.UnionRect(mEffectsBounds,
6060 : other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
6061 : }
6062 :
6063 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
6064 0 : LayerManager* aManager,
6065 : const ContainerLayerParameters& aContainerParameters) override;
6066 0 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
6067 : LayerManager* aManager,
6068 : const ContainerLayerParameters& aParameters) override;
6069 :
6070 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
6071 : nsRegion* aVisibleRegion) override;
6072 :
6073 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
6074 : {
6075 : return new nsDisplayMaskGeometry(this, aBuilder);
6076 : }
6077 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6078 : const nsDisplayItemGeometry* aGeometry,
6079 : nsRegion* aInvalidRegion) const override;
6080 : #ifdef MOZ_DUMP_PAINTING
6081 : void PrintEffects(nsACString& aTo);
6082 : #endif
6083 :
6084 : void PaintAsLayer(nsDisplayListBuilder* aBuilder,
6085 : gfxContext* aCtx,
6086 : LayerManager* aManager);
6087 :
6088 : /*
6089 : * Paint mask onto aMaskContext in mFrame's coordinate space and
6090 : * return whether the mask layer was painted successfully.
6091 : */
6092 : bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
6093 :
6094 : const nsTArray<nsRect>& GetDestRects()
6095 : {
6096 : return mDestRects;
6097 : }
6098 :
6099 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
6100 : mozilla::wr::IpcResourceUpdateQueue& aResources,
6101 : const StackingContextHelper& aSc,
6102 : mozilla::layers::WebRenderLayerManager* aManager,
6103 : nsDisplayListBuilder* aDisplayListBuilder) override;
6104 :
6105 : virtual mozilla::Maybe<nsRect> GetClipWithRespectToASR(
6106 : nsDisplayListBuilder* aBuilder,
6107 : const ActiveScrolledRoot* aASR) const override;
6108 : private:
6109 : // According to mask property and the capability of aManager, determine
6110 : // whether we can paint the mask onto a dedicate mask layer.
6111 : bool CanPaintOnMaskLayer(LayerManager* aManager);
6112 :
6113 : nsTArray<nsRect> mDestRects;
6114 : };
6115 :
6116 : /**
6117 : * A display item to paint a stacking context with filter effects set by the
6118 : * stacking context root frame's style.
6119 : */
6120 : class nsDisplayFilter : public nsDisplaySVGEffects {
6121 : public:
6122 : nsDisplayFilter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6123 : nsDisplayList* aList, bool aHandleOpacity);
6124 : nsDisplayFilter(nsDisplayListBuilder* aBuilder,
6125 : const nsDisplayFilter& aOther)
6126 : : nsDisplaySVGEffects(aBuilder, aOther)
6127 : , mEffectsBounds(aOther.mEffectsBounds)
6128 : {}
6129 : #ifdef NS_BUILD_REFCNT_LOGGING
6130 0 : virtual ~nsDisplayFilter();
6131 : #endif
6132 0 :
6133 : virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
6134 : {
6135 : MOZ_COUNT_CTOR(nsDisplayFilter);
6136 0 : return MakeDisplayItem<nsDisplayFilter>(aBuilder, *this);
6137 : }
6138 :
6139 : NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER)
6140 :
6141 : virtual bool CanMerge(const nsDisplayItem* aItem) const override
6142 : {
6143 : // Items for the same content element should be merged into a single
6144 : // compositing group.
6145 : return HasSameTypeAndClip(aItem) && HasSameContent(aItem);
6146 : }
6147 :
6148 : virtual void Merge(const nsDisplayItem* aItem) override
6149 : {
6150 : nsDisplayWrapList::Merge(aItem);
6151 :
6152 : const nsDisplayFilter* other = static_cast<const nsDisplayFilter*>(aItem);
6153 : mEffectsBounds.UnionRect(mEffectsBounds,
6154 0 : other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
6155 : }
6156 :
6157 0 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
6158 0 : LayerManager* aManager,
6159 : const ContainerLayerParameters& aContainerParameters) override;
6160 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
6161 : LayerManager* aManager,
6162 0 : const ContainerLayerParameters& aParameters) override;
6163 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
6164 0 : bool* aSnap) const override
6165 : {
6166 : *aSnap = false;
6167 : return mEffectsBounds + ToReferenceFrame();
6168 : }
6169 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
6170 : nsRegion* aVisibleRegion) override;
6171 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
6172 : {
6173 : return new nsDisplayFilterGeometry(this, aBuilder);
6174 : }
6175 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6176 : const nsDisplayItemGeometry* aGeometry,
6177 : nsRegion* aInvalidRegion) const override;
6178 : #ifdef MOZ_DUMP_PAINTING
6179 : void PrintEffects(nsACString& aTo);
6180 : #endif
6181 :
6182 : void PaintAsLayer(nsDisplayListBuilder* aBuilder,
6183 : gfxContext* aCtx,
6184 : LayerManager* aManager);
6185 :
6186 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
6187 : mozilla::wr::IpcResourceUpdateQueue& aResources,
6188 : const StackingContextHelper& aSc,
6189 : mozilla::layers::WebRenderLayerManager* aManager,
6190 : nsDisplayListBuilder* aDisplayListBuilder) override;
6191 :
6192 : private:
6193 : // relative to mFrame
6194 : nsRect mEffectsBounds;
6195 : };
6196 :
6197 : /* A display item that applies a transformation to all of its descendant
6198 : * elements. This wrapper should only be used if there is a transform applied
6199 : * to the root element.
6200 : *
6201 : * The reason that a "bounds" rect is involved in transform calculations is
6202 : * because CSS-transforms allow percentage values for the x and y components
6203 : * of <translation-value>s, where percentages are percentages of the element's
6204 : * border box.
6205 : *
6206 : * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
6207 : * function.
6208 : * INVARIANT: The wrapped frame is non-null.
6209 : */
6210 : class nsDisplayTransform: public nsDisplayItem
6211 : {
6212 : typedef mozilla::gfx::Matrix4x4 Matrix4x4;
6213 : typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged;
6214 : typedef mozilla::gfx::Point3D Point3D;
6215 0 :
6216 : /*
6217 0 : * Avoid doing UpdateBounds() during construction.
6218 : */
6219 : class StoreList : public nsDisplayWrapList {
6220 0 : public:
6221 0 : StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6222 : nsDisplayList* aList)
6223 0 : : nsDisplayWrapList(aBuilder, aFrame, aList, true) {}
6224 : virtual ~StoreList() = default;
6225 0 :
6226 : virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override {
6227 0 : // For extending 3d rendering context, the bounds would be
6228 0 : // updated by DoUpdateBoundsPreserves3D(), not here.
6229 0 : if (!mFrame->Extend3DContext()) {
6230 : nsDisplayWrapList::UpdateBounds(aBuilder);
6231 0 : }
6232 0 : }
6233 : void ForceUpdateBounds(nsDisplayListBuilder* aBuilder) {
6234 : nsDisplayWrapList::UpdateBounds(aBuilder);
6235 : }
6236 : virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
6237 : for (nsDisplayItem *i = mList.GetBottom(); i; i = i->GetAbove()) {
6238 : i->DoUpdateBoundsPreserves3D(aBuilder);
6239 : }
6240 : nsDisplayWrapList::UpdateBounds(aBuilder);
6241 : }
6242 : };
6243 :
6244 : public:
6245 : enum PrerenderDecision {
6246 : NoPrerender,
6247 : FullPrerender,
6248 : PartialPrerender
6249 : };
6250 :
6251 : /**
6252 : * Returns a matrix (in pixels) for the current frame. The matrix should be relative to
6253 : * the current frame's coordinate space.
6254 : *
6255 : * @param aFrame The frame to compute the transform for.
6256 : * @param aAppUnitsPerPixel The number of app units per graphics unit.
6257 : */
6258 : typedef Matrix4x4 (* ComputeTransformFunction)(nsIFrame* aFrame, float aAppUnitsPerPixel);
6259 :
6260 : /* Constructor accepts a display list, empties it, and wraps it up. It also
6261 : * ferries the underlying frame to the nsDisplayItem constructor.
6262 : */
6263 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
6264 : nsDisplayList *aList, const nsRect& aChildrenBuildingRect,
6265 0 : uint32_t aIndex = 0, bool aAllowAsyncAnimation = false);
6266 0 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
6267 0 : nsDisplayList *aList, const nsRect& aChildrenBuildingRect,
6268 0 : ComputeTransformFunction aTransformGetter, uint32_t aIndex = 0);
6269 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
6270 : nsDisplayList *aList, const nsRect& aChildrenBuildingRect,
6271 0 : const Matrix4x4& aTransform, uint32_t aIndex = 0);
6272 :
6273 0 : #ifdef NS_BUILD_REFCNT_LOGGING
6274 0 : virtual ~nsDisplayTransform()
6275 0 : {
6276 : MOZ_COUNT_DTOR(nsDisplayTransform);
6277 : }
6278 0 : #endif
6279 0 :
6280 : virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
6281 : {
6282 0 : mHasBounds = false;
6283 : if (IsTransformSeparator()) {
6284 0 : mStoredList.ForceUpdateBounds(aBuilder);
6285 0 : return;
6286 0 : }
6287 : mStoredList.UpdateBounds(aBuilder);
6288 0 : UpdateBoundsFor3D(aBuilder);
6289 : }
6290 0 :
6291 : virtual void Destroy(nsDisplayListBuilder* aBuilder) override
6292 0 : {
6293 0 : mStoredList.GetChildren()->DeleteAll(aBuilder);
6294 : nsDisplayItem::Destroy(aBuilder);
6295 0 : }
6296 :
6297 : NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM)
6298 0 :
6299 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override
6300 0 : {
6301 : if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty())
6302 : return nsRect();
6303 0 : bool snap;
6304 : return GetBounds(aBuilder, &snap);
6305 0 : }
6306 0 :
6307 0 : virtual RetainedDisplayList* GetChildren() const override
6308 : {
6309 : return mStoredList.GetChildren();
6310 : }
6311 :
6312 : virtual void SetActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot) override
6313 : {
6314 : nsDisplayItem::SetActiveScrolledRoot(aActiveScrolledRoot);
6315 : mStoredList.SetActiveScrolledRoot(aActiveScrolledRoot);
6316 : }
6317 :
6318 : virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
6319 : HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames) override;
6320 : virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder,
6321 : bool* aSnap) const override;
6322 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
6323 : bool* aSnap) const override;
6324 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
6325 : LayerManager* aManager,
6326 : const ContainerLayerParameters& aParameters) override;
6327 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
6328 : LayerManager* aManager,
6329 : const ContainerLayerParameters& aContainerParameters) override;
6330 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
6331 : mozilla::wr::IpcResourceUpdateQueue& aResources,
6332 0 : const StackingContextHelper& aSc,
6333 : mozilla::layers::WebRenderLayerManager* aManager,
6334 0 : nsDisplayListBuilder* aDisplayListBuilder) override;
6335 : virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
6336 : mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
6337 0 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override;
6338 0 : virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
6339 : nsRegion *aVisibleRegion) override;
6340 :
6341 0 : virtual bool CanMerge(const nsDisplayItem* aItem) const override
6342 : {
6343 : return false;
6344 : }
6345 :
6346 0 : virtual uint32_t GetPerFrameKey() const override {
6347 : return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
6348 0 : }
6349 :
6350 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6351 : const nsDisplayItemGeometry* aGeometry,
6352 0 : nsRegion* aInvalidRegion) const override
6353 0 : {
6354 : // We don't need to compute an invalidation region since we have LayerTreeInvalidation
6355 0 : }
6356 :
6357 : virtual const nsIFrame* ReferenceFrameForChildren() const override {
6358 0 : // If we were created using a transform-getter, then we don't
6359 0 : // belong to a transformed frame, and aren't a reference frame
6360 : // for our children.
6361 : if (!mTransformGetter) {
6362 0 : return mFrame;
6363 : }
6364 0 : return nsDisplayItem::ReferenceFrameForChildren();
6365 : }
6366 :
6367 : AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const override {
6368 : return mAnimatedGeometryRootForScrollMetadata;
6369 : }
6370 :
6371 : virtual const nsRect& GetBuildingRectForChildren() const override
6372 : {
6373 : return mChildrenBuildingRect;
6374 : }
6375 :
6376 : enum {
6377 : INDEX_MAX = UINT32_MAX >> TYPE_BITS
6378 : };
6379 :
6380 : /**
6381 : * We include the perspective matrix from our containing block for the
6382 : * purposes of visibility calculations, but we exclude it from the transform
6383 : * we set on the layer (for rendering), since there will be an
6384 : * nsDisplayPerspective created for that.
6385 : */
6386 : const Matrix4x4Flagged& GetTransform() const;
6387 : const Matrix4x4Flagged& GetInverseTransform() const;
6388 :
6389 : Matrix4x4 GetTransformForRendering(mozilla::LayoutDevicePoint* aOutOrigin = nullptr);
6390 :
6391 : /**
6392 : * Return the transform that is aggregation of all transform on the
6393 : * preserves3d chain.
6394 : */
6395 : const Matrix4x4& GetAccumulatedPreserved3DTransform(nsDisplayListBuilder* aBuilder);
6396 :
6397 : float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint);
6398 :
6399 : /**
6400 : * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
6401 : * space) and returns the smallest rectangle (in aFrame's coordinate space)
6402 : * containing the transformed image of that rectangle. That is, it takes
6403 : * the four corners of the rectangle, transforms them according to the
6404 : * matrix associated with the specified frame, then returns the smallest
6405 : * rectangle containing the four transformed points.
6406 : *
6407 : * @param untransformedBounds The rectangle (in app units) to transform.
6408 : * @param aFrame The frame whose transformation should be applied. This
6409 : * function raises an assertion if aFrame is null or doesn't have a
6410 : * transform applied to it.
6411 : * @param aOrigin The origin of the transform relative to aFrame's local
6412 : * coordinate space.
6413 : * @param aBoundsOverride (optional) Rather than using the frame's computed
6414 : * bounding rect as frame bounds, use this rectangle instead. Pass
6415 : * nullptr (or nothing at all) to use the default.
6416 : */
6417 : static nsRect TransformRect(const nsRect &aUntransformedBounds,
6418 : const nsIFrame* aFrame,
6419 : const nsRect* aBoundsOverride = nullptr);
6420 :
6421 : /* UntransformRect is like TransformRect, except that it inverts the
6422 : * transform.
6423 : */
6424 : static bool UntransformRect(const nsRect &aTransformedBounds,
6425 : const nsRect &aChildBounds,
6426 : const nsIFrame* aFrame,
6427 : nsRect *aOutRect);
6428 :
6429 : bool UntransformRect(nsDisplayListBuilder* aBuilder,
6430 : const nsRect& aRect,
6431 : nsRect* aOutRect) const;
6432 : bool UntransformBuildingRect(nsDisplayListBuilder* aBuilder,
6433 : nsRect* aOutRect) const
6434 : {
6435 : return UntransformRect(aBuilder, GetBuildingRect(), aOutRect);
6436 :
6437 : }
6438 : bool UntransformPaintRect(nsDisplayListBuilder* aBuilder,
6439 : nsRect* aOutRect) const
6440 : {
6441 : return UntransformRect(aBuilder, GetPaintRect(), aOutRect);
6442 : }
6443 :
6444 : static Point3D GetDeltaToTransformOrigin(const nsIFrame* aFrame,
6445 : float aAppUnitsPerPixel,
6446 : const nsRect* aBoundsOverride);
6447 :
6448 : /*
6449 : * Returns true if aFrame has perspective applied from its containing
6450 : * block.
6451 : * Returns the matrix to append to apply the persective (taking
6452 0 : * perspective-origin into account), relative to aFrames coordinate
6453 : * space).
6454 : * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
6455 : * cleared.
6456 : */
6457 : static bool ComputePerspectiveMatrix(const nsIFrame* aFrame,
6458 : float aAppUnitsPerPixel,
6459 : Matrix4x4& aOutMatrix);
6460 0 :
6461 0 : struct FrameTransformProperties
6462 0 : {
6463 : FrameTransformProperties(const nsIFrame* aFrame,
6464 : float aAppUnitsPerPixel,
6465 : const nsRect* aBoundsOverride);
6466 : FrameTransformProperties(RefPtr<const nsCSSValueSharedList>&&
6467 : aTransformList,
6468 : const Point3D& aToTransformOrigin)
6469 : : mFrame(nullptr)
6470 : , mTransformList(std::move(aTransformList))
6471 : , mToTransformOrigin(aToTransformOrigin)
6472 : {}
6473 :
6474 : const nsIFrame* mFrame;
6475 : const RefPtr<const nsCSSValueSharedList> mTransformList;
6476 : const Point3D mToTransformOrigin;
6477 : };
6478 :
6479 : /**
6480 : * Given a frame with the -moz-transform property or an SVG transform,
6481 : * returns the transformation matrix for that frame.
6482 : *
6483 : * @param aFrame The frame to get the matrix from.
6484 : * @param aOrigin Relative to which point this transform should be applied.
6485 : * @param aAppUnitsPerPixel The number of app units per graphics unit.
6486 : * @param aBoundsOverride [optional] If this is nullptr (the default), the
6487 : * computation will use the value of TransformReferenceBox(aFrame).
6488 : * Otherwise, it will use the value of aBoundsOverride. This is
6489 : * mostly for internal use and in most cases you will not need to
6490 : * specify a value.
6491 : * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
6492 : * by aOrigin. This translation is applied *before* the CSS transform.
6493 : * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
6494 : * include the transform of any ancestors participating in the same
6495 : * 3d rendering context.
6496 : * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
6497 : * perspective transform from the containing block if applicable.
6498 : */
6499 : enum {
6500 : OFFSET_BY_ORIGIN = 1 << 0,
6501 : INCLUDE_PRESERVE3D_ANCESTORS = 1 << 1,
6502 : INCLUDE_PERSPECTIVE = 1 << 2,
6503 : };
6504 : static Matrix4x4 GetResultingTransformMatrix(const nsIFrame* aFrame,
6505 : const nsPoint& aOrigin,
6506 : float aAppUnitsPerPixel,
6507 : uint32_t aFlags,
6508 : const nsRect* aBoundsOverride = nullptr);
6509 : static Matrix4x4 GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
6510 : const nsPoint& aOrigin,
6511 : float aAppUnitsPerPixel,
6512 : uint32_t aFlags,
6513 : const nsRect* aBoundsOverride = nullptr);
6514 : /**
6515 : * Decide whether we should prerender some or all of the contents of the
6516 : * transformed frame even when it's not completely visible (yet).
6517 : * Return FullPrerender if the entire contents should be prerendered,
6518 : * PartialPrerender if some but not all of the contents should be prerendered,
6519 : * or NoPrerender if only the visible area should be rendered.
6520 : * |aDirtyRect| is updated to the area that should be prerendered.
6521 : */
6522 : static PrerenderDecision ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
6523 : nsIFrame* aFrame,
6524 : nsRect* aDirtyRect);
6525 : bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
6526 0 :
6527 0 : bool MayBeAnimated(nsDisplayListBuilder* aBuilder) const;
6528 :
6529 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
6530 0 :
6531 0 : // Force the layer created for this item not to extend 3D context.
6532 : // See nsIFrame::BuildDisplayListForStackingContext()
6533 : void SetNoExtendContext() { mNoExtendContext = true; }
6534 :
6535 : virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
6536 : MOZ_ASSERT(mFrame->Combines3DTransformWithAncestors() ||
6537 : IsTransformSeparator());
6538 : // Updating is not going through to child 3D context.
6539 0 : ComputeBounds(aBuilder);
6540 0 : }
6541 0 :
6542 0 : /**
6543 : * This function updates bounds for items with a frame establishing
6544 0 : * 3D rendering context.
6545 : *
6546 : * \see nsDisplayItem::DoUpdateBoundsPreserves3D()
6547 : */
6548 0 : void UpdateBoundsFor3D(nsDisplayListBuilder* aBuilder) {
6549 0 : if (!mFrame->Extend3DContext() ||
6550 0 : mFrame->Combines3DTransformWithAncestors() ||
6551 0 : IsTransformSeparator()) {
6552 0 : // Not an establisher of a 3D rendering context.
6553 0 : return;
6554 : }
6555 : // Always start updating from an establisher of a 3D rendering context.
6556 :
6557 : nsDisplayListBuilder::AutoAccumulateRect accRect(aBuilder);
6558 : nsDisplayListBuilder::AutoAccumulateTransform accTransform(aBuilder);
6559 : accTransform.StartRoot();
6560 : ComputeBounds(aBuilder);
6561 : mBounds = aBuilder->GetAccumulatedRect();
6562 : mHasBounds = true;
6563 : }
6564 :
6565 : /**
6566 : * This item is an additional item as the boundary between parent
6567 : * and child 3D rendering context.
6568 : * \see nsIFrame::BuildDisplayListForStackingContext().
6569 : */
6570 : bool IsTransformSeparator() { return mIsTransformSeparator; }
6571 : /**
6572 : * This item is the boundary between parent and child 3D rendering
6573 : * context.
6574 : */
6575 : bool IsLeafOf3DContext() {
6576 : return (IsTransformSeparator() ||
6577 : (!mFrame->Extend3DContext() &&
6578 : mFrame->Combines3DTransformWithAncestors()));
6579 : }
6580 0 : /**
6581 : * The backing frame of this item participates a 3D rendering
6582 0 : * context.
6583 0 : */
6584 0 : bool IsParticipating3DContext() {
6585 : return mFrame->Extend3DContext() ||
6586 : mFrame->Combines3DTransformWithAncestors();
6587 : }
6588 :
6589 : virtual void RemoveFrame(nsIFrame* aFrame) override
6590 : {
6591 : nsDisplayItem::RemoveFrame(aFrame);
6592 : mStoredList.RemoveFrame(aFrame);
6593 : }
6594 :
6595 : private:
6596 : void ComputeBounds(nsDisplayListBuilder* aBuilder);
6597 : void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
6598 : void Init(nsDisplayListBuilder* aBuilder);
6599 :
6600 : static Matrix4x4 GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
6601 : const nsPoint& aOrigin,
6602 : float aAppUnitsPerPixel,
6603 : uint32_t aFlags,
6604 : const nsRect* aBoundsOverride);
6605 :
6606 : StoreList mStoredList;
6607 : mutable mozilla::Maybe<Matrix4x4Flagged> mTransform;
6608 : mutable mozilla::Maybe<Matrix4x4Flagged> mInverseTransform;
6609 : // Accumulated transform of ancestors on the preserves-3d chain.
6610 : Matrix4x4 mTransformPreserves3D;
6611 : ComputeTransformFunction mTransformGetter;
6612 : RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForChildren;
6613 : RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForScrollMetadata;
6614 : nsRect mChildrenBuildingRect;
6615 : uint32_t mIndex;
6616 : mutable nsRect mBounds;
6617 : // True for mBounds is valid.
6618 : mutable bool mHasBounds;
6619 : // Be forced not to extend 3D context. Since we don't create a
6620 : // transform item, a container layer, for every frames in a
6621 : // preserves3d context, the transform items of a child preserves3d
6622 : // context may extend the parent context not intented if the root of
6623 : // the child preserves3d context doesn't create a transform item.
6624 : // With this flags, we force the item not extending 3D context.
6625 : bool mNoExtendContext;
6626 : // This item is a separator between 3D rendering contexts, and
6627 : // mTransform have been presetted by the constructor.
6628 : bool mIsTransformSeparator;
6629 : // True if mTransformPreserves3D have been initialized.
6630 : bool mTransformPreserves3DInited;
6631 : // True if async animation of the transform is allowed.
6632 : bool mAllowAsyncAnimation;
6633 : };
6634 :
6635 : /* A display item that applies a perspective transformation to a single
6636 0 : * nsDisplayTransform child item. We keep this as a separate item since the
6637 : * perspective-origin is relative to an ancestor of the transformed frame, and
6638 : * APZ can scroll the child separately.
6639 : */
6640 0 : class nsDisplayPerspective : public nsDisplayItem
6641 0 : {
6642 0 : typedef mozilla::gfx::Point3D Point3D;
6643 :
6644 0 : public:
6645 : NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE)
6646 :
6647 0 : nsDisplayPerspective(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6648 : nsDisplayList* aList);
6649 : ~nsDisplayPerspective()
6650 0 : {
6651 : }
6652 :
6653 0 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
6654 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override
6655 : {
6656 0 : return mList.HitTest(aBuilder, aRect, aState, aOutFrames);
6657 : }
6658 0 :
6659 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
6660 : bool* aSnap) const override
6661 0 : {
6662 : return mList.GetBounds(aBuilder, aSnap);
6663 : }
6664 0 :
6665 : virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
6666 0 : {
6667 : mList.UpdateBounds(aBuilder);
6668 : }
6669 0 :
6670 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6671 : const nsDisplayItemGeometry* aGeometry,
6672 0 : nsRegion* aInvalidRegion) const override
6673 : {}
6674 0 :
6675 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
6676 : bool* aSnap) const override
6677 : {
6678 : return mList.GetOpaqueRegion(aBuilder, aSnap);
6679 : }
6680 :
6681 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override
6682 : {
6683 : return mList.IsUniform(aBuilder);
6684 : }
6685 :
6686 0 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
6687 : LayerManager* aManager,
6688 0 : const ContainerLayerParameters& aParameters) override;
6689 : bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
6690 : mozilla::wr::IpcResourceUpdateQueue& aResources,
6691 0 : const StackingContextHelper& aSc,
6692 : mozilla::layers::WebRenderLayerManager* aManager,
6693 : nsDisplayListBuilder* aDisplayListBuilder) override;
6694 :
6695 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override
6696 : {
6697 : if (!mList.GetChildren()->GetTop()) {
6698 0 : return false;
6699 : }
6700 : return mList.GetChildren()->GetTop()->ShouldBuildLayerEvenIfInvisible(aBuilder);
6701 0 : }
6702 0 :
6703 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
6704 : LayerManager* aManager,
6705 0 : const ContainerLayerParameters& aContainerParameters) override;
6706 :
6707 0 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
6708 : nsRegion* aVisibleRegion) override
6709 : {
6710 0 : mList.RecomputeVisibility(aBuilder, aVisibleRegion);
6711 : return true;
6712 0 : }
6713 :
6714 : virtual nsDisplayList* GetSameCoordinateSystemChildren() const override
6715 0 : {
6716 : return mList.GetChildren();
6717 0 : }
6718 0 :
6719 0 : virtual RetainedDisplayList* GetChildren() const override
6720 : {
6721 0 : return mList.GetChildren();
6722 : }
6723 0 :
6724 : virtual void SetActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot) override
6725 : {
6726 : nsDisplayItem::SetActiveScrolledRoot(aActiveScrolledRoot);
6727 0 : mList.SetActiveScrolledRoot(aActiveScrolledRoot);
6728 0 : }
6729 0 :
6730 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override
6731 0 : {
6732 : return mList.GetComponentAlphaBounds(aBuilder);
6733 0 : }
6734 :
6735 0 : virtual void
6736 0 : DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
6737 0 : if (mList.GetChildren()->GetTop()) {
6738 : static_cast<nsDisplayTransform*>(mList.GetChildren()->GetTop())->DoUpdateBoundsPreserves3D(aBuilder);
6739 0 : }
6740 : }
6741 0 :
6742 0 : virtual void Destroy(nsDisplayListBuilder* aBuilder) override
6743 0 : {
6744 : mList.GetChildren()->DeleteAll(aBuilder);
6745 : nsDisplayItem::Destroy(aBuilder);
6746 : }
6747 :
6748 : virtual void RemoveFrame(nsIFrame* aFrame) override
6749 : {
6750 : nsDisplayItem::RemoveFrame(aFrame);
6751 : mList.RemoveFrame(aFrame);
6752 : }
6753 :
6754 : private:
6755 : nsDisplayWrapList mList;
6756 : };
6757 :
6758 : /**
6759 : * This class adds basic support for limiting the rendering (in the inline axis
6760 : * of the writing mode) to the part inside the specified edges. It's a base
6761 : * class for the display item classes that do the actual work.
6762 : * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
6763 : * of the frame's scrollable overflow rectangle and are the amount to suppress
6764 : * on each side.
6765 : *
6766 : * Setting none, both or only one edge is allowed.
6767 : * The values must be non-negative.
6768 : * The default value for both edges is zero, which means everything is painted.
6769 : */
6770 : class nsCharClipDisplayItem : public nsDisplayItem {
6771 : public:
6772 : nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
6773 : : nsDisplayItem(aBuilder, aFrame), mVisIStartEdge(0), mVisIEndEdge(0) {}
6774 :
6775 : explicit nsCharClipDisplayItem(nsIFrame* aFrame)
6776 : : nsDisplayItem(aFrame), mVisIStartEdge(0), mVisIEndEdge(0) {}
6777 :
6778 : virtual void RestoreState() override
6779 : {
6780 : nsDisplayItem::RestoreState();
6781 : mIsFrameSelected.reset();
6782 : }
6783 :
6784 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
6785 :
6786 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6787 : const nsDisplayItemGeometry* aGeometry,
6788 : nsRegion* aInvalidRegion) const override;
6789 :
6790 : struct ClipEdges {
6791 : ClipEdges(const nsDisplayItem& aItem,
6792 : nscoord aVisIStartEdge, nscoord aVisIEndEdge) {
6793 : nsRect r = aItem.Frame()->GetScrollableOverflowRect() +
6794 : aItem.ToReferenceFrame();
6795 : if (aItem.Frame()->GetWritingMode().IsVertical()) {
6796 : mVisIStart = aVisIStartEdge > 0 ? r.y + aVisIStartEdge : nscoord_MIN;
6797 : mVisIEnd =
6798 : aVisIEndEdge > 0 ? std::max(r.YMost() - aVisIEndEdge, mVisIStart)
6799 : : nscoord_MAX;
6800 : } else {
6801 : mVisIStart = aVisIStartEdge > 0 ? r.x + aVisIStartEdge : nscoord_MIN;
6802 : mVisIEnd =
6803 : aVisIEndEdge > 0 ? std::max(r.XMost() - aVisIEndEdge, mVisIStart)
6804 : : nscoord_MAX;
6805 : }
6806 : }
6807 : void Intersect(nscoord* aVisIStart, nscoord* aVisISize) const {
6808 : nscoord end = *aVisIStart + *aVisISize;
6809 : *aVisIStart = std::max(*aVisIStart, mVisIStart);
6810 : *aVisISize = std::max(std::min(end, mVisIEnd) - *aVisIStart, 0);
6811 : }
6812 : nscoord mVisIStart;
6813 : nscoord mVisIEnd;
6814 : };
6815 :
6816 : ClipEdges Edges() const {
6817 : return ClipEdges(*this, mVisIStartEdge, mVisIEndEdge);
6818 : }
6819 :
6820 : static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) {
6821 : DisplayItemType t = aItem->GetType();
6822 : return (t == DisplayItemType::TYPE_TEXT ||
6823 : t == DisplayItemType::TYPE_SVG_CHAR_CLIP)
6824 : ? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr;
6825 : }
6826 :
6827 : // Lengths measured from the visual inline start and end sides
6828 : // (i.e. left and right respectively in horizontal writing modes,
6829 : // regardless of bidi directionality; top and bottom in vertical modes).
6830 : nscoord mVisIStartEdge;
6831 : nscoord mVisIEndEdge;
6832 0 : // Cached result of mFrame->IsSelected(). Only initialized when needed.
6833 : mutable mozilla::Maybe<bool> mIsFrameSelected;
6834 : };
6835 :
6836 : /**
6837 : * A display item that for webrender to handle SVG
6838 : */
6839 : class nsDisplaySVGWrapper : public nsDisplayWrapList {
6840 : public:
6841 : NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER)
6842 :
6843 : nsDisplaySVGWrapper(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6844 : nsDisplayList* aList);
6845 : #ifdef NS_BUILD_REFCNT_LOGGING
6846 : virtual ~nsDisplaySVGWrapper();
6847 : #endif
6848 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
6849 : LayerManager* aManager,
6850 : const ContainerLayerParameters& aContainerParameters) override;
6851 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
6852 : LayerManager* aManager,
6853 : const ContainerLayerParameters& aParameters) override;
6854 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
6855 :
6856 : bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
6857 : mozilla::wr::IpcResourceUpdateQueue& aResources,
6858 : const StackingContextHelper& aSc,
6859 : mozilla::layers::WebRenderLayerManager* aManager,
6860 : nsDisplayListBuilder* aDisplayListBuilder) override;
6861 : };
6862 :
6863 : namespace mozilla {
6864 :
6865 : class PaintTelemetry
6866 : {
6867 : public:
6868 : enum class Metric {
6869 : DisplayList,
6870 : Layerization,
6871 : Rasterization,
6872 : COUNT,
6873 : };
6874 :
6875 : class AutoRecord
6876 : {
6877 : public:
6878 : explicit AutoRecord(Metric aMetric);
6879 : ~AutoRecord();
6880 :
6881 : TimeStamp GetStart() const {
6882 : return mStart;
6883 : }
6884 : private:
6885 : Metric mMetric;
6886 : mozilla::TimeStamp mStart;
6887 : };
6888 :
6889 : class AutoRecordPaint
6890 : {
6891 : public:
6892 : AutoRecordPaint();
6893 : ~AutoRecordPaint();
6894 : private:
6895 : mozilla::TimeStamp mStart;
6896 : };
6897 :
6898 : private:
6899 : static uint32_t sPaintLevel;
6900 : static uint32_t sMetricLevel;
6901 : static mozilla::EnumeratedArray<Metric, Metric::COUNT, double> sMetrics;
6902 : };
6903 :
6904 : } // namespace mozilla
6905 :
6906 : #endif /*NSDISPLAYLIST_H_*/
|