Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: set ts=2 sw=2 et tw=78:
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 "gfxContext.h"
17 : #include "mozilla/ArenaAllocator.h"
18 : #include "mozilla/Attributes.h"
19 : #include "mozilla/Array.h"
20 : #include "mozilla/DebugOnly.h"
21 : #include "mozilla/EnumSet.h"
22 : #include "mozilla/Maybe.h"
23 : #include "mozilla/TemplateLib.h" // mozilla::tl::Max
24 : #include "nsCOMPtr.h"
25 : #include "nsContainerFrame.h"
26 : #include "nsPoint.h"
27 : #include "nsRect.h"
28 : #include "nsRegion.h"
29 : #include "nsDisplayListInvalidation.h"
30 : #include "DisplayListClipState.h"
31 : #include "LayerState.h"
32 : #include "FrameMetrics.h"
33 : #include "mozilla/EnumeratedArray.h"
34 : #include "mozilla/Maybe.h"
35 : #include "mozilla/UniquePtr.h"
36 : #include "mozilla/TimeStamp.h"
37 : #include "mozilla/gfx/UserData.h"
38 : #include "mozilla/layers/LayerAttributes.h"
39 : #include "nsCSSRenderingBorders.h"
40 :
41 : #include <stdint.h>
42 : #include "nsTHashtable.h"
43 :
44 : #include <stdlib.h>
45 : #include <algorithm>
46 :
47 : class gfxContext;
48 : class nsIContent;
49 : class nsDisplayList;
50 : class nsDisplayTableItem;
51 : class nsISelection;
52 : class nsIScrollableFrame;
53 : class nsDisplayLayerEventRegions;
54 : class nsDisplayScrollInfoLayer;
55 : class nsCaret;
56 :
57 : namespace mozilla {
58 : class FrameLayerBuilder;
59 : namespace layers {
60 : class Layer;
61 : class ImageLayer;
62 : class ImageContainer;
63 : class StackingContextHelper;
64 : class WebRenderCommand;
65 : class WebRenderParentCommand;
66 : class WebRenderDisplayItemLayer;
67 : } // namespace layers
68 : namespace wr {
69 : class DisplayListBuilder;
70 : } // namespace wr
71 : } // namespace mozilla
72 :
73 : // A set of blend modes, that never includes OP_OVER (since it's
74 : // considered the default, rather than a specific blend mode).
75 : typedef mozilla::EnumSet<mozilla::gfx::CompositionOp> BlendModeSet;
76 :
77 : /*
78 : * An nsIFrame can have many different visual parts. For example an image frame
79 : * can have a background, border, and outline, the image itself, and a
80 : * translucent selection overlay. In general these parts can be drawn at
81 : * discontiguous z-levels; see CSS2.1 appendix E:
82 : * http://www.w3.org/TR/CSS21/zindex.html
83 : *
84 : * We construct a display list for a frame tree that contains one item
85 : * for each visual part. The display list is itself a tree since some items
86 : * are containers for other items; however, its structure does not match
87 : * the structure of its source frame tree. The display list items are sorted
88 : * by z-order. A display list can be used to paint the frames, to determine
89 : * which frame is the target of a mouse event, and to determine what areas
90 : * need to be repainted when scrolling. The display lists built for each task
91 : * may be different for efficiency; in particular some frames need special
92 : * display list items only for event handling, and do not create these items
93 : * when the display list will be used for painting (the common case). For
94 : * example, when painting we avoid creating nsDisplayBackground items for
95 : * frames that don't display a visible background, but for event handling
96 : * we need those backgrounds because they are not transparent to events.
97 : *
98 : * We could avoid constructing an explicit display list by traversing the
99 : * frame tree multiple times in clever ways. However, reifying the display list
100 : * reduces code complexity and reduces the number of times each frame must be
101 : * traversed to one, which seems to be good for performance. It also means
102 : * we can share code for painting, event handling and scroll analysis.
103 : *
104 : * Display lists are short-lived; content and frame trees cannot change
105 : * between a display list being created and destroyed. Display lists should
106 : * not be created during reflow because the frame tree may be in an
107 : * inconsistent state (e.g., a frame's stored overflow-area may not include
108 : * the bounds of all its children). However, it should be fine to create
109 : * a display list while a reflow is pending, before it starts.
110 : *
111 : * A display list covers the "extended" frame tree; the display list for a frame
112 : * tree containing FRAME/IFRAME elements can include frames from the subdocuments.
113 : *
114 : * Display item's coordinates are relative to their nearest reference frame ancestor.
115 : * Both the display root and any frame with a transform act as a reference frame
116 : * for their frame subtrees.
117 : */
118 :
119 : // All types are defined in nsDisplayItemTypes.h
120 : #define NS_DISPLAY_DECL_NAME(n, e) \
121 : virtual const char* Name() override { return n; } \
122 : virtual Type GetType() override { return e; }
123 :
124 :
125 : /**
126 : * Represents a frame that is considered to have (or will have) "animated geometry"
127 : * for itself and descendant frames.
128 : *
129 : * For example the scrolled frames of scrollframes which are actively being scrolled
130 : * fall into this category. Frames with certain CSS properties that are being animated
131 : * (e.g. 'left'/'top' etc) are also placed in this category. Frames with different
132 : * active geometry roots are in different PaintedLayers, so that we can animate the
133 : * geometry root by changing its transform (either on the main thread or in the
134 : * compositor).
135 : *
136 : * nsDisplayListBuilder constructs a tree of these (for fast traversals) and assigns
137 : * one for each display item.
138 : *
139 : * The animated geometry root for a display item is required to be a descendant (or
140 : * equal to) the item's ReferenceFrame(), which means that we will fall back to
141 : * returning aItem->ReferenceFrame() when we can't find another animated geometry root.
142 : *
143 : * The animated geometry root isn't strongly defined for a frame as transforms and
144 : * background-attachment:fixed can cause it to vary between display items for a given
145 : * frame.
146 : */
147 : struct AnimatedGeometryRoot
148 : {
149 55 : AnimatedGeometryRoot(nsIFrame* aFrame, AnimatedGeometryRoot* aParent)
150 55 : : mFrame(aFrame)
151 55 : , mParentAGR(aParent)
152 55 : {}
153 :
154 7446 : operator nsIFrame*() { return mFrame; }
155 :
156 2351 : nsIFrame* operator ->() const { return mFrame; }
157 :
158 : void* operator new(size_t aSize,
159 : nsDisplayListBuilder* aBuilder);
160 :
161 : nsIFrame* mFrame;
162 : AnimatedGeometryRoot* mParentAGR;
163 : };
164 :
165 : namespace mozilla {
166 :
167 : /**
168 : * An active scrolled root (ASR) is similar to an animated geometry root (AGR).
169 : * The differences are:
170 : * - ASRs are only created for async-scrollable scroll frames. This is a
171 : * (hopefully) temporary restriction. In the future we will want to create
172 : * ASRs for all the things that are currently creating AGRs, and then
173 : * replace AGRs with ASRs and rename them from "active scrolled root" to
174 : * "animated geometry root".
175 : * - ASR objects are created during display list construction by the nsIFrames
176 : * that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter.
177 : * The current ASR is returned by nsDisplayListBuilder::CurrentActiveScrolledRoot().
178 : * - There is no way to go from an nsIFrame pointer to the ASR of that frame.
179 : * If you need to look up an ASR after display list construction, you need
180 : * to store it while the AutoCurrentActiveScrolledRootSetter that creates it
181 : * is on the stack.
182 : */
183 : struct ActiveScrolledRoot {
184 2 : ActiveScrolledRoot(const ActiveScrolledRoot* aParent,
185 : nsIScrollableFrame* aScrollableFrame)
186 2 : : mParent(aParent)
187 : , mScrollableFrame(aScrollableFrame)
188 2 : , mDepth(mParent ? mParent->mDepth + 1 : 1)
189 : {
190 2 : }
191 :
192 1409 : static const ActiveScrolledRoot* PickAncestor(const ActiveScrolledRoot* aOne,
193 : const ActiveScrolledRoot* aTwo)
194 : {
195 1409 : MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
196 1409 : return Depth(aOne) <= Depth(aTwo) ? aOne : aTwo;
197 : }
198 :
199 2731 : static const ActiveScrolledRoot* PickDescendant(const ActiveScrolledRoot* aOne,
200 : const ActiveScrolledRoot* aTwo)
201 : {
202 2731 : MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
203 2731 : return Depth(aOne) >= Depth(aTwo) ? aOne : aTwo;
204 : }
205 :
206 : static bool IsAncestor(const ActiveScrolledRoot* aAncestor,
207 : const ActiveScrolledRoot* aDescendant);
208 :
209 : static nsCString ToString(const mozilla::ActiveScrolledRoot* aActiveScrolledRoot);
210 :
211 : // Call this when inserting an ancestor.
212 0 : void IncrementDepth() { mDepth++; }
213 :
214 : const ActiveScrolledRoot* mParent;
215 : nsIScrollableFrame* mScrollableFrame;
216 :
217 : private:
218 8328 : static uint32_t Depth(const ActiveScrolledRoot* aActiveScrolledRoot) {
219 8328 : return aActiveScrolledRoot ? aActiveScrolledRoot->mDepth : 0;
220 : }
221 :
222 : uint32_t mDepth;
223 : };
224 :
225 : }
226 :
227 : enum class nsDisplayListBuilderMode : uint8_t {
228 : PAINTING,
229 : EVENT_DELIVERY,
230 : PLUGIN_GEOMETRY,
231 : FRAME_VISIBILITY,
232 : TRANSFORM_COMPUTATION,
233 : GENERATE_GLYPH,
234 : PAINTING_SELECTION_BACKGROUND
235 : };
236 :
237 : /**
238 : * This manages a display list and is passed as a parameter to
239 : * nsIFrame::BuildDisplayList.
240 : * It contains the parameters that don't change from frame to frame and manages
241 : * the display list memory using an arena. It also establishes the reference
242 : * coordinate system for all display list items. Some of the parameters are
243 : * available from the prescontext/presshell, but we copy them into the builder
244 : * for faster/more convenient access.
245 : */
246 : class nsDisplayListBuilder {
247 : typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
248 : typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
249 :
250 : /**
251 : * This manages status of a 3d context to collect visible rects of
252 : * descendants and passing a dirty rect.
253 : *
254 : * Since some transforms maybe singular, passing visible rects or
255 : * the dirty rect level by level from parent to children may get a
256 : * wrong result, being different from the result of appling with
257 : * effective transform directly.
258 : *
259 : * nsFrame::BuildDisplayListForStackingContext() uses
260 : * AutoPreserves3DContext to install an instance on the builder.
261 : *
262 : * \see AutoAccumulateTransform, AutoAccumulateRect,
263 : * AutoPreserves3DContext, Accumulate, GetCurrentTransform,
264 : * StartRoot.
265 : */
266 53 : class Preserves3DContext {
267 : public:
268 : typedef mozilla::gfx::Matrix4x4 Matrix4x4;
269 :
270 53 : Preserves3DContext()
271 53 : : mAccumulatedRectLevels(0)
272 53 : {}
273 0 : Preserves3DContext(const Preserves3DContext &aOther)
274 0 : : mAccumulatedTransform()
275 : , mAccumulatedRect()
276 : , mAccumulatedRectLevels(0)
277 0 : , mDirtyRect(aOther.mDirtyRect) {}
278 :
279 : // Accmulate transforms of ancestors on the preserves-3d chain.
280 : Matrix4x4 mAccumulatedTransform;
281 : // Accmulate visible rect of descendants in the preserves-3d context.
282 : nsRect mAccumulatedRect;
283 : // How far this frame is from the root of the current 3d context.
284 : int mAccumulatedRectLevels;
285 : nsRect mDirtyRect;
286 : };
287 :
288 : /**
289 : * A frame can be in one of three states of AGR.
290 : * AGR_NO means the frame is not an AGR for now.
291 : * AGR_YES means the frame is an AGR for now.
292 : * AGR_MAYBE means the frame is not an AGR for now, but a transition
293 : * to AGR_YES without restyling is possible.
294 : */
295 : enum AGRState { AGR_NO, AGR_YES, AGR_MAYBE };
296 :
297 : public:
298 : typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
299 : typedef mozilla::DisplayItemClip DisplayItemClip;
300 : typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
301 : typedef mozilla::DisplayListClipState DisplayListClipState;
302 : typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
303 : typedef nsIWidget::ThemeGeometry ThemeGeometry;
304 : typedef mozilla::layers::Layer Layer;
305 : typedef mozilla::layers::FrameMetrics FrameMetrics;
306 : typedef mozilla::layers::FrameMetrics::ViewID ViewID;
307 : typedef mozilla::gfx::Matrix4x4 Matrix4x4;
308 :
309 : /**
310 : * @param aReferenceFrame the frame at the root of the subtree; its origin
311 : * is the origin of the reference coordinate system for this display list
312 : * @param aMode encodes what the builder is being used for.
313 : * @param aBuildCaret whether or not we should include the caret in any
314 : * display lists that we make.
315 : */
316 : nsDisplayListBuilder(nsIFrame* aReferenceFrame,
317 : nsDisplayListBuilderMode aMode,
318 : bool aBuildCaret);
319 : ~nsDisplayListBuilder();
320 :
321 0 : void SetWillComputePluginGeometry(bool aWillComputePluginGeometry)
322 : {
323 0 : mWillComputePluginGeometry = aWillComputePluginGeometry;
324 0 : }
325 0 : void SetForPluginGeometry()
326 : {
327 0 : NS_ASSERTION(mMode == nsDisplayListBuilderMode::PAINTING, "Can only switch from PAINTING to PLUGIN_GEOMETRY");
328 0 : NS_ASSERTION(mWillComputePluginGeometry, "Should have signalled this in advance");
329 0 : mMode = nsDisplayListBuilderMode::PLUGIN_GEOMETRY;
330 0 : }
331 :
332 : mozilla::layers::LayerManager* GetWidgetLayerManager(nsView** aView = nullptr);
333 :
334 : /**
335 : * @return true if the display is being built in order to determine which
336 : * frame is under the mouse position.
337 : */
338 4705 : bool IsForEventDelivery()
339 : {
340 4705 : return mMode == nsDisplayListBuilderMode::EVENT_DELIVERY;
341 : }
342 :
343 : /**
344 : * Be careful with this. The display list will be built in PAINTING mode
345 : * first and then switched to PLUGIN_GEOMETRY before a second call to
346 : * ComputeVisibility.
347 : * @return true if the display list is being built to compute geometry
348 : * for plugins.
349 : */
350 349 : bool IsForPluginGeometry()
351 : {
352 349 : return mMode == nsDisplayListBuilderMode::PLUGIN_GEOMETRY;
353 : }
354 :
355 : /**
356 : * @return true if the display list is being built for painting.
357 : */
358 2878 : bool IsForPainting()
359 : {
360 2878 : return mMode == nsDisplayListBuilderMode::PAINTING;
361 : }
362 :
363 : /**
364 : * @return true if the display list is being built for determining frame
365 : * visibility.
366 : */
367 697 : bool IsForFrameVisibility()
368 : {
369 697 : return mMode == nsDisplayListBuilderMode::FRAME_VISIBILITY;
370 : }
371 :
372 : /**
373 : * @return true if the display list is being built for creating the glyph
374 : * mask from text items.
375 : */
376 4775 : bool IsForGenerateGlyphMask()
377 : {
378 4775 : return mMode == nsDisplayListBuilderMode::GENERATE_GLYPH;
379 : }
380 :
381 : /**
382 : * @return true if the display list is being built for painting selection
383 : * background.
384 : */
385 4775 : bool IsForPaintingSelectionBG()
386 : {
387 4775 : return mMode == nsDisplayListBuilderMode::PAINTING_SELECTION_BACKGROUND;
388 : }
389 :
390 74 : bool WillComputePluginGeometry() { return mWillComputePluginGeometry; }
391 : /**
392 : * @return true if "painting is suppressed" during page load and we
393 : * should paint only the background of the document.
394 : */
395 5451 : bool IsBackgroundOnly() {
396 5451 : NS_ASSERTION(mPresShellStates.Length() > 0,
397 : "don't call this if we're not in a presshell");
398 5451 : return CurrentPresShellState()->mIsBackgroundOnly;
399 : }
400 : /**
401 : * @return true if the currently active BuildDisplayList call is being
402 : * applied to a frame at the root of a pseudo stacking context. A pseudo
403 : * stacking context is either a real stacking context or basically what
404 : * CSS2.1 appendix E refers to with "treat the element as if it created
405 : * a new stacking context
406 : */
407 : bool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; }
408 :
409 : /**
410 : * @return the selection that painting should be restricted to (or nullptr
411 : * in the normal unrestricted case)
412 : */
413 3751 : nsISelection* GetBoundingSelection() { return mBoundingSelection; }
414 :
415 : /**
416 : * @return the root of given frame's (sub)tree, whose origin
417 : * establishes the coordinate system for the child display items.
418 : */
419 : const nsIFrame* FindReferenceFrameFor(const nsIFrame *aFrame,
420 : nsPoint* aOffset = nullptr);
421 :
422 : /**
423 : * @return the root of the display list's frame (sub)tree, whose origin
424 : * establishes the coordinate system for the display list
425 : */
426 8186 : nsIFrame* RootReferenceFrame()
427 : {
428 8186 : return mReferenceFrame;
429 : }
430 :
431 : /**
432 : * @return a point pt such that adding pt to a coordinate relative to aFrame
433 : * makes it relative to ReferenceFrame(), i.e., returns
434 : * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
435 : * the appunits of aFrame.
436 : */
437 4559 : const nsPoint ToReferenceFrame(const nsIFrame* aFrame) {
438 4559 : nsPoint result;
439 4559 : FindReferenceFrameFor(aFrame, &result);
440 4559 : return result;
441 : }
442 : /**
443 : * When building the display list, the scrollframe aFrame will be "ignored"
444 : * for the purposes of clipping, and its scrollbars will be hidden. We use
445 : * this to allow RenderOffscreen to render a whole document without beign
446 : * clipped by the viewport or drawing the viewport scrollbars.
447 : */
448 18 : void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
449 : /**
450 : * Get the scrollframe to ignore, if any.
451 : */
452 3762 : nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
453 : /**
454 : * Get the ViewID of the nearest scrolling ancestor frame.
455 : */
456 460 : ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
457 : /**
458 : * Get and set the flag that indicates if scroll parents should have layers
459 : * forcibly created. This flag is set when a deeply nested scrollframe has
460 : * a displayport, and for scroll handoff to work properly the ancestor
461 : * scrollframes should also get their own scrollable layers.
462 : */
463 2 : void ForceLayerForScrollParent() { mForceLayerForScrollParent = true; }
464 : /**
465 : * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
466 : * which we are building display items at the moment.
467 : */
468 0 : ViewID GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget; }
469 0 : uint32_t GetCurrentScrollbarFlags() const { return mCurrentScrollbarFlags; }
470 : /**
471 : * Returns true if building a scrollbar, and the scrollbar will not be
472 : * layerized.
473 : */
474 2125 : bool IsBuildingNonLayerizedScrollbar() const {
475 2125 : return mIsBuildingScrollbar && !mCurrentScrollbarWillHaveLayer;
476 : }
477 : /**
478 : * Calling this setter makes us include all out-of-flow descendant
479 : * frames in the display list, wherever they may be positioned (even
480 : * outside the dirty rects).
481 : */
482 0 : void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
483 4384 : bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
484 : /**
485 : * Calling this setter makes us exclude all leaf frames that aren't
486 : * selected.
487 : */
488 0 : void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
489 4147 : bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
490 : /**
491 : * Calling this setter makes us compute accurate visible regions at the cost
492 : * of performance if regions get very complex.
493 : */
494 0 : void SetAccurateVisibleRegions() { mAccurateVisibleRegions = true; }
495 52 : bool GetAccurateVisibleRegions() { return mAccurateVisibleRegions; }
496 : /**
497 : * @return Returns true if we should include the caret in any display lists
498 : * that we make.
499 : */
500 112 : bool IsBuildingCaret() { return mBuildCaret; }
501 : /**
502 : * Allows callers to selectively override the regular paint suppression checks,
503 : * so that methods like GetFrameForPoint work when painting is suppressed.
504 : */
505 18 : void IgnorePaintSuppression() { mIgnoreSuppression = true; }
506 : /**
507 : * @return Returns if this builder will ignore paint suppression.
508 : */
509 0 : bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
510 : /**
511 : * Call this if we're doing normal painting to the window.
512 : */
513 26 : void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
514 16074 : bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
515 : /**
516 : * Call this to prevent descending into subdocuments.
517 : */
518 0 : void SetDescendIntoSubdocuments(bool aDescend) { mDescendIntoSubdocuments = aDescend; }
519 33 : bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }
520 :
521 : /**
522 : * Get dirty rect relative to current frame (the frame that we're calling
523 : * BuildDisplayList on right now).
524 : */
525 5226 : const nsRect& GetDirtyRect() { return mDirtyRect; }
526 : const nsIFrame* GetCurrentFrame() { return mCurrentFrame; }
527 0 : const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; }
528 2613 : const nsPoint& GetCurrentFrameOffsetToReferenceFrame() { return mCurrentOffsetToReferenceFrame; }
529 : AnimatedGeometryRoot* GetCurrentAnimatedGeometryRoot() {
530 : return mCurrentAGR;
531 : }
532 44 : AnimatedGeometryRoot* GetRootAnimatedGeometryRoot() {
533 44 : return &mRootAGR;
534 : }
535 :
536 : void RecomputeCurrentAnimatedGeometryRoot();
537 :
538 : /**
539 : * Returns true if merging and flattening of display lists should be
540 : * performed while computing visibility.
541 : */
542 : bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; }
543 0 : void SetAllowMergingAndFlattening(bool aAllow) { mAllowMergingAndFlattening = aAllow; }
544 :
545 2167 : nsDisplayLayerEventRegions* GetLayerEventRegions() { return mLayerEventRegions; }
546 785 : void SetLayerEventRegions(nsDisplayLayerEventRegions* aItem)
547 : {
548 785 : mLayerEventRegions = aItem;
549 785 : }
550 : bool IsBuildingLayerEventRegions();
551 : static bool LayerEventRegionsEnabled();
552 2838 : bool IsInsidePointerEventsNoneDoc()
553 : {
554 2838 : return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
555 : }
556 :
557 2125 : bool GetAncestorHasApzAwareEventHandler() { return mAncestorHasApzAwareEventHandler; }
558 72 : void SetAncestorHasApzAwareEventHandler(bool aValue)
559 : {
560 72 : mAncestorHasApzAwareEventHandler = aValue;
561 72 : }
562 :
563 231 : bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; }
564 0 : void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; }
565 :
566 88 : bool SetIsCompositingCheap(bool aCompositingCheap) {
567 88 : bool temp = mIsCompositingCheap;
568 88 : mIsCompositingCheap = aCompositingCheap;
569 88 : return temp;
570 : }
571 0 : bool IsCompositingCheap() const { return mIsCompositingCheap; }
572 : /**
573 : * Display the caret if needed.
574 : */
575 3083 : void DisplayCaret(nsIFrame* aFrame, const nsRect& aDirtyRect,
576 : nsDisplayList* aList) {
577 3083 : nsIFrame* frame = GetCaretFrame();
578 3083 : if (aFrame == frame) {
579 0 : frame->DisplayCaret(this, aDirtyRect, aList);
580 : }
581 3083 : }
582 : /**
583 : * Get the frame that the caret is supposed to draw in.
584 : * If the caret is currently invisible, this will be null.
585 : */
586 3083 : nsIFrame* GetCaretFrame() {
587 3083 : return CurrentPresShellState()->mCaretFrame;
588 : }
589 : /**
590 : * Get the rectangle we're supposed to draw the caret into.
591 : */
592 0 : const nsRect& GetCaretRect() {
593 0 : return CurrentPresShellState()->mCaretRect;
594 : }
595 : /**
596 : * Get the caret associated with the current presshell.
597 : */
598 : nsCaret* GetCaret();
599 : /**
600 : * Notify the display list builder that we're entering a presshell.
601 : * aReferenceFrame should be a frame in the new presshell.
602 : * aPointerEventsNoneDoc should be set to true if the frame generating this
603 : * document is pointer-events:none.
604 : */
605 : void EnterPresShell(nsIFrame* aReferenceFrame,
606 : bool aPointerEventsNoneDoc = false);
607 : /**
608 : * For print-preview documents, we sometimes need to build display items for
609 : * the same frames multiple times in the same presentation, with different
610 : * clipping. Between each such batch of items, call
611 : * ResetMarkedFramesForDisplayList to make sure that the results of
612 : * MarkFramesForDisplayList do not carry over between batches.
613 : */
614 : void ResetMarkedFramesForDisplayList();
615 : /**
616 : * Notify the display list builder that we're leaving a presshell.
617 : */
618 : void LeavePresShell(nsIFrame* aReferenceFrame, nsDisplayList* aPaintedContents);
619 :
620 : /**
621 : * Returns true if we're currently building a display list that's
622 : * directly or indirectly under an nsDisplayTransform.
623 : */
624 1118 : bool IsInTransform() const { return mInTransform; }
625 : /**
626 : * Indicate whether or not we're directly or indirectly under and
627 : * nsDisplayTransform or SVG foreignObject.
628 : */
629 3 : void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }
630 :
631 : /**
632 : * Return true if we're currently building a display list for a
633 : * nested presshell.
634 : */
635 53 : bool IsInSubdocument() { return mPresShellStates.Length() > 1; }
636 :
637 : /**
638 : * Return true if we're currently building a display list for the presshell
639 : * of a chrome document, or if we're building the display list for a popup.
640 : */
641 0 : bool IsInChromeDocumentOrPopup() {
642 0 : return mIsInChromePresContext || mIsBuildingForPopup;
643 : }
644 :
645 : /**
646 : * @return true if images have been set to decode synchronously.
647 : */
648 960 : bool ShouldSyncDecodeImages() { return mSyncDecodeImages; }
649 :
650 : /**
651 : * Indicates whether we should synchronously decode images. If true, we decode
652 : * and draw whatever image data has been loaded. If false, we just draw
653 : * whatever has already been decoded.
654 : */
655 0 : void SetSyncDecodeImages(bool aSyncDecodeImages) {
656 0 : mSyncDecodeImages = aSyncDecodeImages;
657 0 : }
658 :
659 : /**
660 : * Helper method to generate background painting flags based on the
661 : * information available in the display list builder. Currently only
662 : * accounts for mSyncDecodeImages.
663 : */
664 : uint32_t GetBackgroundPaintFlags();
665 :
666 : /**
667 : * Subtracts aRegion from *aVisibleRegion. We avoid letting
668 : * aVisibleRegion become overcomplex by simplifying it if necessary ---
669 : * unless mAccurateVisibleRegions is set, in which case we let it
670 : * get arbitrarily complex.
671 : */
672 : void SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
673 : const nsRegion& aRegion);
674 :
675 : /**
676 : * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
677 : * (which is relative to aDirtyFrame). If the frames have placeholders
678 : * that might not be displayed, we mark the placeholders and their ancestors
679 : * to ensure that display list construction descends into them
680 : * anyway. nsDisplayListBuilder will take care of unmarking them when it is
681 : * destroyed.
682 : */
683 : void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
684 : const nsFrameList& aFrames,
685 : const nsRect& aDirtyRect);
686 : /**
687 : * Mark all child frames that Preserve3D() as needing display.
688 : * Because these frames include transforms set on their parent, dirty rects
689 : * for intermediate frames may be empty, yet child frames could still be visible.
690 : */
691 : void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame);
692 :
693 26 : const nsTArray<ThemeGeometry>& GetThemeGeometries() { return mThemeGeometries; }
694 :
695 : /**
696 : * Returns true if we need to descend into this frame when building
697 : * the display list, even though it doesn't intersect the dirty
698 : * rect, because it may have out-of-flows that do so.
699 : */
700 272 : bool ShouldDescendIntoFrame(nsIFrame* aFrame) const {
701 : return
702 509 : (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
703 509 : GetIncludeAllOutOfFlows();
704 : }
705 :
706 : /**
707 : * Notifies the builder that a particular themed widget exists
708 : * at the given rectangle within the currently built display list.
709 : * For certain appearance values (currently only NS_THEME_TOOLBAR and
710 : * NS_THEME_WINDOW_TITLEBAR) this gets called during every display list
711 : * construction, for every themed widget of the right type within the
712 : * display list, except for themed widgets which are transformed or have
713 : * effects applied to them (e.g. CSS opacity or filters).
714 : *
715 : * @param aWidgetType the -moz-appearance value for the themed widget
716 : * @param aRect the device-pixel rect relative to the widget's displayRoot
717 : * for the themed widget
718 : */
719 0 : void RegisterThemeGeometry(uint8_t aWidgetType,
720 : const mozilla::LayoutDeviceIntRect& aRect) {
721 0 : if (mIsPaintingToWindow) {
722 0 : mThemeGeometries.AppendElement(ThemeGeometry(aWidgetType, aRect));
723 : }
724 0 : }
725 :
726 : /**
727 : * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
728 : * -moz-window-dragging value is |drag|, its border box is added to the
729 : * collected dragging region; if the value is |no-drag|, the border box is
730 : * subtracted from the region; if the value is |default|, that frame does
731 : * not influence the window dragging region.
732 : */
733 : void AdjustWindowDraggingRegion(nsIFrame* aFrame);
734 :
735 : LayoutDeviceIntRegion GetWindowDraggingRegion() const;
736 :
737 : /**
738 : * Allocate memory in our arena. It will only be freed when this display list
739 : * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
740 : * destructors are called as soon as the item is no longer used.
741 : */
742 : void* Allocate(size_t aSize);
743 :
744 : /**
745 : * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
746 : * automatically when the arena goes away.
747 : */
748 : ActiveScrolledRoot* AllocateActiveScrolledRoot(const ActiveScrolledRoot* aParent,
749 : nsIScrollableFrame* aScrollableFrame);
750 :
751 : /**
752 : * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
753 : * up automatically when the arena goes away.
754 : */
755 : const DisplayItemClipChain* AllocateDisplayItemClipChain(const DisplayItemClip& aClip,
756 : const ActiveScrolledRoot* aASR,
757 : const DisplayItemClipChain* aParent);
758 :
759 : /**
760 : * Intersect two clip chains, allocating the new clip chain items in this
761 : * builder's arena. The result is parented to aAncestor, and no intersections
762 : * happen past aAncestor's ASR.
763 : * That means aAncestor has to be living in this builder's arena already.
764 : * aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
765 : * their values are copied into the newly-allocated intersected clip chain
766 : * and this function does not hold on to any pointers to them.
767 : */
768 : const DisplayItemClipChain* CreateClipChainIntersection(const DisplayItemClipChain* aAncestor,
769 : const DisplayItemClipChain* aLeafClip1,
770 : const DisplayItemClipChain* aLeafClip2);
771 :
772 : /**
773 : * Clone the supplied clip chain's chain items into this builder's arena.
774 : */
775 : const DisplayItemClipChain* CopyWholeChain(const DisplayItemClipChain* aClipChain);
776 :
777 : /**
778 : * Only used for containerful root scrolling. This is a workaround.
779 : */
780 0 : void SetActiveScrolledRootForRootScrollframe(const ActiveScrolledRoot* aASR)
781 0 : { mActiveScrolledRootForRootScrollframe = aASR; }
782 0 : const ActiveScrolledRoot* ActiveScrolledRootForRootScrollframe() const
783 0 : { return mActiveScrolledRootForRootScrollframe; }
784 :
785 : /**
786 : * Transfer off main thread animations to the layer. May be called
787 : * with aBuilder and aItem both null, but only if the caller has
788 : * already checked that off main thread animations should be sent to
789 : * the layer. When they are both null, the animations are added to
790 : * the layer as pending animations.
791 : */
792 : static void AddAnimationsAndTransitionsToLayer(Layer* aLayer,
793 : nsDisplayListBuilder* aBuilder,
794 : nsDisplayItem* aItem,
795 : nsIFrame* aFrame,
796 : nsCSSPropertyID aProperty);
797 :
798 : /**
799 : * A helper class to temporarily set the value of
800 : * mIsAtRootOfPseudoStackingContext, and temporarily
801 : * set mCurrentFrame and related state. Also temporarily sets mDirtyRect.
802 : * aDirtyRect is relative to aForChild.
803 : */
804 : class AutoBuildingDisplayList;
805 : friend class AutoBuildingDisplayList;
806 : class AutoBuildingDisplayList {
807 : public:
808 3746 : AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder,
809 : nsIFrame* aForChild,
810 : const nsRect& aDirtyRect, bool aIsRoot)
811 3746 : : mBuilder(aBuilder),
812 3746 : mPrevFrame(aBuilder->mCurrentFrame),
813 3746 : mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame),
814 3746 : mPrevLayerEventRegions(aBuilder->mLayerEventRegions),
815 : mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame),
816 : mPrevDirtyRect(aBuilder->mDirtyRect),
817 3746 : mPrevAGR(aBuilder->mCurrentAGR),
818 3746 : mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext),
819 3746 : mPrevAncestorHasApzAwareEventHandler(aBuilder->mAncestorHasApzAwareEventHandler),
820 26222 : mPrevBuildingInvisibleItems(aBuilder->mBuildingInvisibleItems)
821 : {
822 3746 : if (aForChild->IsTransformed()) {
823 48 : aBuilder->mCurrentOffsetToReferenceFrame = nsPoint();
824 48 : aBuilder->mCurrentReferenceFrame = aForChild;
825 3698 : } else if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
826 2980 : aBuilder->mCurrentOffsetToReferenceFrame += aForChild->GetPosition();
827 : } else {
828 718 : aBuilder->mCurrentReferenceFrame =
829 718 : aBuilder->FindReferenceFrameFor(aForChild,
830 : &aBuilder->mCurrentOffsetToReferenceFrame);
831 : }
832 3746 : mCurrentAGRState = aBuilder->IsAnimatedGeometryRoot(aForChild);
833 3746 : if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
834 3004 : if (mCurrentAGRState == AGR_YES) {
835 2 : aBuilder->mCurrentAGR = aBuilder->WrapAGRForFrame(aForChild, aBuilder->mCurrentAGR);
836 : }
837 742 : } else if (aForChild != aBuilder->mCurrentFrame) {
838 85 : aBuilder->mCurrentAGR = aBuilder->FindAnimatedGeometryRootFor(aForChild);
839 : }
840 3746 : MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(), *aBuilder->mCurrentAGR));
841 3746 : aBuilder->mCurrentFrame = aForChild;
842 3746 : aBuilder->mDirtyRect = aDirtyRect;
843 3746 : aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
844 3746 : }
845 31 : void SetDirtyRect(const nsRect& aRect) {
846 31 : mBuilder->mDirtyRect = aRect;
847 31 : }
848 24 : void SetReferenceFrameAndCurrentOffset(const nsIFrame* aFrame, const nsPoint& aOffset) {
849 24 : mBuilder->mCurrentReferenceFrame = aFrame;
850 24 : mBuilder->mCurrentOffsetToReferenceFrame = aOffset;
851 24 : }
852 : // Return the previous frame's animated geometry root, whether or not the
853 : // current frame is an immediate descendant.
854 : const nsIFrame* GetPrevAnimatedGeometryRoot() const {
855 : return mPrevAnimatedGeometryRoot;
856 : }
857 544 : bool IsAnimatedGeometryRoot() const {
858 544 : return mCurrentAGRState == AGR_YES;
859 : }
860 386 : bool MaybeAnimatedGeometryRoot() const {
861 386 : return mCurrentAGRState == AGR_MAYBE;
862 : }
863 691 : void RestoreBuildingInvisibleItemsValue() {
864 691 : mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
865 691 : }
866 7492 : ~AutoBuildingDisplayList() {
867 3746 : mBuilder->mCurrentFrame = mPrevFrame;
868 3746 : mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
869 3746 : mBuilder->mLayerEventRegions = mPrevLayerEventRegions;
870 3746 : mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
871 3746 : mBuilder->mDirtyRect = mPrevDirtyRect;
872 3746 : mBuilder->mCurrentAGR = mPrevAGR;
873 3746 : mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext;
874 3746 : mBuilder->mAncestorHasApzAwareEventHandler = mPrevAncestorHasApzAwareEventHandler;
875 3746 : mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
876 3746 : }
877 : private:
878 : nsDisplayListBuilder* mBuilder;
879 : AGRState mCurrentAGRState;
880 : const nsIFrame* mPrevFrame;
881 : const nsIFrame* mPrevReferenceFrame;
882 : nsIFrame* mPrevAnimatedGeometryRoot;
883 : nsDisplayLayerEventRegions* mPrevLayerEventRegions;
884 : nsPoint mPrevOffset;
885 : nsRect mPrevDirtyRect;
886 : AnimatedGeometryRoot* mPrevAGR;
887 : bool mPrevIsAtRootOfPseudoStackingContext;
888 : bool mPrevAncestorHasApzAwareEventHandler;
889 : bool mPrevBuildingInvisibleItems;
890 : };
891 :
892 : /**
893 : * A helper class to temporarily set the value of mInTransform.
894 : */
895 : class AutoInTransformSetter;
896 : friend class AutoInTransformSetter;
897 : class AutoInTransformSetter {
898 : public:
899 613 : AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
900 613 : : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
901 613 : aBuilder->mInTransform = aInTransform;
902 613 : }
903 1226 : ~AutoInTransformSetter() {
904 613 : mBuilder->mInTransform = mOldValue;
905 613 : }
906 : private:
907 : nsDisplayListBuilder* mBuilder;
908 : bool mOldValue;
909 : };
910 :
911 : class AutoSaveRestorePerspectiveIndex;
912 : friend class AutoSaveRestorePerspectiveIndex;
913 : class AutoSaveRestorePerspectiveIndex {
914 : public:
915 613 : AutoSaveRestorePerspectiveIndex(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
916 613 : : mBuilder(nullptr)
917 : {
918 613 : if (aFrame->ChildrenHavePerspective()) {
919 0 : mBuilder = aBuilder;
920 0 : mCachedItemIndex = aBuilder->mPerspectiveItemIndex;
921 0 : aBuilder->mPerspectiveItemIndex = 0;
922 : }
923 613 : }
924 :
925 613 : ~AutoSaveRestorePerspectiveIndex()
926 613 : {
927 613 : if (mBuilder) {
928 0 : mBuilder->mPerspectiveItemIndex = mCachedItemIndex;
929 : }
930 613 : }
931 :
932 : private:
933 : nsDisplayListBuilder* mBuilder;
934 : uint32_t mCachedItemIndex;
935 : };
936 :
937 : /**
938 : * A helper class to temporarily set the value of mCurrentScrollParentId.
939 : */
940 : class AutoCurrentScrollParentIdSetter;
941 : friend class AutoCurrentScrollParentIdSetter;
942 : class AutoCurrentScrollParentIdSetter {
943 : public:
944 275 : AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId)
945 275 : : mBuilder(aBuilder)
946 275 : , mOldValue(aBuilder->mCurrentScrollParentId)
947 550 : , mOldForceLayer(aBuilder->mForceLayerForScrollParent) {
948 : // If this AutoCurrentScrollParentIdSetter has the same scrollId as the
949 : // previous one on the stack, then that means the scrollframe that
950 : // created this isn't actually scrollable and cannot participate in
951 : // scroll handoff. We set mCanBeScrollParent to false to indicate this.
952 275 : mCanBeScrollParent = (mOldValue != aScrollId);
953 275 : aBuilder->mCurrentScrollParentId = aScrollId;
954 275 : aBuilder->mForceLayerForScrollParent = false;
955 275 : }
956 462 : bool ShouldForceLayerForScrollParent() const {
957 : // Only scrollframes participating in scroll handoff can be forced to
958 : // layerize
959 462 : return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent;
960 : };
961 550 : ~AutoCurrentScrollParentIdSetter() {
962 275 : mBuilder->mCurrentScrollParentId = mOldValue;
963 275 : if (mCanBeScrollParent) {
964 : // If this flag is set, caller code is responsible for having dealt
965 : // with the current value of mBuilder->mForceLayerForScrollParent, so
966 : // we can just restore the old value.
967 26 : mBuilder->mForceLayerForScrollParent = mOldForceLayer;
968 : } else {
969 : // Otherwise we need to keep propagating the force-layerization flag
970 : // upwards to the next ancestor scrollframe that does participate in
971 : // scroll handoff.
972 249 : mBuilder->mForceLayerForScrollParent |= mOldForceLayer;
973 : }
974 275 : }
975 : private:
976 : nsDisplayListBuilder* mBuilder;
977 : ViewID mOldValue;
978 : bool mOldForceLayer;
979 : bool mCanBeScrollParent;
980 : };
981 :
982 : /**
983 : * Used to update the current active scrolled root on the display list
984 : * builder, and to create new active scrolled roots.
985 : */
986 : class AutoCurrentActiveScrolledRootSetter;
987 : friend class AutoCurrentActiveScrolledRootSetter;
988 : class AutoCurrentActiveScrolledRootSetter {
989 : public:
990 1613 : explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder* aBuilder)
991 1613 : : mBuilder(aBuilder)
992 1613 : , mSavedActiveScrolledRoot(aBuilder->mCurrentActiveScrolledRoot)
993 1613 : , mContentClipASR(aBuilder->ClipState().GetContentClipASR())
994 1613 : , mDescendantsStartIndex(aBuilder->mActiveScrolledRoots.Length())
995 6452 : , mUsed(false)
996 : {
997 1613 : }
998 :
999 1613 : ~AutoCurrentActiveScrolledRootSetter()
1000 1613 : {
1001 1613 : mBuilder->mCurrentActiveScrolledRoot = mSavedActiveScrolledRoot;
1002 1613 : }
1003 :
1004 85 : void SetCurrentActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot)
1005 : {
1006 85 : MOZ_ASSERT(!mUsed);
1007 :
1008 : // Set the builder's mCurrentActiveScrolledRoot.
1009 85 : mBuilder->mCurrentActiveScrolledRoot = aActiveScrolledRoot;
1010 :
1011 : // We also need to adjust the builder's mCurrentContainerASR.
1012 : // mCurrentContainerASR needs to be an ASR that all the container's
1013 : // contents have finite bounds with respect to. If aActiveScrolledRoot
1014 : // is an ancestor ASR of mCurrentContainerASR, that means we need to
1015 : // set mCurrentContainerASR to aActiveScrolledRoot, because otherwise
1016 : // the items that will be created with aActiveScrolledRoot wouldn't
1017 : // have finite bounds with respect to mCurrentContainerASR. There's one
1018 : // exception, in the case where there's a content clip on the builder
1019 : // that is scrolled by a descendant ASR of aActiveScrolledRoot. This
1020 : // content clip will clip all items that are created while this
1021 : // AutoCurrentActiveScrolledRootSetter exists. This means that the items
1022 : // created during our lifetime will have finite bounds with respect to
1023 : // the content clip's ASR, even if the items' actual ASR is an ancestor
1024 : // of that. And it also means that mCurrentContainerASR only needs to be
1025 : // set to the content clip's ASR and not all the way to aActiveScrolledRoot.
1026 : // This case is tested by fixed-pos-scrolled-clip-opacity-layerize.html
1027 : // and fixed-pos-scrolled-clip-opacity-inside-layerize.html.
1028 :
1029 : // finiteBoundsASR is the leafmost ASR that all items created during
1030 : // object's lifetime have finite bounds with respect to.
1031 85 : const ActiveScrolledRoot* finiteBoundsASR = ActiveScrolledRoot::PickDescendant(
1032 85 : mContentClipASR, aActiveScrolledRoot);
1033 :
1034 : // mCurrentContainerASR is adjusted so that it's still an ancestor of
1035 : // finiteBoundsASR.
1036 170 : mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
1037 85 : mBuilder->mCurrentContainerASR, finiteBoundsASR);
1038 :
1039 85 : mUsed = true;
1040 85 : }
1041 :
1042 2 : void EnterScrollFrame(nsIScrollableFrame* aScrollableFrame)
1043 : {
1044 2 : MOZ_ASSERT(!mUsed);
1045 2 : ActiveScrolledRoot* asr = mBuilder->AllocateActiveScrolledRoot(
1046 4 : mBuilder->mCurrentActiveScrolledRoot, aScrollableFrame);
1047 2 : mBuilder->mCurrentActiveScrolledRoot = asr;
1048 2 : mUsed = true;
1049 2 : }
1050 :
1051 : void InsertScrollFrame(nsIScrollableFrame* aScrollableFrame);
1052 :
1053 : private:
1054 : nsDisplayListBuilder* mBuilder;
1055 : /**
1056 : * The builder's mCurrentActiveScrolledRoot at construction time which
1057 : * needs to be restored at destruction time.
1058 : */
1059 : const ActiveScrolledRoot* mSavedActiveScrolledRoot;
1060 : /**
1061 : * If there's a content clip on the builder at construction time, then
1062 : * mContentClipASR is that content clip's ASR, otherwise null. The
1063 : * assumption is that the content clip doesn't get relaxed while this
1064 : * object is on the stack.
1065 : */
1066 : const ActiveScrolledRoot* mContentClipASR;
1067 : /**
1068 : * InsertScrollFrame needs to mutate existing ASRs (those that were
1069 : * created while this object was on the stack), and mDescendantsStartIndex
1070 : * makes it easier to skip ASRs that were created in the past.
1071 : */
1072 : size_t mDescendantsStartIndex;
1073 : /**
1074 : * Flag to make sure that only one of SetCurrentActiveScrolledRoot /
1075 : * EnterScrollFrame / InsertScrollFrame is called per instance of this
1076 : * class.
1077 : */
1078 : bool mUsed;
1079 : };
1080 :
1081 : /**
1082 : * Keeps track of the innermost ASR that can be used as the ASR for a
1083 : * container item that wraps all items that were created while this
1084 : * object was on the stack.
1085 : * The rule is: all child items of the container item need to have
1086 : * clipped bounds with respect to the container ASR.
1087 : */
1088 : class AutoContainerASRTracker;
1089 : friend class AutoContainerASRTracker;
1090 : class AutoContainerASRTracker {
1091 : public:
1092 1324 : explicit AutoContainerASRTracker(nsDisplayListBuilder* aBuilder)
1093 1324 : : mBuilder(aBuilder)
1094 1324 : , mSavedContainerASR(aBuilder->mCurrentContainerASR)
1095 : {
1096 3972 : mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickDescendant(
1097 1324 : mBuilder->ClipState().GetContentClipASR(),
1098 1324 : mBuilder->mCurrentActiveScrolledRoot);
1099 1324 : }
1100 :
1101 1304 : const ActiveScrolledRoot* GetContainerASR()
1102 : {
1103 1304 : return mBuilder->mCurrentContainerASR;
1104 : }
1105 :
1106 1324 : ~AutoContainerASRTracker()
1107 1324 : {
1108 2648 : mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
1109 1324 : mBuilder->mCurrentContainerASR, mSavedContainerASR);
1110 1324 : }
1111 :
1112 : private:
1113 : nsDisplayListBuilder* mBuilder;
1114 : const ActiveScrolledRoot* mSavedContainerASR;
1115 : };
1116 :
1117 : /**
1118 : * A helper class to temporarily set the value of mCurrentScrollbarTarget
1119 : * and mCurrentScrollbarFlags.
1120 : */
1121 : class AutoCurrentScrollbarInfoSetter;
1122 : friend class AutoCurrentScrollbarInfoSetter;
1123 : class AutoCurrentScrollbarInfoSetter {
1124 : public:
1125 6 : AutoCurrentScrollbarInfoSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollTargetID,
1126 : uint32_t aScrollbarFlags, bool aWillHaveLayer)
1127 6 : : mBuilder(aBuilder) {
1128 6 : aBuilder->mIsBuildingScrollbar = true;
1129 6 : aBuilder->mCurrentScrollbarTarget = aScrollTargetID;
1130 6 : aBuilder->mCurrentScrollbarFlags = aScrollbarFlags;
1131 6 : aBuilder->mCurrentScrollbarWillHaveLayer = aWillHaveLayer;
1132 6 : }
1133 12 : ~AutoCurrentScrollbarInfoSetter() {
1134 : // No need to restore old values because scrollbars cannot be nested.
1135 6 : mBuilder->mIsBuildingScrollbar = false;
1136 6 : mBuilder->mCurrentScrollbarTarget = FrameMetrics::NULL_SCROLL_ID;
1137 6 : mBuilder->mCurrentScrollbarFlags = 0;
1138 6 : mBuilder->mCurrentScrollbarWillHaveLayer = false;
1139 6 : }
1140 : private:
1141 : nsDisplayListBuilder* mBuilder;
1142 : };
1143 :
1144 : /**
1145 : * A helper class to track current effective transform for items.
1146 : *
1147 : * For frames that is Combines3DTransformWithAncestors(), we need to
1148 : * apply all transforms of ancestors on the same preserves3D chain
1149 : * on the bounds of current frame to the coordination of the 3D
1150 : * context root. The 3D context root computes it's bounds from
1151 : * these transformed bounds.
1152 : */
1153 : class AutoAccumulateTransform;
1154 : friend class AutoAccumulateTransform;
1155 : class AutoAccumulateTransform {
1156 : public:
1157 : typedef mozilla::gfx::Matrix4x4 Matrix4x4;
1158 :
1159 0 : explicit AutoAccumulateTransform(nsDisplayListBuilder* aBuilder)
1160 0 : : mBuilder(aBuilder)
1161 0 : , mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform) {}
1162 :
1163 0 : ~AutoAccumulateTransform() {
1164 0 : mBuilder->mPreserves3DCtx.mAccumulatedTransform = mSavedTransform;
1165 0 : }
1166 :
1167 0 : void Accumulate(const Matrix4x4& aTransform) {
1168 0 : mBuilder->mPreserves3DCtx.mAccumulatedTransform =
1169 0 : aTransform * mBuilder->mPreserves3DCtx.mAccumulatedTransform;
1170 0 : }
1171 :
1172 0 : const Matrix4x4& GetCurrentTransform() {
1173 0 : return mBuilder->mPreserves3DCtx.mAccumulatedTransform;
1174 : }
1175 :
1176 0 : void StartRoot() {
1177 0 : mBuilder->mPreserves3DCtx.mAccumulatedTransform = Matrix4x4();
1178 0 : }
1179 :
1180 : private:
1181 : nsDisplayListBuilder* mBuilder;
1182 : Matrix4x4 mSavedTransform;
1183 : };
1184 :
1185 : /**
1186 : * A helper class to collect bounds rects of descendants.
1187 : *
1188 : * For a 3D context root, it's bounds is computed from the bounds of
1189 : * descendants. If we transform bounds frame by frame applying
1190 : * transforms, the bounds may turn to empty for any singular
1191 : * transform on the path, but it is not empty for the accumulated
1192 : * transform.
1193 : */
1194 : class AutoAccumulateRect;
1195 : friend class AutoAccumulateRect;
1196 : class AutoAccumulateRect {
1197 : public:
1198 0 : explicit AutoAccumulateRect(nsDisplayListBuilder* aBuilder)
1199 0 : : mBuilder(aBuilder)
1200 0 : , mSavedRect(aBuilder->mPreserves3DCtx.mAccumulatedRect) {
1201 0 : aBuilder->mPreserves3DCtx.mAccumulatedRect = nsRect();
1202 0 : aBuilder->mPreserves3DCtx.mAccumulatedRectLevels++;
1203 0 : }
1204 0 : ~AutoAccumulateRect() {
1205 0 : mBuilder->mPreserves3DCtx.mAccumulatedRect = mSavedRect;
1206 0 : mBuilder->mPreserves3DCtx.mAccumulatedRectLevels--;
1207 0 : }
1208 :
1209 : private:
1210 : nsDisplayListBuilder* mBuilder;
1211 : nsRect mSavedRect;
1212 : };
1213 :
1214 0 : void AccumulateRect(const nsRect& aRect) {
1215 0 : mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect, aRect);
1216 0 : }
1217 0 : const nsRect& GetAccumulatedRect() {
1218 0 : return mPreserves3DCtx.mAccumulatedRect;
1219 : }
1220 : /**
1221 : * The level is increased by one for items establishing 3D rendering
1222 : * context and starting a new accumulation.
1223 : */
1224 : int GetAccumulatedRectLevels() {
1225 : return mPreserves3DCtx.mAccumulatedRectLevels;
1226 : }
1227 :
1228 : // Helpers for tables
1229 0 : nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
1230 0 : void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
1231 :
1232 138 : struct OutOfFlowDisplayData {
1233 138 : OutOfFlowDisplayData(const DisplayItemClipChain* aContainingBlockClipChain,
1234 : const DisplayItemClipChain* aCombinedClipChain,
1235 : const ActiveScrolledRoot* aContainingBlockActiveScrolledRoot,
1236 : const nsRect &aDirtyRect)
1237 138 : : mContainingBlockClipChain(aContainingBlockClipChain)
1238 : , mCombinedClipChain(aCombinedClipChain)
1239 : , mContainingBlockActiveScrolledRoot(aContainingBlockActiveScrolledRoot)
1240 138 : , mDirtyRect(aDirtyRect)
1241 138 : {}
1242 : const DisplayItemClipChain* mContainingBlockClipChain;
1243 : const DisplayItemClipChain* mCombinedClipChain; // only necessary for the special case of top layer
1244 : const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot;
1245 : nsRect mDirtyRect;
1246 : };
1247 :
1248 282 : NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty,
1249 : OutOfFlowDisplayData)
1250 :
1251 85 : static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame)
1252 : {
1253 85 : return aFrame->GetProperty(OutOfFlowDisplayDataProperty());
1254 : }
1255 :
1256 0 : nsPresContext* CurrentPresContext() {
1257 0 : return CurrentPresShellState()->mPresShell->GetPresContext();
1258 : }
1259 :
1260 0 : OutOfFlowDisplayData* GetCurrentFixedBackgroundDisplayData()
1261 : {
1262 0 : auto& displayData = CurrentPresShellState()->mFixedBackgroundDisplayData;
1263 0 : return displayData ? displayData.ptr() : nullptr;
1264 : }
1265 :
1266 : /**
1267 : * Accumulates the bounds of box frames that have moz-appearance
1268 : * -moz-win-exclude-glass style. Used in setting glass margins on
1269 : * Windows.
1270 : *
1271 : * We set the window opaque region (from which glass margins are computed)
1272 : * to the intersection of the glass region specified here and the opaque
1273 : * region computed during painting. So the excluded glass region actually
1274 : * *limits* the extent of the opaque area reported to Windows. We limit it
1275 : * so that changes to the computed opaque region (which can vary based on
1276 : * region optimizations and the placement of UI elements) outside the
1277 : * -moz-win-exclude-glass area don't affect the glass margins reported to
1278 : * Windows; changing those margins willy-nilly can cause the Windows 7 glass
1279 : * haze effect to jump around disconcertingly.
1280 : */
1281 0 : void AddWindowExcludeGlassRegion(const nsRegion& bounds) {
1282 0 : mWindowExcludeGlassRegion.Or(mWindowExcludeGlassRegion, bounds);
1283 0 : }
1284 26 : const nsRegion& GetWindowExcludeGlassRegion() {
1285 26 : return mWindowExcludeGlassRegion;
1286 : }
1287 : /**
1288 : * Accumulates opaque stuff into the window opaque region.
1289 : */
1290 172 : void AddWindowOpaqueRegion(const nsRegion& bounds) {
1291 172 : mWindowOpaqueRegion.Or(mWindowOpaqueRegion, bounds);
1292 172 : }
1293 : /**
1294 : * Returns the window opaque region built so far. This may be incomplete
1295 : * since the opaque region is built during layer construction.
1296 : */
1297 31 : const nsRegion& GetWindowOpaqueRegion() {
1298 31 : return mWindowOpaqueRegion;
1299 : }
1300 0 : void SetGlassDisplayItem(nsDisplayItem* aItem) {
1301 0 : if (mGlassDisplayItem) {
1302 : // Web pages or extensions could trigger this by using
1303 : // -moz-appearance:win-borderless-glass etc on their own elements.
1304 : // Keep the first one, since that will be the background of the root
1305 : // window
1306 0 : NS_WARNING("Multiple glass backgrounds found?");
1307 : } else {
1308 0 : mGlassDisplayItem = aItem;
1309 : }
1310 0 : }
1311 : bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem);
1312 :
1313 0 : void SetContainsPluginItem() { mContainsPluginItem = true; }
1314 0 : bool ContainsPluginItem() { return mContainsPluginItem; }
1315 :
1316 : /**
1317 : * mContainsBlendMode is true if we processed a display item that
1318 : * has a blend mode attached. We do this so we can insert a
1319 : * nsDisplayBlendContainer in the parent stacking context.
1320 : */
1321 1226 : void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; }
1322 1226 : bool ContainsBlendMode() const { return mContainsBlendMode; }
1323 :
1324 0 : uint32_t AllocatePerspectiveItemIndex() { return mPerspectiveItemIndex++; }
1325 :
1326 16487 : DisplayListClipState& ClipState() { return mClipState; }
1327 6973 : const ActiveScrolledRoot* CurrentActiveScrolledRoot() { return mCurrentActiveScrolledRoot; }
1328 : const ActiveScrolledRoot* CurrentAncestorASRStackingContextContents() { return mCurrentContainerASR; }
1329 :
1330 : /**
1331 : * Add the current frame to the will-change budget if possible and
1332 : * remeber the outcome. Subsequent calls to IsInWillChangeBudget
1333 : * will return the same value as return here.
1334 : */
1335 : bool AddToWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
1336 :
1337 : /**
1338 : * This will add the current frame to the will-change budget the first
1339 : * time it is seen. On subsequent calls this will return the same
1340 : * answer. This effectively implements a first-come, first-served
1341 : * allocation of the will-change budget.
1342 : */
1343 : bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
1344 :
1345 : void EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage);
1346 : void ExitSVGEffectsContents();
1347 :
1348 : /**
1349 : * Note: if changing the conditions under which scroll info layers
1350 : * are created, make a corresponding change to
1351 : * ScrollFrameWillBuildScrollInfoLayer() in nsSliderFrame.cpp.
1352 : */
1353 2 : bool ShouldBuildScrollInfoItemsForHoisting() const
1354 2 : { return mSVGEffectsBuildingDepth > 0; }
1355 :
1356 : void AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem);
1357 :
1358 : /**
1359 : * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
1360 : *
1361 : * mPreserves3DCtx is used by class AutoAccumulateTransform &
1362 : * AutoAccumulateRect to passing data between frames in the 3D
1363 : * context. If a frame create a new 3D context, it should restore
1364 : * the value of mPreserves3DCtx before returning back to the parent.
1365 : * This class do it for the users.
1366 : */
1367 : class AutoPreserves3DContext;
1368 : friend class AutoPreserves3DContext;
1369 : class AutoPreserves3DContext {
1370 : public:
1371 0 : explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder)
1372 0 : : mBuilder(aBuilder)
1373 0 : , mSavedCtx(aBuilder->mPreserves3DCtx) {}
1374 0 : ~AutoPreserves3DContext() {
1375 0 : mBuilder->mPreserves3DCtx = mSavedCtx;
1376 0 : }
1377 :
1378 : private:
1379 : nsDisplayListBuilder* mBuilder;
1380 : Preserves3DContext mSavedCtx;
1381 : };
1382 :
1383 0 : const nsRect GetPreserves3DDirtyRect(const nsIFrame *aFrame) const {
1384 0 : return mPreserves3DCtx.mDirtyRect;
1385 : }
1386 0 : void SetPreserves3DDirtyRect(const nsRect &aDirtyRect) {
1387 0 : mPreserves3DCtx.mDirtyRect = aDirtyRect;
1388 0 : }
1389 :
1390 2589 : bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems; }
1391 85 : void SetBuildingInvisibleItems(bool aBuildingInvisibleItems) {
1392 85 : mBuildingInvisibleItems = aBuildingInvisibleItems;
1393 85 : }
1394 :
1395 : /**
1396 : * This is a convenience function to ease the transition until AGRs and ASRs
1397 : * are unified.
1398 : */
1399 : AnimatedGeometryRoot* AnimatedGeometryRootForASR(const ActiveScrolledRoot* aASR);
1400 :
1401 171 : bool HitTestShouldStopAtFirstOpaque() const {
1402 171 : return mHitTestShouldStopAtFirstOpaque;
1403 : }
1404 9 : void SetHitTestShouldStopAtFirstOpaque(bool aHitTestShouldStopAtFirstOpaque) {
1405 9 : mHitTestShouldStopAtFirstOpaque = aHitTestShouldStopAtFirstOpaque;
1406 9 : }
1407 :
1408 : private:
1409 : void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
1410 : const nsRect& aDirtyRect);
1411 :
1412 : /**
1413 : * Returns whether a frame acts as an animated geometry root, optionally
1414 : * returning the next ancestor to check.
1415 : */
1416 : AGRState IsAnimatedGeometryRoot(nsIFrame* aFrame,
1417 : nsIFrame** aParent = nullptr);
1418 :
1419 : /**
1420 : * Returns the nearest ancestor frame to aFrame that is considered to have
1421 : * (or will have) animated geometry. This can return aFrame.
1422 : */
1423 : nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame);
1424 :
1425 : friend class nsDisplayCanvasBackgroundImage;
1426 : friend class nsDisplayBackgroundImage;
1427 : friend class nsDisplayFixedPosition;
1428 : AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsDisplayItem* aItem);
1429 :
1430 : friend class nsDisplayItem;
1431 : friend class nsDisplayOwnLayer;
1432 : AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsIFrame* aFrame);
1433 :
1434 : AnimatedGeometryRoot* WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
1435 : AnimatedGeometryRoot* aParent = nullptr);
1436 :
1437 : nsDataHashtable<nsPtrHashKey<nsIFrame>, AnimatedGeometryRoot*> mFrameToAnimatedGeometryRootMap;
1438 :
1439 : /**
1440 : * Add the current frame to the AGR budget if possible and remember
1441 : * the outcome. Subsequent calls will return the same value as
1442 : * returned here.
1443 : */
1444 : bool AddToAGRBudget(nsIFrame* aFrame);
1445 :
1446 106 : struct PresShellState {
1447 : nsIPresShell* mPresShell;
1448 : nsIFrame* mCaretFrame;
1449 : nsRect mCaretRect;
1450 : mozilla::Maybe<OutOfFlowDisplayData> mFixedBackgroundDisplayData;
1451 : uint32_t mFirstFrameMarkedForDisplay;
1452 : bool mIsBackgroundOnly;
1453 : // This is a per-document flag turning off event handling for all content
1454 : // in the document, and is set when we enter a subdocument for a pointer-
1455 : // events:none frame.
1456 : bool mInsidePointerEventsNoneDoc;
1457 : };
1458 :
1459 11639 : PresShellState* CurrentPresShellState() {
1460 11639 : NS_ASSERTION(mPresShellStates.Length() > 0,
1461 : "Someone forgot to enter a presshell");
1462 11639 : return &mPresShellStates[mPresShellStates.Length() - 1];
1463 : }
1464 :
1465 : struct DocumentWillChangeBudget {
1466 0 : DocumentWillChangeBudget()
1467 0 : : mBudget(0)
1468 0 : {}
1469 :
1470 : uint32_t mBudget;
1471 : };
1472 :
1473 : nsIFrame* const mReferenceFrame;
1474 : nsIFrame* mIgnoreScrollFrame;
1475 : nsDisplayLayerEventRegions* mLayerEventRegions;
1476 :
1477 : static const size_t kArenaAlignment =
1478 : mozilla::tl::Max<NS_ALIGNMENT_OF(void*), NS_ALIGNMENT_OF(double)>::value;
1479 : mozilla::ArenaAllocator<4096, kArenaAlignment> mPool;
1480 :
1481 : nsCOMPtr<nsISelection> mBoundingSelection;
1482 : AutoTArray<PresShellState,8> mPresShellStates;
1483 : AutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
1484 : AutoTArray<ThemeGeometry,2> mThemeGeometries;
1485 : nsDisplayTableItem* mCurrentTableItem;
1486 : DisplayListClipState mClipState;
1487 : const ActiveScrolledRoot* mCurrentActiveScrolledRoot;
1488 : const ActiveScrolledRoot* mCurrentContainerASR;
1489 : // mCurrentFrame is the frame that we're currently calling (or about to call)
1490 : // BuildDisplayList on.
1491 : const nsIFrame* mCurrentFrame;
1492 : // The reference frame for mCurrentFrame.
1493 : const nsIFrame* mCurrentReferenceFrame;
1494 : // The offset from mCurrentFrame to mCurrentReferenceFrame.
1495 : nsPoint mCurrentOffsetToReferenceFrame;
1496 :
1497 : AnimatedGeometryRoot* mCurrentAGR;
1498 : AnimatedGeometryRoot mRootAGR;
1499 :
1500 : // will-change budget tracker
1501 : nsDataHashtable<nsPtrHashKey<nsPresContext>, DocumentWillChangeBudget>
1502 : mWillChangeBudget;
1503 :
1504 : // Any frame listed in this set is already counted in the budget
1505 : // and thus is in-budget.
1506 : nsTHashtable<nsPtrHashKey<nsIFrame> > mWillChangeBudgetSet;
1507 :
1508 : // Area of animated geometry root budget already allocated
1509 : uint32_t mUsedAGRBudget;
1510 : // Set of frames already counted in budget
1511 : nsTHashtable<nsPtrHashKey<nsIFrame> > mAGRBudgetSet;
1512 :
1513 : // Relative to mCurrentFrame.
1514 : nsRect mDirtyRect;
1515 : nsRegion mWindowExcludeGlassRegion;
1516 : nsRegion mWindowOpaqueRegion;
1517 : LayoutDeviceIntRegion mWindowDraggingRegion;
1518 : LayoutDeviceIntRegion mWindowNoDraggingRegion;
1519 : // The display item for the Windows window glass background, if any
1520 : nsDisplayItem* mGlassDisplayItem;
1521 : // A temporary list that we append scroll info items to while building
1522 : // display items for the contents of frames with SVG effects.
1523 : // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
1524 : // This is a pointer and not a real nsDisplayList value because the
1525 : // nsDisplayList class is defined below this class, so we can't use it here.
1526 : nsDisplayList* mScrollInfoItemsForHoisting;
1527 : nsTArray<ActiveScrolledRoot*> mActiveScrolledRoots;
1528 : nsTArray<DisplayItemClipChain*> mClipChainsToDestroy;
1529 : const ActiveScrolledRoot* mActiveScrolledRootForRootScrollframe;
1530 : nsDisplayListBuilderMode mMode;
1531 : ViewID mCurrentScrollParentId;
1532 : ViewID mCurrentScrollbarTarget;
1533 : uint32_t mCurrentScrollbarFlags;
1534 : Preserves3DContext mPreserves3DCtx;
1535 : uint32_t mPerspectiveItemIndex;
1536 : int32_t mSVGEffectsBuildingDepth;
1537 : bool mContainsBlendMode;
1538 : bool mIsBuildingScrollbar;
1539 : bool mCurrentScrollbarWillHaveLayer;
1540 : bool mBuildCaret;
1541 : bool mIgnoreSuppression;
1542 : bool mIsAtRootOfPseudoStackingContext;
1543 : bool mIncludeAllOutOfFlows;
1544 : bool mDescendIntoSubdocuments;
1545 : bool mSelectedFramesOnly;
1546 : bool mAccurateVisibleRegions;
1547 : bool mAllowMergingAndFlattening;
1548 : bool mWillComputePluginGeometry;
1549 : // True when we're building a display list that's directly or indirectly
1550 : // under an nsDisplayTransform
1551 : bool mInTransform;
1552 : bool mIsInChromePresContext;
1553 : bool mSyncDecodeImages;
1554 : bool mIsPaintingToWindow;
1555 : bool mIsCompositingCheap;
1556 : bool mContainsPluginItem;
1557 : bool mAncestorHasApzAwareEventHandler;
1558 : // True when the first async-scrollable scroll frame for which we build a
1559 : // display list has a display port. An async-scrollable scroll frame is one
1560 : // which WantsAsyncScroll().
1561 : bool mHaveScrollableDisplayPort;
1562 : bool mWindowDraggingAllowed;
1563 : bool mIsBuildingForPopup;
1564 : bool mForceLayerForScrollParent;
1565 : bool mAsyncPanZoomEnabled;
1566 : bool mBuildingInvisibleItems;
1567 : bool mHitTestShouldStopAtFirstOpaque;
1568 : };
1569 :
1570 : class nsDisplayItem;
1571 : class nsDisplayList;
1572 : /**
1573 : * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
1574 : * nsDisplayItemLink holds the link. The lists are linked from lowest to
1575 : * highest in z-order.
1576 : */
1577 : class nsDisplayItemLink {
1578 : // This is never instantiated directly, so no need to count constructors and
1579 : // destructors.
1580 : protected:
1581 27915 : nsDisplayItemLink() : mAbove(nullptr) {}
1582 : nsDisplayItem* mAbove;
1583 :
1584 : friend class nsDisplayList;
1585 : };
1586 :
1587 : /**
1588 : * This is the unit of rendering and event testing. Each instance of this
1589 : * class represents an entity that can be drawn on the screen, e.g., a
1590 : * frame's CSS background, or a frame's text string.
1591 : *
1592 : * nsDisplayItems can be containers --- i.e., they can perform hit testing
1593 : * and painting by recursively traversing a list of child items.
1594 : *
1595 : * These are arena-allocated during display list construction. A typical
1596 : * subclass would just have a frame pointer, so its object would be just three
1597 : * pointers (vtable, next-item, frame).
1598 : *
1599 : * Display items belong to a list at all times (except temporarily as they
1600 : * move from one list to another).
1601 : */
1602 : class nsDisplayItem : public nsDisplayItemLink {
1603 : public:
1604 : typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
1605 : typedef mozilla::DisplayItemClip DisplayItemClip;
1606 : typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
1607 : typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
1608 : typedef mozilla::layers::FrameMetrics FrameMetrics;
1609 : typedef mozilla::layers::ScrollMetadata ScrollMetadata;
1610 : typedef mozilla::layers::FrameMetrics::ViewID ViewID;
1611 : typedef mozilla::layers::Layer Layer;
1612 : typedef mozilla::layers::LayerManager LayerManager;
1613 : typedef mozilla::layers::StackingContextHelper StackingContextHelper;
1614 : typedef mozilla::layers::WebRenderCommand WebRenderCommand;
1615 : typedef mozilla::layers::WebRenderParentCommand WebRenderParentCommand;
1616 : typedef mozilla::layers::WebRenderDisplayItemLayer WebRenderDisplayItemLayer;
1617 : typedef mozilla::LayerState LayerState;
1618 : typedef mozilla::image::imgDrawingParams imgDrawingParams;
1619 : typedef mozilla::image::DrawResult DrawResult;
1620 : typedef class mozilla::gfx::DrawTarget DrawTarget;
1621 :
1622 : // This is never instantiated directly (it has pure virtual methods), so no
1623 : // need to count constructors and destructors.
1624 : nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
1625 : nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1626 : const ActiveScrolledRoot* aActiveScrolledRoot);
1627 : /**
1628 : * This constructor is only used in rare cases when we need to construct
1629 : * temporary items.
1630 : */
1631 0 : explicit nsDisplayItem(nsIFrame* aFrame)
1632 0 : : mFrame(aFrame)
1633 : , mClipChain(nullptr)
1634 : , mClip(nullptr)
1635 : , mActiveScrolledRoot(nullptr)
1636 : , mReferenceFrame(nullptr)
1637 : , mAnimatedGeometryRoot(nullptr)
1638 : , mForceNotVisible(false)
1639 : #ifdef MOZ_DUMP_PAINTING
1640 0 : , mPainted(false)
1641 : #endif
1642 : {
1643 0 : }
1644 2589 : virtual ~nsDisplayItem() {}
1645 :
1646 2565 : void* operator new(size_t aSize,
1647 : nsDisplayListBuilder* aBuilder) {
1648 2565 : return aBuilder->Allocate(aSize);
1649 : }
1650 :
1651 : // Contains all the type integers for each display list item type
1652 : #include "nsDisplayItemTypes.h"
1653 :
1654 : struct HitTestState {
1655 9 : explicit HitTestState() : mInPreserves3D(false) {}
1656 :
1657 18 : ~HitTestState() {
1658 9 : NS_ASSERTION(mItemBuffer.Length() == 0,
1659 : "mItemBuffer should have been cleared");
1660 9 : }
1661 :
1662 : // Handling transform items for preserve 3D frames.
1663 : bool mInPreserves3D;
1664 : AutoTArray<nsDisplayItem*, 100> mItemBuffer;
1665 : };
1666 :
1667 : /**
1668 : * Some consecutive items should be rendered together as a unit, e.g.,
1669 : * outlines for the same element. For this, we need a way for items to
1670 : * identify their type. We use the type for other purposes too.
1671 : */
1672 : virtual Type GetType() = 0;
1673 : /**
1674 : * Pairing this with the GetUnderlyingFrame() pointer gives a key that
1675 : * uniquely identifies this display item in the display item tree.
1676 : * XXX check nsOptionEventGrabberWrapper/nsXULEventRedirectorWrapper
1677 : */
1678 6715 : virtual uint32_t GetPerFrameKey() { return uint32_t(GetType()); }
1679 : /**
1680 : * This is called after we've constructed a display list for event handling.
1681 : * When this is called, we've already ensured that aRect intersects the
1682 : * item's bounds and that clipping has been taking into account.
1683 : *
1684 : * @param aRect the point or rect being tested, relative to the reference
1685 : * frame. If the width and height are both 1 app unit, it indicates we're
1686 : * hit testing a point, not a rect.
1687 : * @param aState must point to a HitTestState. If you don't have one,
1688 : * just create one with the default constructor and pass it in.
1689 : * @param aOutFrames each item appends the frame(s) in this display item that
1690 : * the rect is considered over (if any) to aOutFrames.
1691 : */
1692 9 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
1693 9 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {}
1694 : /**
1695 : * @return the frame that this display item is based on. This is used to sort
1696 : * items by z-index and content order and for some other uses. Never
1697 : * returns null.
1698 : */
1699 14779 : inline nsIFrame* Frame() const { return mFrame; }
1700 : /**
1701 : * Compute the used z-index of our frame; returns zero for elements to which
1702 : * z-index does not apply, and for z-index:auto.
1703 : * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
1704 : */
1705 : virtual int32_t ZIndex() const;
1706 : /**
1707 : * The default bounds is the frame border rect.
1708 : * @param aSnap *aSnap is set to true if the returned rect will be
1709 : * snapped to nearest device pixel edges during actual drawing.
1710 : * It might be set to false and snap anyway, so code computing the set of
1711 : * pixels affected by this display item needs to round outwards to pixel
1712 : * boundaries when *aSnap is set to false.
1713 : * This does not take the item's clipping into account.
1714 : * @return a rectangle relative to aBuilder->ReferenceFrame() that
1715 : * contains the area drawn by this display item
1716 : */
1717 269 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
1718 : {
1719 269 : *aSnap = false;
1720 269 : return nsRect(ToReferenceFrame(), Frame()->GetSize());
1721 : }
1722 :
1723 219 : virtual nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
1724 : {
1725 219 : *aSnap = false;
1726 219 : return nsRegion();
1727 : }
1728 :
1729 : /**
1730 : * Returns true if nothing will be rendered inside aRect, false if uncertain.
1731 : * aRect is assumed to be contained in this item's bounds.
1732 : */
1733 294 : virtual bool IsInvisibleInRect(const nsRect& aRect)
1734 : {
1735 294 : return false;
1736 : }
1737 : /**
1738 : * Returns the result of GetBounds intersected with the item's clip.
1739 : * The intersection is approximate since rounded corners are not taking into
1740 : * account.
1741 : */
1742 : nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder);
1743 609 : nsRect GetBorderRect() {
1744 609 : return nsRect(ToReferenceFrame(), Frame()->GetSize());
1745 : }
1746 25 : nsRect GetPaddingRect() {
1747 25 : return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
1748 : }
1749 179 : nsRect GetContentRect() {
1750 179 : return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
1751 : }
1752 :
1753 : /**
1754 : * Checks if the frame(s) owning this display item have been marked as invalid,
1755 : * and needing repainting.
1756 : */
1757 1075 : virtual bool IsInvalid(nsRect& aRect) {
1758 1075 : bool result = mFrame ? mFrame->IsInvalid(aRect) : false;
1759 1075 : aRect += ToReferenceFrame();
1760 1075 : return result;
1761 : }
1762 :
1763 : /**
1764 : * Creates and initializes an nsDisplayItemGeometry object that retains the current
1765 : * areas covered by this display item. These need to retain enough information
1766 : * such that they can be compared against a future nsDisplayItem of the same type,
1767 : * and determine if repainting needs to happen.
1768 : *
1769 : * Subclasses wishing to store more information need to override both this
1770 : * and ComputeInvalidationRegion, as well as implementing an nsDisplayItemGeometry
1771 : * subclass.
1772 : *
1773 : * The default implementation tracks both the display item bounds, and the frame's
1774 : * border rect.
1775 : */
1776 139 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
1777 : {
1778 139 : return new nsDisplayItemGenericGeometry(this, aBuilder);
1779 : }
1780 :
1781 : /**
1782 : * Compares an nsDisplayItemGeometry object from a previous paint against the
1783 : * current item. Computes if the geometry of the item has changed, and the
1784 : * invalidation area required for correct repainting.
1785 : *
1786 : * The existing geometry will have been created from a display item with a
1787 : * matching GetPerFrameKey()/mFrame pair to the current item.
1788 : *
1789 : * The default implementation compares the display item bounds, and the frame's
1790 : * border rect, and invalidates the entire bounds if either rect changes.
1791 : *
1792 : * @param aGeometry The geometry of the matching display item from the
1793 : * previous paint.
1794 : * @param aInvalidRegion Output param, the region to invalidate, or
1795 : * unchanged if none.
1796 : */
1797 296 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
1798 : const nsDisplayItemGeometry* aGeometry,
1799 : nsRegion* aInvalidRegion)
1800 : {
1801 296 : const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
1802 : bool snap;
1803 1148 : if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
1804 852 : !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
1805 18 : aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
1806 : }
1807 296 : }
1808 :
1809 : /**
1810 : * An alternative default implementation of ComputeInvalidationRegion,
1811 : * that instead invalidates only the changed area between the two items.
1812 : */
1813 167 : void ComputeInvalidationRegionDifference(nsDisplayListBuilder* aBuilder,
1814 : const nsDisplayItemBoundsGeometry* aGeometry,
1815 : nsRegion* aInvalidRegion)
1816 : {
1817 : bool snap;
1818 334 : nsRect bounds = GetBounds(aBuilder, &snap);
1819 :
1820 167 : if (!aGeometry->mBounds.IsEqualInterior(bounds)) {
1821 : nscoord radii[8];
1822 12 : if (aGeometry->mHasRoundedCorners ||
1823 3 : Frame()->GetBorderRadii(radii)) {
1824 6 : aInvalidRegion->Or(aGeometry->mBounds, bounds);
1825 : } else {
1826 3 : aInvalidRegion->Xor(aGeometry->mBounds, bounds);
1827 : }
1828 : }
1829 167 : }
1830 :
1831 : /**
1832 : * Called when the area rendered by this display item has changed (been
1833 : * invalidated or changed geometry) since the last paint. This includes
1834 : * when the display item was not rendered at all in the last paint.
1835 : * It does NOT get called when a display item was being rendered and no
1836 : * longer is, because generally that means there is no display item to
1837 : * call this method on.
1838 : */
1839 225 : virtual void NotifyRenderingChanged() {}
1840 :
1841 : /**
1842 : * @param aSnap set to true if the edges of the rectangles of the opaque
1843 : * region would be snapped to device pixels when drawing
1844 : * @return a region of the item that is opaque --- that is, every pixel
1845 : * that is visible is painted with an opaque
1846 : * color. This is useful for determining when one piece
1847 : * of content completely obscures another so that we can do occlusion
1848 : * culling.
1849 : * This does not take clipping into account.
1850 : */
1851 926 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
1852 : bool* aSnap)
1853 : {
1854 926 : *aSnap = false;
1855 926 : return nsRegion();
1856 : }
1857 : /**
1858 : * @return Some(nscolor) if the item is guaranteed to paint every pixel in its
1859 : * bounds with the same (possibly translucent) color
1860 : */
1861 169 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder)
1862 169 : { return mozilla::Nothing(); }
1863 : /**
1864 : * @return true if the contents of this item are rendered fixed relative
1865 : * to the nearest viewport.
1866 : */
1867 76 : virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
1868 76 : { return false; }
1869 :
1870 3157 : virtual bool ClearsBackground()
1871 3157 : { return false; }
1872 :
1873 172 : virtual bool ProvidesFontSmoothingBackgroundColor(nscolor* aColor)
1874 172 : { return false; }
1875 :
1876 : /**
1877 : * Returns true if all layers that can be active should be forced to be
1878 : * active. Requires setting the pref layers.force-active=true.
1879 : */
1880 : static bool ForceActiveLayers();
1881 :
1882 : /**
1883 : * @return LAYER_NONE if BuildLayer will return null. In this case
1884 : * there is no layer for the item, and Paint should be called instead
1885 : * to paint the content using Thebes.
1886 : * Return LAYER_INACTIVE if there is a layer --- BuildLayer will
1887 : * not return null (unless there's an error) --- but the layer contents
1888 : * are not changing frequently. In this case it makes sense to composite
1889 : * the layer into a PaintedLayer with other content, so we don't have to
1890 : * recomposite it every time we paint.
1891 : * Note: GetLayerState is only allowed to return LAYER_INACTIVE if all
1892 : * descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also,
1893 : * all descendant display item frames must have an active scrolled root
1894 : * that's either the same as this item's frame's active scrolled root, or
1895 : * a descendant of this item's frame. This ensures that the entire
1896 : * set of display items can be collapsed onto a single PaintedLayer.
1897 : * Return LAYER_ACTIVE if the layer is active, that is, its contents are
1898 : * changing frequently. In this case it makes sense to keep the layer
1899 : * as a separate buffer in VRAM and composite it into the destination
1900 : * every time we paint.
1901 : *
1902 : * Users of GetLayerState should check ForceActiveLayers() and if it returns
1903 : * true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE.
1904 : */
1905 1193 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
1906 : LayerManager* aManager,
1907 : const ContainerLayerParameters& aParameters)
1908 1193 : { return mozilla::LAYER_NONE; }
1909 : /**
1910 : * Return true to indicate the layer should be constructed even if it's
1911 : * completely invisible.
1912 : */
1913 0 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
1914 0 : { return false; }
1915 : /**
1916 : * Actually paint this item to some rendering context.
1917 : * Content outside mVisibleRect need not be painted.
1918 : * aCtx must be set up as for nsDisplayList::Paint.
1919 : */
1920 0 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {}
1921 :
1922 : #ifdef MOZ_DUMP_PAINTING
1923 : /**
1924 : * Mark this display item as being painted via FrameLayerBuilder::DrawPaintedLayer.
1925 : */
1926 0 : bool Painted() { return mPainted; }
1927 :
1928 : /**
1929 : * Check if this display item has been painted.
1930 : */
1931 0 : void SetPainted() { mPainted = true; }
1932 : #endif
1933 :
1934 : /**
1935 : * Get the layer drawn by this display item. Call this only if
1936 : * GetLayerState() returns something other than LAYER_NONE.
1937 : * If GetLayerState returned LAYER_NONE then Paint will be called
1938 : * instead.
1939 : * This is called while aManager is in the construction phase.
1940 : *
1941 : * The caller (nsDisplayList) is responsible for setting the visible
1942 : * region of the layer.
1943 : *
1944 : * @param aContainerParameters should be passed to
1945 : * FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is
1946 : * constructed.
1947 : */
1948 0 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
1949 : LayerManager* aManager,
1950 : const ContainerLayerParameters& aContainerParameters)
1951 0 : { return nullptr; }
1952 :
1953 : /**
1954 : * Function to create the WebRenderCommands without
1955 : * Layer. For layers mode, aManager->IsLayersFreeTransaction()
1956 : * should be false to prevent doing GetLayerState again. For
1957 : * layers-free mode, we should check if the layer state is
1958 : * active first and have an early return if the layer state is
1959 : * not active.
1960 : *
1961 : * @return true if successfully creating webrender commands.
1962 : */
1963 0 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
1964 : const StackingContextHelper& aSc,
1965 : nsTArray<WebRenderParentCommand>& aParentCommands,
1966 : mozilla::layers::WebRenderLayerManager* aManager,
1967 0 : nsDisplayListBuilder* aDisplayListBuilder) { return false; }
1968 :
1969 : /**
1970 : * Builds a DisplayItemLayer and sets the display item to this.
1971 : */
1972 : already_AddRefed<Layer>
1973 : BuildDisplayItemLayer(nsDisplayListBuilder* aBuilder,
1974 : LayerManager* aManager,
1975 : const ContainerLayerParameters& aContainerParameters);
1976 :
1977 : /**
1978 : * On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
1979 : * which may be visible. If the display item opaquely covers an area, it
1980 : * can remove that area from aVisibleRegion before returning.
1981 : * nsDisplayList::ComputeVisibility automatically subtracts the region
1982 : * returned by GetOpaqueRegion, and automatically removes items whose bounds
1983 : * do not intersect the visible area, so implementations of
1984 : * nsDisplayItem::ComputeVisibility do not need to do these things.
1985 : * nsDisplayList::ComputeVisibility will already have set mVisibleRect on
1986 : * this item to the intersection of *aVisibleRegion and this item's bounds.
1987 : * We rely on that, so this should only be called by
1988 : * nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility.
1989 : * aAllowVisibleRegionExpansion is a rect where we are allowed to
1990 : * expand the visible region and is only used for making sure the
1991 : * background behind a plugin is visible.
1992 : * This method needs to be idempotent.
1993 : *
1994 : * @return true if the item is visible, false if no part of the item
1995 : * is visible.
1996 : */
1997 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1998 : nsRegion* aVisibleRegion);
1999 :
2000 : /**
2001 : * Try to merge with the other item (which is below us in the display
2002 : * list). This gets used by nsDisplayClip to coalesce clipping operations
2003 : * (optimization), by nsDisplayOpacity to merge rendering for the same
2004 : * content element into a single opacity group (correctness), and will be
2005 : * used by nsDisplayOutline to merge multiple outlines for the same element
2006 : * (also for correctness).
2007 : * @return true if the merge was successful and the other item should be deleted
2008 : */
2009 1132 : virtual bool TryMerge(nsDisplayItem* aItem) {
2010 1132 : return false;
2011 : }
2012 :
2013 : /**
2014 : * Appends the underlying frames of all display items that have been
2015 : * merged into this one (excluding this item's own underlying frame)
2016 : * to aFrames.
2017 : */
2018 1050 : virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) {}
2019 :
2020 : /**
2021 : * During the visibility computation and after TryMerge, display lists may
2022 : * return true here to flatten themselves away, removing them. This
2023 : * flattening is distinctly different from FlattenTo, which occurs before
2024 : * items are merged together.
2025 : */
2026 1688 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
2027 1688 : return false;
2028 : }
2029 :
2030 : /**
2031 : * If this has a child list where the children are in the same coordinate
2032 : * system as this item (i.e., they have the same reference frame),
2033 : * return the list.
2034 : */
2035 2094 : virtual nsDisplayList* GetSameCoordinateSystemChildren() { return nullptr; }
2036 0 : virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) {}
2037 : /**
2038 : * Do UpdateBounds() for items with frames establishing or extending
2039 : * 3D rendering context.
2040 : *
2041 : * This function is called by UpdateBoundsFor3D() of
2042 : * nsDisplayTransform(), and it is called by
2043 : * BuildDisplayListForStackingContext() on transform items
2044 : * establishing 3D rendering context.
2045 : *
2046 : * The bounds of a transform item with the frame establishing 3D
2047 : * rendering context should be computed by calling
2048 : * DoUpdateBoundsPreserves3D() on all descendants that participate
2049 : * the same 3d rendering context.
2050 : */
2051 0 : virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) {}
2052 :
2053 : /**
2054 : * If this has a child list, return it, even if the children are in
2055 : * a different coordinate system to this item.
2056 : */
2057 96 : virtual nsDisplayList* GetChildren() { return nullptr; }
2058 :
2059 : /**
2060 : * Returns the visible rect.
2061 : */
2062 4810 : const nsRect& GetVisibleRect() const { return mVisibleRect; }
2063 :
2064 : /**
2065 : * Returns the visible rect for the children, relative to their
2066 : * reference frame. Can be different from mVisibleRect for nsDisplayTransform,
2067 : * since the reference frame for the children is different from the reference
2068 : * frame for the item itself.
2069 : */
2070 171 : virtual const nsRect& GetVisibleRectForChildren() const { return mVisibleRect; }
2071 :
2072 : /**
2073 : * Stores the given opacity value to be applied when drawing. It is an error to
2074 : * call this if CanApplyOpacity returned false.
2075 : */
2076 0 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
2077 : float aOpacity,
2078 : const DisplayItemClipChain* aClip) {
2079 0 : NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity not supported on this type");
2080 0 : }
2081 : /**
2082 : * Returns true if this display item would return true from ApplyOpacity without
2083 : * actually applying the opacity. Otherwise returns false.
2084 : */
2085 64 : virtual bool CanApplyOpacity() const {
2086 64 : return false;
2087 : }
2088 :
2089 : /**
2090 : * For debugging and stuff
2091 : */
2092 : virtual const char* Name() = 0;
2093 :
2094 0 : virtual void WriteDebugInfo(std::stringstream& aStream) {}
2095 :
2096 6336 : nsDisplayItem* GetAbove() { return mAbove; }
2097 :
2098 : /**
2099 : * Like ComputeVisibility, but does the work that nsDisplayList
2100 : * does per-item:
2101 : * -- Intersects GetBounds with aVisibleRegion and puts the result
2102 : * in mVisibleRect
2103 : * -- Subtracts bounds from aVisibleRegion if the item is opaque
2104 : */
2105 : bool RecomputeVisibility(nsDisplayListBuilder* aBuilder,
2106 : nsRegion* aVisibleRegion);
2107 :
2108 : /**
2109 : * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
2110 : */
2111 4866 : const nsPoint& ToReferenceFrame() const {
2112 4866 : NS_ASSERTION(mFrame, "No frame?");
2113 4866 : return mToReferenceFrame;
2114 : }
2115 : /**
2116 : * @return the root of the display list's frame (sub)tree, whose origin
2117 : * establishes the coordinate system for the display list
2118 : */
2119 2456 : const nsIFrame* ReferenceFrame() const { return mReferenceFrame; }
2120 :
2121 : /**
2122 : * Returns the reference frame for display item children of this item.
2123 : */
2124 171 : virtual const nsIFrame* ReferenceFrameForChildren() const { return mReferenceFrame; }
2125 :
2126 2242 : AnimatedGeometryRoot* GetAnimatedGeometryRoot() const {
2127 2242 : MOZ_ASSERT(mAnimatedGeometryRoot, "Must have cached AGR before accessing it!");
2128 2242 : return mAnimatedGeometryRoot;
2129 : }
2130 :
2131 0 : virtual struct AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const {
2132 0 : return GetAnimatedGeometryRoot();
2133 : }
2134 :
2135 : /**
2136 : * Checks if this display item (or any children) contains content that might
2137 : * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
2138 : * bounds of the area that needs component alpha, or an empty rect if nothing
2139 : * in the item does.
2140 : */
2141 311 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) { return nsRect(); }
2142 :
2143 : /**
2144 : * Disable usage of component alpha. Currently only relevant for items that have text.
2145 : */
2146 0 : virtual void DisableComponentAlpha() {}
2147 :
2148 : /**
2149 : * Check if we can add async animations to the layer for this display item.
2150 : */
2151 0 : virtual bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
2152 0 : return false;
2153 : }
2154 :
2155 139 : virtual bool SupportsOptimizingToImage() { return false; }
2156 :
2157 9562 : const DisplayItemClip& GetClip()
2158 : {
2159 9562 : return mClip ? *mClip : DisplayItemClip::NoClip();
2160 : }
2161 : void IntersectClip(nsDisplayListBuilder* aBuilder, const DisplayItemClipChain* aOther);
2162 :
2163 : void SetActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot) { mActiveScrolledRoot = aActiveScrolledRoot; }
2164 4350 : const ActiveScrolledRoot* GetActiveScrolledRoot() const { return mActiveScrolledRoot; }
2165 :
2166 : virtual void SetClipChain(const DisplayItemClipChain* aClipChain);
2167 1519 : const DisplayItemClipChain* GetClipChain() const { return mClipChain; }
2168 :
2169 : /**
2170 : * Intersect all clips in our clip chain up to (and including) aASR and set
2171 : * set the intersection as this item's clip.
2172 : */
2173 : void FuseClipChainUpTo(nsDisplayListBuilder* aBuilder,
2174 : const ActiveScrolledRoot* aASR);
2175 :
2176 76 : bool BackfaceIsHidden() {
2177 76 : return mFrame->BackfaceIsHidden();
2178 : }
2179 :
2180 : protected:
2181 : friend class nsDisplayList;
2182 :
2183 : nsDisplayItem() { mAbove = nullptr; }
2184 :
2185 : typedef bool (*PrefFunc)(void);
2186 : bool ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc);
2187 :
2188 : nsIFrame* mFrame;
2189 : const DisplayItemClipChain* mClipChain;
2190 : const DisplayItemClip* mClip;
2191 : const ActiveScrolledRoot* mActiveScrolledRoot;
2192 : // Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
2193 : const nsIFrame* mReferenceFrame;
2194 : struct AnimatedGeometryRoot* mAnimatedGeometryRoot;
2195 : // Result of ToReferenceFrame(mFrame), if mFrame is non-null
2196 : nsPoint mToReferenceFrame;
2197 : // This is the rectangle that needs to be painted.
2198 : // Display item construction sets this to the dirty rect.
2199 : // nsDisplayList::ComputeVisibility sets this to the visible region
2200 : // of the item by intersecting the current visible region with the bounds
2201 : // of the item. Paint implementations can use this to limit their drawing.
2202 : // Guaranteed to be contained in GetBounds().
2203 : nsRect mVisibleRect;
2204 : bool mForceNotVisible;
2205 : #ifdef MOZ_DUMP_PAINTING
2206 : // True if this frame has been painted.
2207 : bool mPainted;
2208 : #endif
2209 : };
2210 :
2211 : /**
2212 : * Manages a singly-linked list of display list items.
2213 : *
2214 : * mSentinel is the sentinel list value, the first value in the null-terminated
2215 : * linked list of items. mTop is the last item in the list (whose 'above'
2216 : * pointer is null). This class has no virtual methods. So list objects are just
2217 : * two pointers.
2218 : *
2219 : * Stepping upward through this list is very fast. Stepping downward is very
2220 : * slow so we don't support it. The methods that need to step downward
2221 : * (HitTest(), ComputeVisibility()) internally build a temporary array of all
2222 : * the items while they do the downward traversal, so overall they're still
2223 : * linear time. We have optimized for efficient AppendToTop() of both
2224 : * items and lists, with minimal codesize. AppendToBottom() is efficient too.
2225 : */
2226 : class nsDisplayList {
2227 : public:
2228 : typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
2229 : typedef mozilla::layers::Layer Layer;
2230 : typedef mozilla::layers::LayerManager LayerManager;
2231 : typedef mozilla::layers::PaintedLayer PaintedLayer;
2232 :
2233 : /**
2234 : * Create an empty list.
2235 : */
2236 25326 : nsDisplayList()
2237 25326 : : mIsOpaque(false)
2238 25326 : , mForceTransparentSurface(false)
2239 : {
2240 25326 : mTop = &mSentinel;
2241 25326 : mSentinel.mAbove = nullptr;
2242 25326 : }
2243 50652 : ~nsDisplayList() {
2244 25326 : if (mSentinel.mAbove) {
2245 0 : NS_WARNING("Nonempty list left over?");
2246 : }
2247 25326 : DeleteAll();
2248 25326 : }
2249 :
2250 : /**
2251 : * Append an item to the top of the list. The item must not currently
2252 : * be in a list and cannot be null.
2253 : */
2254 4581 : void AppendToTop(nsDisplayItem* aItem) {
2255 4581 : NS_ASSERTION(aItem, "No item to append!");
2256 4581 : NS_ASSERTION(!aItem->mAbove, "Already in a list!");
2257 4581 : mTop->mAbove = aItem;
2258 4581 : mTop = aItem;
2259 4581 : }
2260 :
2261 : /**
2262 : * Append a new item to the top of the list. The intended usage is
2263 : * AppendNewToTop(new ...);
2264 : */
2265 2231 : void AppendNewToTop(nsDisplayItem* aItem) {
2266 2231 : if (aItem) {
2267 2231 : AppendToTop(aItem);
2268 : }
2269 2231 : }
2270 :
2271 : /**
2272 : * Append a new item to the bottom of the list. The intended usage is
2273 : * AppendNewToBottom(new ...);
2274 : */
2275 26 : void AppendNewToBottom(nsDisplayItem* aItem) {
2276 26 : if (aItem) {
2277 26 : AppendToBottom(aItem);
2278 : }
2279 26 : }
2280 :
2281 : /**
2282 : * Append a new item to the bottom of the list. The item must be non-null
2283 : * and not already in a list.
2284 : */
2285 625 : void AppendToBottom(nsDisplayItem* aItem) {
2286 625 : NS_ASSERTION(aItem, "No item to append!");
2287 625 : NS_ASSERTION(!aItem->mAbove, "Already in a list!");
2288 625 : aItem->mAbove = mSentinel.mAbove;
2289 625 : mSentinel.mAbove = aItem;
2290 625 : if (mTop == &mSentinel) {
2291 440 : mTop = aItem;
2292 : }
2293 625 : }
2294 :
2295 : /**
2296 : * Removes all items from aList and appends them to the top of this list
2297 : */
2298 11050 : void AppendToTop(nsDisplayList* aList) {
2299 11050 : if (aList->mSentinel.mAbove) {
2300 3999 : mTop->mAbove = aList->mSentinel.mAbove;
2301 3999 : mTop = aList->mTop;
2302 3999 : aList->mTop = &aList->mSentinel;
2303 3999 : aList->mSentinel.mAbove = nullptr;
2304 : }
2305 11050 : }
2306 :
2307 : /**
2308 : * Removes all items from aList and prepends them to the bottom of this list
2309 : */
2310 349 : void AppendToBottom(nsDisplayList* aList) {
2311 349 : if (aList->mSentinel.mAbove) {
2312 349 : aList->mTop->mAbove = mSentinel.mAbove;
2313 349 : mSentinel.mAbove = aList->mSentinel.mAbove;
2314 349 : if (mTop == &mSentinel) {
2315 24 : mTop = aList->mTop;
2316 : }
2317 :
2318 349 : aList->mTop = &aList->mSentinel;
2319 349 : aList->mSentinel.mAbove = nullptr;
2320 : }
2321 349 : }
2322 :
2323 : /**
2324 : * Remove an item from the bottom of the list and return it.
2325 : */
2326 : nsDisplayItem* RemoveBottom();
2327 :
2328 : /**
2329 : * Remove all items from the list and call their destructors.
2330 : */
2331 : void DeleteAll();
2332 :
2333 : /**
2334 : * @return the item at the top of the list, or null if the list is empty
2335 : */
2336 0 : nsDisplayItem* GetTop() const {
2337 0 : return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nullptr;
2338 : }
2339 : /**
2340 : * @return the item at the bottom of the list, or null if the list is empty
2341 : */
2342 6348 : nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
2343 1477 : bool IsEmpty() const { return mTop == &mSentinel; }
2344 :
2345 : /**
2346 : * This is *linear time*!
2347 : * @return the number of items in the list
2348 : */
2349 : uint32_t Count() const;
2350 : /**
2351 : * Stable sort the list by the z-order of GetUnderlyingFrame() on
2352 : * each item. 'auto' is counted as zero.
2353 : * It is assumed that the list is already in content document order.
2354 : */
2355 : void SortByZOrder();
2356 : /**
2357 : * Stable sort the list by the tree order of the content of
2358 : * GetUnderlyingFrame() on each item. z-index is ignored.
2359 : * @param aCommonAncestor a common ancestor of all the content elements
2360 : * associated with the display items, for speeding up tree order
2361 : * checks, or nullptr if not known; it's only a hint, if it is not an
2362 : * ancestor of some elements, then we lose performance but not correctness
2363 : */
2364 : void SortByContentOrder(nsIContent* aCommonAncestor);
2365 :
2366 : /**
2367 : * Sort the display list using a stable sort. Take care, because some of the
2368 : * items might be nsDisplayLists themselves.
2369 : * aComparator(Item item1, Item item2) should return true if item1 should go
2370 : * before item2.
2371 : * We sort the items into increasing order.
2372 : */
2373 : template<typename Item, typename Comparator>
2374 1226 : void Sort(const Comparator& aComparator) {
2375 2452 : nsTArray<Item> items;
2376 :
2377 2058 : while (nsDisplayItem* item = RemoveBottom()) {
2378 416 : items.AppendElement(Item(item));
2379 : }
2380 :
2381 1226 : std::stable_sort(items.begin(), items.end(), aComparator);
2382 :
2383 1642 : for (Item& item : items) {
2384 416 : AppendToTop(item);
2385 : }
2386 1226 : }
2387 :
2388 : /**
2389 : * Compute visiblity for the items in the list.
2390 : * We put this logic here so it can be shared by top-level
2391 : * painting and also display items that maintain child lists.
2392 : * This is also a good place to put ComputeVisibility-related logic
2393 : * that must be applied to every display item. In particular, this
2394 : * sets mVisibleRect on each display item.
2395 : * This sets mIsOpaque if the entire visible area of this list has
2396 : * been removed from aVisibleRegion when we return.
2397 : * This does not remove any items from the list, so we can recompute
2398 : * visiblity with different regions later (see
2399 : * FrameLayerBuilder::DrawPaintedLayer).
2400 : * This method needs to be idempotent.
2401 : *
2402 : * @param aVisibleRegion the area that is visible, relative to the
2403 : * reference frame; on return, this contains the area visible under the list.
2404 : * I.e., opaque contents of this list are subtracted from aVisibleRegion.
2405 : * @param aListVisibleBounds must be equal to the bounds of the intersection
2406 : * of aVisibleRegion and GetBounds() for this list.
2407 : * @return true if any item in the list is visible.
2408 : */
2409 : bool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
2410 : nsRegion* aVisibleRegion,
2411 : const nsRect& aListVisibleBounds);
2412 :
2413 : /**
2414 : * As ComputeVisibilityForSublist, but computes visibility for a root
2415 : * list (a list that does not belong to an nsDisplayItem).
2416 : * This method needs to be idempotent.
2417 : *
2418 : * @param aVisibleRegion the area that is visible
2419 : */
2420 : bool ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
2421 : nsRegion* aVisibleRegion);
2422 :
2423 : /**
2424 : * Returns true if the visible region output from ComputeVisiblity was
2425 : * empty, i.e. everything visible in this list is opaque.
2426 : */
2427 271 : bool IsOpaque() const {
2428 271 : return mIsOpaque;
2429 : }
2430 :
2431 : /**
2432 : * Returns true if any display item requires the surface to be transparent.
2433 : */
2434 199 : bool NeedsTransparentSurface() const {
2435 199 : return mForceTransparentSurface;
2436 : }
2437 : /**
2438 : * Paint the list to the rendering context. We assume that (0,0) in aCtx
2439 : * corresponds to the origin of the reference frame. For best results,
2440 : * aCtx's current transform should make (0,0) pixel-aligned. The
2441 : * rectangle in aDirtyRect is painted, which *must* be contained in the
2442 : * dirty rect used to construct the display list.
2443 : *
2444 : * If aFlags contains PAINT_USE_WIDGET_LAYERS and
2445 : * ShouldUseWidgetLayerManager() is set, then we will paint using
2446 : * the reference frame's widget's layer manager (and ctx may be null),
2447 : * otherwise we will use a temporary BasicLayerManager and ctx must
2448 : * not be null.
2449 : *
2450 : * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
2451 : * layer manager has already had BeginTransaction() called on it and
2452 : * we should not call it again.
2453 : *
2454 : * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode
2455 : * to avoid short cut optimizations.
2456 : *
2457 : * This must only be called on the root display list of the display list
2458 : * tree.
2459 : *
2460 : * We return the layer manager used for painting --- mainly so that
2461 : * callers can dump its layer tree if necessary.
2462 : */
2463 : enum {
2464 : PAINT_DEFAULT = 0,
2465 : PAINT_USE_WIDGET_LAYERS = 0x01,
2466 : PAINT_EXISTING_TRANSACTION = 0x04,
2467 : PAINT_NO_COMPOSITE = 0x08,
2468 : PAINT_COMPRESSED = 0x10
2469 : };
2470 : already_AddRefed<LayerManager> PaintRoot(nsDisplayListBuilder* aBuilder,
2471 : gfxContext* aCtx,
2472 : uint32_t aFlags);
2473 : /**
2474 : * Get the bounds. Takes the union of the bounds of all children.
2475 : * The result is not cached.
2476 : */
2477 : nsRect GetBounds(nsDisplayListBuilder* aBuilder) const;
2478 :
2479 : /**
2480 : * Get this list's bounds, respecting clips relative to aASR. The result is
2481 : * the union of each item's clipped bounds with respect to aASR. That means
2482 : * that if an item can move asynchronously with an ASR that is a descendant
2483 : * of aASR, then the clipped bounds with respect to aASR will be the clip of
2484 : * that item for aASR, because the item can move anywhere inside that clip.
2485 : * If there is an item in this list which is not bounded with respect to
2486 : * aASR (i.e. which does not have "finite bounds" with respect to aASR),
2487 : * then this method trigger an assertion failure.
2488 : */
2489 : nsRect GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
2490 : const ActiveScrolledRoot* aASR) const;
2491 :
2492 : /**
2493 : * Find the topmost display item that returns a non-null frame, and return
2494 : * the frame.
2495 : */
2496 : void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2497 : nsDisplayItem::HitTestState* aState,
2498 : nsTArray<nsIFrame*> *aOutFrames) const;
2499 : /**
2500 : * Compute the union of the visible rects of the items in the list. The
2501 : * result is not cached.
2502 : */
2503 : nsRect GetVisibleRect() const;
2504 :
2505 78 : void SetIsOpaque()
2506 : {
2507 78 : mIsOpaque = true;
2508 78 : }
2509 0 : void SetNeedsTransparentSurface()
2510 : {
2511 0 : mForceTransparentSurface = true;
2512 0 : }
2513 :
2514 : private:
2515 : // This class is only used on stack, so we don't have to worry about leaking
2516 : // it. Don't let us be heap-allocated!
2517 : void* operator new(size_t sz) CPP_THROW_NEW;
2518 :
2519 : nsDisplayItemLink mSentinel;
2520 : nsDisplayItemLink* mTop;
2521 :
2522 : // This is set to true by FrameLayerBuilder if the final visible region
2523 : // is empty (i.e. everything that was visible is covered by some
2524 : // opaque content in this list).
2525 : bool mIsOpaque;
2526 : // This is set to true by FrameLayerBuilder if any display item in this
2527 : // list needs to force the surface containing this list to be transparent.
2528 : bool mForceTransparentSurface;
2529 : };
2530 :
2531 : /**
2532 : * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
2533 : * will put any generated items onto the appropriate list given here. It's
2534 : * basically just a collection with one list for each separate stacking layer.
2535 : * The lists themselves are external to this object and thus can be shared
2536 : * with others. Some of the list pointers may even refer to the same list.
2537 : */
2538 : class nsDisplayListSet {
2539 : public:
2540 : /**
2541 : * @return a list where one should place the border and/or background for
2542 : * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
2543 : */
2544 3122 : nsDisplayList* BorderBackground() const { return mBorderBackground; }
2545 : /**
2546 : * @return a list where one should place the borders and/or backgrounds for
2547 : * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
2548 : */
2549 5773 : nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; }
2550 : /**
2551 : * @return a list where one should place descendant floats (step 5 of
2552 : * CSS 2.1 appendix E)
2553 : */
2554 3926 : nsDisplayList* Floats() const { return mFloats; }
2555 : /**
2556 : * @return a list where one should place the (pseudo) stacking contexts
2557 : * for descendants of this frame (everything from steps 3, 7 and 8
2558 : * of CSS 2.1 appendix E)
2559 : */
2560 6479 : nsDisplayList* PositionedDescendants() const { return mPositioned; }
2561 : /**
2562 : * @return a list where one should place the outlines
2563 : * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
2564 : */
2565 4539 : nsDisplayList* Outlines() const { return mOutlines; }
2566 : /**
2567 : * @return a list where one should place all other content
2568 : */
2569 9227 : nsDisplayList* Content() const { return mContent; }
2570 :
2571 3401 : nsDisplayListSet(nsDisplayList* aBorderBackground,
2572 : nsDisplayList* aBlockBorderBackgrounds,
2573 : nsDisplayList* aFloats,
2574 : nsDisplayList* aContent,
2575 : nsDisplayList* aPositionedDescendants,
2576 3401 : nsDisplayList* aOutlines) :
2577 : mBorderBackground(aBorderBackground),
2578 : mBlockBorderBackgrounds(aBlockBorderBackgrounds),
2579 : mFloats(aFloats),
2580 : mContent(aContent),
2581 : mPositioned(aPositionedDescendants),
2582 3401 : mOutlines(aOutlines) {
2583 3401 : }
2584 :
2585 : /**
2586 : * A copy constructor that lets the caller override the BorderBackground
2587 : * list.
2588 : */
2589 2031 : nsDisplayListSet(const nsDisplayListSet& aLists,
2590 2031 : nsDisplayList* aBorderBackground) :
2591 : mBorderBackground(aBorderBackground),
2592 2031 : mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
2593 2031 : mFloats(aLists.Floats()),
2594 2031 : mContent(aLists.Content()),
2595 2031 : mPositioned(aLists.PositionedDescendants()),
2596 10155 : mOutlines(aLists.Outlines()) {
2597 2031 : }
2598 :
2599 : /**
2600 : * Move all display items in our lists to top of the corresponding lists in the
2601 : * destination.
2602 : */
2603 : void MoveTo(const nsDisplayListSet& aDestination) const;
2604 :
2605 : private:
2606 : // This class is only used on stack, so we don't have to worry about leaking
2607 : // it. Don't let us be heap-allocated!
2608 : void* operator new(size_t sz) CPP_THROW_NEW;
2609 :
2610 : protected:
2611 : nsDisplayList* mBorderBackground;
2612 : nsDisplayList* mBlockBorderBackgrounds;
2613 : nsDisplayList* mFloats;
2614 : nsDisplayList* mContent;
2615 : nsDisplayList* mPositioned;
2616 : nsDisplayList* mOutlines;
2617 : };
2618 :
2619 : /**
2620 : * A specialization of nsDisplayListSet where the lists are actually internal
2621 : * to the object, and all distinct.
2622 : */
2623 3230 : struct nsDisplayListCollection : public nsDisplayListSet {
2624 3230 : nsDisplayListCollection() :
2625 : nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4],
2626 3230 : &mLists[5]) {}
2627 : explicit nsDisplayListCollection(nsDisplayList* aBorderBackground) :
2628 : nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4],
2629 : &mLists[5]) {}
2630 :
2631 : /**
2632 : * Sort all lists by content order.
2633 : */
2634 : void SortAllByContentOrder(nsIContent* aCommonAncestor) {
2635 : for (int32_t i = 0; i < 6; ++i) {
2636 : mLists[i].SortByContentOrder(aCommonAncestor);
2637 : }
2638 : }
2639 :
2640 : private:
2641 : // This class is only used on stack, so we don't have to worry about leaking
2642 : // it. Don't let us be heap-allocated!
2643 : void* operator new(size_t sz) CPP_THROW_NEW;
2644 :
2645 : nsDisplayList mLists[6];
2646 : };
2647 :
2648 :
2649 535 : class nsDisplayImageContainer : public nsDisplayItem {
2650 : public:
2651 : typedef mozilla::LayerIntPoint LayerIntPoint;
2652 : typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
2653 : typedef mozilla::layers::ImageContainer ImageContainer;
2654 : typedef mozilla::layers::ImageLayer ImageLayer;
2655 :
2656 535 : nsDisplayImageContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
2657 535 : : nsDisplayItem(aBuilder, aFrame)
2658 535 : {}
2659 :
2660 : /**
2661 : * @return true if this display item can be optimized into an image layer.
2662 : * It is an error to call GetContainer() unless you've called
2663 : * CanOptimizeToImageLayer() first and it returned true.
2664 : */
2665 : virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
2666 : nsDisplayListBuilder* aBuilder);
2667 :
2668 : already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
2669 : nsDisplayListBuilder* aBuilder);
2670 : void ConfigureLayer(ImageLayer* aLayer,
2671 : const ContainerLayerParameters& aParameters);
2672 :
2673 : virtual already_AddRefed<imgIContainer> GetImage() = 0;
2674 :
2675 : virtual nsRect GetDestRect() = 0;
2676 :
2677 57 : virtual bool SupportsOptimizingToImage() override { return true; }
2678 : };
2679 :
2680 : /**
2681 : * Use this class to implement not-very-frequently-used display items
2682 : * that are not opaque, do not receive events, and are bounded by a frame's
2683 : * border-rect.
2684 : *
2685 : * This should not be used for display items which are created frequently,
2686 : * because each item is one or two pointers bigger than an item from a
2687 : * custom display item class could be, and fractionally slower. However it does
2688 : * save code size. We use this for infrequently-used item types.
2689 : */
2690 : class nsDisplayGeneric : public nsDisplayItem {
2691 : public:
2692 : typedef void (* PaintCallback)(nsIFrame* aFrame, DrawTarget* aDrawTarget,
2693 : const nsRect& aDirtyRect, nsPoint aFramePt);
2694 :
2695 : // XXX: should be removed eventually
2696 : typedef void (* OldPaintCallback)(nsIFrame* aFrame, gfxContext* aCtx,
2697 : const nsRect& aDirtyRect, nsPoint aFramePt);
2698 :
2699 0 : nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2700 : PaintCallback aPaint, const char* aName, Type aType)
2701 0 : : nsDisplayItem(aBuilder, aFrame)
2702 : , mPaint(aPaint)
2703 : , mOldPaint(nullptr)
2704 : , mName(aName)
2705 0 : , mType(aType)
2706 : {
2707 0 : MOZ_COUNT_CTOR(nsDisplayGeneric);
2708 0 : }
2709 :
2710 : // XXX: should be removed eventually
2711 0 : nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2712 : OldPaintCallback aOldPaint, const char* aName, Type aType)
2713 0 : : nsDisplayItem(aBuilder, aFrame)
2714 : , mPaint(nullptr)
2715 : , mOldPaint(aOldPaint)
2716 : , mName(aName)
2717 0 : , mType(aType)
2718 : {
2719 0 : MOZ_COUNT_CTOR(nsDisplayGeneric);
2720 0 : }
2721 : #ifdef NS_BUILD_REFCNT_LOGGING
2722 0 : virtual ~nsDisplayGeneric() {
2723 0 : MOZ_COUNT_DTOR(nsDisplayGeneric);
2724 0 : }
2725 : #endif
2726 :
2727 0 : virtual void Paint(nsDisplayListBuilder* aBuilder,
2728 : gfxContext* aCtx) override {
2729 0 : MOZ_ASSERT(!!mPaint != !!mOldPaint);
2730 0 : if (mPaint) {
2731 0 : mPaint(mFrame, aCtx->GetDrawTarget(), mVisibleRect, ToReferenceFrame());
2732 : } else {
2733 0 : mOldPaint(mFrame, aCtx, mVisibleRect, ToReferenceFrame());
2734 : }
2735 0 : }
2736 0 : NS_DISPLAY_DECL_NAME(mName, mType)
2737 :
2738 : protected:
2739 : PaintCallback mPaint;
2740 : OldPaintCallback mOldPaint; // XXX: should be removed eventually
2741 : const char* mName;
2742 : Type mType;
2743 : };
2744 :
2745 : #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
2746 : /**
2747 : * This class implements painting of reflow counts. Ideally, we would simply
2748 : * make all the frame names be those returned by nsFrame::GetFrameName
2749 : * (except that tosses in the content tag name!) and support only one color
2750 : * and eliminate this class altogether in favor of nsDisplayGeneric, but for
2751 : * the time being we can't pass args to a PaintCallback, so just have a
2752 : * separate class to do the right thing. Sadly, this alsmo means we need to
2753 : * hack all leaf frame classes to handle this.
2754 : *
2755 : * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
2756 : * here... I could switch it all to nscolor, but why bother?
2757 : */
2758 : class nsDisplayReflowCount : public nsDisplayItem {
2759 : public:
2760 0 : nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2761 : const char* aFrameName,
2762 : uint32_t aColor = 0)
2763 0 : : nsDisplayItem(aBuilder, aFrame),
2764 : mFrameName(aFrameName),
2765 0 : mColor(aColor)
2766 : {
2767 0 : MOZ_COUNT_CTOR(nsDisplayReflowCount);
2768 0 : }
2769 : #ifdef NS_BUILD_REFCNT_LOGGING
2770 0 : virtual ~nsDisplayReflowCount() {
2771 0 : MOZ_COUNT_DTOR(nsDisplayReflowCount);
2772 0 : }
2773 : #endif
2774 :
2775 0 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
2776 0 : mFrame->PresContext()->PresShell()->PaintCount(mFrameName, aCtx,
2777 0 : mFrame->PresContext(),
2778 : mFrame, ToReferenceFrame(),
2779 0 : mColor);
2780 0 : }
2781 0 : NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT)
2782 : protected:
2783 : const char* mFrameName;
2784 : nscolor mColor;
2785 : };
2786 :
2787 : #define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
2788 : PR_BEGIN_MACRO \
2789 : if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
2790 : PresContext()->PresShell()->IsPaintingFrameCounts()) { \
2791 : aLists.Outlines()->AppendNewToTop( \
2792 : new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name)); \
2793 : } \
2794 : PR_END_MACRO
2795 :
2796 : #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
2797 : PR_BEGIN_MACRO \
2798 : if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
2799 : PresContext()->PresShell()->IsPaintingFrameCounts()) { \
2800 : aLists.Outlines()->AppendNewToTop( \
2801 : new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name, _color)); \
2802 : } \
2803 : PR_END_MACRO
2804 :
2805 : /*
2806 : Macro to be used for classes that don't actually implement BuildDisplayList
2807 : */
2808 : #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
2809 : void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
2810 : const nsRect& aDirtyRect, \
2811 : const nsDisplayListSet& aLists) { \
2812 : DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
2813 : _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
2814 : }
2815 :
2816 : #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
2817 :
2818 : #define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
2819 : #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
2820 : #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
2821 :
2822 : #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
2823 :
2824 : class nsDisplayCaret : public nsDisplayItem {
2825 : public:
2826 : nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame);
2827 : #ifdef NS_BUILD_REFCNT_LOGGING
2828 : virtual ~nsDisplayCaret();
2829 : #endif
2830 :
2831 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
2832 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
2833 0 : NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
2834 :
2835 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2836 : LayerManager* aManager,
2837 : const ContainerLayerParameters& aParameters) override;
2838 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2839 : LayerManager* aManager,
2840 : const ContainerLayerParameters& aContainerParameters) override;
2841 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
2842 : const StackingContextHelper& aSc,
2843 : nsTArray<WebRenderParentCommand>& aParentCommands,
2844 : mozilla::layers::WebRenderLayerManager* aManager,
2845 : nsDisplayListBuilder* aDisplayListBuilder) override;
2846 :
2847 : protected:
2848 : RefPtr<nsCaret> mCaret;
2849 : nsRect mBounds;
2850 : };
2851 :
2852 : /**
2853 : * The standard display item to paint the CSS borders of a frame.
2854 : */
2855 : class nsDisplayBorder : public nsDisplayItem {
2856 : public:
2857 : nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
2858 :
2859 : #ifdef NS_BUILD_REFCNT_LOGGING
2860 358 : virtual ~nsDisplayBorder() {
2861 179 : MOZ_COUNT_DTOR(nsDisplayBorder);
2862 179 : }
2863 : #endif
2864 :
2865 : virtual bool IsInvisibleInRect(const nsRect& aRect) override;
2866 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
2867 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2868 : LayerManager* aManager,
2869 : const ContainerLayerParameters& aParameters) override;
2870 :
2871 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2872 : LayerManager* aManager,
2873 : const ContainerLayerParameters& aContainerParameters) override;
2874 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
2875 : const StackingContextHelper& aSc,
2876 : nsTArray<WebRenderParentCommand>& aParentCommands,
2877 : mozilla::layers::WebRenderLayerManager* aManager,
2878 : nsDisplayListBuilder* aDisplayListBuilder) override;
2879 :
2880 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
2881 :
2882 1628 : NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
2883 :
2884 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
2885 :
2886 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2887 : const nsDisplayItemGeometry* aGeometry,
2888 : nsRegion* aInvalidRegion) override;
2889 :
2890 0 : virtual nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override
2891 : {
2892 0 : *aSnap = true;
2893 0 : return CalculateBounds(*mFrame->StyleBorder());
2894 : }
2895 :
2896 : protected:
2897 : void CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
2898 : const StackingContextHelper& aSc,
2899 : nsTArray<WebRenderParentCommand>& aParentCommands,
2900 : mozilla::layers::WebRenderLayerManager* aManager,
2901 : nsDisplayListBuilder* aDisplayListBuilder);
2902 : nsRegion CalculateBounds(const nsStyleBorder& aStyleBorder);
2903 :
2904 : mozilla::Array<mozilla::gfx::Color, 4> mColors;
2905 : mozilla::Array<mozilla::LayerCoord, 4> mWidths;
2906 : mozilla::Array<mozilla::LayerSize, 4> mCorners;
2907 : mozilla::Array<uint8_t, 4> mBorderStyles;
2908 : mozilla::LayerRect mRect;
2909 :
2910 : mozilla::Maybe<nsCSSBorderRenderer> mBorderRenderer;
2911 : mozilla::Maybe<nsCSSBorderImageRenderer> mBorderImageRenderer;
2912 :
2913 : nsRect mBounds;
2914 : };
2915 :
2916 : /**
2917 : * A simple display item that just renders a solid color across the
2918 : * specified bounds. For canvas frames (in the CSS sense) we split off the
2919 : * drawing of the background color into this class (from nsDisplayBackground
2920 : * via nsDisplayCanvasBackground). This is done so that we can always draw a
2921 : * background color to avoid ugly flashes of white when we can't draw a full
2922 : * frame tree (ie when a page is loading). The bounds can differ from the
2923 : * frame's bounds -- this is needed when a frame/iframe is loading and there
2924 : * is not yet a frame tree to go in the frame/iframe so we use the subdoc
2925 : * frame of the parent document as a standin.
2926 : */
2927 46 : class nsDisplaySolidColorBase : public nsDisplayItem {
2928 : public:
2929 46 : nsDisplaySolidColorBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nscolor aColor)
2930 46 : : nsDisplayItem(aBuilder, aFrame), mColor(aColor)
2931 46 : {}
2932 :
2933 3 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
2934 : {
2935 3 : return new nsDisplaySolidColorGeometry(this, aBuilder, mColor);
2936 : }
2937 :
2938 23 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2939 : const nsDisplayItemGeometry* aGeometry,
2940 : nsRegion* aInvalidRegion) override
2941 : {
2942 : const nsDisplaySolidColorGeometry* geometry =
2943 23 : static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
2944 23 : if (mColor != geometry->mColor) {
2945 : bool dummy;
2946 0 : aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
2947 0 : return;
2948 : }
2949 23 : ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
2950 : }
2951 :
2952 47 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2953 : bool* aSnap) override {
2954 47 : *aSnap = false;
2955 47 : nsRegion result;
2956 47 : if (NS_GET_A(mColor) == 255) {
2957 29 : result = GetBounds(aBuilder, aSnap);
2958 : }
2959 47 : return result;
2960 : }
2961 :
2962 46 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) override
2963 : {
2964 46 : return mozilla::Some(mColor);
2965 : }
2966 :
2967 : protected:
2968 : nscolor mColor;
2969 : };
2970 :
2971 : class nsDisplaySolidColor : public nsDisplaySolidColorBase {
2972 : public:
2973 26 : nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2974 : const nsRect& aBounds, nscolor aColor)
2975 26 : : nsDisplaySolidColorBase(aBuilder, aFrame, aColor), mBounds(aBounds)
2976 : {
2977 26 : NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
2978 26 : MOZ_COUNT_CTOR(nsDisplaySolidColor);
2979 26 : }
2980 : #ifdef NS_BUILD_REFCNT_LOGGING
2981 52 : virtual ~nsDisplaySolidColor() {
2982 26 : MOZ_COUNT_DTOR(nsDisplaySolidColor);
2983 26 : }
2984 : #endif
2985 :
2986 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
2987 :
2988 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2989 : LayerManager* aManager,
2990 : const ContainerLayerParameters& aParameters) override;
2991 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2992 : LayerManager* aManager,
2993 : const ContainerLayerParameters& aContainerParameters) override;
2994 :
2995 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
2996 :
2997 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
2998 :
2999 232 : NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
3000 :
3001 : private:
3002 : nsRect mBounds;
3003 : };
3004 :
3005 : /**
3006 : * A display item that renders a solid color over a region. This is not
3007 : * exposed through CSS, its only purpose is efficient invalidation of
3008 : * the find bar highlighter dimmer.
3009 : */
3010 : class nsDisplaySolidColorRegion : public nsDisplayItem {
3011 : typedef mozilla::gfx::Color Color;
3012 :
3013 : public:
3014 0 : nsDisplaySolidColorRegion(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3015 : const nsRegion& aRegion, nscolor aColor)
3016 0 : : nsDisplayItem(aBuilder, aFrame), mRegion(aRegion), mColor(Color::FromABGR(aColor))
3017 : {
3018 0 : NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColorRegions!");
3019 0 : MOZ_COUNT_CTOR(nsDisplaySolidColorRegion);
3020 0 : }
3021 : #ifdef NS_BUILD_REFCNT_LOGGING
3022 0 : virtual ~nsDisplaySolidColorRegion() {
3023 0 : MOZ_COUNT_DTOR(nsDisplaySolidColorRegion);
3024 0 : }
3025 : #endif
3026 :
3027 0 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
3028 : {
3029 0 : return new nsDisplaySolidColorRegionGeometry(this, aBuilder, mRegion, mColor);
3030 : }
3031 :
3032 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3033 : const nsDisplayItemGeometry* aGeometry,
3034 : nsRegion* aInvalidRegion) override
3035 : {
3036 : const nsDisplaySolidColorRegionGeometry* geometry =
3037 0 : static_cast<const nsDisplaySolidColorRegionGeometry*>(aGeometry);
3038 0 : if (mColor == geometry->mColor) {
3039 0 : aInvalidRegion->Xor(geometry->mRegion, mRegion);
3040 : } else {
3041 0 : aInvalidRegion->Or(geometry->mRegion.GetBounds(), mRegion.GetBounds());
3042 : }
3043 0 : }
3044 :
3045 : protected:
3046 :
3047 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
3048 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3049 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
3050 :
3051 0 : NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION)
3052 :
3053 : private:
3054 : nsRegion mRegion;
3055 : Color mColor;
3056 : };
3057 :
3058 : /**
3059 : * A display item to paint one background-image for a frame. Each background
3060 : * image layer gets its own nsDisplayBackgroundImage.
3061 : */
3062 : class nsDisplayBackgroundImage : public nsDisplayImageContainer {
3063 : public:
3064 : typedef mozilla::StyleGeometryBox StyleGeometryBox;
3065 :
3066 194 : struct InitData {
3067 : nsDisplayListBuilder* builder;
3068 : nsIFrame* frame;
3069 : const nsStyleBackground* backgroundStyle;
3070 : nsCOMPtr<imgIContainer> image;
3071 : nsRect backgroundRect;
3072 : nsRect fillArea;
3073 : nsRect destArea;
3074 : uint32_t layer;
3075 : bool isRasterImage;
3076 : bool shouldFixToViewport;
3077 : };
3078 :
3079 : /**
3080 : * aLayer signifies which background layer this item represents.
3081 : * aIsThemed should be the value of aFrame->IsThemed.
3082 : * aBackgroundStyle should be the result of
3083 : * nsCSSRendering::FindBackground, or null if FindBackground returned false.
3084 : * aBackgroundRect is relative to aFrame.
3085 : */
3086 : enum class LayerizeFixed : uint8_t {
3087 : ALWAYS_LAYERIZE_FIXED_BACKGROUND,
3088 : DO_NOT_LAYERIZE_FIXED_BACKGROUND_IF_AVOIDING_COMPONENT_ALPHA_LAYERS
3089 : };
3090 : static InitData GetInitData(nsDisplayListBuilder* aBuilder,
3091 : nsIFrame* aFrame,
3092 : uint32_t aLayer,
3093 : const nsRect& aBackgroundRect,
3094 : const nsStyleBackground* aBackgroundStyle,
3095 : LayerizeFixed aLayerizeFixed);
3096 :
3097 : explicit nsDisplayBackgroundImage(const InitData& aInitData);
3098 : virtual ~nsDisplayBackgroundImage();
3099 :
3100 : // This will create and append new items for all the layers of the
3101 : // background. Returns whether we appended a themed background.
3102 : // aAllowWillPaintBorderOptimization should usually be left at true, unless
3103 : // aFrame has special border drawing that causes opaque borders to not
3104 : // actually be opaque.
3105 : static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
3106 : nsIFrame* aFrame,
3107 : const nsRect& aBackgroundRect,
3108 : nsDisplayList* aList,
3109 : bool aAllowWillPaintBorderOptimization = true,
3110 : nsStyleContext* aStyleContext = nullptr,
3111 : const nsRect& aBackgroundOriginRect = nsRect(),
3112 : nsIFrame* aSecondaryReferenceFrame = nullptr);
3113 :
3114 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3115 : LayerManager* aManager,
3116 : const ContainerLayerParameters& aParameters) override;
3117 :
3118 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3119 : LayerManager* aManager,
3120 : const ContainerLayerParameters& aContainerParameters) override;
3121 :
3122 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3123 : const StackingContextHelper& aSc,
3124 : nsTArray<WebRenderParentCommand>& aParentCommands,
3125 : mozilla::layers::WebRenderLayerManager* aManager,
3126 : nsDisplayListBuilder* aDisplayListBuilder) override;
3127 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
3128 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
3129 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
3130 : nsRegion* aVisibleRegion) override;
3131 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3132 : bool* aSnap) override;
3133 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) override;
3134 : /**
3135 : * GetBounds() returns the background painting area.
3136 : */
3137 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
3138 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3139 : virtual uint32_t GetPerFrameKey() override;
3140 1530 : NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
3141 :
3142 : /**
3143 : * Return the background positioning area.
3144 : * (GetBounds() returns the background painting area.)
3145 : * Can be called only when mBackgroundStyle is non-null.
3146 : */
3147 : nsRect GetPositioningArea();
3148 :
3149 : /**
3150 : * Returns true if existing rendered pixels of this display item may need
3151 : * to be redrawn if the positioning area size changes but its position does
3152 : * not.
3153 : * If false, only the changed painting area needs to be redrawn when the
3154 : * positioning area size changes but its position does not.
3155 : */
3156 : bool RenderingMightDependOnPositioningAreaSizeChange();
3157 :
3158 16 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
3159 : {
3160 16 : return new nsDisplayBackgroundGeometry(this, aBuilder);
3161 : }
3162 :
3163 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3164 : const nsDisplayItemGeometry* aGeometry,
3165 : nsRegion* aInvalidRegion) override;
3166 :
3167 : virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
3168 : nsDisplayListBuilder* aBuilder) override;
3169 : virtual already_AddRefed<imgIContainer> GetImage() override;
3170 : virtual nsRect GetDestRect() override;
3171 :
3172 : static nsRegion GetInsideClipRegion(nsDisplayItem* aItem,
3173 : StyleGeometryBox aClip,
3174 : const nsRect& aRect,
3175 : const nsRect& aBackgroundRect);
3176 :
3177 0 : virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) override { return mShouldFixToViewport; }
3178 :
3179 : protected:
3180 : typedef class mozilla::layers::ImageContainer ImageContainer;
3181 : typedef class mozilla::layers::ImageLayer ImageLayer;
3182 :
3183 : bool CanBuildWebRenderDisplayItems(LayerManager* aManager);
3184 : bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
3185 : nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder);
3186 :
3187 : void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
3188 : const nsRect& aBounds, nsRect* aClipRect);
3189 :
3190 310 : virtual nsIFrame* StyleFrame() { return mFrame; }
3191 :
3192 : // Determine whether we want to be separated into our own layer, independent
3193 : // of whether this item can actually be layerized.
3194 : enum ImageLayerization {
3195 : WHENEVER_POSSIBLE,
3196 : ONLY_FOR_SCALING,
3197 : NO_LAYER_NEEDED
3198 : };
3199 : ImageLayerization ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
3200 : LayerManager* aManager);
3201 :
3202 : // Cache the result of nsCSSRendering::FindBackground. Always null if
3203 : // mIsThemed is true or if FindBackground returned false.
3204 : const nsStyleBackground* mBackgroundStyle;
3205 : nsCOMPtr<imgIContainer> mImage;
3206 : nsRect mBackgroundRect; // relative to the reference frame
3207 : nsRect mFillRect;
3208 : nsRect mDestRect;
3209 : /* Bounds of this display item */
3210 : nsRect mBounds;
3211 : uint32_t mLayer;
3212 : bool mIsRasterImage;
3213 : /* Whether the image should be treated as fixed to the viewport. */
3214 : bool mShouldFixToViewport;
3215 : uint32_t mImageFlags;
3216 : };
3217 :
3218 : enum class TableType : uint8_t {
3219 : TABLE,
3220 : TABLE_COL,
3221 : TABLE_COL_GROUP,
3222 : TABLE_ROW,
3223 : TABLE_ROW_GROUP,
3224 : TABLE_CELL,
3225 :
3226 : TABLE_TYPE_MAX
3227 : };
3228 :
3229 : enum class TableTypeBits : uint8_t {
3230 : COUNT = 3
3231 : };
3232 :
3233 : static_assert(
3234 : static_cast<uint8_t>(TableType::TABLE_TYPE_MAX) < (1 << (static_cast<uint8_t>(TableTypeBits::COUNT) + 1)),
3235 : "TableType cannot fit with TableTypeBits::COUNT");
3236 : TableType GetTableTypeFromFrame(nsIFrame* aFrame);
3237 :
3238 : /**
3239 : * A display item to paint background image for table. For table parts, such
3240 : * as row, row group, col, col group, when drawing its background, we'll
3241 : * create separate background image display item for its containning cell.
3242 : * Those background image display items will reference to same DisplayItemData
3243 : * if we keep the mFrame point to cell's ancestor frame. We don't want to this
3244 : * happened bacause share same DisplatItemData will cause many bugs. So that
3245 : * we let mFrame point to cell frame and store the table type of the ancestor
3246 : * frame. And use mFrame and table type as key to generate DisplayItemData to
3247 : * avoid sharing DisplayItemData.
3248 : *
3249 : * Also store ancestor frame as mStyleFrame for all rendering informations.
3250 : */
3251 0 : class nsDisplayTableBackgroundImage : public nsDisplayBackgroundImage {
3252 : public:
3253 : nsDisplayTableBackgroundImage(const InitData& aInitData, nsIFrame* aCellFrame);
3254 :
3255 0 : virtual uint32_t GetPerFrameKey() override {
3256 0 : return (static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
3257 0 : nsDisplayItem::GetPerFrameKey();
3258 : }
3259 :
3260 : virtual bool IsInvalid(nsRect& aRect) override;
3261 : protected:
3262 0 : virtual nsIFrame* StyleFrame() override { return mStyleFrame; }
3263 :
3264 : nsIFrame* mStyleFrame;
3265 : TableType mTableType;
3266 : };
3267 :
3268 : /**
3269 : * A display item to paint the native theme background for a frame.
3270 : */
3271 : class nsDisplayThemedBackground : public nsDisplayItem {
3272 : public:
3273 : nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3274 : const nsRect& aBackgroundRect);
3275 : virtual ~nsDisplayThemedBackground();
3276 :
3277 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
3278 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
3279 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3280 : bool* aSnap) override;
3281 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) override;
3282 : virtual bool ProvidesFontSmoothingBackgroundColor(nscolor* aColor) override;
3283 :
3284 : /**
3285 : * GetBounds() returns the background painting area.
3286 : */
3287 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
3288 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3289 406 : NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND)
3290 :
3291 : /**
3292 : * Return the background positioning area.
3293 : * (GetBounds() returns the background painting area.)
3294 : * Can be called only when mBackgroundStyle is non-null.
3295 : */
3296 : nsRect GetPositioningArea();
3297 :
3298 : /**
3299 : * Return whether our frame's document does not have the state
3300 : * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
3301 : */
3302 : bool IsWindowActive();
3303 :
3304 4 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
3305 : {
3306 4 : return new nsDisplayThemedBackgroundGeometry(this, aBuilder);
3307 : }
3308 :
3309 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3310 : const nsDisplayItemGeometry* aGeometry,
3311 : nsRegion* aInvalidRegion) override;
3312 :
3313 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
3314 : protected:
3315 : nsRect GetBoundsInternal();
3316 :
3317 : void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
3318 : const nsRect& aBounds, nsRect* aClipRect);
3319 :
3320 : nsRect mBackgroundRect;
3321 : nsRect mBounds;
3322 : nsITheme::Transparency mThemeTransparency;
3323 : uint8_t mAppearance;
3324 : };
3325 :
3326 292 : class nsDisplayBackgroundColor : public nsDisplayItem
3327 : {
3328 : typedef mozilla::gfx::Color Color;
3329 :
3330 : public:
3331 292 : nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3332 : const nsRect& aBackgroundRect,
3333 : const nsStyleBackground* aBackgroundStyle,
3334 : nscolor aColor)
3335 292 : : nsDisplayItem(aBuilder, aFrame)
3336 : , mBackgroundRect(aBackgroundRect)
3337 : , mBackgroundStyle(aBackgroundStyle)
3338 292 : , mColor(Color::FromABGR(aColor))
3339 292 : { }
3340 :
3341 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3342 : LayerManager* aManager,
3343 : const ContainerLayerParameters& aParameters) override;
3344 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3345 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3346 : LayerManager* aManager,
3347 : const ContainerLayerParameters& aContainerParameters) override;
3348 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3349 : const StackingContextHelper& aSc,
3350 : nsTArray<WebRenderParentCommand>& aParentCommands,
3351 : mozilla::layers::WebRenderLayerManager* aManager,
3352 : nsDisplayListBuilder* aDisplayListBuilder) override;
3353 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3354 : bool* aSnap) override;
3355 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) override;
3356 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
3357 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
3358 :
3359 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
3360 : float aOpacity,
3361 : const DisplayItemClipChain* aClip) override;
3362 : virtual bool CanApplyOpacity() const override;
3363 :
3364 862 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override
3365 : {
3366 862 : *aSnap = true;
3367 862 : return mBackgroundRect;
3368 : }
3369 :
3370 19 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
3371 : {
3372 38 : return new nsDisplaySolidColorGeometry(this, aBuilder, mColor.ToABGR());
3373 : }
3374 :
3375 144 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3376 : const nsDisplayItemGeometry* aGeometry,
3377 : nsRegion* aInvalidRegion) override
3378 : {
3379 144 : const nsDisplaySolidColorGeometry* geometry = static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
3380 144 : if (mColor.ToABGR() != geometry->mColor) {
3381 : bool dummy;
3382 0 : aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
3383 0 : return;
3384 : }
3385 144 : ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
3386 : }
3387 :
3388 1508 : NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
3389 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
3390 :
3391 : protected:
3392 : const nsRect mBackgroundRect;
3393 : const nsStyleBackground* mBackgroundStyle;
3394 : mozilla::gfx::Color mColor;
3395 : };
3396 :
3397 0 : class nsDisplayTableBackgroundColor : public nsDisplayBackgroundColor
3398 : {
3399 : public:
3400 0 : nsDisplayTableBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3401 : const nsRect& aBackgroundRect,
3402 : const nsStyleBackground* aBackgroundStyle,
3403 : nscolor aColor,
3404 : nsIFrame* aAncestorFrame)
3405 0 : : nsDisplayBackgroundColor(aBuilder, aFrame, aBackgroundRect, aBackgroundStyle, aColor)
3406 0 : , mTableType(GetTableTypeFromFrame(aAncestorFrame))
3407 0 : { }
3408 :
3409 0 : virtual uint32_t GetPerFrameKey() override {
3410 0 : return (static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
3411 0 : nsDisplayItem::GetPerFrameKey();
3412 : }
3413 : protected:
3414 : TableType mTableType;
3415 : };
3416 :
3417 0 : class nsDisplayClearBackground : public nsDisplayItem
3418 : {
3419 : public:
3420 0 : nsDisplayClearBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
3421 0 : : nsDisplayItem(aBuilder, aFrame)
3422 0 : { }
3423 :
3424 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override
3425 : {
3426 0 : *aSnap = true;
3427 0 : return nsRect(ToReferenceFrame(), Frame()->GetSize());
3428 : }
3429 :
3430 0 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3431 : bool* aSnap) override {
3432 0 : *aSnap = false;
3433 0 : return GetBounds(aBuilder, aSnap);
3434 : }
3435 :
3436 0 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) override
3437 : {
3438 0 : return mozilla::Some(NS_RGBA(0, 0, 0, 0));
3439 : }
3440 :
3441 0 : virtual bool ClearsBackground() override
3442 : {
3443 0 : return true;
3444 : }
3445 :
3446 0 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3447 : LayerManager* aManager,
3448 : const ContainerLayerParameters& aParameters) override
3449 : {
3450 0 : return mozilla::LAYER_ACTIVE_FORCE;
3451 : }
3452 :
3453 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3454 : LayerManager* aManager,
3455 : const ContainerLayerParameters& aContainerParameters) override;
3456 :
3457 0 : NS_DISPLAY_DECL_NAME("ClearBackground", TYPE_CLEAR_BACKGROUND)
3458 : };
3459 :
3460 : /**
3461 : * The standard display item to paint the outer CSS box-shadows of a frame.
3462 : */
3463 : class nsDisplayBoxShadowOuter final : public nsDisplayItem {
3464 : public:
3465 48 : nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
3466 48 : : nsDisplayItem(aBuilder, aFrame)
3467 48 : , mOpacity(1.0) {
3468 48 : MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
3469 48 : mBounds = GetBoundsInternal();
3470 48 : }
3471 : #ifdef NS_BUILD_REFCNT_LOGGING
3472 96 : virtual ~nsDisplayBoxShadowOuter() {
3473 48 : MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter);
3474 48 : }
3475 : #endif
3476 :
3477 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3478 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
3479 : virtual bool IsInvisibleInRect(const nsRect& aRect) override;
3480 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
3481 : nsRegion* aVisibleRegion) override;
3482 331 : NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
3483 :
3484 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3485 : const nsDisplayItemGeometry* aGeometry,
3486 : nsRegion* aInvalidRegion) override;
3487 :
3488 0 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
3489 : float aOpacity,
3490 : const DisplayItemClipChain* aClip) override
3491 : {
3492 0 : NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
3493 0 : mOpacity = aOpacity;
3494 0 : IntersectClip(aBuilder, aClip);
3495 0 : }
3496 0 : virtual bool CanApplyOpacity() const override
3497 : {
3498 0 : return true;
3499 : }
3500 :
3501 8 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
3502 : {
3503 8 : return new nsDisplayBoxShadowOuterGeometry(this, aBuilder, mOpacity);
3504 : }
3505 :
3506 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3507 : LayerManager* aManager,
3508 : const ContainerLayerParameters& aParameters) override;
3509 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3510 : LayerManager* aManager,
3511 : const ContainerLayerParameters& aContainerParameters) override;
3512 :
3513 : bool CanBuildWebRenderDisplayItems();
3514 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3515 : const StackingContextHelper& aSc,
3516 : nsTArray<WebRenderParentCommand>& aParentCommands,
3517 : mozilla::layers::WebRenderLayerManager* aManager,
3518 : nsDisplayListBuilder* aDisplayListBuilder) override;
3519 : nsRect GetBoundsInternal();
3520 :
3521 : private:
3522 : nsRegion mVisibleRegion;
3523 : nsRect mBounds;
3524 : float mOpacity;
3525 : };
3526 :
3527 : /**
3528 : * The standard display item to paint the inner CSS box-shadows of a frame.
3529 : */
3530 : class nsDisplayBoxShadowInner : public nsDisplayItem {
3531 : public:
3532 24 : nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
3533 24 : : nsDisplayItem(aBuilder, aFrame) {
3534 24 : MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
3535 24 : }
3536 : #ifdef NS_BUILD_REFCNT_LOGGING
3537 48 : virtual ~nsDisplayBoxShadowInner() {
3538 24 : MOZ_COUNT_DTOR(nsDisplayBoxShadowInner);
3539 24 : }
3540 : #endif
3541 :
3542 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3543 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
3544 : nsRegion* aVisibleRegion) override;
3545 219 : NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
3546 :
3547 2 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
3548 : {
3549 2 : return new nsDisplayBoxShadowInnerGeometry(this, aBuilder);
3550 : }
3551 :
3552 23 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3553 : const nsDisplayItemGeometry* aGeometry,
3554 : nsRegion* aInvalidRegion) override
3555 : {
3556 23 : const nsDisplayBoxShadowInnerGeometry* geometry = static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry);
3557 23 : if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
3558 : // nsDisplayBoxShadowInner is based around the padding rect, but it can
3559 : // touch pixels outside of this. We should invalidate the entire bounds.
3560 : bool snap;
3561 1 : aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
3562 : }
3563 23 : }
3564 :
3565 : static bool CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder,
3566 : nsIFrame* aFrame,
3567 : nsPoint aReferencePoint);
3568 : static void CreateInsetBoxShadowWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3569 : const StackingContextHelper& aSc,
3570 : nsRegion& aVisibleRegion,
3571 : nsIFrame* aFrame,
3572 : const nsRect aBorderRect);
3573 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3574 : LayerManager* aManager,
3575 : const ContainerLayerParameters& aParameters) override;
3576 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3577 : LayerManager* aManager,
3578 : const ContainerLayerParameters& aContainerParameters) override;
3579 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3580 : const StackingContextHelper& aSc,
3581 : nsTArray<WebRenderParentCommand>& aParentCommands,
3582 : mozilla::layers::WebRenderLayerManager* aManager,
3583 : nsDisplayListBuilder* aDisplayListBuilder) override;
3584 :
3585 : private:
3586 : nsRegion mVisibleRegion;
3587 : };
3588 :
3589 : /**
3590 : * The standard display item to paint the CSS outline of a frame.
3591 : */
3592 : class nsDisplayOutline : public nsDisplayItem {
3593 : public:
3594 0 : nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
3595 0 : nsDisplayItem(aBuilder, aFrame) {
3596 0 : MOZ_COUNT_CTOR(nsDisplayOutline);
3597 0 : }
3598 : #ifdef NS_BUILD_REFCNT_LOGGING
3599 0 : virtual ~nsDisplayOutline() {
3600 0 : MOZ_COUNT_DTOR(nsDisplayOutline);
3601 0 : }
3602 : #endif
3603 :
3604 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3605 : LayerManager* aManager,
3606 : const ContainerLayerParameters& aParameters) override;
3607 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3608 : LayerManager* aManager,
3609 : const ContainerLayerParameters& aContainerParameters) override;
3610 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
3611 : const StackingContextHelper& aSc,
3612 : nsTArray<WebRenderParentCommand>& aParentCommands,
3613 : mozilla::layers::WebRenderLayerManager* aManager,
3614 : nsDisplayListBuilder* aDisplayListBuilder) override;
3615 : virtual bool IsInvisibleInRect(const nsRect& aRect) override;
3616 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
3617 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3618 0 : NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
3619 :
3620 : mozilla::Maybe<nsCSSBorderRenderer> mBorderRenderer;
3621 : };
3622 :
3623 : /**
3624 : * A class that lets you receive events within the frame bounds but never paints.
3625 : */
3626 : class nsDisplayEventReceiver : public nsDisplayItem {
3627 : public:
3628 0 : nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
3629 0 : : nsDisplayItem(aBuilder, aFrame) {
3630 0 : MOZ_COUNT_CTOR(nsDisplayEventReceiver);
3631 0 : }
3632 : #ifdef NS_BUILD_REFCNT_LOGGING
3633 0 : virtual ~nsDisplayEventReceiver() {
3634 0 : MOZ_COUNT_DTOR(nsDisplayEventReceiver);
3635 0 : }
3636 : #endif
3637 :
3638 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
3639 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
3640 0 : NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
3641 : };
3642 :
3643 : /**
3644 : * A display item that tracks event-sensitive regions which will be set
3645 : * on the ContainerLayer that eventually contains this item.
3646 : *
3647 : * One of these is created for each stacking context and pseudo-stacking-context.
3648 : * It accumulates regions for event targets contributed by the border-boxes of
3649 : * frames in its (pseudo) stacking context. A nsDisplayLayerEventRegions
3650 : * eventually contributes its regions to the PaintedLayer it is placed in by
3651 : * FrameLayerBuilder. (We don't create a display item for every frame that
3652 : * could be an event target (i.e. almost all frames), because that would be
3653 : * high overhead.)
3654 : *
3655 : * We always make leaf layers other than PaintedLayers transparent to events.
3656 : * For example, an event targeting a canvas or video will actually target the
3657 : * background of that element, which is logically in the PaintedLayer behind the
3658 : * CanvasFrame or ImageFrame. We only need to create a
3659 : * nsDisplayLayerEventRegions when an element's background could be in front
3660 : * of a lower z-order element with its own layer.
3661 : */
3662 : class nsDisplayLayerEventRegions final : public nsDisplayItem {
3663 : public:
3664 647 : nsDisplayLayerEventRegions(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
3665 647 : : nsDisplayItem(aBuilder, aFrame)
3666 : {
3667 647 : MOZ_COUNT_CTOR(nsDisplayLayerEventRegions);
3668 647 : }
3669 : #ifdef NS_BUILD_REFCNT_LOGGING
3670 1294 : virtual ~nsDisplayLayerEventRegions() {
3671 647 : MOZ_COUNT_DTOR(nsDisplayLayerEventRegions);
3672 647 : }
3673 : #endif
3674 1720 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override
3675 : {
3676 1720 : *aSnap = false;
3677 1720 : return nsRect();
3678 : }
3679 461 : nsRect GetHitRegionBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
3680 : {
3681 461 : *aSnap = false;
3682 461 : return mHitRegion.GetBounds().Union(mMaybeHitRegion.GetBounds());
3683 : }
3684 :
3685 0 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
3686 : float aOpacity,
3687 : const DisplayItemClipChain* aClip) override
3688 : {
3689 0 : NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
3690 0 : }
3691 0 : virtual bool CanApplyOpacity() const override
3692 : {
3693 0 : return true;
3694 : }
3695 :
3696 1481 : NS_DISPLAY_DECL_NAME("LayerEventRegions", TYPE_LAYER_EVENT_REGIONS)
3697 :
3698 : // Indicate that aFrame's border-box contributes to the event regions for
3699 : // this layer. aFrame must have the same reference frame as mFrame.
3700 : void AddFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
3701 :
3702 : // Indicate that an inactive scrollframe's scrollport should be added to the
3703 : // dispatch-to-content region, to ensure that APZ lets content create a
3704 : // displayport.
3705 : void AddInactiveScrollPort(const nsRect& aRect);
3706 :
3707 : bool IsEmpty() const;
3708 :
3709 : int32_t ZIndex() const override;
3710 : void SetOverrideZIndex(int32_t aZIndex);
3711 :
3712 461 : const nsRegion& HitRegion() { return mHitRegion; }
3713 461 : const nsRegion& MaybeHitRegion() { return mMaybeHitRegion; }
3714 461 : const nsRegion& DispatchToContentHitRegion() { return mDispatchToContentHitRegion; }
3715 461 : const nsRegion& NoActionRegion() { return mNoActionRegion; }
3716 461 : const nsRegion& HorizontalPanRegion() { return mHorizontalPanRegion; }
3717 461 : const nsRegion& VerticalPanRegion() { return mVerticalPanRegion; }
3718 : nsRegion CombinedTouchActionRegion();
3719 :
3720 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
3721 :
3722 : private:
3723 : // Relative to aFrame's reference frame.
3724 : // These are the points that are definitely in the hit region.
3725 : nsRegion mHitRegion;
3726 : // These are points that may or may not be in the hit region. Only main-thread
3727 : // event handling can tell for sure (e.g. because complex shapes are present).
3728 : nsRegion mMaybeHitRegion;
3729 : // These are points that need to be dispatched to the content thread for
3730 : // resolution. Always contained in the union of mHitRegion and mMaybeHitRegion.
3731 : nsRegion mDispatchToContentHitRegion;
3732 : // These are points where panning is disabled, as determined by the touch-action
3733 : // property. Always contained in the union of mHitRegion and mMaybeHitRegion.
3734 : nsRegion mNoActionRegion;
3735 : // These are points where panning is horizontal, as determined by the touch-action
3736 : // property. Always contained in the union of mHitRegion and mMaybeHitRegion.
3737 : nsRegion mHorizontalPanRegion;
3738 : // These are points where panning is vertical, as determined by the touch-action
3739 : // property. Always contained in the union of mHitRegion and mMaybeHitRegion.
3740 : nsRegion mVerticalPanRegion;
3741 : // If these event regions are for an inactive scroll frame, the z-index of
3742 : // this display item is overridden to be the largest z-index of the content
3743 : // in the scroll frame. This ensures that the event regions item remains on
3744 : // top of the content after sorting items by z-index.
3745 : mozilla::Maybe<int32_t> mOverrideZIndex;
3746 : };
3747 :
3748 : /**
3749 : * A class that lets you wrap a display list as a display item.
3750 : *
3751 : * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
3752 : * list has many items, it's not clear which one has the 'underlying frame'.
3753 : * Thus we force the creator to specify what the underlying frame is. The
3754 : * underlying frame should be the root of a stacking context, because sorting
3755 : * a list containing this item will not get at the children.
3756 : *
3757 : * In some cases (e.g., clipping) we want to wrap a list but we don't have a
3758 : * particular underlying frame that is a stacking context root. In that case
3759 : * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
3760 : * detect and handle this case.
3761 : */
3762 : class nsDisplayWrapList : public nsDisplayItem {
3763 : public:
3764 : /**
3765 : * Takes all the items from aList and puts them in our list.
3766 : */
3767 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3768 : nsDisplayList* aList);
3769 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3770 : nsDisplayList* aList,
3771 : const ActiveScrolledRoot* aActiveScrolledRoot);
3772 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3773 : nsDisplayItem* aItem);
3774 0 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
3775 0 : : nsDisplayItem(aBuilder, aFrame), mOverrideZIndex(0), mHasZIndexOverride(false)
3776 : {
3777 0 : MOZ_COUNT_CTOR(nsDisplayWrapList);
3778 0 : mBaseVisibleRect = mVisibleRect;
3779 0 : }
3780 : virtual ~nsDisplayWrapList();
3781 : /**
3782 : * Call this if the wrapped list is changed.
3783 : */
3784 562 : virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
3785 : {
3786 562 : mBounds = mList.GetClippedBoundsWithRespectToASR(aBuilder, mActiveScrolledRoot);
3787 : // The display list may contain content that's visible outside the visible
3788 : // rect (i.e. the current dirty rect) passed in when the item was created.
3789 : // This happens when the dirty rect has been restricted to the visual
3790 : // overflow rect of a frame for some reason (e.g. when setting up dirty
3791 : // rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
3792 : // frame contains placeholders for out-of-flows that aren't descendants of
3793 : // the frame.
3794 562 : mVisibleRect.UnionRect(mBaseVisibleRect, mList.GetVisibleRect());
3795 562 : }
3796 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
3797 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
3798 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
3799 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3800 : bool* aSnap) override;
3801 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) override;
3802 : virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3803 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
3804 : nsRegion* aVisibleRegion) override;
3805 517 : virtual bool TryMerge(nsDisplayItem* aItem) override {
3806 517 : return false;
3807 : }
3808 310 : virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) override
3809 : {
3810 310 : aFrames->AppendElements(mMergedFrames);
3811 310 : }
3812 312 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
3813 312 : return true;
3814 : }
3815 90 : virtual bool IsInvalid(nsRect& aRect) override
3816 : {
3817 90 : if (mFrame->IsInvalid(aRect) && aRect.IsEmpty()) {
3818 17 : return true;
3819 : }
3820 146 : nsRect temp;
3821 73 : for (uint32_t i = 0; i < mMergedFrames.Length(); i++) {
3822 0 : if (mMergedFrames[i]->IsInvalid(temp) && temp.IsEmpty()) {
3823 0 : aRect.SetEmpty();
3824 0 : return true;
3825 : }
3826 0 : aRect = aRect.Union(temp);
3827 : }
3828 73 : aRect += ToReferenceFrame();
3829 73 : return !aRect.IsEmpty();
3830 : }
3831 378 : NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
3832 :
3833 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override;
3834 :
3835 520 : virtual nsDisplayList* GetSameCoordinateSystemChildren() override
3836 : {
3837 520 : NS_ASSERTION(mList.IsEmpty() || !ReferenceFrame() ||
3838 : !mList.GetBottom()->ReferenceFrame() ||
3839 : mList.GetBottom()->ReferenceFrame() == ReferenceFrame(),
3840 : "Children must have same reference frame");
3841 520 : return &mList;
3842 : }
3843 76 : virtual nsDisplayList* GetChildren() override { return &mList; }
3844 :
3845 493 : virtual int32_t ZIndex() const override
3846 : {
3847 493 : return (mHasZIndexOverride) ? mOverrideZIndex : nsDisplayItem::ZIndex();
3848 : }
3849 :
3850 0 : void SetOverrideZIndex(int32_t aZIndex)
3851 : {
3852 0 : mHasZIndexOverride = true;
3853 0 : mOverrideZIndex = aZIndex;
3854 0 : }
3855 :
3856 : void SetVisibleRect(const nsRect& aRect);
3857 :
3858 : void SetReferenceFrame(const nsIFrame* aFrame);
3859 :
3860 : /**
3861 : * This creates a copy of this item, but wrapping aItem instead of
3862 : * our existing list. Only gets called if this item returned nullptr
3863 : * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
3864 : * GetUnderlyingFrame().
3865 : */
3866 0 : virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
3867 : nsDisplayItem* aItem) {
3868 0 : NS_NOTREACHED("We never returned nullptr for GetUnderlyingFrame!");
3869 0 : return nullptr;
3870 : }
3871 :
3872 : protected:
3873 : nsDisplayWrapList() {}
3874 :
3875 0 : void MergeFromTrackingMergedFrames(nsDisplayWrapList* aOther)
3876 : {
3877 0 : mList.AppendToBottom(&aOther->mList);
3878 0 : mBounds.UnionRect(mBounds, aOther->mBounds);
3879 0 : mVisibleRect.UnionRect(mVisibleRect, aOther->mVisibleRect);
3880 0 : mMergedFrames.AppendElement(aOther->mFrame);
3881 0 : mMergedFrames.AppendElements(mozilla::Move(aOther->mMergedFrames));
3882 0 : }
3883 :
3884 : nsDisplayList mList;
3885 : // The frames from items that have been merged into this item, excluding
3886 : // this item's own frame.
3887 : nsTArray<nsIFrame*> mMergedFrames;
3888 : nsRect mBounds;
3889 : // Visible rect contributed by this display item itself.
3890 : // Our mVisibleRect may include the visible areas of children.
3891 : nsRect mBaseVisibleRect;
3892 : int32_t mOverrideZIndex;
3893 : bool mHasZIndexOverride;
3894 : };
3895 :
3896 : /**
3897 : * We call WrapDisplayList on the in-flow lists: BorderBackground(),
3898 : * BlockBorderBackgrounds() and Content().
3899 : * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
3900 : * and Floats(). This is done to support special wrapping processing for frames
3901 : * that may not be in-flow descendants of the current frame.
3902 : */
3903 : class nsDisplayWrapper {
3904 : public:
3905 : // This is never instantiated directly (it has pure virtual methods), so no
3906 : // need to count constructors and destructors.
3907 :
3908 0 : virtual bool WrapBorderBackground() { return true; }
3909 : virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
3910 : nsIFrame* aFrame, nsDisplayList* aList) = 0;
3911 : virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
3912 : nsDisplayItem* aItem) = 0;
3913 :
3914 : nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3915 : const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
3916 : nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3917 : const nsDisplayListSet& aLists);
3918 : protected:
3919 0 : nsDisplayWrapper() {}
3920 : };
3921 :
3922 : /**
3923 : * The standard display item to paint a stacking context with translucency
3924 : * set by the stacking context root frame's 'opacity' style.
3925 : */
3926 : class nsDisplayOpacity : public nsDisplayWrapList {
3927 : public:
3928 : nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3929 : nsDisplayList* aList,
3930 : const ActiveScrolledRoot* aActiveScrolledRoot,
3931 : bool aForEventsAndPluginsOnly);
3932 : #ifdef NS_BUILD_REFCNT_LOGGING
3933 : virtual ~nsDisplayOpacity();
3934 : #endif
3935 :
3936 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3937 : bool* aSnap) override;
3938 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3939 : LayerManager* aManager,
3940 : const ContainerLayerParameters& aContainerParameters) override;
3941 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
3942 : LayerManager* aManager,
3943 : const ContainerLayerParameters& aParameters) override;
3944 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
3945 : nsRegion* aVisibleRegion) override;
3946 : virtual bool TryMerge(nsDisplayItem* aItem) override;
3947 123 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3948 : const nsDisplayItemGeometry* aGeometry,
3949 : nsRegion* aInvalidRegion) override
3950 : {
3951 : // We don't need to compute an invalidation region since we have LayerTreeInvalidation
3952 123 : }
3953 127 : virtual bool IsInvalid(nsRect& aRect) override
3954 : {
3955 127 : if (mForEventsAndPluginsOnly) {
3956 69 : return false;
3957 : }
3958 58 : return nsDisplayWrapList::IsInvalid(aRect);
3959 : }
3960 : virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
3961 : float aOpacity,
3962 : const DisplayItemClipChain* aClip) override;
3963 : virtual bool CanApplyOpacity() const override;
3964 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
3965 : static bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
3966 2458 : NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
3967 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
3968 :
3969 : bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
3970 :
3971 : private:
3972 : float mOpacity;
3973 : bool mForEventsAndPluginsOnly;
3974 : };
3975 :
3976 : class nsDisplayBlendMode : public nsDisplayWrapList {
3977 : public:
3978 : nsDisplayBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3979 : nsDisplayList* aList, uint8_t aBlendMode,
3980 : const ActiveScrolledRoot* aActiveScrolledRoot,
3981 : uint32_t aIndex = 0);
3982 : #ifdef NS_BUILD_REFCNT_LOGGING
3983 : virtual ~nsDisplayBlendMode();
3984 : #endif
3985 :
3986 : nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3987 : bool* aSnap) override;
3988 :
3989 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
3990 : LayerManager* aManager,
3991 : const ContainerLayerParameters& aContainerParameters) override;
3992 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3993 : const nsDisplayItemGeometry* aGeometry,
3994 : nsRegion* aInvalidRegion) override
3995 : {
3996 : // We don't need to compute an invalidation region since we have LayerTreeInvalidation
3997 0 : }
3998 0 : virtual uint32_t GetPerFrameKey() override {
3999 0 : return (mIndex << nsDisplayItem::TYPE_BITS) |
4000 0 : nsDisplayItem::GetPerFrameKey();
4001 : }
4002 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4003 : LayerManager* aManager,
4004 : const ContainerLayerParameters& aParameters) override;
4005 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4006 : nsRegion* aVisibleRegion) override;
4007 : virtual bool TryMerge(nsDisplayItem* aItem) override;
4008 0 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
4009 0 : return false;
4010 : }
4011 0 : NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE)
4012 :
4013 : private:
4014 : uint8_t mBlendMode;
4015 : uint32_t mIndex;
4016 : };
4017 :
4018 : class nsDisplayBlendContainer : public nsDisplayWrapList {
4019 : public:
4020 : static nsDisplayBlendContainer*
4021 : CreateForMixBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4022 : nsDisplayList* aList,
4023 : const ActiveScrolledRoot* aActiveScrolledRoot);
4024 :
4025 : static nsDisplayBlendContainer*
4026 : CreateForBackgroundBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4027 : nsDisplayList* aList,
4028 : const ActiveScrolledRoot* aActiveScrolledRoot);
4029 :
4030 : #ifdef NS_BUILD_REFCNT_LOGGING
4031 : virtual ~nsDisplayBlendContainer();
4032 : #endif
4033 :
4034 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4035 : LayerManager* aManager,
4036 : const ContainerLayerParameters& aContainerParameters) override;
4037 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4038 : LayerManager* aManager,
4039 : const ContainerLayerParameters& aParameters) override;
4040 : virtual bool TryMerge(nsDisplayItem* aItem) override;
4041 0 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
4042 0 : return false;
4043 : }
4044 0 : virtual uint32_t GetPerFrameKey() override {
4045 0 : return (mIsForBackground ? 1 << nsDisplayItem::TYPE_BITS : 0) |
4046 0 : nsDisplayItem::GetPerFrameKey();
4047 : }
4048 0 : NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
4049 :
4050 : private:
4051 : nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4052 : nsDisplayList* aList,
4053 : const ActiveScrolledRoot* aActiveScrolledRoot,
4054 : bool aIsForBackground);
4055 :
4056 : // Used to distinguish containers created at building stacking
4057 : // context or appending background.
4058 : bool mIsForBackground;
4059 : };
4060 :
4061 : /**
4062 : * A display item that has no purpose but to ensure its contents get
4063 : * their own layer.
4064 : */
4065 : class nsDisplayOwnLayer : public nsDisplayWrapList {
4066 : public:
4067 : typedef mozilla::layers::ScrollThumbData ScrollThumbData;
4068 :
4069 : /**
4070 : * nsDisplayOwnLayer constructor flags
4071 : */
4072 : enum {
4073 : GENERATE_SUBDOC_INVALIDATIONS = 0x01,
4074 : VERTICAL_SCROLLBAR = 0x02,
4075 : HORIZONTAL_SCROLLBAR = 0x04,
4076 : GENERATE_SCROLLABLE_LAYER = 0x08,
4077 : SCROLLBAR_CONTAINER = 0x10
4078 : };
4079 :
4080 : /**
4081 : * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
4082 : * Add UserData to the created ContainerLayer, so that invalidations
4083 : * for this layer are send to our nsPresContext.
4084 : * GENERATE_SCROLLABLE_LAYER : only valid on nsDisplaySubDocument (and
4085 : * subclasses), indicates this layer is to be a scrollable layer, so call
4086 : * ComputeFrameMetrics, etc.
4087 : * @param aScrollTarget when VERTICAL_SCROLLBAR or HORIZONTAL_SCROLLBAR
4088 : * is set in the flags, this parameter should be the ViewID of the
4089 : * scrollable content this scrollbar is for.
4090 : */
4091 : nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4092 : nsDisplayList* aList,
4093 : const ActiveScrolledRoot* aActiveScrolledRoot,
4094 : uint32_t aFlags = 0,
4095 : ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID,
4096 : const ScrollThumbData& aThumbData = ScrollThumbData{},
4097 : bool aForceActive = true);
4098 : #ifdef NS_BUILD_REFCNT_LOGGING
4099 : virtual ~nsDisplayOwnLayer();
4100 : #endif
4101 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) override;
4102 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4103 : LayerManager* aManager,
4104 : const ContainerLayerParameters& aContainerParameters) override;
4105 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4106 : LayerManager* aManager,
4107 : const ContainerLayerParameters& aParameters) override;
4108 39 : virtual bool TryMerge(nsDisplayItem* aItem) override
4109 : {
4110 : // Don't allow merging, each sublist must have its own layer
4111 39 : return false;
4112 : }
4113 28 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
4114 28 : return false;
4115 : }
4116 : uint32_t GetFlags() { return mFlags; }
4117 : bool IsScrollThumbLayer() const;
4118 389 : NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
4119 : protected:
4120 : uint32_t mFlags;
4121 : ViewID mScrollTarget;
4122 : // If this nsDisplayOwnLayer represents a scroll thumb layer, mThumbData
4123 : // stores information about the scroll thumb. Otherwise, mThumbData will be
4124 : // default-constructed (in particular with mDirection == ScrollDirection::NONE)
4125 : // and can be ignored.
4126 : ScrollThumbData mThumbData;
4127 : bool mForceActive;
4128 : };
4129 :
4130 : /**
4131 : * A display item for subdocuments. This is more or less the same as nsDisplayOwnLayer,
4132 : * except that it always populates the FrameMetrics instance on the ContainerLayer it
4133 : * builds.
4134 : */
4135 : class nsDisplaySubDocument : public nsDisplayOwnLayer {
4136 : public:
4137 : nsDisplaySubDocument(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4138 : nsDisplayList* aList, uint32_t aFlags);
4139 : #ifdef NS_BUILD_REFCNT_LOGGING
4140 : virtual ~nsDisplaySubDocument();
4141 : #endif
4142 :
4143 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4144 : LayerManager* aManager,
4145 : const ContainerLayerParameters& aContainerParameters) override;
4146 :
4147 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
4148 :
4149 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4150 : nsRegion* aVisibleRegion) override;
4151 :
4152 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) override;
4153 :
4154 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
4155 :
4156 0 : NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT)
4157 :
4158 : mozilla::UniquePtr<ScrollMetadata> ComputeScrollMetadata(Layer* aLayer,
4159 : const ContainerLayerParameters& aContainerParameters);
4160 :
4161 : protected:
4162 : ViewID mScrollParentId;
4163 : bool mForceDispatchToContentRegion;
4164 : };
4165 :
4166 : /**
4167 : * A display item for subdocuments to capture the resolution from the presShell
4168 : * and ensure that it gets applied to all the right elements. This item creates
4169 : * a container layer.
4170 : */
4171 : class nsDisplayResolution : public nsDisplaySubDocument {
4172 : public:
4173 : nsDisplayResolution(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4174 : nsDisplayList* aList, uint32_t aFlags);
4175 : #ifdef NS_BUILD_REFCNT_LOGGING
4176 : virtual ~nsDisplayResolution();
4177 : #endif
4178 : virtual void HitTest(nsDisplayListBuilder* aBuilder,
4179 : const nsRect& aRect,
4180 : HitTestState* aState,
4181 : nsTArray<nsIFrame*> *aOutFrames) override;
4182 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4183 : LayerManager* aManager,
4184 : const ContainerLayerParameters& aContainerParameters) override;
4185 0 : NS_DISPLAY_DECL_NAME("Resolution", TYPE_RESOLUTION)
4186 : };
4187 :
4188 : /**
4189 : * A display item used to represent sticky position elements. The contents
4190 : * gets its own layer and creates a stacking context, and the layer will have
4191 : * position-related metadata set on it.
4192 : */
4193 : class nsDisplayStickyPosition : public nsDisplayOwnLayer {
4194 : public:
4195 : nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4196 : nsDisplayList* aList,
4197 : const ActiveScrolledRoot* aActiveScrolledRoot);
4198 : #ifdef NS_BUILD_REFCNT_LOGGING
4199 : virtual ~nsDisplayStickyPosition();
4200 : #endif
4201 :
4202 : void SetClipChain(const DisplayItemClipChain* aClipChain) override;
4203 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4204 : LayerManager* aManager,
4205 : const ContainerLayerParameters& aContainerParameters) override;
4206 0 : NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION)
4207 0 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4208 : LayerManager* aManager,
4209 : const ContainerLayerParameters& aParameters) override
4210 : {
4211 0 : return mozilla::LAYER_ACTIVE;
4212 : }
4213 : virtual bool TryMerge(nsDisplayItem* aItem) override;
4214 : };
4215 :
4216 : class nsDisplayFixedPosition : public nsDisplayOwnLayer {
4217 : public:
4218 : nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4219 : nsDisplayList* aList,
4220 : const ActiveScrolledRoot* aActiveScrolledRoot);
4221 :
4222 : static nsDisplayFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
4223 : nsIFrame* aFrame,
4224 : nsDisplayBackgroundImage* aImage,
4225 : uint32_t aIndex);
4226 :
4227 :
4228 : #ifdef NS_BUILD_REFCNT_LOGGING
4229 : virtual ~nsDisplayFixedPosition();
4230 : #endif
4231 :
4232 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4233 : LayerManager* aManager,
4234 : const ContainerLayerParameters& aContainerParameters) override;
4235 0 : NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
4236 0 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4237 : LayerManager* aManager,
4238 : const ContainerLayerParameters& aParameters) override
4239 : {
4240 0 : return mozilla::LAYER_ACTIVE_FORCE;
4241 : }
4242 : virtual bool TryMerge(nsDisplayItem* aItem) override;
4243 :
4244 0 : virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) override { return mIsFixedBackground; }
4245 :
4246 0 : virtual uint32_t GetPerFrameKey() override { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); }
4247 :
4248 0 : AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const override {
4249 0 : return mAnimatedGeometryRootForScrollMetadata;
4250 : }
4251 :
4252 : protected:
4253 : // For background-attachment:fixed
4254 : nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4255 : nsDisplayList* aList, uint32_t aIndex);
4256 : void Init(nsDisplayListBuilder* aBuilder);
4257 :
4258 : AnimatedGeometryRoot* mAnimatedGeometryRootForScrollMetadata;
4259 : uint32_t mIndex;
4260 : bool mIsFixedBackground;
4261 : };
4262 :
4263 0 : class nsDisplayTableFixedPosition : public nsDisplayFixedPosition
4264 : {
4265 : public:
4266 : static nsDisplayTableFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
4267 : nsIFrame* aFrame,
4268 : nsDisplayBackgroundImage* aImage,
4269 : uint32_t aIndex,
4270 : nsIFrame* aAncestorFrame);
4271 :
4272 0 : virtual uint32_t GetPerFrameKey() override {
4273 0 : return (mIndex << (nsDisplayItem::TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
4274 0 : (static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
4275 0 : nsDisplayItem::GetPerFrameKey();
4276 : }
4277 : protected:
4278 : nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4279 : nsDisplayList* aList, uint32_t aIndex, nsIFrame* aAncestorFrame);
4280 :
4281 : TableType mTableType;
4282 : };
4283 :
4284 : /**
4285 : * This creates an empty scrollable layer. It has no child layers.
4286 : * It is used to record the existence of a scrollable frame in the layer
4287 : * tree.
4288 : */
4289 : class nsDisplayScrollInfoLayer : public nsDisplayWrapList
4290 : {
4291 : public:
4292 : nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder,
4293 : nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame);
4294 0 : NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER)
4295 :
4296 :
4297 : #ifdef NS_BUILD_REFCNT_LOGGING
4298 : virtual ~nsDisplayScrollInfoLayer();
4299 : #endif
4300 :
4301 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4302 : LayerManager* aManager,
4303 : const ContainerLayerParameters& aContainerParameters) override;
4304 :
4305 0 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) override
4306 0 : { return true; }
4307 :
4308 0 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4309 : bool* aSnap) override {
4310 0 : *aSnap = false;
4311 0 : return nsRegion();
4312 : }
4313 :
4314 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4315 : LayerManager* aManager,
4316 : const ContainerLayerParameters& aParameters) override;
4317 :
4318 0 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
4319 0 : { return false; }
4320 :
4321 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
4322 :
4323 : mozilla::UniquePtr<ScrollMetadata> ComputeScrollMetadata(Layer* aLayer,
4324 : const ContainerLayerParameters& aContainerParameters);
4325 :
4326 : protected:
4327 : nsIFrame* mScrollFrame;
4328 : nsIFrame* mScrolledFrame;
4329 : ViewID mScrollParentId;
4330 : };
4331 :
4332 : /**
4333 : * nsDisplayZoom is used for subdocuments that have a different full zoom than
4334 : * their parent documents. This item creates a container layer.
4335 : */
4336 : class nsDisplayZoom : public nsDisplaySubDocument {
4337 : public:
4338 : /**
4339 : * @param aFrame is the root frame of the subdocument.
4340 : * @param aList contains the display items for the subdocument.
4341 : * @param aAPD is the app units per dev pixel ratio of the subdocument.
4342 : * @param aParentAPD is the app units per dev pixel ratio of the parent
4343 : * document.
4344 : * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
4345 : * Add UserData to the created ContainerLayer, so that invalidations
4346 : * for this layer are send to our nsPresContext.
4347 : */
4348 : nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4349 : nsDisplayList* aList,
4350 : int32_t aAPD, int32_t aParentAPD,
4351 : uint32_t aFlags = 0);
4352 : #ifdef NS_BUILD_REFCNT_LOGGING
4353 : virtual ~nsDisplayZoom();
4354 : #endif
4355 :
4356 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
4357 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4358 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
4359 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4360 : nsRegion* aVisibleRegion) override;
4361 0 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4362 : LayerManager* aManager,
4363 : const ContainerLayerParameters& aParameters) override
4364 : {
4365 0 : return mozilla::LAYER_ACTIVE;
4366 : }
4367 0 : NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
4368 :
4369 : // Get the app units per dev pixel ratio of the child document.
4370 : int32_t GetChildAppUnitsPerDevPixel() { return mAPD; }
4371 : // Get the app units per dev pixel ratio of the parent document.
4372 0 : int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD; }
4373 :
4374 : private:
4375 : int32_t mAPD, mParentAPD;
4376 : };
4377 :
4378 : class nsDisplaySVGEffects: public nsDisplayWrapList {
4379 : public:
4380 : nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4381 : nsDisplayList* aList, bool aHandleOpacity,
4382 : const ActiveScrolledRoot* aActiveScrolledRoot);
4383 : nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4384 : nsDisplayList* aList, bool aHandleOpacity);
4385 : #ifdef NS_BUILD_REFCNT_LOGGING
4386 : virtual ~nsDisplaySVGEffects();
4387 : #endif
4388 :
4389 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4390 : bool* aSnap) override;
4391 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4392 : HitTestState* aState,
4393 : nsTArray<nsIFrame*> *aOutFrames) override;
4394 :
4395 7 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
4396 7 : return false;
4397 : }
4398 :
4399 : gfxRect BBoxInUserSpace() const;
4400 : gfxPoint UserSpaceOffset() const;
4401 :
4402 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4403 : const nsDisplayItemGeometry* aGeometry,
4404 : nsRegion* aInvalidRegion) override;
4405 : protected:
4406 : bool ValidateSVGFrame();
4407 :
4408 : // relative to mFrame
4409 : nsRect mEffectsBounds;
4410 : // True if we need to handle css opacity in this display item.
4411 : bool mHandleOpacity;
4412 : };
4413 :
4414 : /**
4415 : * A display item to paint a stacking context with mask and clip effects
4416 : * set by the stacking context root frame's style.
4417 : */
4418 : class nsDisplayMask : public nsDisplaySVGEffects {
4419 : public:
4420 : typedef mozilla::layers::ImageLayer ImageLayer;
4421 :
4422 : nsDisplayMask(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4423 : nsDisplayList* aList, bool aHandleOpacity,
4424 : const ActiveScrolledRoot* aActiveScrolledRoot);
4425 : #ifdef NS_BUILD_REFCNT_LOGGING
4426 : virtual ~nsDisplayMask();
4427 : #endif
4428 :
4429 126 : NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK)
4430 :
4431 : virtual bool TryMerge(nsDisplayItem* aItem) override;
4432 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4433 : LayerManager* aManager,
4434 : const ContainerLayerParameters& aContainerParameters) override;
4435 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4436 : LayerManager* aManager,
4437 : const ContainerLayerParameters& aParameters) override;
4438 :
4439 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4440 : nsRegion* aVisibleRegion) override;
4441 :
4442 2 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
4443 : {
4444 2 : return new nsDisplayMaskGeometry(this, aBuilder);
4445 : }
4446 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4447 : const nsDisplayItemGeometry* aGeometry,
4448 : nsRegion* aInvalidRegion) override;
4449 : #ifdef MOZ_DUMP_PAINTING
4450 : void PrintEffects(nsACString& aTo);
4451 : #endif
4452 :
4453 : void PaintAsLayer(nsDisplayListBuilder* aBuilder,
4454 : gfxContext* aCtx,
4455 : LayerManager* aManager);
4456 :
4457 : /*
4458 : * Paint mask onto aMaskContext in mFrame's coordinate space and
4459 : * return whether the mask layer was painted successfully.
4460 : */
4461 : bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
4462 :
4463 2 : const nsTArray<nsRect>& GetDestRects()
4464 : {
4465 2 : return mDestRects;
4466 : }
4467 : private:
4468 : // According to mask property and the capability of aManager, determine
4469 : // whether paint mask onto a dedicate mask layer.
4470 : bool ShouldPaintOnMaskLayer(LayerManager* aManager);
4471 :
4472 : nsTArray<nsRect> mDestRects;
4473 : };
4474 :
4475 : /**
4476 : * A display item to paint a stacking context with filter effects set by the
4477 : * stacking context root frame's style.
4478 : */
4479 : class nsDisplayFilter : public nsDisplaySVGEffects {
4480 : public:
4481 : nsDisplayFilter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4482 : nsDisplayList* aList, bool aHandleOpacity);
4483 : #ifdef NS_BUILD_REFCNT_LOGGING
4484 : virtual ~nsDisplayFilter();
4485 : #endif
4486 :
4487 0 : NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER)
4488 :
4489 : virtual bool TryMerge(nsDisplayItem* aItem) override;
4490 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4491 : LayerManager* aManager,
4492 : const ContainerLayerParameters& aContainerParameters) override;
4493 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4494 : LayerManager* aManager,
4495 : const ContainerLayerParameters& aParameters) override;
4496 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
4497 : bool* aSnap) override {
4498 0 : *aSnap = false;
4499 0 : return mEffectsBounds + ToReferenceFrame();
4500 : }
4501 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4502 : nsRegion* aVisibleRegion) override;
4503 0 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
4504 : {
4505 0 : return new nsDisplayFilterGeometry(this, aBuilder);
4506 : }
4507 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4508 : const nsDisplayItemGeometry* aGeometry,
4509 : nsRegion* aInvalidRegion) override;
4510 : #ifdef MOZ_DUMP_PAINTING
4511 : void PrintEffects(nsACString& aTo);
4512 : #endif
4513 :
4514 : void PaintAsLayer(nsDisplayListBuilder* aBuilder,
4515 : gfxContext* aCtx,
4516 : LayerManager* aManager);
4517 : };
4518 :
4519 : /* A display item that applies a transformation to all of its descendant
4520 : * elements. This wrapper should only be used if there is a transform applied
4521 : * to the root element.
4522 : *
4523 : * The reason that a "bounds" rect is involved in transform calculations is
4524 : * because CSS-transforms allow percentage values for the x and y components
4525 : * of <translation-value>s, where percentages are percentages of the element's
4526 : * border box.
4527 : *
4528 : * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
4529 : * function.
4530 : * INVARIANT: The wrapped frame is non-null.
4531 : */
4532 : class nsDisplayTransform: public nsDisplayItem
4533 : {
4534 : typedef mozilla::gfx::Matrix4x4 Matrix4x4;
4535 : typedef mozilla::gfx::Point3D Point3D;
4536 :
4537 : /*
4538 : * Avoid doing UpdateBounds() during construction.
4539 : */
4540 : class StoreList : public nsDisplayWrapList {
4541 : public:
4542 24 : StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4543 24 : nsDisplayList* aList) :
4544 24 : nsDisplayWrapList(aBuilder, aFrame, aList) {}
4545 0 : StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4546 0 : nsDisplayItem* aItem) :
4547 0 : nsDisplayWrapList(aBuilder, aFrame, aItem) {}
4548 24 : virtual ~StoreList() {}
4549 :
4550 0 : virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override {
4551 : // For extending 3d rendering context, the bounds would be
4552 : // updated by DoUpdateBoundsPreserves3D(), not here.
4553 0 : if (!mFrame->Extend3DContext()) {
4554 0 : nsDisplayWrapList::UpdateBounds(aBuilder);
4555 : }
4556 0 : }
4557 0 : virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
4558 0 : for (nsDisplayItem *i = mList.GetBottom(); i; i = i->GetAbove()) {
4559 0 : i->DoUpdateBoundsPreserves3D(aBuilder);
4560 : }
4561 0 : nsDisplayWrapList::UpdateBounds(aBuilder);
4562 0 : }
4563 : };
4564 :
4565 : public:
4566 : enum PrerenderDecision {
4567 : NoPrerender,
4568 : FullPrerender,
4569 : PartialPrerender
4570 : };
4571 :
4572 : /**
4573 : * Returns a matrix (in pixels) for the current frame. The matrix should be relative to
4574 : * the current frame's coordinate space.
4575 : *
4576 : * @param aFrame The frame to compute the transform for.
4577 : * @param aAppUnitsPerPixel The number of app units per graphics unit.
4578 : */
4579 : typedef Matrix4x4 (* ComputeTransformFunction)(nsIFrame* aFrame, float aAppUnitsPerPixel);
4580 :
4581 : /* Constructor accepts a display list, empties it, and wraps it up. It also
4582 : * ferries the underlying frame to the nsDisplayItem constructor.
4583 : */
4584 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
4585 : nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
4586 : uint32_t aIndex = 0, bool aAllowAsyncAnimation = false);
4587 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
4588 : nsDisplayItem *aItem, const nsRect& aChildrenVisibleRect,
4589 : uint32_t aIndex = 0);
4590 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
4591 : nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
4592 : ComputeTransformFunction aTransformGetter, uint32_t aIndex = 0);
4593 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
4594 : nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
4595 : const Matrix4x4& aTransform, uint32_t aIndex = 0);
4596 :
4597 : #ifdef NS_BUILD_REFCNT_LOGGING
4598 24 : virtual ~nsDisplayTransform()
4599 48 : {
4600 24 : MOZ_COUNT_DTOR(nsDisplayTransform);
4601 24 : }
4602 : #endif
4603 :
4604 216 : NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM)
4605 :
4606 2 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override
4607 : {
4608 2 : if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty())
4609 2 : return nsRect();
4610 : bool snap;
4611 0 : return GetBounds(aBuilder, &snap);
4612 : }
4613 :
4614 0 : virtual nsDisplayList* GetChildren() override { return mStoredList.GetChildren(); }
4615 :
4616 : virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
4617 : HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames) override;
4618 : virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap) override;
4619 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
4620 : bool* aSnap) override;
4621 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder *aBuilder) override;
4622 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4623 : LayerManager* aManager,
4624 : const ContainerLayerParameters& aParameters) override;
4625 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4626 : LayerManager* aManager,
4627 : const ContainerLayerParameters& aContainerParameters) override;
4628 : virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
4629 : const StackingContextHelper& aSc,
4630 : nsTArray<WebRenderParentCommand>& aParentCommands,
4631 : mozilla::layers::WebRenderLayerManager* aManager,
4632 : nsDisplayListBuilder* aDisplayListBuilder) override;
4633 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) override;
4634 : virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
4635 : nsRegion *aVisibleRegion) override;
4636 : virtual bool TryMerge(nsDisplayItem *aItem) override;
4637 :
4638 72 : virtual uint32_t GetPerFrameKey() override { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); }
4639 :
4640 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4641 : const nsDisplayItemGeometry* aGeometry,
4642 : nsRegion* aInvalidRegion) override
4643 : {
4644 : // We don't need to compute an invalidation region since we have LayerTreeInvalidation
4645 0 : }
4646 :
4647 24 : virtual const nsIFrame* ReferenceFrameForChildren() const override {
4648 : // If we were created using a transform-getter, then we don't
4649 : // belong to a transformed frame, and aren't a reference frame
4650 : // for our children.
4651 24 : if (!mTransformGetter) {
4652 24 : return mFrame;
4653 : }
4654 0 : return nsDisplayItem::ReferenceFrameForChildren();
4655 : }
4656 :
4657 0 : AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const override {
4658 0 : return mAnimatedGeometryRootForScrollMetadata;
4659 : }
4660 :
4661 24 : virtual const nsRect& GetVisibleRectForChildren() const override
4662 : {
4663 24 : return mChildrenVisibleRect;
4664 : }
4665 :
4666 : enum {
4667 : INDEX_MAX = UINT32_MAX >> nsDisplayItem::TYPE_BITS
4668 : };
4669 :
4670 : /**
4671 : * We include the perspective matrix from our containing block for the
4672 : * purposes of visibility calculations, but we exclude it from the transform
4673 : * we set on the layer (for rendering), since there will be an
4674 : * nsDisplayPerspective created for that.
4675 : */
4676 : const Matrix4x4& GetTransform();
4677 : Matrix4x4 GetTransformForRendering();
4678 :
4679 : /**
4680 : * Return the transform that is aggregation of all transform on the
4681 : * preserves3d chain.
4682 : */
4683 : const Matrix4x4& GetAccumulatedPreserved3DTransform(nsDisplayListBuilder* aBuilder);
4684 :
4685 : float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint);
4686 :
4687 : /**
4688 : * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
4689 : * space) and returns the smallest rectangle (in aFrame's coordinate space)
4690 : * containing the transformed image of that rectangle. That is, it takes
4691 : * the four corners of the rectangle, transforms them according to the
4692 : * matrix associated with the specified frame, then returns the smallest
4693 : * rectangle containing the four transformed points.
4694 : *
4695 : * @param untransformedBounds The rectangle (in app units) to transform.
4696 : * @param aFrame The frame whose transformation should be applied. This
4697 : * function raises an assertion if aFrame is null or doesn't have a
4698 : * transform applied to it.
4699 : * @param aOrigin The origin of the transform relative to aFrame's local
4700 : * coordinate space.
4701 : * @param aBoundsOverride (optional) Rather than using the frame's computed
4702 : * bounding rect as frame bounds, use this rectangle instead. Pass
4703 : * nullptr (or nothing at all) to use the default.
4704 : */
4705 : static nsRect TransformRect(const nsRect &aUntransformedBounds,
4706 : const nsIFrame* aFrame,
4707 : const nsRect* aBoundsOverride = nullptr);
4708 :
4709 : /* UntransformRect is like TransformRect, except that it inverts the
4710 : * transform.
4711 : */
4712 : static bool UntransformRect(const nsRect &aTransformedBounds,
4713 : const nsRect &aChildBounds,
4714 : const nsIFrame* aFrame,
4715 : nsRect *aOutRect);
4716 :
4717 : bool UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
4718 : nsRect* aOutRect);
4719 :
4720 : static Point3D GetDeltaToTransformOrigin(const nsIFrame* aFrame,
4721 : float aAppUnitsPerPixel,
4722 : const nsRect* aBoundsOverride);
4723 :
4724 : /*
4725 : * Returns true if aFrame has perspective applied from its containing
4726 : * block.
4727 : * Returns the matrix to append to apply the persective (taking
4728 : * perspective-origin into account), relative to aFrames coordinate
4729 : * space).
4730 : * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
4731 : * cleared.
4732 : */
4733 : static bool ComputePerspectiveMatrix(const nsIFrame* aFrame,
4734 : float aAppUnitsPerPixel,
4735 : Matrix4x4& aOutMatrix);
4736 :
4737 194 : struct FrameTransformProperties
4738 : {
4739 : FrameTransformProperties(const nsIFrame* aFrame,
4740 : float aAppUnitsPerPixel,
4741 : const nsRect* aBoundsOverride);
4742 0 : FrameTransformProperties(nsCSSValueSharedList* aTransformList,
4743 : const Point3D& aToTransformOrigin)
4744 0 : : mFrame(nullptr)
4745 : , mTransformList(aTransformList)
4746 0 : , mToTransformOrigin(aToTransformOrigin)
4747 0 : {}
4748 :
4749 : const nsIFrame* mFrame;
4750 : RefPtr<nsCSSValueSharedList> mTransformList;
4751 : const Point3D mToTransformOrigin;
4752 : };
4753 :
4754 : /**
4755 : * Given a frame with the -moz-transform property or an SVG transform,
4756 : * returns the transformation matrix for that frame.
4757 : *
4758 : * @param aFrame The frame to get the matrix from.
4759 : * @param aOrigin Relative to which point this transform should be applied.
4760 : * @param aAppUnitsPerPixel The number of app units per graphics unit.
4761 : * @param aBoundsOverride [optional] If this is nullptr (the default), the
4762 : * computation will use the value of TransformReferenceBox(aFrame).
4763 : * Otherwise, it will use the value of aBoundsOverride. This is
4764 : * mostly for internal use and in most cases you will not need to
4765 : * specify a value.
4766 : * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
4767 : * by aOrigin. This translation is applied *before* the CSS transform.
4768 : * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
4769 : * include the transform of any ancestors participating in the same
4770 : * 3d rendering context.
4771 : * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
4772 : * perspective transform from the containing block if applicable.
4773 : */
4774 : enum {
4775 : OFFSET_BY_ORIGIN = 1 << 0,
4776 : INCLUDE_PRESERVE3D_ANCESTORS = 1 << 1,
4777 : INCLUDE_PERSPECTIVE = 1 << 2,
4778 : };
4779 : static Matrix4x4 GetResultingTransformMatrix(const nsIFrame* aFrame,
4780 : const nsPoint& aOrigin,
4781 : float aAppUnitsPerPixel,
4782 : uint32_t aFlags,
4783 : const nsRect* aBoundsOverride = nullptr);
4784 : static Matrix4x4 GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
4785 : const nsPoint& aOrigin,
4786 : float aAppUnitsPerPixel,
4787 : uint32_t aFlags,
4788 : const nsRect* aBoundsOverride = nullptr);
4789 : /**
4790 : * Decide whether we should prerender some or all of the contents of the
4791 : * transformed frame even when it's not completely visible (yet).
4792 : * Return FullPrerender if the entire contents should be prerendered,
4793 : * PartialPrerender if some but not all of the contents should be prerendered,
4794 : * or NoPrerender if only the visible area should be rendered.
4795 : * |aDirtyRect| is updated to the area that should be prerendered.
4796 : */
4797 : static PrerenderDecision ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
4798 : nsIFrame* aFrame,
4799 : nsRect* aDirtyRect);
4800 : bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
4801 :
4802 : bool MayBeAnimated(nsDisplayListBuilder* aBuilder);
4803 :
4804 : virtual void WriteDebugInfo(std::stringstream& aStream) override;
4805 :
4806 : // Force the layer created for this item not to extend 3D context.
4807 : // See nsIFrame::BuildDisplayListForStackingContext()
4808 0 : void SetNoExtendContext() { mNoExtendContext = true; }
4809 :
4810 0 : virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
4811 0 : MOZ_ASSERT(mFrame->Combines3DTransformWithAncestors() ||
4812 : IsTransformSeparator());
4813 : // Updating is not going through to child 3D context.
4814 0 : ComputeBounds(aBuilder);
4815 0 : }
4816 :
4817 : /**
4818 : * This function updates bounds for items with a frame establishing
4819 : * 3D rendering context.
4820 : *
4821 : * \see nsDisplayItem::DoUpdateBoundsPreserves3D()
4822 : */
4823 24 : void UpdateBoundsFor3D(nsDisplayListBuilder* aBuilder) {
4824 48 : if (!mFrame->Extend3DContext() ||
4825 24 : mFrame->Combines3DTransformWithAncestors() ||
4826 0 : IsTransformSeparator()) {
4827 : // Not an establisher of a 3D rendering context.
4828 24 : return;
4829 : }
4830 : // Always start updating from an establisher of a 3D rendering context.
4831 :
4832 0 : nsDisplayListBuilder::AutoAccumulateRect accRect(aBuilder);
4833 0 : nsDisplayListBuilder::AutoAccumulateTransform accTransform(aBuilder);
4834 0 : accTransform.StartRoot();
4835 0 : ComputeBounds(aBuilder);
4836 0 : mBounds = aBuilder->GetAccumulatedRect();
4837 0 : mHasBounds = true;
4838 : }
4839 :
4840 : /**
4841 : * This item is an additional item as the boundary between parent
4842 : * and child 3D rendering context.
4843 : * \see nsIFrame::BuildDisplayListForStackingContext().
4844 : */
4845 0 : bool IsTransformSeparator() { return mIsTransformSeparator; }
4846 : /**
4847 : * This item is the boundary between parent and child 3D rendering
4848 : * context.
4849 : */
4850 0 : bool IsLeafOf3DContext() {
4851 0 : return (IsTransformSeparator() ||
4852 0 : (!mFrame->Extend3DContext() &&
4853 0 : mFrame->Combines3DTransformWithAncestors()));
4854 : }
4855 : /**
4856 : * The backing frame of this item participates a 3D rendering
4857 : * context.
4858 : */
4859 0 : bool IsParticipating3DContext() {
4860 0 : return mFrame->Extend3DContext() ||
4861 0 : mFrame->Combines3DTransformWithAncestors();
4862 : }
4863 :
4864 : private:
4865 : void ComputeBounds(nsDisplayListBuilder* aBuilder);
4866 : void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
4867 : void Init(nsDisplayListBuilder* aBuilder);
4868 :
4869 : static Matrix4x4 GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
4870 : const nsPoint& aOrigin,
4871 : float aAppUnitsPerPixel,
4872 : uint32_t aFlags,
4873 : const nsRect* aBoundsOverride);
4874 :
4875 : StoreList mStoredList;
4876 : Matrix4x4 mTransform;
4877 : // Accumulated transform of ancestors on the preserves-3d chain.
4878 : Matrix4x4 mTransformPreserves3D;
4879 : ComputeTransformFunction mTransformGetter;
4880 : AnimatedGeometryRoot* mAnimatedGeometryRootForChildren;
4881 : AnimatedGeometryRoot* mAnimatedGeometryRootForScrollMetadata;
4882 : nsRect mChildrenVisibleRect;
4883 : uint32_t mIndex;
4884 : nsRect mBounds;
4885 : // True for mBounds is valid.
4886 : bool mHasBounds;
4887 : // Be forced not to extend 3D context. Since we don't create a
4888 : // transform item, a container layer, for every frames in a
4889 : // preserves3d context, the transform items of a child preserves3d
4890 : // context may extend the parent context not intented if the root of
4891 : // the child preserves3d context doesn't create a transform item.
4892 : // With this flags, we force the item not extending 3D context.
4893 : bool mNoExtendContext;
4894 : // This item is a separator between 3D rendering contexts, and
4895 : // mTransform have been presetted by the constructor.
4896 : bool mIsTransformSeparator;
4897 : // True if mTransformPreserves3D have been initialized.
4898 : bool mTransformPreserves3DInited;
4899 : // True if async animation of the transform is allowed.
4900 : bool mAllowAsyncAnimation;
4901 : };
4902 :
4903 : /* A display item that applies a perspective transformation to a single
4904 : * nsDisplayTransform child item. We keep this as a separate item since the
4905 : * perspective-origin is relative to an ancestor of the transformed frame, and
4906 : * APZ can scroll the child separately.
4907 : */
4908 0 : class nsDisplayPerspective : public nsDisplayItem
4909 : {
4910 : typedef mozilla::gfx::Point3D Point3D;
4911 :
4912 : public:
4913 0 : NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE)
4914 :
4915 : nsDisplayPerspective(nsDisplayListBuilder* aBuilder, nsIFrame* aTransformFrame,
4916 : nsIFrame* aPerspectiveFrame,
4917 : nsDisplayList* aList);
4918 :
4919 0 : virtual uint32_t GetPerFrameKey() override { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); }
4920 :
4921 0 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4922 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override
4923 : {
4924 0 : return mList.HitTest(aBuilder, aRect, aState, aOutFrames);
4925 : }
4926 :
4927 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override
4928 : {
4929 0 : return mList.GetBounds(aBuilder, aSnap);
4930 : }
4931 :
4932 0 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4933 : const nsDisplayItemGeometry* aGeometry,
4934 : nsRegion* aInvalidRegion) override
4935 0 : {}
4936 :
4937 0 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4938 : bool* aSnap) override
4939 : {
4940 0 : return mList.GetOpaqueRegion(aBuilder, aSnap);
4941 : }
4942 :
4943 0 : virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) override
4944 : {
4945 0 : return mList.IsUniform(aBuilder);
4946 : }
4947 :
4948 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
4949 : LayerManager* aManager,
4950 : const ContainerLayerParameters& aParameters) override;
4951 :
4952 0 : virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) override
4953 : {
4954 0 : if (!mList.GetChildren()->GetTop()) {
4955 0 : return false;
4956 : }
4957 0 : return mList.GetChildren()->GetTop()->ShouldBuildLayerEvenIfInvisible(aBuilder);
4958 : }
4959 :
4960 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
4961 : LayerManager* aManager,
4962 : const ContainerLayerParameters& aContainerParameters) override;
4963 :
4964 0 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
4965 : nsRegion* aVisibleRegion) override
4966 : {
4967 0 : mList.RecomputeVisibility(aBuilder, aVisibleRegion);
4968 0 : return true;
4969 : }
4970 0 : virtual nsDisplayList* GetSameCoordinateSystemChildren() override { return mList.GetChildren(); }
4971 0 : virtual nsDisplayList* GetChildren() override { return mList.GetChildren(); }
4972 0 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override
4973 : {
4974 0 : return mList.GetComponentAlphaBounds(aBuilder);
4975 : }
4976 :
4977 0 : nsIFrame* TransformFrame() { return mTransformFrame; }
4978 :
4979 : virtual int32_t ZIndex() const override;
4980 :
4981 : virtual void
4982 0 : DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
4983 0 : if (mList.GetChildren()->GetTop()) {
4984 0 : static_cast<nsDisplayTransform*>(mList.GetChildren()->GetTop())->DoUpdateBoundsPreserves3D(aBuilder);
4985 : }
4986 0 : }
4987 :
4988 : private:
4989 : nsDisplayWrapList mList;
4990 : nsIFrame* mTransformFrame;
4991 : uint32_t mIndex;
4992 : };
4993 :
4994 : /**
4995 : * This class adds basic support for limiting the rendering (in the inline axis
4996 : * of the writing mode) to the part inside the specified edges. It's a base
4997 : * class for the display item classes that do the actual work.
4998 : * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
4999 : * of the frame's scrollable overflow rectangle and are the amount to suppress
5000 : * on each side.
5001 : *
5002 : * Setting none, both or only one edge is allowed.
5003 : * The values must be non-negative.
5004 : * The default value for both edges is zero, which means everything is painted.
5005 : */
5006 73 : class nsCharClipDisplayItem : public nsDisplayItem {
5007 : public:
5008 73 : nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
5009 73 : : nsDisplayItem(aBuilder, aFrame), mVisIStartEdge(0), mVisIEndEdge(0) {}
5010 :
5011 0 : explicit nsCharClipDisplayItem(nsIFrame* aFrame)
5012 0 : : nsDisplayItem(aFrame) {}
5013 :
5014 : virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
5015 :
5016 : virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
5017 : const nsDisplayItemGeometry* aGeometry,
5018 : nsRegion* aInvalidRegion) override;
5019 :
5020 : struct ClipEdges {
5021 17 : ClipEdges(const nsDisplayItem& aItem,
5022 17 : nscoord aVisIStartEdge, nscoord aVisIEndEdge) {
5023 34 : nsRect r = aItem.Frame()->GetScrollableOverflowRect() +
5024 51 : aItem.ToReferenceFrame();
5025 17 : if (aItem.Frame()->GetWritingMode().IsVertical()) {
5026 0 : mVisIStart = aVisIStartEdge > 0 ? r.y + aVisIStartEdge : nscoord_MIN;
5027 0 : mVisIEnd =
5028 0 : aVisIEndEdge > 0 ? std::max(r.YMost() - aVisIEndEdge, mVisIStart)
5029 0 : : nscoord_MAX;
5030 : } else {
5031 17 : mVisIStart = aVisIStartEdge > 0 ? r.x + aVisIStartEdge : nscoord_MIN;
5032 17 : mVisIEnd =
5033 34 : aVisIEndEdge > 0 ? std::max(r.XMost() - aVisIEndEdge, mVisIStart)
5034 17 : : nscoord_MAX;
5035 : }
5036 17 : }
5037 0 : void Intersect(nscoord* aVisIStart, nscoord* aVisISize) const {
5038 0 : nscoord end = *aVisIStart + *aVisISize;
5039 0 : *aVisIStart = std::max(*aVisIStart, mVisIStart);
5040 0 : *aVisISize = std::max(std::min(end, mVisIEnd) - *aVisIStart, 0);
5041 0 : }
5042 : nscoord mVisIStart;
5043 : nscoord mVisIEnd;
5044 : };
5045 :
5046 : ClipEdges Edges() const {
5047 : return ClipEdges(*this, mVisIStartEdge, mVisIEndEdge);
5048 : }
5049 :
5050 0 : static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) {
5051 0 : nsDisplayItem::Type t = aItem->GetType();
5052 : return (t == nsDisplayItem::TYPE_TEXT)
5053 0 : ? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr;
5054 : }
5055 :
5056 : // Lengths measured from the visual inline start and end sides
5057 : // (i.e. left and right respectively in horizontal writing modes,
5058 : // regardless of bidi directionality; top and bottom in vertical modes).
5059 : nscoord mVisIStartEdge;
5060 : nscoord mVisIEndEdge;
5061 : // Cached result of mFrame->IsSelected(). Only initialized when needed.
5062 : mutable mozilla::Maybe<bool> mIsFrameSelected;
5063 : };
5064 :
5065 : namespace mozilla {
5066 :
5067 : class PaintTelemetry
5068 : {
5069 : public:
5070 : enum class Metric {
5071 : DisplayList,
5072 : Layerization,
5073 : Rasterization,
5074 : COUNT,
5075 : };
5076 :
5077 : class AutoRecord
5078 : {
5079 : public:
5080 : explicit AutoRecord(Metric aMetric);
5081 : ~AutoRecord();
5082 :
5083 88 : TimeStamp GetStart() const {
5084 88 : return mStart;
5085 : }
5086 : private:
5087 : Metric mMetric;
5088 : mozilla::TimeStamp mStart;
5089 : };
5090 :
5091 : class AutoRecordPaint
5092 : {
5093 : public:
5094 : AutoRecordPaint();
5095 : ~AutoRecordPaint();
5096 : private:
5097 : mozilla::TimeStamp mStart;
5098 : };
5099 :
5100 : private:
5101 : static uint32_t sPaintLevel;
5102 : static uint32_t sMetricLevel;
5103 : static mozilla::EnumeratedArray<Metric, Metric::COUNT, double> sMetrics;
5104 : };
5105 :
5106 : } // namespace mozilla
5107 :
5108 : #endif /*NSDISPLAYLIST_H_*/
|