gecko-dev/layout/painting/nsDisplayList.h

6484 lines
242 KiB
C
Raw Normal View History

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
2012-05-21 11:12:37 +00:00
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* structures that represent things to be painted (ordered in z-order),
* used during painting and hit testing
*/
#ifndef NSDISPLAYLIST_H_
#define NSDISPLAYLIST_H_
#include "mozilla/Attributes.h"
#include "gfxContext.h"
#include "mozilla/ArenaAllocator.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Array.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/EnumSet.h"
#include "mozilla/Maybe.h"
#include "mozilla/TemplateLib.h" // mozilla::tl::Max
#include "nsCOMPtr.h"
#include "nsContainerFrame.h"
#include "nsPoint.h"
#include "nsRect.h"
#include "nsRegion.h"
#include "nsDisplayListInvalidation.h"
#include "DisplayListClipState.h"
#include "LayerState.h"
#include "FrameMetrics.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/gfx/UserData.h"
#include "mozilla/layers/LayerAttributes.h"
#include "nsCSSRenderingBorders.h"
#include "nsPresArena.h"
#include "nsAutoLayoutPhase.h"
#include "nsDisplayItemTypes.h"
#include <stdint.h>
#include "nsTHashtable.h"
#include <stdlib.h>
#include <algorithm>
class gfxContext;
class nsIContent;
class nsDisplayList;
class nsDisplayTableItem;
class nsISelection;
class nsIScrollableFrame;
class nsSubDocumentFrame;
class nsDisplayLayerEventRegions;
class nsDisplayScrollInfoLayer;
class nsCaret;
enum class nsDisplayOwnLayerFlags;
namespace mozilla {
class FrameLayerBuilder;
namespace layers {
class Layer;
class ImageLayer;
class ImageContainer;
class StackingContextHelper;
class WebRenderCommand;
class WebRenderScrollData;
class WebRenderLayerScrollData;
} // namespace layers
namespace wr {
class DisplayListBuilder;
} // namespace wr
} // namespace mozilla
// A set of blend modes, that never includes OP_OVER (since it's
// considered the default, rather than a specific blend mode).
typedef mozilla::EnumSet<mozilla::gfx::CompositionOp> BlendModeSet;
/*
* An nsIFrame can have many different visual parts. For example an image frame
* can have a background, border, and outline, the image itself, and a
* translucent selection overlay. In general these parts can be drawn at
* discontiguous z-levels; see CSS2.1 appendix E:
* http://www.w3.org/TR/CSS21/zindex.html
*
* We construct a display list for a frame tree that contains one item
* for each visual part. The display list is itself a tree since some items
* are containers for other items; however, its structure does not match
* the structure of its source frame tree. The display list items are sorted
* by z-order. A display list can be used to paint the frames, to determine
* which frame is the target of a mouse event, and to determine what areas
* need to be repainted when scrolling. The display lists built for each task
* may be different for efficiency; in particular some frames need special
* display list items only for event handling, and do not create these items
* when the display list will be used for painting (the common case). For
* example, when painting we avoid creating nsDisplayBackground items for
* frames that don't display a visible background, but for event handling
* we need those backgrounds because they are not transparent to events.
*
* We could avoid constructing an explicit display list by traversing the
* frame tree multiple times in clever ways. However, reifying the display list
* reduces code complexity and reduces the number of times each frame must be
* traversed to one, which seems to be good for performance. It also means
* we can share code for painting, event handling and scroll analysis.
*
* Display lists are short-lived; content and frame trees cannot change
* between a display list being created and destroyed. Display lists should
* not be created during reflow because the frame tree may be in an
* inconsistent state (e.g., a frame's stored overflow-area may not include
* the bounds of all its children). However, it should be fine to create
* a display list while a reflow is pending, before it starts.
*
* A display list covers the "extended" frame tree; the display list for a frame
* tree containing FRAME/IFRAME elements can include frames from the subdocuments.
*
* Display item's coordinates are relative to their nearest reference frame ancestor.
* Both the display root and any frame with a transform act as a reference frame
* for their frame subtrees.
*/
// All types are defined in nsDisplayItemTypes.h
#define NS_DISPLAY_DECL_NAME(n, e) \
virtual const char* Name() const override { return n; } \
virtual DisplayItemType GetType() const override { return DisplayItemType::e; } \
void* operator new(size_t aSize, \
nsDisplayListBuilder* aBuilder) { \
return aBuilder->Allocate(aSize, DisplayItemType::e); \
}
/**
* Represents a frame that is considered to have (or will have) "animated geometry"
* for itself and descendant frames.
*
* For example the scrolled frames of scrollframes which are actively being scrolled
* fall into this category. Frames with certain CSS properties that are being animated
* (e.g. 'left'/'top' etc) are also placed in this category. Frames with different
* active geometry roots are in different PaintedLayers, so that we can animate the
* geometry root by changing its transform (either on the main thread or in the
* compositor).
*
* nsDisplayListBuilder constructs a tree of these (for fast traversals) and assigns
* one for each display item.
*
* The animated geometry root for a display item is required to be a descendant (or
* equal to) the item's ReferenceFrame(), which means that we will fall back to
* returning aItem->ReferenceFrame() when we can't find another animated geometry root.
*
* The animated geometry root isn't strongly defined for a frame as transforms and
* background-attachment:fixed can cause it to vary between display items for a given
* frame.
*/
struct AnimatedGeometryRoot
{
static already_AddRefed<AnimatedGeometryRoot>
CreateAGRForFrame(nsIFrame* aFrame, AnimatedGeometryRoot* aParent, bool aIsAsync, bool aIsRetained)
{
RefPtr<AnimatedGeometryRoot> result;
if (aIsRetained) {
result = aFrame->GetProperty(AnimatedGeometryRootCache());
}
if (result) {
result->mParentAGR = aParent;
result->mIsAsync = aIsAsync;
} else {
result = new AnimatedGeometryRoot(aFrame, aParent, aIsAsync, aIsRetained);
}
return result.forget();
}
operator nsIFrame*() { return mFrame; }
nsIFrame* operator ->() const { return mFrame; }
AnimatedGeometryRoot* GetAsyncAGR() {
AnimatedGeometryRoot* agr = this;
while (!agr->mIsAsync && agr->mParentAGR) {
agr = agr->mParentAGR;
}
return agr;
}
NS_INLINE_DECL_REFCOUNTING(AnimatedGeometryRoot)
nsIFrame* mFrame;
RefPtr<AnimatedGeometryRoot> mParentAGR;
bool mIsAsync;
bool mIsRetained;
protected:
static void DetachAGR(AnimatedGeometryRoot* aAGR) {
aAGR->mFrame = nullptr;
aAGR->mParentAGR = nullptr;
NS_RELEASE(aAGR);
}
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnimatedGeometryRootCache, AnimatedGeometryRoot, DetachAGR)
AnimatedGeometryRoot(nsIFrame* aFrame, AnimatedGeometryRoot* aParent, bool aIsAsync, bool aIsRetained)
: mFrame(aFrame)
, mParentAGR(aParent)
, mIsAsync(aIsAsync)
, mIsRetained(aIsRetained)
{
MOZ_ASSERT(mParentAGR || mIsAsync, "The root AGR should always be treated as an async AGR.");
if (mIsRetained) {
NS_ADDREF(this);
aFrame->SetProperty(AnimatedGeometryRootCache(), this);
}
}
~AnimatedGeometryRoot()
{
if (mFrame && mIsRetained) {
mFrame->DeleteProperty(AnimatedGeometryRootCache());
}
}
};
namespace mozilla {
/**
* An active scrolled root (ASR) is similar to an animated geometry root (AGR).
* The differences are:
* - ASRs are only created for async-scrollable scroll frames. This is a
* (hopefully) temporary restriction. In the future we will want to create
* ASRs for all the things that are currently creating AGRs, and then
* replace AGRs with ASRs and rename them from "active scrolled root" to
* "animated geometry root".
* - ASR objects are created during display list construction by the nsIFrames
* that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter.
* The current ASR is returned by nsDisplayListBuilder::CurrentActiveScrolledRoot().
* - There is no way to go from an nsIFrame pointer to the ASR of that frame.
* If you need to look up an ASR after display list construction, you need
* to store it while the AutoCurrentActiveScrolledRootSetter that creates it
* is on the stack.
*/
struct ActiveScrolledRoot {
static already_AddRefed<ActiveScrolledRoot>
CreateASRForFrame(const ActiveScrolledRoot* aParent,
nsIScrollableFrame* aScrollableFrame,
bool aIsRetained)
{
nsIFrame* f = do_QueryFrame(aScrollableFrame);
RefPtr<ActiveScrolledRoot> asr;
if (aIsRetained) {
asr = f->GetProperty(ActiveScrolledRootCache());
}
if (!asr) {
asr = new ActiveScrolledRoot();
if (aIsRetained) {
RefPtr<ActiveScrolledRoot> ref = asr;
f->SetProperty(ActiveScrolledRootCache(), ref.forget().take());
}
}
asr->mParent = aParent;
asr->mScrollableFrame = aScrollableFrame;
asr->mViewId = Nothing();
asr->mDepth = aParent ? aParent->mDepth + 1 : 1;
asr->mRetained = aIsRetained;
return asr.forget();
}
static const ActiveScrolledRoot* PickAncestor(const ActiveScrolledRoot* aOne,
const ActiveScrolledRoot* aTwo)
{
MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
return Depth(aOne) <= Depth(aTwo) ? aOne : aTwo;
}
static const ActiveScrolledRoot* PickDescendant(const ActiveScrolledRoot* aOne,
const ActiveScrolledRoot* aTwo)
{
MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
return Depth(aOne) >= Depth(aTwo) ? aOne : aTwo;
}
static bool IsAncestor(const ActiveScrolledRoot* aAncestor,
const ActiveScrolledRoot* aDescendant);
static nsCString ToString(const mozilla::ActiveScrolledRoot* aActiveScrolledRoot);
// Call this when inserting an ancestor.
void IncrementDepth() { mDepth++; }
/**
* Find the view ID (or generate a new one) for the content element
* corresponding to the ASR.
*/
mozilla::layers::FrameMetrics::ViewID GetViewId() const {
if (!mViewId.isSome()) {
nsIContent* content = mScrollableFrame->GetScrolledFrame()->GetContent();
mViewId = Some(nsLayoutUtils::FindOrCreateIDFor(content));
}
return *mViewId;
}
RefPtr<const ActiveScrolledRoot> mParent;
nsIScrollableFrame* mScrollableFrame;
NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot)
private:
ActiveScrolledRoot()
{
}
~ActiveScrolledRoot()
{
if (mScrollableFrame && mRetained) {
nsIFrame* f = do_QueryFrame(mScrollableFrame);
f->DeleteProperty(ActiveScrolledRootCache());
}
}
static void DetachASR(ActiveScrolledRoot* aASR) {
aASR->mParent = nullptr;
aASR->mScrollableFrame = nullptr;
NS_RELEASE(aASR);
}
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache, ActiveScrolledRoot, DetachASR)
static uint32_t Depth(const ActiveScrolledRoot* aActiveScrolledRoot) {
return aActiveScrolledRoot ? aActiveScrolledRoot->mDepth : 0;
}
// This field is lazily populated in GetViewId(). We don't want to do the
// work of populating if webrender is disabled, because it is often not
// needed.
mutable Maybe<mozilla::layers::FrameMetrics::ViewID> mViewId;
uint32_t mDepth;
bool mRetained;
};
}
enum class nsDisplayListBuilderMode : uint8_t {
PAINTING,
EVENT_DELIVERY,
PLUGIN_GEOMETRY,
FRAME_VISIBILITY,
TRANSFORM_COMPUTATION,
GENERATE_GLYPH,
PAINTING_SELECTION_BACKGROUND
};
/**
* This manages a display list and is passed as a parameter to
* nsIFrame::BuildDisplayList.
* It contains the parameters that don't change from frame to frame and manages
* the display list memory using an arena. It also establishes the reference
* coordinate system for all display list items. Some of the parameters are
* available from the prescontext/presshell, but we copy them into the builder
* for faster/more convenient access.
*/
class nsDisplayListBuilder {
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
/**
* This manages status of a 3d context to collect visible rects of
* descendants and passing a dirty rect.
*
* Since some transforms maybe singular, passing visible rects or
* the dirty rect level by level from parent to children may get a
* wrong result, being different from the result of appling with
* effective transform directly.
*
* nsFrame::BuildDisplayListForStackingContext() uses
* AutoPreserves3DContext to install an instance on the builder.
*
* \see AutoAccumulateTransform, AutoAccumulateRect,
* AutoPreserves3DContext, Accumulate, GetCurrentTransform,
* StartRoot.
*/
class Preserves3DContext {
public:
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
Preserves3DContext()
: mAccumulatedRectLevels(0)
{}
Preserves3DContext(const Preserves3DContext &aOther)
: mAccumulatedTransform()
, mAccumulatedRect()
, mAccumulatedRectLevels(0)
, mVisibleRect(aOther.mVisibleRect) {}
// Accmulate transforms of ancestors on the preserves-3d chain.
Matrix4x4 mAccumulatedTransform;
// Accmulate visible rect of descendants in the preserves-3d context.
nsRect mAccumulatedRect;
// How far this frame is from the root of the current 3d context.
int mAccumulatedRectLevels;
nsRect mVisibleRect;
};
/**
* A frame can be in one of three states of AGR.
* AGR_NO means the frame is not an AGR for now.
* AGR_YES means the frame is an AGR for now.
* AGR_MAYBE means the frame is not an AGR for now, but a transition
* to AGR_YES without restyling is possible.
*/
enum AGRState { AGR_NO, AGR_YES, AGR_MAYBE };
public:
typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
typedef mozilla::DisplayItemClip DisplayItemClip;
typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
typedef mozilla::DisplayListClipState DisplayListClipState;
typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
typedef nsIWidget::ThemeGeometry ThemeGeometry;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::FrameMetrics::ViewID ViewID;
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
/**
* @param aReferenceFrame the frame at the root of the subtree; its origin
* is the origin of the reference coordinate system for this display list
* @param aMode encodes what the builder is being used for.
* @param aBuildCaret whether or not we should include the caret in any
* display lists that we make.
*/
nsDisplayListBuilder(nsIFrame* aReferenceFrame,
nsDisplayListBuilderMode aMode,
bool aBuildCaret,
bool aRetainingDisplayList = false);
~nsDisplayListBuilder();
void BeginFrame();
void EndFrame();
void AddTemporaryItem(nsDisplayItem* aItem)
{
mTemporaryItems.AppendElement(aItem);
}
void SetWillComputePluginGeometry(bool aWillComputePluginGeometry)
{
mWillComputePluginGeometry = aWillComputePluginGeometry;
}
void SetForPluginGeometry(bool aForPlugin)
{
if (aForPlugin) {
NS_ASSERTION(mMode == nsDisplayListBuilderMode::PAINTING, "Can only switch from PAINTING to PLUGIN_GEOMETRY");
NS_ASSERTION(mWillComputePluginGeometry, "Should have signalled this in advance");
mMode = nsDisplayListBuilderMode::PLUGIN_GEOMETRY;
} else {
NS_ASSERTION(mMode == nsDisplayListBuilderMode::PLUGIN_GEOMETRY, "Can only switch from PAINTING to PLUGIN_GEOMETRY");
mMode = nsDisplayListBuilderMode::PAINTING;
}
}
mozilla::layers::LayerManager* GetWidgetLayerManager(nsView** aView = nullptr);
/**
* @return true if the display is being built in order to determine which
* frame is under the mouse position.
*/
bool IsForEventDelivery()
{
return mMode == nsDisplayListBuilderMode::EVENT_DELIVERY;
}
/**
* Be careful with this. The display list will be built in PAINTING mode
* first and then switched to PLUGIN_GEOMETRY before a second call to
* ComputeVisibility.
* @return true if the display list is being built to compute geometry
* for plugins.
*/
bool IsForPluginGeometry()
{
return mMode == nsDisplayListBuilderMode::PLUGIN_GEOMETRY;
}
/**
* @return true if the display list is being built for painting.
*/
bool IsForPainting()
{
return mMode == nsDisplayListBuilderMode::PAINTING;
}
/**
* @return true if the display list is being built for determining frame
* visibility.
*/
bool IsForFrameVisibility()
{
return mMode == nsDisplayListBuilderMode::FRAME_VISIBILITY;
}
/**
* @return true if the display list is being built for creating the glyph
* mask from text items.
*/
bool IsForGenerateGlyphMask()
{
return mMode == nsDisplayListBuilderMode::GENERATE_GLYPH;
}
/**
* @return true if the display list is being built for painting selection
* background.
*/
bool IsForPaintingSelectionBG()
{
return mMode == nsDisplayListBuilderMode::PAINTING_SELECTION_BACKGROUND;
}
bool BuildCompositorHitTestInfo()
{
return mBuildCompositorHitTestInfo;
}
bool WillComputePluginGeometry() { return mWillComputePluginGeometry; }
/**
* @return true if "painting is suppressed" during page load and we
* should paint only the background of the document.
*/
bool IsBackgroundOnly() {
NS_ASSERTION(mPresShellStates.Length() > 0,
"don't call this if we're not in a presshell");
return CurrentPresShellState()->mIsBackgroundOnly;
}
/**
* @return true if the currently active BuildDisplayList call is being
* applied to a frame at the root of a pseudo stacking context. A pseudo
* stacking context is either a real stacking context or basically what
* CSS2.1 appendix E refers to with "treat the element as if it created
* a new stacking context
*/
bool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; }
/**
* @return the selection that painting should be restricted to (or nullptr
* in the normal unrestricted case)
*/
nsISelection* GetBoundingSelection() { return mBoundingSelection; }
/**
* @return the root of given frame's (sub)tree, whose origin
* establishes the coordinate system for the child display items.
*/
const nsIFrame* FindReferenceFrameFor(const nsIFrame *aFrame,
nsPoint* aOffset = nullptr);
/**
* @return the root of the display list's frame (sub)tree, whose origin
* establishes the coordinate system for the display list
*/
nsIFrame* RootReferenceFrame()
{
return mReferenceFrame;
}
/**
* @return a point pt such that adding pt to a coordinate relative to aFrame
* makes it relative to ReferenceFrame(), i.e., returns
* aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
* the appunits of aFrame.
*/
const nsPoint ToReferenceFrame(const nsIFrame* aFrame) {
nsPoint result;
FindReferenceFrameFor(aFrame, &result);
return result;
}
/**
* When building the display list, the scrollframe aFrame will be "ignored"
* for the purposes of clipping, and its scrollbars will be hidden. We use
* this to allow RenderOffscreen to render a whole document without beign
* clipped by the viewport or drawing the viewport scrollbars.
*/
void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
/**
* Get the scrollframe to ignore, if any.
*/
nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
/**
* Get the ViewID of the nearest scrolling ancestor frame.
*/
ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
/**
* Get and set the flag that indicates if scroll parents should have layers
* forcibly created. This flag is set when a deeply nested scrollframe has
* a displayport, and for scroll handoff to work properly the ancestor
* scrollframes should also get their own scrollable layers.
*/
void ForceLayerForScrollParent() { mForceLayerForScrollParent = true; }
/**
* Get the ViewID and the scrollbar flags corresponding to the scrollbar for
* which we are building display items at the moment.
*/
ViewID GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget; }
nsDisplayOwnLayerFlags GetCurrentScrollbarFlags() const { return mCurrentScrollbarFlags; }
/**
* Returns true if building a scrollbar, and the scrollbar will not be
* layerized.
*/
bool IsBuildingNonLayerizedScrollbar() const {
return mIsBuildingScrollbar && !mCurrentScrollbarWillHaveLayer;
}
/**
* Calling this setter makes us include all out-of-flow descendant
* frames in the display list, wherever they may be positioned (even
* outside the dirty rects).
*/
void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
/**
* Calling this setter makes us exclude all leaf frames that aren't
* selected.
*/
void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
/**
* Calling this setter makes us compute accurate visible regions at the cost
* of performance if regions get very complex.
*/
bool GetAccurateVisibleRegions() { return mMode == nsDisplayListBuilderMode::PLUGIN_GEOMETRY; }
/**
* @return Returns true if we should include the caret in any display lists
* that we make.
*/
bool IsBuildingCaret() const { return mBuildCaret; }
bool IsRetainingDisplayList() const { return mRetainingDisplayList; }
bool IsPartialUpdate() const { return mPartialUpdate; }
void SetPartialUpdate(bool aPartial) { mPartialUpdate = aPartial; }
bool IsBuilding() const { return mIsBuilding; }
void SetIsBuilding(bool aIsBuilding)
{
mIsBuilding = aIsBuilding;
for (nsIFrame* f : mModifiedFramesDuringBuilding) {
f->SetFrameIsModified(false);
}
mModifiedFramesDuringBuilding.Clear();
}
bool InInvalidSubtree() const { return mInInvalidSubtree; }
/**
* Allows callers to selectively override the regular paint suppression checks,
* so that methods like GetFrameForPoint work when painting is suppressed.
*/
void IgnorePaintSuppression() { mIgnoreSuppression = true; }
/**
* @return Returns if this builder will ignore paint suppression.
*/
bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
/**
* Call this if we're doing normal painting to the window.
*/
void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
/**
* Call this to prevent descending into subdocuments.
*/
void SetDescendIntoSubdocuments(bool aDescend) { mDescendIntoSubdocuments = aDescend; }
bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }
/**
* Get dirty rect relative to current frame (the frame that we're calling
* BuildDisplayList on right now).
*/
const nsRect& GetVisibleRect() { return mVisibleRect; }
const nsRect& GetDirtyRect() { return mDirtyRect; }
void SetVisibleRect(const nsRect& aVisibleRect) { mVisibleRect = aVisibleRect; }
void IntersectVisibleRect(const nsRect& aVisibleRect) { mVisibleRect.IntersectRect(mVisibleRect, aVisibleRect); }
void SetDirtyRect(const nsRect& aDirtyRect) { mDirtyRect = aDirtyRect; }
void IntersectDirtyRect(const nsRect& aDirtyRect) { mDirtyRect.IntersectRect(mDirtyRect, aDirtyRect); }
const nsIFrame* GetCurrentFrame() { return mCurrentFrame; }
const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; }
const nsPoint& GetCurrentFrameOffsetToReferenceFrame() { return mCurrentOffsetToReferenceFrame; }
AnimatedGeometryRoot* GetCurrentAnimatedGeometryRoot() {
return mCurrentAGR;
}
AnimatedGeometryRoot* GetRootAnimatedGeometryRoot() {
return mRootAGR;
}
void RecomputeCurrentAnimatedGeometryRoot();
2017-11-16 03:09:28 +00:00
void Check() {
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2017-11-16 03:09:28 +00:00
mPool.Check();
#endif
2017-11-16 03:09:28 +00:00
}
/**
* Returns true if merging and flattening of display lists should be
* performed while computing visibility.
*/
bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; }
void SetAllowMergingAndFlattening(bool aAllow) { mAllowMergingAndFlattening = aAllow; }
nsDisplayLayerEventRegions* GetLayerEventRegions() { return mLayerEventRegions; }
void SetLayerEventRegions(nsDisplayLayerEventRegions* aItem)
{
mLayerEventRegions = aItem;
}
bool IsBuildingLayerEventRegions();
static bool LayerEventRegionsEnabled();
bool IsInsidePointerEventsNoneDoc()
{
return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
}
bool GetAncestorHasApzAwareEventHandler() const { return mAncestorHasApzAwareEventHandler; }
void SetAncestorHasApzAwareEventHandler(bool aValue)
{
mAncestorHasApzAwareEventHandler = aValue;
}
bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; }
void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; }
void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = false; }
bool SetIsCompositingCheap(bool aCompositingCheap) {
bool temp = mIsCompositingCheap;
mIsCompositingCheap = aCompositingCheap;
return temp;
}
bool IsCompositingCheap() const { return mIsCompositingCheap; }
/**
* Display the caret if needed.
*/
bool DisplayCaret(nsIFrame* aFrame, nsDisplayList* aList)
{
nsIFrame* frame = GetCaretFrame();
if (aFrame == frame) {
frame->DisplayCaret(this, aList);
return true;
}
return false;
}
/**
* Get the frame that the caret is supposed to draw in.
* If the caret is currently invisible, this will be null.
*/
nsIFrame* GetCaretFrame() {
return CurrentPresShellState()->mCaretFrame;
}
/**
* Get the rectangle we're supposed to draw the caret into.
*/
const nsRect& GetCaretRect() {
return CurrentPresShellState()->mCaretRect;
}
/**
* Get the caret associated with the current presshell.
*/
nsCaret* GetCaret();
/**
* Notify the display list builder that we're entering a presshell.
* aReferenceFrame should be a frame in the new presshell.
* aPointerEventsNoneDoc should be set to true if the frame generating this
* document is pointer-events:none.
*/
void EnterPresShell(nsIFrame* aReferenceFrame,
bool aPointerEventsNoneDoc = false);
/**
* For print-preview documents, we sometimes need to build display items for
* the same frames multiple times in the same presentation, with different
* clipping. Between each such batch of items, call
* ResetMarkedFramesForDisplayList to make sure that the results of
* MarkFramesForDisplayList do not carry over between batches.
*/
void ResetMarkedFramesForDisplayList(nsIFrame* aReferenceFrame);
/**
* Notify the display list builder that we're leaving a presshell.
*/
void LeavePresShell(nsIFrame* aReferenceFrame, nsDisplayList* aPaintedContents);
void IncrementPresShellPaintCount(nsIPresShell* aPresShell);
/**
* Returns true if we're currently building a display list that's
* directly or indirectly under an nsDisplayTransform.
*/
bool IsInTransform() const { return mInTransform; }
/**
* Indicate whether or not we're directly or indirectly under and
* nsDisplayTransform or SVG foreignObject.
*/
void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }
/**
* Return true if we're currently building a display list for a
* nested presshell.
*/
bool IsInSubdocument() { return mPresShellStates.Length() > 1; }
/**
* Return true if we're currently building a display list for the presshell
* of a chrome document, or if we're building the display list for a popup.
*/
bool IsInChromeDocumentOrPopup() {
return mIsInChromePresContext || mIsBuildingForPopup;
}
/**
* @return true if images have been set to decode synchronously.
*/
bool ShouldSyncDecodeImages() { return mSyncDecodeImages; }
/**
* Indicates whether we should synchronously decode images. If true, we decode
* and draw whatever image data has been loaded. If false, we just draw
* whatever has already been decoded.
*/
void SetSyncDecodeImages(bool aSyncDecodeImages) {
mSyncDecodeImages = aSyncDecodeImages;
}
void FreeClipChains();
/**
* Helper method to generate background painting flags based on the
* information available in the display list builder. Currently only
* accounts for mSyncDecodeImages.
*/
uint32_t GetBackgroundPaintFlags();
/**
* Subtracts aRegion from *aVisibleRegion. We avoid letting
* aVisibleRegion become overcomplex by simplifying it if necessary.
*/
void SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
const nsRegion& aRegion);
/**
* Mark the frames in aFrames to be displayed if they intersect aDirtyRect
* (which is relative to aDirtyFrame). If the frames have placeholders
* that might not be displayed, we mark the placeholders and their ancestors
* to ensure that display list construction descends into them
* anyway. nsDisplayListBuilder will take care of unmarking them when it is
* destroyed.
*/
void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
const nsFrameList& aFrames);
void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame, bool aAlreadyAddedFrame = false);
void MarkFrameForDisplayIfVisible(nsIFrame* aFrame, nsIFrame* aStopAtFrame);
void ClearFixedBackgroundDisplayData();
/**
* Mark all child frames that Preserve3D() as needing display.
* Because these frames include transforms set on their parent, dirty rects
* for intermediate frames may be empty, yet child frames could still be visible.
*/
void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame);
/**
* Returns true if we need to descend into this frame when building
* the display list, even though it doesn't intersect the dirty
* rect, because it may have out-of-flows that do so.
*/
bool ShouldDescendIntoFrame(nsIFrame* aFrame, bool aVisible) const {
return
(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
(aVisible && aFrame->ForceDescendIntoIfVisible()) ||
GetIncludeAllOutOfFlows();
}
/**
* Returns the list of registered theme geometries.
*/
nsTArray<ThemeGeometry> GetThemeGeometries() const
{
nsTArray<ThemeGeometry> geometries;
for (auto iter = mThemeGeometries.ConstIter(); !iter.Done(); iter.Next()) {
geometries.AppendElements(*iter.Data());
}
return geometries;
}
/**
* Notifies the builder that a particular themed widget exists
* at the given rectangle within the currently built display list.
* For certain appearance values (currently only NS_THEME_TOOLBAR and
* NS_THEME_WINDOW_TITLEBAR) this gets called during every display list
* construction, for every themed widget of the right type within the
* display list, except for themed widgets which are transformed or have
* effects applied to them (e.g. CSS opacity or filters).
*
* @param aWidgetType the -moz-appearance value for the themed widget
* @param aItem the item associated with the theme geometry
* @param aRect the device-pixel rect relative to the widget's displayRoot
* for the themed widget
*/
void RegisterThemeGeometry(uint8_t aWidgetType, nsDisplayItem* aItem,
const mozilla::LayoutDeviceIntRect& aRect)
{
if (!mIsPaintingToWindow) {
return;
}
nsTArray<ThemeGeometry>* geometries = mThemeGeometries.LookupOrAdd(aItem);
geometries->AppendElement(ThemeGeometry(aWidgetType, aRect));
}
/**
* Removes theme geometries associated with the given display item |aItem|.
*/
void UnregisterThemeGeometry(nsDisplayItem* aItem)
{
mThemeGeometries.Remove(aItem);
}
/**
* Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
* -moz-window-dragging value is |drag|, its border box is added to the
* collected dragging region; if the value is |no-drag|, the border box is
* subtracted from the region; if the value is |default|, that frame does
* not influence the window dragging region.
*/
void AdjustWindowDraggingRegion(nsIFrame* aFrame);
LayoutDeviceIntRegion GetWindowDraggingRegion() const;
void RemoveModifiedWindowDraggingRegion();
void ClearWindowDraggingRegion();
/**
* Allocate memory in our arena. It will only be freed when this display list
* builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
* destructors are called as soon as the item is no longer used.
*/
void* Allocate(size_t aSize, DisplayItemType aType);
void Destroy(DisplayItemType aType, void* aPtr);
/**
* Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
* automatically when the arena goes away.
*/
ActiveScrolledRoot* AllocateActiveScrolledRoot(const ActiveScrolledRoot* aParent,
nsIScrollableFrame* aScrollableFrame);
/**
* Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
* up automatically when the arena goes away.
*/
const DisplayItemClipChain* AllocateDisplayItemClipChain(const DisplayItemClip& aClip,
const ActiveScrolledRoot* aASR,
const DisplayItemClipChain* aParent);
/**
* Intersect two clip chains, allocating the new clip chain items in this
* builder's arena. The result is parented to aAncestor, and no intersections
* happen past aAncestor's ASR.
* That means aAncestor has to be living in this builder's arena already.
* aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
* their values are copied into the newly-allocated intersected clip chain
* and this function does not hold on to any pointers to them.
*/
const DisplayItemClipChain* CreateClipChainIntersection(const DisplayItemClipChain* aAncestor,
const DisplayItemClipChain* aLeafClip1,
const DisplayItemClipChain* aLeafClip2);
/**
* Clone the supplied clip chain's chain items into this builder's arena.
*/
const DisplayItemClipChain* CopyWholeChain(const DisplayItemClipChain* aClipChain);
/**
* Only used for containerful root scrolling. This is a workaround.
*/
void SetActiveScrolledRootForRootScrollframe(const ActiveScrolledRoot* aASR)
{ mActiveScrolledRootForRootScrollframe = aASR; }
const ActiveScrolledRoot* ActiveScrolledRootForRootScrollframe() const
{ return mActiveScrolledRootForRootScrollframe; }
/**
* Transfer off main thread animations to the layer. May be called
* with aBuilder and aItem both null, but only if the caller has
* already checked that off main thread animations should be sent to
* the layer. When they are both null, the animations are added to
* the layer as pending animations.
*/
static void AddAnimationsAndTransitionsToLayer(Layer* aLayer,
nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
nsIFrame* aFrame,
nsCSSPropertyID aProperty);
/**
* Merges the display items in |aMergedItems| and returns a new temporary
* display item.
* The display items in |aMergedItems| have to be mergeable with each other.
*/
nsDisplayItem* MergeItems(nsTArray<nsDisplayItem*>& aMergedItems);
/**
* A helper class to temporarily set the value of
* mIsAtRootOfPseudoStackingContext, and temporarily
* set mCurrentFrame and related state. Also temporarily sets mDirtyRect.
* aDirtyRect is relative to aForChild.
*/
class AutoBuildingDisplayList;
friend class AutoBuildingDisplayList;
class AutoBuildingDisplayList {
public:
AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder,
nsIFrame* aForChild,
const nsRect& aVisibleRect,
const nsRect& aDirtyRect,
bool aIsRoot)
: mBuilder(aBuilder),
mPrevFrame(aBuilder->mCurrentFrame),
mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame),
mPrevLayerEventRegions(aBuilder->mLayerEventRegions),
mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame),
mPrevVisibleRect(aBuilder->mVisibleRect),
mPrevDirtyRect(aBuilder->mDirtyRect),
mPrevAGR(aBuilder->mCurrentAGR),
mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext),
mPrevAncestorHasApzAwareEventHandler(aBuilder->mAncestorHasApzAwareEventHandler),
mPrevBuildingInvisibleItems(aBuilder->mBuildingInvisibleItems),
mPrevInInvalidSubtree(aBuilder->mInInvalidSubtree)
{
if (aForChild->IsTransformed()) {
aBuilder->mCurrentOffsetToReferenceFrame = nsPoint();
aBuilder->mCurrentReferenceFrame = aForChild;
} else if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
aBuilder->mCurrentOffsetToReferenceFrame += aForChild->GetPosition();
} else {
aBuilder->mCurrentReferenceFrame =
aBuilder->FindReferenceFrameFor(aForChild,
&aBuilder->mCurrentOffsetToReferenceFrame);
}
bool isAsync;
mCurrentAGRState = aBuilder->IsAnimatedGeometryRoot(aForChild, isAsync);
if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
if (mCurrentAGRState == AGR_YES) {
aBuilder->mCurrentAGR = aBuilder->WrapAGRForFrame(aForChild, isAsync, aBuilder->mCurrentAGR);
}
} else if (aForChild != aBuilder->mCurrentFrame) {
aBuilder->mCurrentAGR = aBuilder->FindAnimatedGeometryRootFor(aForChild);
}
MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(), *aBuilder->mCurrentAGR));
aBuilder->mCurrentFrame = aForChild;
aBuilder->mVisibleRect = aVisibleRect;
aBuilder->mDirtyRect = aDirtyRect;
aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
aBuilder->mInInvalidSubtree = aBuilder->mInInvalidSubtree || aForChild->IsFrameModified();
}
void SetReferenceFrameAndCurrentOffset(const nsIFrame* aFrame, const nsPoint& aOffset) {
mBuilder->mCurrentReferenceFrame = aFrame;
mBuilder->mCurrentOffsetToReferenceFrame = aOffset;
}
bool IsAnimatedGeometryRoot() const {
return mCurrentAGRState == AGR_YES;
}
bool MaybeAnimatedGeometryRoot() const {
return mCurrentAGRState == AGR_MAYBE;
}
void RestoreBuildingInvisibleItemsValue() {
mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
}
~AutoBuildingDisplayList() {
mBuilder->mCurrentFrame = mPrevFrame;
mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
mBuilder->mLayerEventRegions = mPrevLayerEventRegions;
mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
mBuilder->mVisibleRect = mPrevVisibleRect;
mBuilder->mDirtyRect = mPrevDirtyRect;
mBuilder->mCurrentAGR = mPrevAGR;
mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext;
mBuilder->mAncestorHasApzAwareEventHandler = mPrevAncestorHasApzAwareEventHandler;
mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
mBuilder->mInInvalidSubtree = mPrevInInvalidSubtree;
}
private:
nsDisplayListBuilder* mBuilder;
AGRState mCurrentAGRState;
const nsIFrame* mPrevFrame;
const nsIFrame* mPrevReferenceFrame;
nsDisplayLayerEventRegions* mPrevLayerEventRegions;
nsPoint mPrevOffset;
nsRect mPrevVisibleRect;
nsRect mPrevDirtyRect;
RefPtr<AnimatedGeometryRoot> mPrevAGR;
bool mPrevIsAtRootOfPseudoStackingContext;
bool mPrevAncestorHasApzAwareEventHandler;
bool mPrevBuildingInvisibleItems;
bool mPrevInInvalidSubtree;
};
/**
* A helper class to temporarily set the value of mInTransform.
*/
class AutoInTransformSetter;
friend class AutoInTransformSetter;
class AutoInTransformSetter {
public:
AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
: mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
aBuilder->mInTransform = aInTransform;
}
~AutoInTransformSetter() {
mBuilder->mInTransform = mOldValue;
}
private:
nsDisplayListBuilder* mBuilder;
bool mOldValue;
};
class AutoSaveRestorePerspectiveIndex;
friend class AutoSaveRestorePerspectiveIndex;
class AutoSaveRestorePerspectiveIndex {
public:
AutoSaveRestorePerspectiveIndex(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: mBuilder(nullptr)
{
if (aFrame->ChildrenHavePerspective()) {
mBuilder = aBuilder;
mCachedItemIndex = aBuilder->mPerspectiveItemIndex;
aBuilder->mPerspectiveItemIndex = 0;
}
}
~AutoSaveRestorePerspectiveIndex()
{
if (mBuilder) {
mBuilder->mPerspectiveItemIndex = mCachedItemIndex;
}
}
private:
nsDisplayListBuilder* mBuilder;
uint32_t mCachedItemIndex;
};
/**
* A helper class to temporarily set the value of mCurrentScrollParentId.
*/
class AutoCurrentScrollParentIdSetter;
friend class AutoCurrentScrollParentIdSetter;
class AutoCurrentScrollParentIdSetter {
public:
AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId)
: mBuilder(aBuilder)
, mOldValue(aBuilder->mCurrentScrollParentId)
, mOldForceLayer(aBuilder->mForceLayerForScrollParent) {
// If this AutoCurrentScrollParentIdSetter has the same scrollId as the
// previous one on the stack, then that means the scrollframe that
// created this isn't actually scrollable and cannot participate in
// scroll handoff. We set mCanBeScrollParent to false to indicate this.
mCanBeScrollParent = (mOldValue != aScrollId);
aBuilder->mCurrentScrollParentId = aScrollId;
aBuilder->mForceLayerForScrollParent = false;
}
bool ShouldForceLayerForScrollParent() const {
// Only scrollframes participating in scroll handoff can be forced to
// layerize
return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent;
};
~AutoCurrentScrollParentIdSetter() {
mBuilder->mCurrentScrollParentId = mOldValue;
if (mCanBeScrollParent) {
// If this flag is set, caller code is responsible for having dealt
// with the current value of mBuilder->mForceLayerForScrollParent, so
// we can just restore the old value.
mBuilder->mForceLayerForScrollParent = mOldForceLayer;
} else {
// Otherwise we need to keep propagating the force-layerization flag
// upwards to the next ancestor scrollframe that does participate in
// scroll handoff.
mBuilder->mForceLayerForScrollParent |= mOldForceLayer;
}
}
private:
nsDisplayListBuilder* mBuilder;
ViewID mOldValue;
bool mOldForceLayer;
bool mCanBeScrollParent;
};
/**
* Used to update the current active scrolled root on the display list
* builder, and to create new active scrolled roots.
*/
class AutoCurrentActiveScrolledRootSetter;
friend class AutoCurrentActiveScrolledRootSetter;
class AutoCurrentActiveScrolledRootSetter {
public:
explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder* aBuilder)
: mBuilder(aBuilder)
, mSavedActiveScrolledRoot(aBuilder->mCurrentActiveScrolledRoot)
, mContentClipASR(aBuilder->ClipState().GetContentClipASR())
, mDescendantsStartIndex(aBuilder->mActiveScrolledRoots.Length())
, mUsed(false)
{
}
~AutoCurrentActiveScrolledRootSetter()
{
mBuilder->mCurrentActiveScrolledRoot = mSavedActiveScrolledRoot;
}
void SetCurrentActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot)
{
MOZ_ASSERT(!mUsed);
// Set the builder's mCurrentActiveScrolledRoot.
mBuilder->mCurrentActiveScrolledRoot = aActiveScrolledRoot;
// We also need to adjust the builder's mCurrentContainerASR.
// mCurrentContainerASR needs to be an ASR that all the container's
// contents have finite bounds with respect to. If aActiveScrolledRoot
// is an ancestor ASR of mCurrentContainerASR, that means we need to
// set mCurrentContainerASR to aActiveScrolledRoot, because otherwise
// the items that will be created with aActiveScrolledRoot wouldn't
// have finite bounds with respect to mCurrentContainerASR. There's one
// exception, in the case where there's a content clip on the builder
// that is scrolled by a descendant ASR of aActiveScrolledRoot. This
// content clip will clip all items that are created while this
// AutoCurrentActiveScrolledRootSetter exists. This means that the items
// created during our lifetime will have finite bounds with respect to
// the content clip's ASR, even if the items' actual ASR is an ancestor
// of that. And it also means that mCurrentContainerASR only needs to be
// set to the content clip's ASR and not all the way to aActiveScrolledRoot.
// This case is tested by fixed-pos-scrolled-clip-opacity-layerize.html
// and fixed-pos-scrolled-clip-opacity-inside-layerize.html.
// finiteBoundsASR is the leafmost ASR that all items created during
// object's lifetime have finite bounds with respect to.
const ActiveScrolledRoot* finiteBoundsASR = ActiveScrolledRoot::PickDescendant(
mContentClipASR, aActiveScrolledRoot);
// mCurrentContainerASR is adjusted so that it's still an ancestor of
// finiteBoundsASR.
mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
mBuilder->mCurrentContainerASR, finiteBoundsASR);
mUsed = true;
}
void EnterScrollFrame(nsIScrollableFrame* aScrollableFrame)
{
MOZ_ASSERT(!mUsed);
ActiveScrolledRoot* asr = mBuilder->AllocateActiveScrolledRoot(
mBuilder->mCurrentActiveScrolledRoot, aScrollableFrame);
mBuilder->mCurrentActiveScrolledRoot = asr;
mUsed = true;
}
void InsertScrollFrame(nsIScrollableFrame* aScrollableFrame);
private:
nsDisplayListBuilder* mBuilder;
/**
* The builder's mCurrentActiveScrolledRoot at construction time which
* needs to be restored at destruction time.
*/
const ActiveScrolledRoot* mSavedActiveScrolledRoot;
/**
* If there's a content clip on the builder at construction time, then
* mContentClipASR is that content clip's ASR, otherwise null. The
* assumption is that the content clip doesn't get relaxed while this
* object is on the stack.
*/
const ActiveScrolledRoot* mContentClipASR;
/**
* InsertScrollFrame needs to mutate existing ASRs (those that were
* created while this object was on the stack), and mDescendantsStartIndex
* makes it easier to skip ASRs that were created in the past.
*/
size_t mDescendantsStartIndex;
/**
* Flag to make sure that only one of SetCurrentActiveScrolledRoot /
* EnterScrollFrame / InsertScrollFrame is called per instance of this
* class.
*/
bool mUsed;
};
/**
* Keeps track of the innermost ASR that can be used as the ASR for a
* container item that wraps all items that were created while this
* object was on the stack.
* The rule is: all child items of the container item need to have
* clipped bounds with respect to the container ASR.
*/
class AutoContainerASRTracker;
friend class AutoContainerASRTracker;
class AutoContainerASRTracker {
public:
explicit AutoContainerASRTracker(nsDisplayListBuilder* aBuilder)
: mBuilder(aBuilder)
, mSavedContainerASR(aBuilder->mCurrentContainerASR)
{
mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickDescendant(
mBuilder->ClipState().GetContentClipASR(),
mBuilder->mCurrentActiveScrolledRoot);
}
const ActiveScrolledRoot* GetContainerASR()
{
return mBuilder->mCurrentContainerASR;
}
~AutoContainerASRTracker()
{
mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
mBuilder->mCurrentContainerASR, mSavedContainerASR);
}
private:
nsDisplayListBuilder* mBuilder;
const ActiveScrolledRoot* mSavedContainerASR;
};
/**
* A helper class to temporarily set the value of mCurrentScrollbarTarget
* and mCurrentScrollbarFlags.
*/
class AutoCurrentScrollbarInfoSetter;
friend class AutoCurrentScrollbarInfoSetter;
class AutoCurrentScrollbarInfoSetter {
public:
AutoCurrentScrollbarInfoSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollTargetID,
nsDisplayOwnLayerFlags aScrollbarFlags, bool aWillHaveLayer)
: mBuilder(aBuilder) {
aBuilder->mIsBuildingScrollbar = true;
aBuilder->mCurrentScrollbarTarget = aScrollTargetID;
aBuilder->mCurrentScrollbarFlags = aScrollbarFlags;
aBuilder->mCurrentScrollbarWillHaveLayer = aWillHaveLayer;
}
~AutoCurrentScrollbarInfoSetter() {
// No need to restore old values because scrollbars cannot be nested.
mBuilder->mIsBuildingScrollbar = false;
mBuilder->mCurrentScrollbarTarget = FrameMetrics::NULL_SCROLL_ID;
mBuilder->mCurrentScrollbarFlags = (nsDisplayOwnLayerFlags)0;
mBuilder->mCurrentScrollbarWillHaveLayer = false;
}
private:
nsDisplayListBuilder* mBuilder;
};
/**
* A helper class to track current effective transform for items.
*
* For frames that is Combines3DTransformWithAncestors(), we need to
* apply all transforms of ancestors on the same preserves3D chain
* on the bounds of current frame to the coordination of the 3D
* context root. The 3D context root computes it's bounds from
* these transformed bounds.
*/
class AutoAccumulateTransform;
friend class AutoAccumulateTransform;
class AutoAccumulateTransform {
public:
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
explicit AutoAccumulateTransform(nsDisplayListBuilder* aBuilder)
: mBuilder(aBuilder)
, mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform) {}
~AutoAccumulateTransform() {
mBuilder->mPreserves3DCtx.mAccumulatedTransform = mSavedTransform;
}
void Accumulate(const Matrix4x4& aTransform) {
mBuilder->mPreserves3DCtx.mAccumulatedTransform =
aTransform * mBuilder->mPreserves3DCtx.mAccumulatedTransform;
}
const Matrix4x4& GetCurrentTransform() {
return mBuilder->mPreserves3DCtx.mAccumulatedTransform;
}
void StartRoot() {
mBuilder->mPreserves3DCtx.mAccumulatedTransform = Matrix4x4();
}
private:
nsDisplayListBuilder* mBuilder;
Matrix4x4 mSavedTransform;
};
/**
* A helper class to collect bounds rects of descendants.
*
* For a 3D context root, it's bounds is computed from the bounds of
* descendants. If we transform bounds frame by frame applying
* transforms, the bounds may turn to empty for any singular
* transform on the path, but it is not empty for the accumulated
* transform.
*/
class AutoAccumulateRect;
friend class AutoAccumulateRect;
class AutoAccumulateRect {
public:
explicit AutoAccumulateRect(nsDisplayListBuilder* aBuilder)
: mBuilder(aBuilder)
, mSavedRect(aBuilder->mPreserves3DCtx.mAccumulatedRect) {
aBuilder->mPreserves3DCtx.mAccumulatedRect = nsRect();
aBuilder->mPreserves3DCtx.mAccumulatedRectLevels++;
}
~AutoAccumulateRect() {
mBuilder->mPreserves3DCtx.mAccumulatedRect = mSavedRect;
mBuilder->mPreserves3DCtx.mAccumulatedRectLevels--;
}
private:
nsDisplayListBuilder* mBuilder;
nsRect mSavedRect;
};
void AccumulateRect(const nsRect& aRect) {
mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect, aRect);
}
const nsRect& GetAccumulatedRect() {
return mPreserves3DCtx.mAccumulatedRect;
}
/**
* The level is increased by one for items establishing 3D rendering
* context and starting a new accumulation.
*/
int GetAccumulatedRectLevels() {
return mPreserves3DCtx.mAccumulatedRectLevels;
}
// Helpers for tables
nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
struct OutOfFlowDisplayData {
OutOfFlowDisplayData(const DisplayItemClipChain* aContainingBlockClipChain,
const DisplayItemClipChain* aCombinedClipChain,
const ActiveScrolledRoot* aContainingBlockActiveScrolledRoot,
const nsRect &aVisibleRect,
const nsRect &aDirtyRect)
: mContainingBlockClipChain(aContainingBlockClipChain)
, mCombinedClipChain(aCombinedClipChain)
, mContainingBlockActiveScrolledRoot(aContainingBlockActiveScrolledRoot)
, mVisibleRect(aVisibleRect)
, mDirtyRect(aDirtyRect)
{}
const DisplayItemClipChain* mContainingBlockClipChain;
const DisplayItemClipChain* mCombinedClipChain; // only necessary for the special case of top layer
const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot;
nsRect mVisibleRect;
nsRect mDirtyRect;
};
NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty,
OutOfFlowDisplayData)
struct DisplayListBuildingData {
RefPtr<AnimatedGeometryRoot> mModifiedAGR = nullptr;
nsRect mDirtyRect;
};
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect, DisplayListBuildingData)
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect, nsRect)
static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame)
{
return aFrame->GetProperty(OutOfFlowDisplayDataProperty());
}
nsPresContext* CurrentPresContext() {
return CurrentPresShellState()->mPresShell->GetPresContext();
}
OutOfFlowDisplayData* GetCurrentFixedBackgroundDisplayData()
{
auto& displayData = CurrentPresShellState()->mFixedBackgroundDisplayData;
return displayData ? displayData.ptr() : nullptr;
}
/**
* Accumulates the bounds of box frames that have moz-appearance
* -moz-win-exclude-glass style. Used in setting glass margins on
* Windows.
*
* We set the window opaque region (from which glass margins are computed)
* to the intersection of the glass region specified here and the opaque
* region computed during painting. So the excluded glass region actually
* *limits* the extent of the opaque area reported to Windows. We limit it
* so that changes to the computed opaque region (which can vary based on
* region optimizations and the placement of UI elements) outside the
* -moz-win-exclude-glass area don't affect the glass margins reported to
* Windows; changing those margins willy-nilly can cause the Windows 7 glass
* haze effect to jump around disconcertingly.
*/
void AddWindowExcludeGlassRegion(const nsRegion& bounds) {
mWindowExcludeGlassRegion.Or(mWindowExcludeGlassRegion, bounds);
}
const nsRegion& GetWindowExcludeGlassRegion() {
return mWindowExcludeGlassRegion;
}
/**
* Accumulates opaque stuff into the window opaque region.
*/
void AddWindowOpaqueRegion(const nsRegion& bounds) {
mWindowOpaqueRegion.Or(mWindowOpaqueRegion, bounds);
}
/**
* Returns the window opaque region built so far. This may be incomplete
* since the opaque region is built during layer construction.
*/
const nsRegion& GetWindowOpaqueRegion() {
return mWindowOpaqueRegion;
}
void SetGlassDisplayItem(nsDisplayItem* aItem) {
if (mGlassDisplayItem) {
// Web pages or extensions could trigger this by using
// -moz-appearance:win-borderless-glass etc on their own elements.
// Keep the first one, since that will be the background of the root
// window
NS_WARNING("Multiple glass backgrounds found?");
} else {
mGlassDisplayItem = aItem;
}
}
bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem);
void SetContainsPluginItem() { mContainsPluginItem = true; }
bool ContainsPluginItem() { return mContainsPluginItem; }
/**
* mContainsBlendMode is true if we processed a display item that
* has a blend mode attached. We do this so we can insert a
* nsDisplayBlendContainer in the parent stacking context.
*/
void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; }
bool ContainsBlendMode() const { return mContainsBlendMode; }
uint32_t AllocatePerspectiveItemIndex() { return mPerspectiveItemIndex++; }
DisplayListClipState& ClipState() { return mClipState; }
const ActiveScrolledRoot* CurrentActiveScrolledRoot() { return mCurrentActiveScrolledRoot; }
const ActiveScrolledRoot* CurrentAncestorASRStackingContextContents() { return mCurrentContainerASR; }
/**
* Add the current frame to the will-change budget if possible and
* remeber the outcome. Subsequent calls to IsInWillChangeBudget
* will return the same value as return here.
*/
bool AddToWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
/**
* This will add the current frame to the will-change budget the first
* time it is seen. On subsequent calls this will return the same
* answer. This effectively implements a first-come, first-served
* allocation of the will-change budget.
*/
bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
void ClearWillChangeBudget(nsIFrame* aFrame);
void EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage);
void ExitSVGEffectsContents();
/**
* Note: if changing the conditions under which scroll info layers
* are created, make a corresponding change to
* ScrollFrameWillBuildScrollInfoLayer() in nsSliderFrame.cpp.
*/
bool ShouldBuildScrollInfoItemsForHoisting() const
{ return mSVGEffectsBuildingDepth > 0; }
void AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem);
/**
* A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
*
* mPreserves3DCtx is used by class AutoAccumulateTransform &
* AutoAccumulateRect to passing data between frames in the 3D
* context. If a frame create a new 3D context, it should restore
* the value of mPreserves3DCtx before returning back to the parent.
* This class do it for the users.
*/
class AutoPreserves3DContext;
friend class AutoPreserves3DContext;
class AutoPreserves3DContext {
public:
explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder)
: mBuilder(aBuilder)
, mSavedCtx(aBuilder->mPreserves3DCtx) {}
~AutoPreserves3DContext() {
mBuilder->mPreserves3DCtx = mSavedCtx;
}
private:
nsDisplayListBuilder* mBuilder;
Preserves3DContext mSavedCtx;
};
const nsRect GetPreserves3DRect() const {
return mPreserves3DCtx.mVisibleRect;
}
void SavePreserves3DRect() {
mPreserves3DCtx.mVisibleRect = mVisibleRect;
}
bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems; }
void SetBuildingInvisibleItems(bool aBuildingInvisibleItems) {
mBuildingInvisibleItems = aBuildingInvisibleItems;
}
bool MarkFrameModifiedDuringBuilding(nsIFrame* aFrame)
{
if (!aFrame->IsFrameModified()) {
mModifiedFramesDuringBuilding.AppendElement(aFrame);
aFrame->SetFrameIsModified(true);
return true;
}
return false;
}
bool MarkCurrentFrameModifiedDuringBuilding()
{
if (MarkFrameModifiedDuringBuilding(const_cast<nsIFrame*>(mCurrentFrame))) {
mInInvalidSubtree = true;
return true;
}
return false;
}
/**
* This is a convenience function to ease the transition until AGRs and ASRs
* are unified.
*/
AnimatedGeometryRoot* AnimatedGeometryRootForASR(const ActiveScrolledRoot* aASR);
bool HitTestIsForVisibility() const {
return mHitTestIsForVisibility;
}
void SetHitTestIsForVisibility(bool aHitTestIsForVisibility) {
mHitTestIsForVisibility = aHitTestIsForVisibility;
}
private:
void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame);
/**
* Returns whether a frame acts as an animated geometry root, optionally
* returning the next ancestor to check.
*/
AGRState IsAnimatedGeometryRoot(nsIFrame* aFrame,
bool& aIsAsync,
nsIFrame** aParent = nullptr);
/**
* Returns the nearest ancestor frame to aFrame that is considered to have
* (or will have) animated geometry. This can return aFrame.
*/
nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame, bool& aIsAsync);
friend class nsDisplayCanvasBackgroundImage;
friend class nsDisplayBackgroundImage;
friend class nsDisplayFixedPosition;
AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsDisplayItem* aItem);
friend class nsDisplayItem;
friend class nsDisplayOwnLayer;
friend struct RetainedDisplayListBuilder;
AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsIFrame* aFrame);
AnimatedGeometryRoot* WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
bool aIsAsync,
AnimatedGeometryRoot* aParent = nullptr);
nsDataHashtable<nsPtrHashKey<nsIFrame>, RefPtr<AnimatedGeometryRoot>> mFrameToAnimatedGeometryRootMap;
/**
* Add the current frame to the AGR budget if possible and remember
* the outcome. Subsequent calls will return the same value as
* returned here.
*/
bool AddToAGRBudget(nsIFrame* aFrame);
struct PresShellState {
nsIPresShell* mPresShell;
#ifdef DEBUG
mozilla::Maybe<nsAutoLayoutPhase> mAutoLayoutPhase;
#endif
nsIFrame* mCaretFrame;
nsRect mCaretRect;
mozilla::Maybe<OutOfFlowDisplayData> mFixedBackgroundDisplayData;
uint32_t mFirstFrameMarkedForDisplay;
bool mIsBackgroundOnly;
// This is a per-document flag turning off event handling for all content
// in the document, and is set when we enter a subdocument for a pointer-
// events:none frame.
bool mInsidePointerEventsNoneDoc;
};
PresShellState* CurrentPresShellState() {
NS_ASSERTION(mPresShellStates.Length() > 0,
"Someone forgot to enter a presshell");
return &mPresShellStates[mPresShellStates.Length() - 1];
}
struct DocumentWillChangeBudget {
DocumentWillChangeBudget()
: mBudget(0)
{}
uint32_t mBudget;
};
struct FrameWillChangeBudget {
FrameWillChangeBudget(nsIFrame* aFrame, uint32_t aUsage)
: mFrame(aFrame)
, mUsage(aUsage)
{}
nsIFrame* mFrame;
uint32_t mUsage;
};
nsIFrame* const mReferenceFrame;
nsIFrame* mIgnoreScrollFrame;
nsDisplayLayerEventRegions* mLayerEventRegions;
nsPresArena mPool;
nsCOMPtr<nsISelection> mBoundingSelection;
AutoTArray<PresShellState,8> mPresShellStates;
AutoTArray<nsIFrame*,400> mFramesMarkedForDisplay;
AutoTArray<nsIFrame*,40> mFramesMarkedForDisplayIfVisible;
nsClassHashtable<nsPtrHashKey<nsDisplayItem>, nsTArray<ThemeGeometry>> mThemeGeometries;
nsDisplayTableItem* mCurrentTableItem;
DisplayListClipState mClipState;
const ActiveScrolledRoot* mCurrentActiveScrolledRoot;
const ActiveScrolledRoot* mCurrentContainerASR;
// mCurrentFrame is the frame that we're currently calling (or about to call)
// BuildDisplayList on.
const nsIFrame* mCurrentFrame;
// The reference frame for mCurrentFrame.
const nsIFrame* mCurrentReferenceFrame;
// The offset from mCurrentFrame to mCurrentReferenceFrame.
nsPoint mCurrentOffsetToReferenceFrame;
RefPtr<AnimatedGeometryRoot> mRootAGR;
RefPtr<AnimatedGeometryRoot> mCurrentAGR;
// will-change budget tracker
nsDataHashtable<nsPtrHashKey<nsPresContext>, DocumentWillChangeBudget>
mWillChangeBudget;
// Any frame listed in this set is already counted in the budget
// and thus is in-budget.
nsDataHashtable<nsPtrHashKey<nsIFrame>, uint32_t> mWillChangeBudgetSet;
// Area of animated geometry root budget already allocated
uint32_t mUsedAGRBudget;
// Set of frames already counted in budget
nsTHashtable<nsPtrHashKey<nsIFrame> > mAGRBudgetSet;
nsTArray<nsIFrame*> mModifiedFramesDuringBuilding;
// Relative to mCurrentFrame.
nsRect mVisibleRect;
nsRect mDirtyRect;
nsRegion mWindowExcludeGlassRegion;
nsRegion mWindowOpaqueRegion;
std::vector<WeakFrame> mWindowDraggingFrames;
nsTArray<pixman_box32_t> mWindowDraggingRects;
LayoutDeviceIntRegion mWindowDraggingRegion;
std::vector<WeakFrame> mWindowNoDraggingFrames;
nsTArray<pixman_box32_t> mWindowNoDraggingRects;
LayoutDeviceIntRegion mWindowNoDraggingRegion;
// The display item for the Windows window glass background, if any
nsDisplayItem* mGlassDisplayItem;
// A temporary list that we append scroll info items to while building
// display items for the contents of frames with SVG effects.
// Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
// This is a pointer and not a real nsDisplayList value because the
// nsDisplayList class is defined below this class, so we can't use it here.
nsDisplayList* mScrollInfoItemsForHoisting;
nsTArray<RefPtr<ActiveScrolledRoot>> mActiveScrolledRoots;
std::list<DisplayItemClipChain*> mClipChainsToDestroy;
nsTArray<nsDisplayItem*> mTemporaryItems;
const ActiveScrolledRoot* mActiveScrolledRootForRootScrollframe;
nsDisplayListBuilderMode mMode;
ViewID mCurrentScrollParentId;
ViewID mCurrentScrollbarTarget;
nsDisplayOwnLayerFlags mCurrentScrollbarFlags;
Preserves3DContext mPreserves3DCtx;
uint32_t mPerspectiveItemIndex;
int32_t mSVGEffectsBuildingDepth;
bool mContainsBlendMode;
bool mIsBuildingScrollbar;
bool mCurrentScrollbarWillHaveLayer;
bool mBuildCaret;
bool mRetainingDisplayList;
bool mPartialUpdate;
bool mIgnoreSuppression;
bool mIsAtRootOfPseudoStackingContext;
bool mIncludeAllOutOfFlows;
bool mDescendIntoSubdocuments;
bool mSelectedFramesOnly;
bool mAllowMergingAndFlattening;
bool mWillComputePluginGeometry;
// True when we're building a display list that's directly or indirectly
// under an nsDisplayTransform
bool mInTransform;
bool mIsInChromePresContext;
bool mSyncDecodeImages;
bool mIsPaintingToWindow;
bool mIsCompositingCheap;
bool mContainsPluginItem;
bool mAncestorHasApzAwareEventHandler;
// True when the first async-scrollable scroll frame for which we build a
// display list has a display port. An async-scrollable scroll frame is one
// which WantsAsyncScroll().
bool mHaveScrollableDisplayPort;
bool mWindowDraggingAllowed;
bool mIsBuildingForPopup;
bool mForceLayerForScrollParent;
bool mAsyncPanZoomEnabled;
bool mBuildingInvisibleItems;
bool mHitTestIsForVisibility;
bool mIsBuilding;
bool mInInvalidSubtree;
bool mBuildCompositorHitTestInfo;
};
class nsDisplayItem;
class nsDisplayList;
/**
* nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
* nsDisplayItemLink holds the link. The lists are linked from lowest to
* highest in z-order.
*/
class nsDisplayItemLink {
// This is never instantiated directly, so no need to count constructors and
// destructors.
protected:
nsDisplayItemLink() : mAbove(nullptr) {}
nsDisplayItemLink(const nsDisplayItemLink&) : mAbove(nullptr) {}
nsDisplayItem* mAbove;
friend class nsDisplayList;
};
class nsDisplayWrapList;
/**
* This is the unit of rendering and event testing. Each instance of this
* class represents an entity that can be drawn on the screen, e.g., a
* frame's CSS background, or a frame's text string.
*
* nsDisplayItems can be containers --- i.e., they can perform hit testing
* and painting by recursively traversing a list of child items.
*
* These are arena-allocated during display list construction. A typical
* subclass would just have a frame pointer, so its object would be just three
* pointers (vtable, next-item, frame).
*
* Display items belong to a list at all times (except temporarily as they
* move from one list to another).
*/
class nsDisplayItem : public nsDisplayItemLink {
public:
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
typedef mozilla::DisplayItemClip DisplayItemClip;
typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::ScrollMetadata ScrollMetadata;
typedef mozilla::layers::FrameMetrics::ViewID ViewID;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::StackingContextHelper StackingContextHelper;
typedef mozilla::layers::WebRenderCommand WebRenderCommand;
typedef mozilla::layers::WebRenderParentCommand WebRenderParentCommand;
typedef mozilla::LayerState LayerState;
typedef mozilla::image::imgDrawingParams imgDrawingParams;
typedef mozilla::image::DrawResult DrawResult;
typedef class mozilla::gfx::DrawTarget DrawTarget;
// This is never instantiated directly (it has pure virtual methods), so no
// need to count constructors and destructors.
nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const ActiveScrolledRoot* aActiveScrolledRoot);
/**
* This constructor is only used in rare cases when we need to construct
* temporary items.
*/
explicit nsDisplayItem(nsIFrame* aFrame)
: mFrame(aFrame)
, mClipChain(nullptr)
, mClip(nullptr)
, mActiveScrolledRoot(nullptr)
, mReferenceFrame(nullptr)
, mAnimatedGeometryRoot(nullptr)
, mForceNotVisible(false)
, mDisableSubpixelAA(false)
, mReusedItem(false)
#ifdef MOZ_DUMP_PAINTING
, mPainted(false)
#endif
{
MOZ_COUNT_CTOR(nsDisplayItem);
}
protected:
virtual ~nsDisplayItem() {
MOZ_COUNT_DTOR(nsDisplayItem);
if (mFrame) {
mFrame->RemoveDisplayItem(this);
}
}
public:
virtual void Destroy(nsDisplayListBuilder* aBuilder)
{
DisplayItemType type = GetType();
this->~nsDisplayItem();
aBuilder->Destroy(type, this);
}
virtual void RestoreState()
{
mVisibleRect = mState.mVisibleRect;
mClipChain = mState.mClipChain;
mClip = mState.mClip;
mDisableSubpixelAA = false;
}
virtual void RemoveFrame(nsIFrame* aFrame)
{
if (aFrame == mFrame) {
MOZ_ASSERT(!mFrame->HasDisplayItem(this));
mFrame = nullptr;
}
}
/**
* Downcasts this item to nsDisplayWrapList, if possible.
*/
virtual const nsDisplayWrapList* AsDisplayWrapList() const { return nullptr; }
virtual nsDisplayWrapList* AsDisplayWrapList() { return nullptr; }
/**
* Create a clone of this item.
*/
virtual nsDisplayItem* Clone(nsDisplayListBuilder* aBuilder) const
{
return nullptr;
}
nsDisplayItem(const nsDisplayItem&) = delete;
/**
* The custom copy-constructor is implemented to prevent copying the saved
* state of the item.
* This is currently only used when creating temporary items for merging.
*/
nsDisplayItem(nsDisplayListBuilder* aBuilder, const nsDisplayItem& aOther)
: mFrame(aOther.mFrame)
, mClipChain(aOther.mClipChain)
, mClip(aOther.mClip)
, mActiveScrolledRoot(aOther.mActiveScrolledRoot)
, mReferenceFrame(aOther.mReferenceFrame)
, mAnimatedGeometryRoot(aOther.mAnimatedGeometryRoot)
, mToReferenceFrame(aOther.mToReferenceFrame)
, mVisibleRect(aOther.mVisibleRect)
, mForceNotVisible(aOther.mForceNotVisible)
, mDisableSubpixelAA(aOther.mDisableSubpixelAA)
, mReusedItem(false)
#ifdef MOZ_DUMP_PAINTING
, mPainted(false)
#endif
{
MOZ_COUNT_CTOR(nsDisplayItem);
if (aBuilder->IsRetainingDisplayList()) {
mFrame->AddDisplayItem(this);
}
}
struct HitTestState {
explicit HitTestState() : mInPreserves3D(false) {}
~HitTestState() {
NS_ASSERTION(mItemBuffer.Length() == 0,
"mItemBuffer should have been cleared");
}
// Handling transform items for preserve 3D frames.
bool mInPreserves3D;
AutoTArray<nsDisplayItem*, 100> mItemBuffer;
};
/**
* Some consecutive items should be rendered together as a unit, e.g.,
* outlines for the same element. For this, we need a way for items to
* identify their type. We use the type for other purposes too.
*/
virtual DisplayItemType GetType() const = 0;
/**
* Pairing this with the GetUnderlyingFrame() pointer gives a key that
* uniquely identifies this display item in the display item tree.
* XXX check nsOptionEventGrabberWrapper/nsXULEventRedirectorWrapper
*/
virtual uint32_t GetPerFrameKey() const { return uint32_t(GetType()); }
uint8_t GetFlags() { return GetDisplayItemFlagsForType(GetType()); }
/**
* This is called after we've constructed a display list for event handling.
* When this is called, we've already ensured that aRect intersects the
* item's bounds and that clipping has been taking into account.
*
* @param aRect the point or rect being tested, relative to the reference
* frame. If the width and height are both 1 app unit, it indicates we're
* hit testing a point, not a rect.
* @param aState must point to a HitTestState. If you don't have one,
* just create one with the default constructor and pass it in.
* @param aOutFrames each item appends the frame(s) in this display item that
* the rect is considered over (if any) to aOutFrames.
*/
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {}
/**
* @return the frame that this display item is based on. This is used to sort
* items by z-index and content order and for some other uses. Never
* returns null.
*/
inline nsIFrame* Frame() const
{
MOZ_ASSERT(mFrame, "Trying to use display item after deletion!");
return mFrame;
}
/**
* @return the nsIFrame that provides the style data, and should
* be checked when deciding if this display item can be reused.
*/
virtual nsIFrame* FrameForInvalidation() const
{
return mFrame;
}
bool HasDeletedFrame() const { return !mFrame; }
virtual nsIFrame* StyleFrame() const { return mFrame; }
/**
* Compute the used z-index of our frame; returns zero for elements to which
* z-index does not apply, and for z-index:auto.
* @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
*/
virtual int32_t ZIndex() const;
/**
* The default bounds is the frame border rect.
* @param aSnap *aSnap is set to true if the returned rect will be
* snapped to nearest device pixel edges during actual drawing.
* It might be set to false and snap anyway, so code computing the set of
* pixels affected by this display item needs to round outwards to pixel
* boundaries when *aSnap is set to false.
* This does not take the item's clipping into account.
* @return a rectangle relative to aBuilder->ReferenceFrame() that
* contains the area drawn by this display item
*/
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const
{
*aSnap = false;
return nsRect(ToReferenceFrame(), Frame()->GetSize());
}
virtual nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const
{
*aSnap = false;
return nsRegion();
}
/**
* Returns true if nothing will be rendered inside aRect, false if uncertain.
* aRect is assumed to be contained in this item's bounds.
*/
virtual bool IsInvisibleInRect(const nsRect& aRect) const { return false; }
/**
* Returns the result of GetBounds intersected with the item's clip.
* The intersection is approximate since rounded corners are not taking into
* account.
*/
nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder) const;
nsRect GetBorderRect() const
{
return nsRect(ToReferenceFrame(), Frame()->GetSize());
}
nsRect GetPaddingRect() const
{
return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
}
nsRect GetContentRect() const
{
return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
}
/**
* Checks if the frame(s) owning this display item have been marked as invalid,
* and needing repainting.
*/
virtual bool IsInvalid(nsRect& aRect) const
{
bool result = mFrame ? mFrame->IsInvalid(aRect) : false;
aRect += ToReferenceFrame();
return result;
}
/**
* Creates and initializes an nsDisplayItemGeometry object that retains the current
* areas covered by this display item. These need to retain enough information
* such that they can be compared against a future nsDisplayItem of the same type,
* and determine if repainting needs to happen.
*
* Subclasses wishing to store more information need to override both this
* and ComputeInvalidationRegion, as well as implementing an nsDisplayItemGeometry
* subclass.
*
* The default implementation tracks both the display item bounds, and the frame's
* border rect.
*/
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
{
return new nsDisplayItemGenericGeometry(this, aBuilder);
}
/**
* Compares an nsDisplayItemGeometry object from a previous paint against the
* current item. Computes if the geometry of the item has changed, and the
* invalidation area required for correct repainting.
*
* The existing geometry will have been created from a display item with a
* matching GetPerFrameKey()/mFrame pair to the current item.
*
* The default implementation compares the display item bounds, and the frame's
* border rect, and invalidates the entire bounds if either rect changes.
*
* @param aGeometry The geometry of the matching display item from the
* previous paint.
* @param aInvalidRegion Output param, the region to invalidate, or
* unchanged if none.
*/
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const
{
const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
bool snap;
if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
!geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
}
}
/**
* An alternative default implementation of ComputeInvalidationRegion,
* that instead invalidates only the changed area between the two items.
*/
void ComputeInvalidationRegionDifference(nsDisplayListBuilder* aBuilder,
const nsDisplayItemBoundsGeometry* aGeometry,
nsRegion* aInvalidRegion) const
{
bool snap;
nsRect bounds = GetBounds(aBuilder, &snap);
if (!aGeometry->mBounds.IsEqualInterior(bounds)) {
nscoord radii[8];
if (aGeometry->mHasRoundedCorners ||
Frame()->GetBorderRadii(radii)) {
aInvalidRegion->Or(aGeometry->mBounds, bounds);
} else {
aInvalidRegion->Xor(aGeometry->mBounds, bounds);
}
}
}
/**
* Called when the area rendered by this display item has changed (been
* invalidated or changed geometry) since the last paint. This includes
* when the display item was not rendered at all in the last paint.
* It does NOT get called when a display item was being rendered and no
* longer is, because generally that means there is no display item to
* call this method on.
*/
virtual void NotifyRenderingChanged() const {}
/**
* @param aSnap set to true if the edges of the rectangles of the opaque
* region would be snapped to device pixels when drawing
2012-04-11 04:48:37 +00:00
* @return a region of the item that is opaque --- that is, every pixel
* that is visible is painted with an opaque
2012-04-11 04:48:37 +00:00
* color. This is useful for determining when one piece
* of content completely obscures another so that we can do occlusion
* culling.
* This does not take clipping into account.
*/
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const
{
*aSnap = false;
return nsRegion();
}
/**
* @return Some(nscolor) if the item is guaranteed to paint every pixel in its
* bounds with the same (possibly translucent) color
*/
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const
{
return mozilla::Nothing();
}
/**
* @return true if the contents of this item are rendered fixed relative
* to the nearest viewport.
*/
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const
{
return false;
}
virtual bool ClearsBackground() const
{
return false;
}
/**
* Returns true if all layers that can be active should be forced to be
* active. Requires setting the pref layers.force-active=true.
*/
static bool ForceActiveLayers();
/**
* @return LAYER_NONE if BuildLayer will return null. In this case
* there is no layer for the item, and Paint should be called instead
* to paint the content using Thebes.
* Return LAYER_INACTIVE if there is a layer --- BuildLayer will
* not return null (unless there's an error) --- but the layer contents
* are not changing frequently. In this case it makes sense to composite
* the layer into a PaintedLayer with other content, so we don't have to
* recomposite it every time we paint.
* Note: GetLayerState is only allowed to return LAYER_INACTIVE if all
* descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also,
* all descendant display item frames must have an active scrolled root
* that's either the same as this item's frame's active scrolled root, or
* a descendant of this item's frame. This ensures that the entire
* set of display items can be collapsed onto a single PaintedLayer.
* Return LAYER_ACTIVE if the layer is active, that is, its contents are
* changing frequently. In this case it makes sense to keep the layer
* as a separate buffer in VRAM and composite it into the destination
* every time we paint.
*
* Users of GetLayerState should check ForceActiveLayers() and if it returns
* true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE.
*/
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
return mozilla::LAYER_NONE;
}
/**
* Return true to indicate the layer should be constructed even if it's
* completely invisible.
*/
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const
{
return false;
}
/**
* Actually paint this item to some rendering context.
* Content outside mVisibleRect need not be painted.
* aCtx must be set up as for nsDisplayList::Paint.
*/
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {}
#ifdef MOZ_DUMP_PAINTING
/**
* Mark this display item as being painted via FrameLayerBuilder::DrawPaintedLayer.
*/
bool Painted() const { return mPainted; }
/**
* Check if this display item has been painted.
*/
void SetPainted() { mPainted = true; }
#endif
/**
* Get the layer drawn by this display item. Call this only if
* GetLayerState() returns something other than LAYER_NONE.
* If GetLayerState returned LAYER_NONE then Paint will be called
* instead.
* This is called while aManager is in the construction phase.
*
* The caller (nsDisplayList) is responsible for setting the visible
* region of the layer.
*
* @param aContainerParameters should be passed to
* FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is
* constructed.
*/
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters)
{
return nullptr;
}
/**
* Function to create the WebRenderCommands.
* We should check if the layer state is
* active first and have an early return if the layer state is
* not active.
*
* @return true if successfully creating webrender commands.
*/
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) { return false; }
/**
* Updates the provided aLayerData with any APZ-relevant scroll data
* that is specific to this display item. This is stuff that would normally
* be put on the layer during BuildLayer, but this is only called in
* layers-free webrender mode, where we don't have layers.
*
* This function returns true if and only if it has APZ-relevant scroll data
* to provide. Note that the arguments passed in may be nullptr, in which case
* the function should still return true if and only if it has APZ-relevant
* scroll data, but obviously in this case it can't actually put the
* data onto aLayerData, because there isn't one.
*
* This function assumes that aData and aLayerData will either both be null,
* or will both be non-null. The caller is responsible for enforcing this.
*/
virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
mozilla::layers::WebRenderLayerScrollData* aLayerData)
{ return false; }
/**
* Builds a DisplayItemLayer and sets the display item to this.
*/
already_AddRefed<Layer>
BuildDisplayItemLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters);
/**
* On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
* which may be visible. If the display item opaquely covers an area, it
* can remove that area from aVisibleRegion before returning.
* nsDisplayList::ComputeVisibility automatically subtracts the region
* returned by GetOpaqueRegion, and automatically removes items whose bounds
* do not intersect the visible area, so implementations of
* nsDisplayItem::ComputeVisibility do not need to do these things.
* nsDisplayList::ComputeVisibility will already have set mVisibleRect on
2010-12-31 22:48:47 +00:00
* this item to the intersection of *aVisibleRegion and this item's bounds.
* We rely on that, so this should only be called by
* nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility.
* aAllowVisibleRegionExpansion is a rect where we are allowed to
* expand the visible region and is only used for making sure the
* background behind a plugin is visible.
* This method needs to be idempotent.
*
* @return true if the item is visible, false if no part of the item
* is visible.
*/
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
/**
* Checks if the given display item can be merged with this item.
* @return true if the merging is possible, otherwise false.
*/
virtual bool CanMerge(const nsDisplayItem* aItem) const { return false; }
/**
* Try to merge with the other item (which is below us in the display
* list). This gets used by nsDisplayClip to coalesce clipping operations
* (optimization), by nsDisplayOpacity to merge rendering for the same
* content element into a single opacity group (correctness), and will be
* used by nsDisplayOutline to merge multiple outlines for the same element
* (also for correctness).
*/
virtual void Merge(const nsDisplayItem* aItem) {}
/**
* Merges the given display list to this item.
*/
virtual void MergeDisplayListFromItem(nsDisplayListBuilder* aBuilder,
const nsDisplayItem* aItem) {}
/**
* Appends the underlying frames of all display items that have been
* merged into this one (excluding this item's own underlying frame)
* to aFrames.
*/
virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) const {}
/**
* During the visibility computation and after TryMerge, display lists may
* return true here to flatten themselves away, removing them. This
* flattening is distinctly different from FlattenTo, which occurs before
* items are merged together.
*/
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
return false;
}
/**
* Some items such as those calling into the native themed widget machinery
* have to be painted on the content process. In this case it is best to avoid
* allocating layers that serializes and forwards the work to the compositor.
*/
virtual bool MustPaintOnContentSide() const { return false; }
/**
* If this has a child list where the children are in the same coordinate
* system as this item (i.e., they have the same reference frame),
* return the list.
*/
virtual nsDisplayList* GetSameCoordinateSystemChildren() const
{
return nullptr;
}
virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) {}
/**
* Do UpdateBounds() for items with frames establishing or extending
* 3D rendering context.
*
* This function is called by UpdateBoundsFor3D() of
* nsDisplayTransform(), and it is called by
* BuildDisplayListForStackingContext() on transform items
* establishing 3D rendering context.
*
* The bounds of a transform item with the frame establishing 3D
* rendering context should be computed by calling
* DoUpdateBoundsPreserves3D() on all descendants that participate
* the same 3d rendering context.
*/
virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) {}
/**
* If this has a child list, return it, even if the children are in
* a different coordinate system to this item.
*/
virtual nsDisplayList* GetChildren() const { return nullptr; }
/**
* Returns the visible rect.
*/
const nsRect& GetVisibleRect() const { return mVisibleRect; }
void SetVisibleRect(const nsRect& aVisibleRect, bool aStore)
{
mVisibleRect = aVisibleRect;
if (aStore) {
mState.mVisibleRect = mVisibleRect;
}
}
/**
* Returns the visible rect for the children, relative to their
* reference frame. Can be different from mVisibleRect for nsDisplayTransform,
* since the reference frame for the children is different from the reference
* frame for the item itself.
*/
virtual const nsRect& GetVisibleRectForChildren() const { return mVisibleRect; }
/**
* Stores the given opacity value to be applied when drawing. It is an error to
* call this if CanApplyOpacity returned false.
*/
virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
float aOpacity,
const DisplayItemClipChain* aClip) {
NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity not supported on this type");
}
/**
* Returns true if this display item would return true from ApplyOpacity without
* actually applying the opacity. Otherwise returns false.
*/
virtual bool CanApplyOpacity() const { return false; }
bool ForceNotVisible() const { return mForceNotVisible; }
/**
* For debugging and stuff
*/
virtual const char* Name() const = 0;
virtual void WriteDebugInfo(std::stringstream& aStream) {}
nsDisplayItem* GetAbove() { return mAbove; }
/**
* Like ComputeVisibility, but does the work that nsDisplayList
* does per-item:
* -- Intersects GetBounds with aVisibleRegion and puts the result
* in mVisibleRect
* -- Subtracts bounds from aVisibleRegion if the item is opaque
*/
bool RecomputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
bool aUseClipBounds = true);
/**
* Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
*/
const nsPoint& ToReferenceFrame() const {
NS_ASSERTION(mFrame, "No frame?");
return mToReferenceFrame;
}
/**
* @return the root of the display list's frame (sub)tree, whose origin
* establishes the coordinate system for the display list
*/
const nsIFrame* ReferenceFrame() const { return mReferenceFrame; }
/**
* Returns the reference frame for display item children of this item.
*/
virtual const nsIFrame* ReferenceFrameForChildren() const { return mReferenceFrame; }
AnimatedGeometryRoot* GetAnimatedGeometryRoot() const {
MOZ_ASSERT(mAnimatedGeometryRoot, "Must have cached AGR before accessing it!");
return mAnimatedGeometryRoot;
}
virtual struct AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const {
return GetAnimatedGeometryRoot();
}
/**
* Checks if this display item (or any children) contains content that might
* be rendered with component alpha (e.g. subpixel antialiasing). Returns the
* bounds of the area that needs component alpha, or an empty rect if nothing
* in the item does.
*/
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const
{
return nsRect();
}
/**
* Disable usage of component alpha. Currently only relevant for items that have text.
*/
void DisableComponentAlpha()
{
mDisableSubpixelAA = true;
}
bool IsSubpixelAADisabled() const { return mDisableSubpixelAA; }
/**
* Check if we can add async animations to the layer for this display item.
*/
virtual bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
return false;
}
virtual bool SupportsOptimizingToImage() const { return false; }
const DisplayItemClip& GetClip() const
{
return mClip ? *mClip : DisplayItemClip::NoClip();
}
void IntersectClip(nsDisplayListBuilder* aBuilder, const DisplayItemClipChain* aOther, bool aStore);
virtual void SetActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot) { mActiveScrolledRoot = aActiveScrolledRoot; }
const ActiveScrolledRoot* GetActiveScrolledRoot() const { return mActiveScrolledRoot; }
virtual void SetClipChain(const DisplayItemClipChain* aClipChain,
bool aStore);
const DisplayItemClipChain* GetClipChain() const { return mClipChain; }
/**
* Intersect all clips in our clip chain up to (and including) aASR and set
* set the intersection as this item's clip.
*/
void FuseClipChainUpTo(nsDisplayListBuilder* aBuilder,
const ActiveScrolledRoot* aASR);
bool BackfaceIsHidden() const { return mFrame->BackfaceIsHidden(); }
bool In3DContextAndBackfaceIsHidden()
{
if (mBackfaceHidden) {
return *mBackfaceHidden;
}
// We never need to invalidate this cached value since we're
// guaranteed to rebuild the display item entirely if it changes.
bool backfaceHidden = Frame()->In3DContextAndBackfaceIsHidden();
mBackfaceHidden.emplace(backfaceHidden);
return backfaceHidden;
}
bool HasSameTypeAndClip(const nsDisplayItem* aOther) const
{
return GetType() == aOther->GetType() &&
GetClipChain() == aOther->GetClipChain();
}
bool HasSameContent(const nsDisplayItem* aOther) const
{
return mFrame->GetContent() == aOther->Frame()->GetContent();
}
bool IsReused() const
{
return mReusedItem;
}
void SetReused(bool aReused)
{
mReusedItem = aReused;
}
virtual bool CanBeReused() const { return true; }
virtual nsIFrame* GetDependentFrame()
{
return nullptr;
}
virtual mozilla::Maybe<nsRect> GetClipWithRespectToASR(
nsDisplayListBuilder* aBuilder,
const ActiveScrolledRoot* aASR) const;
protected:
nsDisplayItem() = delete;
typedef bool (*PrefFunc)(void);
bool ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc) const;
bool CanUseAdvancedLayer(LayerManager* aManager) const;
nsIFrame* mFrame;
RefPtr<const DisplayItemClipChain> mClipChain;
const DisplayItemClip* mClip;
RefPtr<const ActiveScrolledRoot> mActiveScrolledRoot;
// Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
const nsIFrame* mReferenceFrame;
RefPtr<struct AnimatedGeometryRoot> mAnimatedGeometryRoot;
// Result of ToReferenceFrame(mFrame), if mFrame is non-null
nsPoint mToReferenceFrame;
// This is the rectangle that needs to be painted.
// Display item construction sets this to the dirty rect.
// nsDisplayList::ComputeVisibility sets this to the visible region
// of the item by intersecting the current visible region with the bounds
// of the item. Paint implementations can use this to limit their drawing.
// Guaranteed to be contained in GetBounds().
nsRect mVisibleRect;
bool mForceNotVisible;
bool mDisableSubpixelAA;
bool mReusedItem;
#ifdef MOZ_DUMP_PAINTING
// True if this frame has been painted.
bool mPainted;
#endif
mozilla::Maybe<bool> mBackfaceHidden;
struct {
nsRect mVisibleRect;
RefPtr<const DisplayItemClipChain> mClipChain;
const DisplayItemClip* mClip;
} mState;
};
/**
* Manages a singly-linked list of display list items.
*
* mSentinel is the sentinel list value, the first value in the null-terminated
* linked list of items. mTop is the last item in the list (whose 'above'
* pointer is null). This class has no virtual methods. So list objects are just
* two pointers.
*
* Stepping upward through this list is very fast. Stepping downward is very
* slow so we don't support it. The methods that need to step downward
* (HitTest(), ComputeVisibility()) internally build a temporary array of all
* the items while they do the downward traversal, so overall they're still
* linear time. We have optimized for efficient AppendToTop() of both
* items and lists, with minimal codesize. AppendToBottom() is efficient too.
*/
class nsDisplayList {
public:
typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::PaintedLayer PaintedLayer;
/**
* Create an empty list.
*/
2017-11-16 03:09:28 +00:00
nsDisplayList()
: mLength(0)
, mIsOpaque(false)
, mForceTransparentSurface(false)
{
mTop = &mSentinel;
mSentinel.mAbove = nullptr;
}
~nsDisplayList() {
if (mSentinel.mAbove) {
NS_WARNING("Nonempty list left over?");
}
}
/**
* Append an item to the top of the list. The item must not currently
* be in a list and cannot be null.
*/
void AppendToTop(nsDisplayItem* aItem) {
NS_ASSERTION(aItem, "No item to append!");
NS_ASSERTION(!aItem->mAbove, "Already in a list!");
mTop->mAbove = aItem;
mTop = aItem;
mLength++;
}
/**
* Append a new item to the top of the list. The intended usage is
* AppendNewToTop(new ...);
*/
void AppendNewToTop(nsDisplayItem* aItem) {
if (aItem) {
AppendToTop(aItem);
}
}
/**
* Append a new item to the bottom of the list. The intended usage is
* AppendNewToBottom(new ...);
*/
void AppendNewToBottom(nsDisplayItem* aItem) {
if (aItem) {
AppendToBottom(aItem);
}
}
/**
* Append a new item to the bottom of the list. The item must be non-null
* and not already in a list.
*/
void AppendToBottom(nsDisplayItem* aItem) {
NS_ASSERTION(aItem, "No item to append!");
NS_ASSERTION(!aItem->mAbove, "Already in a list!");
aItem->mAbove = mSentinel.mAbove;
mSentinel.mAbove = aItem;
if (mTop == &mSentinel) {
mTop = aItem;
}
mLength++;
}
/**
* Removes all items from aList and appends them to the top of this list
*/
void AppendToTop(nsDisplayList* aList) {
if (aList->mSentinel.mAbove) {
mTop->mAbove = aList->mSentinel.mAbove;
mTop = aList->mTop;
aList->mTop = &aList->mSentinel;
aList->mSentinel.mAbove = nullptr;
mLength += aList->mLength;
aList->mLength = 0;
}
}
/**
* Removes all items from aList and prepends them to the bottom of this list
*/
void AppendToBottom(nsDisplayList* aList) {
if (aList->mSentinel.mAbove) {
aList->mTop->mAbove = mSentinel.mAbove;
mSentinel.mAbove = aList->mSentinel.mAbove;
if (mTop == &mSentinel) {
mTop = aList->mTop;
}
aList->mTop = &aList->mSentinel;
aList->mSentinel.mAbove = nullptr;
mLength += aList->mLength;
aList->mLength = 0;
}
}
/**
* Remove an item from the bottom of the list and return it.
*/
nsDisplayItem* RemoveBottom();
/**
* Remove all items from the list and call their destructors.
*/
void DeleteAll(nsDisplayListBuilder* aBuilder);
/**
* @return the item at the top of the list, or null if the list is empty
*/
nsDisplayItem* GetTop() const {
return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nullptr;
}
/**
* @return the item at the bottom of the list, or null if the list is empty
*/
nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
bool IsEmpty() const { return mTop == &mSentinel; }
/**
* @return the number of items in the list
*/
uint32_t Count() const { return mLength; }
/**
* Stable sort the list by the z-order of GetUnderlyingFrame() on
* each item. 'auto' is counted as zero.
* It is assumed that the list is already in content document order.
*/
void SortByZOrder();
/**
* Stable sort the list by the tree order of the content of
* GetUnderlyingFrame() on each item. z-index is ignored.
* @param aCommonAncestor a common ancestor of all the content elements
* associated with the display items, for speeding up tree order
* checks, or nullptr if not known; it's only a hint, if it is not an
* ancestor of some elements, then we lose performance but not correctness
*/
void SortByContentOrder(nsIContent* aCommonAncestor);
/**
* Sort the display list using a stable sort. Take care, because some of the
* items might be nsDisplayLists themselves.
* aComparator(Item item1, Item item2) should return true if item1 should go
* before item2.
* We sort the items into increasing order.
*/
template<typename Item, typename Comparator>
void Sort(const Comparator& aComparator) {
// Some casual local browsing testing suggests that a local preallocated
// array of 20 items should be able to avoid a lot of dynamic allocations
// here.
AutoTArray<Item, 20> items;
while (nsDisplayItem* item = RemoveBottom()) {
items.AppendElement(Item(item));
}
std::stable_sort(items.begin(), items.end(), aComparator);
for (Item& item : items) {
AppendToTop(item);
}
}
/**
* Compute visiblity for the items in the list.
* We put this logic here so it can be shared by top-level
* painting and also display items that maintain child lists.
* This is also a good place to put ComputeVisibility-related logic
* that must be applied to every display item. In particular, this
* sets mVisibleRect on each display item.
* This sets mIsOpaque if the entire visible area of this list has
* been removed from aVisibleRegion when we return.
* This does not remove any items from the list, so we can recompute
* visiblity with different regions later (see
* FrameLayerBuilder::DrawPaintedLayer).
* This method needs to be idempotent.
*
* @param aVisibleRegion the area that is visible, relative to the
* reference frame; on return, this contains the area visible under the list.
* I.e., opaque contents of this list are subtracted from aVisibleRegion.
* @param aListVisibleBounds must be equal to the bounds of the intersection
* of aVisibleRegion and GetBounds() for this list.
* @return true if any item in the list is visible.
*/
bool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aListVisibleBounds);
/**
* As ComputeVisibilityForSublist, but computes visibility for a root
* list (a list that does not belong to an nsDisplayItem).
* This method needs to be idempotent.
*
* @param aVisibleRegion the area that is visible
*/
bool ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
/**
* Returns true if the visible region output from ComputeVisiblity was
* empty, i.e. everything visible in this list is opaque.
*/
bool IsOpaque() const {
return mIsOpaque;
}
/**
* Returns true if any display item requires the surface to be transparent.
*/
bool NeedsTransparentSurface() const {
return mForceTransparentSurface;
}
/**
* Paint the list to the rendering context. We assume that (0,0) in aCtx
* corresponds to the origin of the reference frame. For best results,
* aCtx's current transform should make (0,0) pixel-aligned. The
* rectangle in aDirtyRect is painted, which *must* be contained in the
* dirty rect used to construct the display list.
*
* If aFlags contains PAINT_USE_WIDGET_LAYERS and
* ShouldUseWidgetLayerManager() is set, then we will paint using
* the reference frame's widget's layer manager (and ctx may be null),
* otherwise we will use a temporary BasicLayerManager and ctx must
* not be null.
*
* If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
* layer manager has already had BeginTransaction() called on it and
* we should not call it again.
*
* If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode
* to avoid short cut optimizations.
*
* This must only be called on the root display list of the display list
* tree.
*
* We return the layer manager used for painting --- mainly so that
* callers can dump its layer tree if necessary.
*/
enum {
PAINT_DEFAULT = 0,
PAINT_USE_WIDGET_LAYERS = 0x01,
PAINT_EXISTING_TRANSACTION = 0x04,
PAINT_NO_COMPOSITE = 0x08,
PAINT_COMPRESSED = 0x10
};
already_AddRefed<LayerManager> PaintRoot(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx,
uint32_t aFlags);
/**
* Get the bounds. Takes the union of the bounds of all children.
* The result is not cached.
*/
nsRect GetBounds(nsDisplayListBuilder* aBuilder) const;
/**
* Get this list's bounds, respecting clips relative to aASR. The result is
* the union of each item's clipped bounds with respect to aASR. That means
* that if an item can move asynchronously with an ASR that is a descendant
* of aASR, then the clipped bounds with respect to aASR will be the clip of
* that item for aASR, because the item can move anywhere inside that clip.
* If there is an item in this list which is not bounded with respect to
* aASR (i.e. which does not have "finite bounds" with respect to aASR),
* then this method trigger an assertion failure.
* The optional aVisibleRect out argument can be set to non-null if the
* caller is also interested to know the visible rect. This can be used
* to get the visible rect efficiently without traversing the display list
* twice.
*/
nsRect GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
const ActiveScrolledRoot* aASR,
nsRect* aVisibleRect = nullptr) const;
/**
* Find the topmost display item that returns a non-null frame, and return
* the frame.
*/
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
nsDisplayItem::HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) const;
/**
* Compute the union of the visible rects of the items in the list. The
* result is not cached.
*/
nsRect GetVisibleRect() const;
void SetIsOpaque()
{
mIsOpaque = true;
}
void SetNeedsTransparentSurface()
{
mForceTransparentSurface = true;
}
void RestoreState() {
mIsOpaque = false;
mForceTransparentSurface = false;
}
private:
nsDisplayItemLink mSentinel;
nsDisplayItemLink* mTop;
uint32_t mLength;
// This is set to true by FrameLayerBuilder if the final visible region
// is empty (i.e. everything that was visible is covered by some
// opaque content in this list).
bool mIsOpaque;
// This is set to true by FrameLayerBuilder if any display item in this
// list needs to force the surface containing this list to be transparent.
bool mForceTransparentSurface;
};
/**
* This is passed as a parameter to nsIFrame::BuildDisplayList. That method
* will put any generated items onto the appropriate list given here. It's
* basically just a collection with one list for each separate stacking layer.
* The lists themselves are external to this object and thus can be shared
* with others. Some of the list pointers may even refer to the same list.
*/
class nsDisplayListSet {
public:
/**
* @return a list where one should place the border and/or background for
* this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
*/
nsDisplayList* BorderBackground() const { return mBorderBackground; }
/**
* @return a list where one should place the borders and/or backgrounds for
* block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
*/
nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; }
/**
* @return a list where one should place descendant floats (step 5 of
* CSS 2.1 appendix E)
*/
nsDisplayList* Floats() const { return mFloats; }
/**
* @return a list where one should place the (pseudo) stacking contexts
* for descendants of this frame (everything from steps 3, 7 and 8
* of CSS 2.1 appendix E)
*/
nsDisplayList* PositionedDescendants() const { return mPositioned; }
/**
* @return a list where one should place the outlines
* for this frame and its descendants (step 9 of CSS 2.1 appendix E)
*/
nsDisplayList* Outlines() const { return mOutlines; }
/**
* @return a list where one should place all other content
*/
nsDisplayList* Content() const { return mContent; }
void DeleteAll(nsDisplayListBuilder* aBuilder) {
BorderBackground()->DeleteAll(aBuilder);
BlockBorderBackgrounds()->DeleteAll(aBuilder);
Floats()->DeleteAll(aBuilder);
PositionedDescendants()->DeleteAll(aBuilder);
Outlines()->DeleteAll(aBuilder);
Content()->DeleteAll(aBuilder);
}
nsDisplayListSet(nsDisplayList* aBorderBackground,
nsDisplayList* aBlockBorderBackgrounds,
nsDisplayList* aFloats,
nsDisplayList* aContent,
nsDisplayList* aPositionedDescendants,
nsDisplayList* aOutlines) :
mBorderBackground(aBorderBackground),
mBlockBorderBackgrounds(aBlockBorderBackgrounds),
mFloats(aFloats),
mContent(aContent),
mPositioned(aPositionedDescendants),
mOutlines(aOutlines) {
}
/**
* A copy constructor that lets the caller override the BorderBackground
* list.
*/
nsDisplayListSet(const nsDisplayListSet& aLists,
nsDisplayList* aBorderBackground) :
mBorderBackground(aBorderBackground),
mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
mFloats(aLists.Floats()),
mContent(aLists.Content()),
mPositioned(aLists.PositionedDescendants()),
mOutlines(aLists.Outlines()) {
}
/**
* Move all display items in our lists to top of the corresponding lists in the
* destination.
*/
void MoveTo(const nsDisplayListSet& aDestination) const;
private:
// This class is only used on stack, so we don't have to worry about leaking
// it. Don't let us be heap-allocated!
void* operator new(size_t sz) CPP_THROW_NEW;
protected:
nsDisplayList* mBorderBackground;
nsDisplayList* mBlockBorderBackgrounds;
nsDisplayList* mFloats;
nsDisplayList* mContent;
nsDisplayList* mPositioned;
nsDisplayList* mOutlines;
};
/**
* A specialization of nsDisplayListSet where the lists are actually internal
* to the object, and all distinct.
*/
struct nsDisplayListCollection : public nsDisplayListSet {
explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder) :
nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4],
2017-11-16 03:09:28 +00:00
&mLists[5]) {}
explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder, nsDisplayList* aBorderBackground) :
nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4],
2017-11-16 03:09:28 +00:00
&mLists[5]) {}
/**
* Sort all lists by content order.
*/
void SortAllByContentOrder(nsIContent* aCommonAncestor) {
for (int32_t i = 0; i < 6; ++i) {
mLists[i].SortByContentOrder(aCommonAncestor);
}
}
private:
// This class is only used on stack, so we don't have to worry about leaking
// it. Don't let us be heap-allocated!
void* operator new(size_t sz) CPP_THROW_NEW;
nsDisplayList mLists[6];
};
class nsDisplayImageContainer : public nsDisplayItem {
public:
typedef mozilla::LayerIntPoint LayerIntPoint;
typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
typedef mozilla::layers::ImageContainer ImageContainer;
typedef mozilla::layers::ImageLayer ImageLayer;
nsDisplayImageContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
{}
/**
* @return true if this display item can be optimized into an image layer.
* It is an error to call GetContainer() unless you've called
* CanOptimizeToImageLayer() first and it returned true.
*/
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder);
already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder);
void ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters);
virtual already_AddRefed<imgIContainer> GetImage() = 0;
virtual nsRect GetDestRect() const = 0;
virtual bool SupportsOptimizingToImage() const override { return true; }
};
/**
* Use this class to implement not-very-frequently-used display items
* that are not opaque, do not receive events, and are bounded by a frame's
* border-rect.
*
* This should not be used for display items which are created frequently,
* because each item is one or two pointers bigger than an item from a
* custom display item class could be, and fractionally slower. However it does
* save code size. We use this for infrequently-used item types.
*/
class nsDisplayGeneric : public nsDisplayItem {
public:
typedef void (* PaintCallback)(nsIFrame* aFrame, DrawTarget* aDrawTarget,
const nsRect& aDirtyRect, nsPoint aFramePt);
// XXX: should be removed eventually
typedef void (* OldPaintCallback)(nsIFrame* aFrame, gfxContext* aCtx,
const nsRect& aDirtyRect, nsPoint aFramePt);
nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
PaintCallback aPaint, const char* aName, DisplayItemType aType)
: nsDisplayItem(aBuilder, aFrame)
, mPaint(aPaint)
, mOldPaint(nullptr)
, mName(aName)
, mType(aType)
{
MOZ_COUNT_CTOR(nsDisplayGeneric);
}
// XXX: should be removed eventually
nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
OldPaintCallback aOldPaint, const char* aName, DisplayItemType aType)
: nsDisplayItem(aBuilder, aFrame)
, mPaint(nullptr)
, mOldPaint(aOldPaint)
, mName(aName)
, mType(aType)
{
MOZ_COUNT_CTOR(nsDisplayGeneric);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayGeneric() {
MOZ_COUNT_DTOR(nsDisplayGeneric);
}
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx) override {
MOZ_ASSERT(!!mPaint != !!mOldPaint);
if (mPaint) {
mPaint(mFrame, aCtx->GetDrawTarget(), mVisibleRect, ToReferenceFrame());
} else {
mOldPaint(mFrame, aCtx, mVisibleRect, ToReferenceFrame());
}
}
virtual const char* Name() const override { return mName; }
virtual DisplayItemType GetType() const override { return mType; }
void* operator new(size_t aSize,
nsDisplayListBuilder* aBuilder) {
return aBuilder->Allocate(aSize, DisplayItemType::TYPE_GENERIC);
}
// This override is needed because GetType() for nsDisplayGeneric subclasses
// does not match TYPE_GENERIC that was used to allocate the object.
virtual void Destroy(nsDisplayListBuilder* aBuilder) override
{
this->~nsDisplayGeneric();
aBuilder->Destroy(DisplayItemType::TYPE_GENERIC, this);
}
protected:
PaintCallback mPaint;
OldPaintCallback mOldPaint; // XXX: should be removed eventually
const char* mName;
DisplayItemType mType;
};
#if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
/**
* This class implements painting of reflow counts. Ideally, we would simply
* make all the frame names be those returned by nsFrame::GetFrameName
* (except that tosses in the content tag name!) and support only one color
* and eliminate this class altogether in favor of nsDisplayGeneric, but for
* the time being we can't pass args to a PaintCallback, so just have a
* separate class to do the right thing. Sadly, this alsmo means we need to
* hack all leaf frame classes to handle this.
*
* XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
* here... I could switch it all to nscolor, but why bother?
*/
class nsDisplayReflowCount : public nsDisplayItem {
public:
nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const char* aFrameName,
uint32_t aColor = 0)
: nsDisplayItem(aBuilder, aFrame),
mFrameName(aFrameName),
mColor(aColor)
{
MOZ_COUNT_CTOR(nsDisplayReflowCount);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayReflowCount() {
MOZ_COUNT_DTOR(nsDisplayReflowCount);
}
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
mFrame->PresShell()->PaintCount(mFrameName, aCtx,
mFrame->PresContext(),
mFrame, ToReferenceFrame(),
mColor);
}
NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT)
protected:
const char* mFrameName;
nscolor mColor;
};
#define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
PR_BEGIN_MACRO \
if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
PresShell()->IsPaintingFrameCounts()) { \
aLists.Outlines()->AppendNewToTop( \
new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name)); \
} \
PR_END_MACRO
#define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
PR_BEGIN_MACRO \
if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
PresShell()->IsPaintingFrameCounts()) { \
aLists.Outlines()->AppendNewToTop( \
new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name, _color)); \
} \
PR_END_MACRO
/*
Macro to be used for classes that don't actually implement BuildDisplayList
*/
#define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
const nsRect& aDirtyRect, \
const nsDisplayListSet& aLists) { \
DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
_super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
}
#else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
#define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
#define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
#define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
#endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
class nsDisplayCaret : public nsDisplayItem {
public:
nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayCaret();
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
protected:
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<nsCaret> mCaret;
nsRect mBounds;
};
/**
* The standard display item to paint the CSS borders of a frame.
*/
class nsDisplayBorder : public nsDisplayItem {
public:
nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayBorder() {
MOZ_COUNT_DTOR(nsDisplayBorder);
}
#endif
virtual bool IsInvisibleInRect(const nsRect& aRect) const override;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override;
virtual nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
*aSnap = true;
return CalculateBounds(*mFrame->StyleBorder());
}
protected:
void CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResource,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder);
nsRegion CalculateBounds(const nsStyleBorder& aStyleBorder) const;
mozilla::Array<mozilla::gfx::Color, 4> mColors;
mozilla::Array<mozilla::LayerCoord, 4> mWidths;
mozilla::Array<mozilla::LayerSize, 4> mCorners;
mozilla::Array<uint8_t, 4> mBorderStyles;
mozilla::LayerRect mRect;
mozilla::Maybe<nsCSSBorderRenderer> mBorderRenderer;
mozilla::Maybe<nsCSSBorderImageRenderer> mBorderImageRenderer;
nsRect mBounds;
bool mBorderIsEmpty;
};
/**
* A simple display item that just renders a solid color across the
* specified bounds. For canvas frames (in the CSS sense) we split off the
* drawing of the background color into this class (from nsDisplayBackground
* via nsDisplayCanvasBackground). This is done so that we can always draw a
* background color to avoid ugly flashes of white when we can't draw a full
* frame tree (ie when a page is loading). The bounds can differ from the
* frame's bounds -- this is needed when a frame/iframe is loading and there
* is not yet a frame tree to go in the frame/iframe so we use the subdoc
* frame of the parent document as a standin.
*/
class nsDisplaySolidColorBase : public nsDisplayItem {
public:
nsDisplaySolidColorBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nscolor aColor)
: nsDisplayItem(aBuilder, aFrame), mColor(aColor)
{}
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplaySolidColorGeometry(this, aBuilder, mColor);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override
{
const nsDisplaySolidColorGeometry* geometry =
static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
if (mColor != geometry->mColor) {
bool dummy;
aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
return;
}
ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
*aSnap = false;
nsRegion result;
if (NS_GET_A(mColor) == 255) {
result = GetBounds(aBuilder, aSnap);
}
return result;
}
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override
{
return mozilla::Some(mColor);
}
protected:
nscolor mColor;
};
class nsDisplaySolidColor : public nsDisplaySolidColorBase {
public:
nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBounds, nscolor aColor, bool aCanBeReused = true)
: nsDisplaySolidColorBase(aBuilder, aFrame, aColor), mBounds(aBounds)
, mCanBeReused(aCanBeReused)
{
NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
MOZ_COUNT_CTOR(nsDisplaySolidColor);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplaySolidColor() {
MOZ_COUNT_DTOR(nsDisplaySolidColor);
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
virtual void WriteDebugInfo(std::stringstream& aStream) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
virtual bool CanBeReused() const override { return mCanBeReused; }
int32_t ZIndex() const override
{
if (mOverrideZIndex) {
return mOverrideZIndex.value();
}
return nsDisplaySolidColorBase::ZIndex();
}
void SetOverrideZIndex(int32_t aZIndex)
{
mOverrideZIndex = mozilla::Some(aZIndex);
}
private:
nsRect mBounds;
bool mCanBeReused;
mozilla::Maybe<int32_t> mOverrideZIndex;
};
/**
* A display item that renders a solid color over a region. This is not
* exposed through CSS, its only purpose is efficient invalidation of
* the find bar highlighter dimmer.
*/
class nsDisplaySolidColorRegion : public nsDisplayItem {
typedef mozilla::gfx::Color Color;
public:
nsDisplaySolidColorRegion(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRegion& aRegion, nscolor aColor)
: nsDisplayItem(aBuilder, aFrame), mRegion(aRegion), mColor(Color::FromABGR(aColor))
{
NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColorRegions!");
MOZ_COUNT_CTOR(nsDisplaySolidColorRegion);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplaySolidColorRegion() {
MOZ_COUNT_DTOR(nsDisplaySolidColorRegion);
}
#endif
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplaySolidColorRegionGeometry(this, aBuilder, mRegion, mColor);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override
{
const nsDisplaySolidColorRegionGeometry* geometry =
static_cast<const nsDisplaySolidColorRegionGeometry*>(aGeometry);
if (mColor == geometry->mColor) {
aInvalidRegion->Xor(geometry->mRegion, mRegion);
} else {
aInvalidRegion->Or(geometry->mRegion.GetBounds(), mRegion.GetBounds());
}
}
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION)
protected:
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
virtual void WriteDebugInfo(std::stringstream& aStream) override;
private:
nsRegion mRegion;
Color mColor;
};
/**
* A display item to paint one background-image for a frame. Each background
* image layer gets its own nsDisplayBackgroundImage.
*/
class nsDisplayBackgroundImage : public nsDisplayImageContainer {
public:
typedef mozilla::StyleGeometryBox StyleGeometryBox;
struct InitData {
nsDisplayListBuilder* builder;
nsIFrame* frame;
const nsStyleBackground* backgroundStyle;
nsCOMPtr<imgIContainer> image;
nsRect backgroundRect;
nsRect fillArea;
nsRect destArea;
uint32_t layer;
bool isRasterImage;
bool shouldFixToViewport;
};
/**
* aLayer signifies which background layer this item represents.
* aIsThemed should be the value of aFrame->IsThemed.
* aBackgroundStyle should be the result of
* nsCSSRendering::FindBackground, or null if FindBackground returned false.
* aBackgroundRect is relative to aFrame.
*/
enum class LayerizeFixed : uint8_t {
ALWAYS_LAYERIZE_FIXED_BACKGROUND,
DO_NOT_LAYERIZE_FIXED_BACKGROUND_IF_AVOIDING_COMPONENT_ALPHA_LAYERS
};
static InitData GetInitData(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
uint32_t aLayer,
const nsRect& aBackgroundRect,
const nsStyleBackground* aBackgroundStyle,
LayerizeFixed aLayerizeFixed);
explicit nsDisplayBackgroundImage(const InitData& aInitData,
nsIFrame* aFrameForBounds = nullptr);
virtual ~nsDisplayBackgroundImage();
// This will create and append new items for all the layers of the
// background. Returns whether we appended a themed background.
// aAllowWillPaintBorderOptimization should usually be left at true, unless
// aFrame has special border drawing that causes opaque borders to not
// actually be opaque.
static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
const nsRect& aBackgroundRect,
nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization = true,
nsStyleContext* aStyleContext = nullptr,
const nsRect& aBackgroundOriginRect = nsRect(),
nsIFrame* aSecondaryReferenceFrame = nullptr);
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
/**
* GetBounds() returns the background painting area.
*/
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
virtual uint32_t GetPerFrameKey() const override
{
return (mLayer << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
}
NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
/**
* Return the background positioning area.
* (GetBounds() returns the background painting area.)
* Can be called only when mBackgroundStyle is non-null.
*/
nsRect GetPositioningArea() const;
/**
* Returns true if existing rendered pixels of this display item may need
* to be redrawn if the positioning area size changes but its position does
* not.
* If false, only the changed painting area needs to be redrawn when the
* positioning area size changes but its position does not.
*/
bool RenderingMightDependOnPositioningAreaSizeChange() const;
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayBackgroundGeometry(this, aBuilder);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override;
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<imgIContainer> GetImage() override;
virtual nsRect GetDestRect() const override;
static nsRegion GetInsideClipRegion(const nsDisplayItem* aItem,
StyleGeometryBox aClip,
const nsRect& aRect,
const nsRect& aBackgroundRect);
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const override
{
return mShouldFixToViewport;
}
virtual nsIFrame* GetDependentFrame() override
{
return mDependentFrame;
}
void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
{
if (!aBuilder->IsRetainingDisplayList()) {
return;
}
mDependentFrame = aFrame;
if (aFrame) {
mDependentFrame->AddDisplayItem(this);
}
}
virtual void RemoveFrame(nsIFrame* aFrame) override
{
if (aFrame == mDependentFrame) {
mDependentFrame = nullptr;
}
nsDisplayItem::RemoveFrame(aFrame);
}
protected:
typedef class mozilla::layers::ImageContainer ImageContainer;
typedef class mozilla::layers::ImageLayer ImageLayer;
bool CanBuildWebRenderDisplayItems(LayerManager* aManager);
bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrameForBounds = nullptr);
void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect);
// Determine whether we want to be separated into our own layer, independent
// of whether this item can actually be layerized.
enum ImageLayerization {
WHENEVER_POSSIBLE,
ONLY_FOR_SCALING,
NO_LAYER_NEEDED
};
ImageLayerization ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager);
// Cache the result of nsCSSRendering::FindBackground. Always null if
// mIsThemed is true or if FindBackground returned false.
const nsStyleBackground* mBackgroundStyle;
nsCOMPtr<imgIContainer> mImage;
nsIFrame* mDependentFrame;
nsRect mBackgroundRect; // relative to the reference frame
nsRect mFillRect;
nsRect mDestRect;
/* Bounds of this display item */
nsRect mBounds;
uint32_t mLayer;
bool mIsRasterImage;
/* Whether the image should be treated as fixed to the viewport. */
bool mShouldFixToViewport;
uint32_t mImageFlags;
};
enum class TableType : uint8_t {
TABLE,
TABLE_COL,
TABLE_COL_GROUP,
TABLE_ROW,
TABLE_ROW_GROUP,
TABLE_CELL,
TABLE_TYPE_MAX
};
enum class TableTypeBits : uint8_t {
COUNT = 3
};
static_assert(
static_cast<uint8_t>(TableType::TABLE_TYPE_MAX) < (1 << (static_cast<uint8_t>(TableTypeBits::COUNT) + 1)),
"TableType cannot fit with TableTypeBits::COUNT");
TableType GetTableTypeFromFrame(nsIFrame* aFrame);
/**
* A display item to paint background image for table. For table parts, such
* as row, row group, col, col group, when drawing its background, we'll
* create separate background image display item for its containning cell.
* Those background image display items will reference to same DisplayItemData
* if we keep the mFrame point to cell's ancestor frame. We don't want to this
* happened bacause share same DisplatItemData will cause many bugs. So that
* we let mFrame point to cell frame and store the table type of the ancestor
* frame. And use mFrame and table type as key to generate DisplayItemData to
* avoid sharing DisplayItemData.
*
* Also store ancestor frame as mStyleFrame for all rendering informations.
*/
class nsDisplayTableBackgroundImage : public nsDisplayBackgroundImage {
public:
nsDisplayTableBackgroundImage(const InitData& aInitData, nsIFrame* aCellFrame);
virtual uint32_t GetPerFrameKey() const override {
return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
nsDisplayItem::GetPerFrameKey();
}
virtual bool IsInvalid(nsRect& aRect) const override;
virtual nsIFrame* FrameForInvalidation() const override { return mStyleFrame; }
NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE)
protected:
virtual nsIFrame* StyleFrame() const override { return mStyleFrame; }
nsIFrame* mStyleFrame;
TableType mTableType;
};
/**
* A display item to paint the native theme background for a frame.
*/
class nsDisplayThemedBackground : public nsDisplayItem {
public:
nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect);
virtual ~nsDisplayThemedBackground();
void Destroy(nsDisplayListBuilder* aBuilder) override
{
aBuilder->UnregisterThemeGeometry(this);
nsDisplayItem::Destroy(aBuilder);
}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual bool MustPaintOnContentSide() const override { return true; }
/**
* GetBounds() returns the background painting area.
*/
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND)
/**
* Return the background positioning area.
* (GetBounds() returns the background painting area.)
* Can be called only when mBackgroundStyle is non-null.
*/
nsRect GetPositioningArea() const;
/**
* Return whether our frame's document does not have the state
* NS_DOCUMENT_STATE_WINDOW_INACTIVE.
*/
bool IsWindowActive() const;
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayThemedBackgroundGeometry(this, aBuilder);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override;
virtual void WriteDebugInfo(std::stringstream& aStream) override;
protected:
nsRect GetBoundsInternal();
void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect);
nsRect mBackgroundRect;
nsRect mBounds;
nsITheme::Transparency mThemeTransparency;
uint8_t mAppearance;
};
class nsDisplayBackgroundColor : public nsDisplayItem
{
typedef mozilla::gfx::Color Color;
public:
nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect,
const nsStyleBackground* aBackgroundStyle,
nscolor aColor)
: nsDisplayItem(aBuilder, aFrame)
, mBackgroundRect(aBackgroundRect)
, mBackgroundStyle(aBackgroundStyle)
, mDependentFrame(nullptr)
, mColor(Color::FromABGR(aColor))
{
mState.mColor = mColor;
}
virtual ~nsDisplayBackgroundColor()
{
if (mDependentFrame) {
mDependentFrame->RemoveDisplayItem(this);
}
}
virtual void RestoreState() override
{
nsDisplayItem::RestoreState();
mColor = mState.mColor;
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
float aOpacity,
const DisplayItemClipChain* aClip) override;
virtual bool CanApplyOpacity() const override;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
*aSnap = true;
return mBackgroundRect;
}
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplaySolidColorGeometry(this, aBuilder, mColor.ToABGR());
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override
{
const nsDisplaySolidColorGeometry* geometry = static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
if (mColor.ToABGR() != geometry->mColor) {
bool dummy;
aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
return;
}
ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
}
virtual nsIFrame* GetDependentFrame() override
{
return mDependentFrame;
}
void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
{
if (!aBuilder->IsRetainingDisplayList()) {
return;
}
mDependentFrame = aFrame;
if (aFrame) {
mDependentFrame->AddDisplayItem(this);
}
}
virtual void RemoveFrame(nsIFrame* aFrame) override
{
if (aFrame == mDependentFrame) {
mDependentFrame = nullptr;
}
nsDisplayItem::RemoveFrame(aFrame);
}
NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
virtual void WriteDebugInfo(std::stringstream& aStream) override;
protected:
const nsRect mBackgroundRect;
const nsStyleBackground* mBackgroundStyle;
nsIFrame* mDependentFrame;
mozilla::gfx::Color mColor;
struct {
mozilla::gfx::Color mColor;
} mState;
};
class nsDisplayTableBackgroundColor : public nsDisplayBackgroundColor
{
public:
nsDisplayTableBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect,
const nsStyleBackground* aBackgroundStyle,
nscolor aColor,
nsIFrame* aAncestorFrame)
: nsDisplayBackgroundColor(aBuilder, aFrame, aBackgroundRect, aBackgroundStyle, aColor)
, mAncestorFrame(aAncestorFrame)
, mTableType(GetTableTypeFromFrame(aAncestorFrame))
{ }
virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
virtual uint32_t GetPerFrameKey() const override {
return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
nsDisplayItem::GetPerFrameKey();
}
NS_DISPLAY_DECL_NAME("TableBackgroundColor", TYPE_TABLE_BACKGROUND_COLOR)
protected:
nsIFrame* mAncestorFrame;
TableType mTableType;
};
class nsDisplayClearBackground : public nsDisplayItem
{
public:
nsDisplayClearBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
{ }
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
*aSnap = true;
return nsRect(ToReferenceFrame(), Frame()->GetSize());
}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override {
*aSnap = false;
return GetBounds(aBuilder, aSnap);
}
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override
{
return mozilla::Some(NS_RGBA(0, 0, 0, 0));
}
virtual bool ClearsBackground() const override
{
return true;
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
return mozilla::LAYER_ACTIVE_FORCE;
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
NS_DISPLAY_DECL_NAME("ClearBackground", TYPE_CLEAR_BACKGROUND)
};
/**
* The standard display item to paint the outer CSS box-shadows of a frame.
*/
class nsDisplayBoxShadowOuter final : public nsDisplayItem {
public:
nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
, mOpacity(1.0f)
{
MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
mBounds = GetBoundsInternal();
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayBoxShadowOuter() {
MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter);
}
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual bool IsInvisibleInRect(const nsRect& aRect) const override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override;
virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
float aOpacity,
const DisplayItemClipChain* aClip) override
{
NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
mOpacity = aOpacity;
IntersectClip(aBuilder, aClip, false);
}
virtual bool CanApplyOpacity() const override
{
return true;
}
virtual void RestoreState() override
{
nsDisplayItem::RestoreState();
mVisibleRegion.SetEmpty();
mOpacity = 1.0f;
}
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayBoxShadowOuterGeometry(this, aBuilder, mOpacity);
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
bool CanBuildWebRenderDisplayItems();
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
nsRect GetBoundsInternal();
private:
nsRegion mVisibleRegion;
nsRect mBounds;
float mOpacity;
};
/**
* The standard display item to paint the inner CSS box-shadows of a frame.
*/
class nsDisplayBoxShadowInner : public nsDisplayItem {
public:
nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayBoxShadowInner() {
MOZ_COUNT_DTOR(nsDisplayBoxShadowInner);
}
#endif
virtual void RestoreState() override
{
nsDisplayItem::RestoreState();
mVisibleRegion.SetEmpty();
}
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayBoxShadowInnerGeometry(this, aBuilder);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override
{
const nsDisplayBoxShadowInnerGeometry* geometry = static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry);
if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
// nsDisplayBoxShadowInner is based around the padding rect, but it can
// touch pixels outside of this. We should invalidate the entire bounds.
bool snap;
aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
}
}
static bool CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
nsPoint aReferencePoint);
static void CreateInsetBoxShadowWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc,
nsRegion& aVisibleRegion,
nsIFrame* aFrame,
const nsRect aBorderRect);
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
private:
nsRegion mVisibleRegion;
};
/**
* The standard display item to paint the CSS outline of a frame.
*/
class nsDisplayOutline : public nsDisplayItem {
public:
nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayOutline);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOutline() {
MOZ_COUNT_DTOR(nsDisplayOutline);
}
#endif
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual bool IsInvisibleInRect(const nsRect& aRect) const override;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
mozilla::Maybe<nsCSSBorderRenderer> mBorderRenderer;
};
/**
* A class that lets you receive events within the frame bounds but never paints.
*/
class nsDisplayEventReceiver : public nsDisplayItem {
public:
nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayEventReceiver);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayEventReceiver() {
MOZ_COUNT_DTOR(nsDisplayEventReceiver);
}
#endif
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
};
/**
* Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
* this gets built when we're doing widget painting and we need to send the
* compositor some hit-test info for a frame. This is effectively a dummy item
* whose sole purpose is to carry the hit-test info to the compositor.
*/
class nsDisplayCompositorHitTestInfo : public nsDisplayEventReceiver {
public:
nsDisplayCompositorHitTestInfo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
mozilla::gfx::CompositorHitTestInfo aHitTestInfo);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayCompositorHitTestInfo()
{
MOZ_COUNT_DTOR(nsDisplayCompositorHitTestInfo);
}
#endif
mozilla::gfx::CompositorHitTestInfo HitTestInfo() const { return mHitTestInfo; }
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
void WriteDebugInfo(std::stringstream& aStream) override;
NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO)
private:
mozilla::gfx::CompositorHitTestInfo mHitTestInfo;
mozilla::Maybe<mozilla::layers::FrameMetrics::ViewID> mScrollTarget;
};
/**
* A display item that tracks event-sensitive regions which will be set
* on the ContainerLayer that eventually contains this item.
*
* One of these is created for each stacking context and pseudo-stacking-context.
* It accumulates regions for event targets contributed by the border-boxes of
* frames in its (pseudo) stacking context. A nsDisplayLayerEventRegions
* eventually contributes its regions to the PaintedLayer it is placed in by
* FrameLayerBuilder. (We don't create a display item for every frame that
* could be an event target (i.e. almost all frames), because that would be
* high overhead.)
*
* We always make leaf layers other than PaintedLayers transparent to events.
* For example, an event targeting a canvas or video will actually target the
* background of that element, which is logically in the PaintedLayer behind the
* CanvasFrame or ImageFrame. We only need to create a
* nsDisplayLayerEventRegions when an element's background could be in front
* of a lower z-order element with its own layer.
*/
class nsDisplayLayerEventRegions final : public nsDisplayItem {
public:
nsDisplayLayerEventRegions(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, uint32_t aIndex = 0)
: nsDisplayItem(aBuilder, aFrame)
, mIndex(aIndex)
{
MOZ_COUNT_CTOR(nsDisplayLayerEventRegions);
}
virtual void Destroy(nsDisplayListBuilder* aBuilder) override
{
if (!aBuilder->IsRetainingDisplayList()) {
nsDisplayItem::Destroy(aBuilder);
return;
}
RemoveItemFromFrames(mHitRegion);
RemoveItemFromFrames(mMaybeHitRegion);
RemoveItemFromFrames(mDispatchToContentHitRegion);
RemoveItemFromFrames(mNoActionRegion);
RemoveItemFromFrames(mHorizontalPanRegion);
RemoveItemFromFrames(mVerticalPanRegion);
nsDisplayItem::Destroy(aBuilder);
}
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
*aSnap = false;
return nsRect();
}
nsRect GetHitRegionBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
// TODO: This constructs the two regions, but we're also doing the same
// work in AccumulateEventRegions. We should avoid doing it twice.
return HitRegion().GetBounds().Union(MaybeHitRegion().GetBounds());
}
virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
float aOpacity,
const DisplayItemClipChain* aClip) override
{
NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
}
virtual bool CanApplyOpacity() const override
{
return true;
}
NS_DISPLAY_DECL_NAME("LayerEventRegions", TYPE_LAYER_EVENT_REGIONS)
// Indicate that aFrame's border-box contributes to the event regions for
// this layer. aFrame must have the same reference frame as mFrame.
void AddFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
// Indicate that an inactive scrollframe's scrollport should be added to the
// dispatch-to-content region, to ensure that APZ lets content create a
// displayport.
void AddInactiveScrollPort(nsIFrame* aFrame, const nsRect& aRect);
bool IsEmpty() const;
int32_t ZIndex() const override;
void SetOverrideZIndex(int32_t aZIndex);
virtual uint32_t GetPerFrameKey() const override
{
return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
}
const nsRegion HitRegion()
{
return nsRegion(mozilla::gfx::ArrayView<pixman_box32_t>(mHitRegion.mBoxes));
}
const nsRegion MaybeHitRegion()
{
nsRegion result(mozilla::gfx::ArrayView<pixman_box32_t>(mMaybeHitRegion.mBoxes));
// Avoid quadratic performance as a result of the region growing to include
// an arbitrarily large number of rects, which can happen on some pages.
// TODO: It would be nice if we could ask the initial construction above
// to include simplification.
result.SimplifyOutward(8);
return result;
}
const nsRegion DispatchToContentHitRegion()
{
nsRegion result(mozilla::gfx::ArrayView<pixman_box32_t>(mDispatchToContentHitRegion.mBoxes));
// If this frame has touch-action areas, and there were already
// touch-action areas from some other element on this same event regions,
// then all we know is that there are multiple elements with touch-action
// properties. In particular, we don't know what the relationship is
// between those elements in terms of DOM ancestry, and so we don't know
// how to combine the regions properly. Instead, we just add all the areas
// to the dispatch-to-content region, so that the APZ knows to check with
// the main thread. XXX we need to come up with a better way to do this,
// see bug 1287829.
uint32_t touchActionCount =
mNoActionRegion.mBoxes.Length() +
mHorizontalPanRegion.mBoxes.Length() +
mVerticalPanRegion.mBoxes.Length();
if (touchActionCount > 1) {
result.OrWith(NoActionRegion());
result.OrWith(HorizontalPanRegion());
result.OrWith(VerticalPanRegion());
}
result.SimplifyOutward(8);
return result;
}
const nsRegion NoActionRegion()
{
return nsRegion(mozilla::gfx::ArrayView<pixman_box32_t>(mNoActionRegion.mBoxes));
}
const nsRegion HorizontalPanRegion()
{
return nsRegion(mozilla::gfx::ArrayView<pixman_box32_t>(mHorizontalPanRegion.mBoxes));
}
const nsRegion VerticalPanRegion()
{
return nsRegion(mozilla::gfx::ArrayView<pixman_box32_t>(mVerticalPanRegion.mBoxes));
}
nsRegion CombinedTouchActionRegion();
virtual void WriteDebugInfo(std::stringstream& aStream) override;
// TODO: nsTArray (vector) might not be a great data structure
// choice since we need to remove elements from the middle.
// Should profile and try figure out the best approach
// here.
struct FrameRects {
void Add(nsIFrame* aFrame, const nsRect& aRect) {
mBoxes.AppendElement(nsRegion::RectToBox(aRect));
mFrames.AppendElement(aFrame);
}
void Add(nsIFrame* aFrame, const pixman_box32& aBox) {
mBoxes.AppendElement(aBox);
mFrames.AppendElement(aFrame);
}
void Add(const FrameRects& aOther) {
mBoxes.AppendElements(aOther.mBoxes);
mFrames.AppendElements(aOther.mFrames);
}
bool IsEmpty() const {
return mBoxes.IsEmpty();
}
nsTArray<pixman_box32_t> mBoxes;
nsTArray<nsIFrame*> mFrames;
};
virtual void RemoveFrame(nsIFrame* aFrame) override;
private:
virtual ~nsDisplayLayerEventRegions()
{
MOZ_COUNT_DTOR(nsDisplayLayerEventRegions);
}
void RemoveItemFromFrames(FrameRects& aFrameRects)
{
for (nsIFrame* f : aFrameRects.mFrames) {
if (f != mFrame) {
f->RemoveDisplayItem(this);
}
}
}
friend void MergeLayerEventRegions(nsDisplayItem*, nsDisplayItem*);
// Relative to aFrame's reference frame.
// These are the points that are definitely in the hit region.
FrameRects mHitRegion;
// These are points that may or may not be in the hit region. Only main-thread
// event handling can tell for sure (e.g. because complex shapes are present).
FrameRects mMaybeHitRegion;
// These are points that need to be dispatched to the content thread for
// resolution. Always contained in the union of mHitRegion and mMaybeHitRegion.
FrameRects mDispatchToContentHitRegion;
// These are points where panning is disabled, as determined by the touch-action
// property. Always contained in the union of mHitRegion and mMaybeHitRegion.
FrameRects mNoActionRegion;
// These are points where panning is horizontal, as determined by the touch-action
// property. Always contained in the union of mHitRegion and mMaybeHitRegion.
FrameRects mHorizontalPanRegion;
// These are points where panning is vertical, as determined by the touch-action
// property. Always contained in the union of mHitRegion and mMaybeHitRegion.
FrameRects mVerticalPanRegion;
// If these event regions are for an inactive scroll frame, the z-index of
// this display item is overridden to be the largest z-index of the content
// in the scroll frame. This ensures that the event regions item remains on
// top of the content after sorting items by z-index.
mozilla::Maybe<int32_t> mOverrideZIndex;
uint32_t mIndex;
};
/**
* A class that lets you wrap a display list as a display item.
*
* GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
* list has many items, it's not clear which one has the 'underlying frame'.
* Thus we force the creator to specify what the underlying frame is. The
* underlying frame should be the root of a stacking context, because sorting
* a list containing this item will not get at the children.
*
* In some cases (e.g., clipping) we want to wrap a list but we don't have a
* particular underlying frame that is a stacking context root. In that case
* we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
* detect and handle this case.
*/
class nsDisplayWrapList : public nsDisplayItem {
public:
/**
* Takes all the items from aList and puts them in our list.
*/
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList);
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot,
bool aClearClipChain = false);
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayItem* aItem);
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
, mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot())
, mOverrideZIndex(0)
, mHasZIndexOverride(false)
{
MOZ_COUNT_CTOR(nsDisplayWrapList);
mBaseVisibleRect = mVisibleRect;
mListPtr = &mList;
}
/**
* A custom copy-constructor that does not copy mList, as this would mutate
* the other item.
*/
nsDisplayWrapList(const nsDisplayWrapList& aOther) = delete;
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, const nsDisplayWrapList& aOther)
: nsDisplayItem(aBuilder, aOther)
, mListPtr(&mList)
, mFrameActiveScrolledRoot(aOther.mFrameActiveScrolledRoot)
, mMergedFrames(aOther.mMergedFrames)
, mBounds(aOther.mBounds)
, mBaseVisibleRect(aOther.mBaseVisibleRect)
, mOverrideZIndex(aOther.mOverrideZIndex)
, mHasZIndexOverride(aOther.mHasZIndexOverride)
, mClearingClipChain(aOther.mClearingClipChain)
{
MOZ_COUNT_CTOR(nsDisplayWrapList);
}
virtual ~nsDisplayWrapList();
virtual const nsDisplayWrapList* AsDisplayWrapList() const override
{
return this;
}
virtual nsDisplayWrapList* AsDisplayWrapList() override
{
return this;
}
virtual void Destroy(nsDisplayListBuilder* aBuilder) override {
mList.DeleteAll(aBuilder);
nsDisplayItem::Destroy(aBuilder);
}
/**
* Creates a new nsDisplayWrapList that holds a pointer to the display list
* owned by the given nsDisplayItem. The new nsDisplayWrapList will be added
* to the bottom of this item's contents.
*/
virtual void MergeDisplayListFromItem(nsDisplayListBuilder* aBuilder,
const nsDisplayItem* aItem) override;
/**
* Call this if the wrapped list is changed.
*/
virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
{
// Clear the clip chain up to the asr, but don't store it, so that we'll recover
// it when we reuse the item.
if (mClearingClipChain) {
const DisplayItemClipChain* clip = mState.mClipChain;
while (clip && ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(), clip->mASR)) {
clip = clip->mParent;
}
SetClipChain(clip, false);
}
nsRect visibleRect;
mBounds =
mListPtr->GetClippedBoundsWithRespectToASR(aBuilder, mActiveScrolledRoot, &visibleRect);
// The display list may contain content that's visible outside the visible
// rect (i.e. the current dirty rect) passed in when the item was created.
// This happens when the dirty rect has been restricted to the visual
// overflow rect of a frame for some reason (e.g. when setting up dirty
// rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
// frame contains placeholders for out-of-flows that aren't descendants of
// the frame.
mVisibleRect.UnionRect(mBaseVisibleRect, visibleRect);
mState.mVisibleRect = mVisibleRect;
}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
return false;
}
virtual void Merge(const nsDisplayItem* aItem) override
{
MOZ_ASSERT(CanMerge(aItem));
MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList*>(aItem));
}
virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) const override
{
aFrames->AppendElements(mMergedFrames);
}
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
{
return true;
}
virtual bool IsInvalid(nsRect& aRect) const override
{
if (mFrame->IsInvalid(aRect) && aRect.IsEmpty()) {
return true;
}
nsRect temp;
for (uint32_t i = 0; i < mMergedFrames.Length(); i++) {
if (mMergedFrames[i]->IsInvalid(temp) && temp.IsEmpty()) {
aRect.SetEmpty();
return true;
}
aRect = aRect.Union(temp);
}
aRect += ToReferenceFrame();
return !aRect.IsEmpty();
}
NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override;
virtual nsDisplayList* GetSameCoordinateSystemChildren() const override
{
NS_ASSERTION(mListPtr->IsEmpty() || !ReferenceFrame() ||
!mListPtr->GetBottom()->ReferenceFrame() ||
mListPtr->GetBottom()->ReferenceFrame() == ReferenceFrame(),
"Children must have same reference frame");
return mListPtr;
}
virtual nsDisplayList* GetChildren() const override { return mListPtr; }
virtual int32_t ZIndex() const override
{
return (mHasZIndexOverride) ? mOverrideZIndex : nsDisplayItem::ZIndex();
}
void SetOverrideZIndex(int32_t aZIndex)
{
mHasZIndexOverride = true;
mOverrideZIndex = aZIndex;
}
void SetReferenceFrame(const nsIFrame* aFrame);
/**
* This creates a copy of this item, but wrapping aItem instead of
* our existing list. Only gets called if this item returned nullptr
* for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
* GetUnderlyingFrame().
*/
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
NS_NOTREACHED("We never returned nullptr for GetUnderlyingFrame!");
return nullptr;
}
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
const ActiveScrolledRoot* GetFrameActiveScrolledRoot() { return mFrameActiveScrolledRoot; }
protected:
nsDisplayWrapList() = delete;
void MergeFromTrackingMergedFrames(const nsDisplayWrapList* aOther)
{
mBounds.UnionRect(mBounds, aOther->mBounds);
mVisibleRect.UnionRect(mVisibleRect, aOther->mVisibleRect);
mMergedFrames.AppendElement(aOther->mFrame);
mMergedFrames.AppendElements(aOther->mMergedFrames);
}
nsDisplayList mList;
nsDisplayList* mListPtr;
// The active scrolled root for the frame that created this
// wrap list.
RefPtr<const ActiveScrolledRoot> mFrameActiveScrolledRoot;
// The frames from items that have been merged into this item, excluding
// this item's own frame.
nsTArray<nsIFrame*> mMergedFrames;
nsRect mBounds;
// Visible rect contributed by this display item itself.
// Our mVisibleRect may include the visible areas of children.
nsRect mBaseVisibleRect;
int32_t mOverrideZIndex;
bool mHasZIndexOverride;
bool mClearingClipChain = false;
};
/**
* We call WrapDisplayList on the in-flow lists: BorderBackground(),
* BlockBorderBackgrounds() and Content().
* We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
* and Floats(). This is done to support special wrapping processing for frames
* that may not be in-flow descendants of the current frame.
*/
class nsDisplayWrapper {
public:
// This is never instantiated directly (it has pure virtual methods), so no
// need to count constructors and destructors.
virtual bool WrapBorderBackground() { return true; }
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList) = 0;
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) = 0;
nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsDisplayListSet& aLists);
protected:
nsDisplayWrapper() = default;
};
/**
* The standard display item to paint a stacking context with translucency
* set by the stacking context root frame's 'opacity' style.
*/
class nsDisplayOpacity : public nsDisplayWrapList {
public:
nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot,
bool aForEventsAndPluginsOnly);
nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
const nsDisplayOpacity& aOther)
: nsDisplayWrapList(aBuilder, aOther)
, mOpacity(aOther.mOpacity)
, mForEventsAndPluginsOnly(aOther.mForEventsAndPluginsOnly)
{}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOpacity();
#endif
virtual void RestoreState() override
{
nsDisplayItem::RestoreState();
mOpacity = mState.mOpacity;
}
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
MOZ_COUNT_CTOR(nsDisplayOpacity);
return new (aBuilder) nsDisplayOpacity(aBuilder, *this);
}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// items for the same content element should be merged into a single
// compositing group
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
return HasSameTypeAndClip(aItem) && HasSameContent(aItem);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override
{
// We don't need to compute an invalidation region since we have LayerTreeInvalidation
}
virtual bool IsInvalid(nsRect& aRect) const override
{
if (mForEventsAndPluginsOnly) {
return false;
}
return nsDisplayWrapList::IsInvalid(aRect);
}
virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
float aOpacity,
const DisplayItemClipChain* aClip) override;
virtual bool CanApplyOpacity() const override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
static bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
virtual void WriteDebugInfo(std::stringstream& aStream) override;
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
private:
float mOpacity;
bool mForEventsAndPluginsOnly;
struct {
float mOpacity;
} mState;
};
class nsDisplayBlendMode : public nsDisplayWrapList {
public:
nsDisplayBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, uint8_t aBlendMode,
const ActiveScrolledRoot* aActiveScrolledRoot,
uint32_t aIndex = 0);
nsDisplayBlendMode(nsDisplayListBuilder* aBuilder,
const nsDisplayBlendMode& aOther)
: nsDisplayWrapList(aBuilder, aOther)
, mBlendMode(aOther.mBlendMode)
, mIndex(aOther.mIndex)
{}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayBlendMode();
#endif
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
MOZ_COUNT_CTOR(nsDisplayBlendMode);
return new (aBuilder) nsDisplayBlendMode(aBuilder, *this);
}
nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override
{
// We don't need to compute an invalidation region since we have LayerTreeInvalidation
}
virtual uint32_t GetPerFrameKey() const override {
return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual bool CanMerge(const nsDisplayItem* aItem) const override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
{
return false;
}
NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE)
private:
uint8_t mBlendMode;
uint32_t mIndex;
};
class nsDisplayBlendContainer : public nsDisplayWrapList {
public:
static nsDisplayBlendContainer*
CreateForMixBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot);
static nsDisplayBlendContainer*
CreateForBackgroundBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayBlendContainer();
#endif
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
MOZ_COUNT_CTOR(nsDisplayBlendContainer);
return new (aBuilder) nsDisplayBlendContainer(aBuilder, *this);
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// Items for the same content element should be merged into a single
// compositing group.
return HasSameTypeAndClip(aItem) && HasSameContent(aItem)
&& mIsForBackground == static_cast<const nsDisplayBlendContainer*>(aItem)->mIsForBackground;
}
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
{
return false;
}
virtual uint32_t GetPerFrameKey() const override {
return (mIsForBackground ? 1 << TYPE_BITS : 0) | nsDisplayItem::GetPerFrameKey();
}
NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
private:
nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot,
bool aIsForBackground);
nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
const nsDisplayBlendContainer& aOther)
: nsDisplayWrapList(aBuilder, aOther)
, mIsForBackground(aOther.mIsForBackground)
{}
// Used to distinguish containers created at building stacking
// context or appending background.
bool mIsForBackground;
};
/**
* nsDisplayOwnLayer constructor flags. If we nest this class inside
* nsDisplayOwnLayer then we can't forward-declare it up at the top of this
* file and that makes it hard to use in all the places that we need to use it.
*/
enum class nsDisplayOwnLayerFlags {
eNone = 0,
eGenerateSubdocInvalidations = 1 << 0,
eVerticalScrollbar = 1 << 1,
eHorizontalScrollbar = 1 << 2,
eGenerateScrollableLayer = 1 << 3,
eScrollbarContainer = 1 << 4,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags)
/**
* A display item that has no purpose but to ensure its contents get
* their own layer.
*/
class nsDisplayOwnLayer : public nsDisplayWrapList {
public:
typedef mozilla::layers::ScrollThumbData ScrollThumbData;
/**
* @param aFlags eGenerateSubdocInvalidations :
* Add UserData to the created ContainerLayer, so that invalidations
* for this layer are send to our nsPresContext.
* eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and
* subclasses), indicates this layer is to be a scrollable layer, so call
* ComputeFrameMetrics, etc.
* @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar
* is set in the flags, this parameter should be the ViewID of the
* scrollable content this scrollbar is for.
*/
nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot,
nsDisplayOwnLayerFlags aFlags = nsDisplayOwnLayerFlags::eNone,
ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID,
const ScrollThumbData& aThumbData = ScrollThumbData{},
bool aForceActive = true,
bool aClearClipChain = false);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOwnLayer();
#endif
nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, const nsDisplayOwnLayer& aOther)
: nsDisplayWrapList(aBuilder, aOther)
, mFlags(aOther.mFlags)
, mScrollTarget(aOther.mScrollTarget)
, mThumbData(aOther.mThumbData)
, mForceActive(aOther.mForceActive)
, mWrAnimationId(aOther.mWrAnimationId)
{
MOZ_COUNT_CTOR(nsDisplayOwnLayer);
}
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// Don't allow merging, each sublist must have its own layer
return false;
}
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
{
return false;
}
void WriteDebugInfo(std::stringstream& aStream) override;
nsDisplayOwnLayerFlags GetFlags() { return mFlags; }
bool IsScrollThumbLayer() const;
NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
protected:
nsDisplayOwnLayerFlags mFlags;
ViewID mScrollTarget;
// If this nsDisplayOwnLayer represents a scroll thumb layer, mThumbData
// stores information about the scroll thumb. Otherwise, mThumbData will be
// default-constructed (in particular with mDirection == Nothing())
// and can be ignored.
ScrollThumbData mThumbData;
bool mForceActive;
uint64_t mWrAnimationId;
};
/**
* A display item for subdocuments. This is more or less the same as nsDisplayOwnLayer,
* except that it always populates the FrameMetrics instance on the ContainerLayer it
* builds.
*/
class nsDisplaySubDocument : public nsDisplayOwnLayer {
public:
nsDisplaySubDocument(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsSubDocumentFrame* aSubDocFrame,
nsDisplayList* aList, nsDisplayOwnLayerFlags aFlags);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplaySubDocument();
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual nsSubDocumentFrame* SubDocumentFrame() { return mSubDocFrame; }
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
Backed out 46 changesets (bug 1022612) for B2G mochitest permafails on a CLOSED TREE. Backed out changeset 34b3014a3112 (bug 1022612) Backed out changeset 6ae9316fd909 (bug 1022612) Backed out changeset b8f3749c95eb (bug 1022612) Backed out changeset caab10bf6ca3 (bug 1022612) Backed out changeset 0c57c620c898 (bug 1022612) Backed out changeset fac64141a00a (bug 1022612) Backed out changeset bf0df1c9d68b (bug 1022612) Backed out changeset b42054800020 (bug 1022612) Backed out changeset 667793b21194 (bug 1022612) Backed out changeset f14ada64fe1b (bug 1022612) Backed out changeset 75b837686bdf (bug 1022612) Backed out changeset 66de53183a22 (bug 1022612) Backed out changeset 0ff86ced4d46 (bug 1022612) Backed out changeset 18eecc5b1ef7 (bug 1022612) Backed out changeset 2763c4878de5 (bug 1022612) Backed out changeset b72413ecc385 (bug 1022612) Backed out changeset b23f1081afb8 (bug 1022612) Backed out changeset f7e2c6a72043 (bug 1022612) Backed out changeset 959917c9027d (bug 1022612) Backed out changeset 0268a46f4880 (bug 1022612) Backed out changeset 3388856a80ad (bug 1022612) Backed out changeset e4b17cf0f806 (bug 1022612) Backed out changeset 2f4e9da0e4b6 (bug 1022612) Backed out changeset 489f6a7c0c03 (bug 1022612) Backed out changeset 8369d9ad7ad3 (bug 1022612) Backed out changeset 0758d2a06002 (bug 1022612) Backed out changeset f2ae9cb22edb (bug 1022612) Backed out changeset 9c48c6ee5dc2 (bug 1022612) Backed out changeset fe7134400f08 (bug 1022612) Backed out changeset cc2c5397ca8b (bug 1022612) Backed out changeset a3d1a3e8b39d (bug 1022612) Backed out changeset 8974b74b0eb0 (bug 1022612) Backed out changeset 75f7dbb5a2a6 (bug 1022612) Backed out changeset 2aa04a071e60 (bug 1022612) Backed out changeset f2ab1bcd4c39 (bug 1022612) Backed out changeset da9152b6ea29 (bug 1022612) Backed out changeset 58abf5b0e148 (bug 1022612) Backed out changeset 797058a09ad2 (bug 1022612) Backed out changeset ea3e99a92ff0 (bug 1022612) Backed out changeset adc4a4a7aa73 (bug 1022612) Backed out changeset 7b18dedd1505 (bug 1022612) Backed out changeset 055dd1921e8e (bug 1022612) Backed out changeset 42fa2c97e989 (bug 1022612) Backed out changeset cd594236388f (bug 1022612) Backed out changeset 9eadc5fee43d (bug 1022612) Backed out changeset 5cc8d30ff7c9 (bug 1022612)
2014-07-17 15:24:47 +00:00
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
{
return mShouldFlatten;
}
void SetShouldFlattenAway(bool aShouldFlatten)
{
mShouldFlatten = aShouldFlatten;
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
if (mShouldFlatten) {
return mozilla::LAYER_NONE;
}
return nsDisplayOwnLayer::GetLayerState(aBuilder, aManager, aParameters);
}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT)
mozilla::UniquePtr<ScrollMetadata> ComputeScrollMetadata(LayerManager* aLayerManager,
const ContainerLayerParameters& aContainerParameters);
protected:
ViewID mScrollParentId;
bool mForceDispatchToContentRegion;
bool mShouldFlatten;
nsSubDocumentFrame* mSubDocFrame;
};
/**
* A display item for subdocuments to capture the resolution from the presShell
* and ensure that it gets applied to all the right elements. This item creates
* a container layer.
*/
class nsDisplayResolution : public nsDisplaySubDocument {
public:
nsDisplayResolution(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, nsDisplayOwnLayerFlags aFlags);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayResolution();
#endif
virtual void HitTest(nsDisplayListBuilder* aBuilder,
const nsRect& aRect,
HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
NS_DISPLAY_DECL_NAME("Resolution", TYPE_RESOLUTION)
};
/**
* A display item used to represent sticky position elements. The contents
* gets its own layer and creates a stacking context, and the layer will have
* position-related metadata set on it.
*/
class nsDisplayStickyPosition : public nsDisplayOwnLayer {
public:
nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot);
nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
const nsDisplayStickyPosition& aOther)
: nsDisplayOwnLayer(aBuilder, aOther)
{}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayStickyPosition();
#endif
void SetClipChain(const DisplayItemClipChain* aClipChain, bool aStore) override;
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
MOZ_COUNT_CTOR(nsDisplayStickyPosition);
return new (aBuilder) nsDisplayStickyPosition(aBuilder, *this);
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION)
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
return mozilla::LAYER_ACTIVE;
}
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// Items with the same fixed position frame can be merged.
return HasSameTypeAndClip(aItem) && mFrame == aItem->Frame();
}
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
};
class nsDisplayFixedPosition : public nsDisplayOwnLayer {
public:
nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot);
nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder,
const nsDisplayFixedPosition& aOther)
: nsDisplayOwnLayer(aBuilder, aOther)
, mAnimatedGeometryRootForScrollMetadata(aOther.mAnimatedGeometryRootForScrollMetadata)
, mIndex(aOther.mIndex)
, mIsFixedBackground(aOther.mIsFixedBackground)
{}
static nsDisplayFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
nsDisplayBackgroundImage* aImage,
uint32_t aIndex);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayFixedPosition();
#endif
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
MOZ_COUNT_CTOR(nsDisplayFixedPosition);
return new (aBuilder) nsDisplayFixedPosition(aBuilder, *this);
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
return mozilla::LAYER_ACTIVE_FORCE;
}
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// Items with the same fixed position frame can be merged.
return HasSameTypeAndClip(aItem) && mFrame == aItem->Frame();
}
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const override
{
return mIsFixedBackground;
}
virtual uint32_t GetPerFrameKey() const override {
return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
}
AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const override {
return mAnimatedGeometryRootForScrollMetadata;
}
virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
protected:
// For background-attachment:fixed
nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, uint32_t aIndex);
void Init(nsDisplayListBuilder* aBuilder);
RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForScrollMetadata;
uint32_t mIndex;
bool mIsFixedBackground;
};
class nsDisplayTableFixedPosition : public nsDisplayFixedPosition
{
public:
static nsDisplayTableFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
nsDisplayBackgroundImage* aImage,
uint32_t aIndex,
nsIFrame* aAncestorFrame);
virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
virtual uint32_t GetPerFrameKey() const override {
return (mIndex << (TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
(static_cast<uint8_t>(mTableType) << TYPE_BITS) |
nsDisplayItem::GetPerFrameKey();
}
NS_DISPLAY_DECL_NAME("TableFixedPosition", TYPE_TABLE_FIXED_POSITION)
protected:
nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, uint32_t aIndex, nsIFrame* aAncestorFrame);
nsIFrame* mAncestorFrame;
TableType mTableType;
};
/**
* This creates an empty scrollable layer. It has no child layers.
* It is used to record the existence of a scrollable frame in the layer
* tree.
*/
class nsDisplayScrollInfoLayer : public nsDisplayWrapList
{
public:
nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder,
nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame);
NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER)
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayScrollInfoLayer();
#endif
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override
{
return true;
}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
*aSnap = false;
return nsRegion();
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
{
return false;
}
virtual void WriteDebugInfo(std::stringstream& aStream) override;
mozilla::UniquePtr<ScrollMetadata> ComputeScrollMetadata(LayerManager* aLayerManager,
const ContainerLayerParameters& aContainerParameters);
virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
protected:
nsIFrame* mScrollFrame;
nsIFrame* mScrolledFrame;
ViewID mScrollParentId;
};
/**
* nsDisplayZoom is used for subdocuments that have a different full zoom than
* their parent documents. This item creates a container layer.
*/
class nsDisplayZoom : public nsDisplaySubDocument {
public:
/**
* @param aFrame is the root frame of the subdocument.
* @param aList contains the display items for the subdocument.
* @param aAPD is the app units per dev pixel ratio of the subdocument.
* @param aParentAPD is the app units per dev pixel ratio of the parent
* document.
* @param aFlags eGenerateSubdocInvalidations :
* Add UserData to the created ContainerLayer, so that invalidations
* for this layer are send to our nsPresContext.
*/
nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
int32_t aAPD, int32_t aParentAPD,
nsDisplayOwnLayerFlags aFlags = nsDisplayOwnLayerFlags::eNone);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayZoom();
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
return mozilla::LAYER_ACTIVE;
}
NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
// Get the app units per dev pixel ratio of the child document.
int32_t GetChildAppUnitsPerDevPixel() { return mAPD; }
// Get the app units per dev pixel ratio of the parent document.
int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD; }
private:
int32_t mAPD, mParentAPD;
};
class nsDisplaySVGEffects: public nsDisplayWrapList {
public:
nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, bool aHandleOpacity,
const ActiveScrolledRoot* aActiveScrolledRoot,
bool aClearClipChain = false);
nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, bool aHandleOpacity);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplaySVGEffects();
#endif
nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
const nsDisplaySVGEffects& aOther)
: nsDisplayWrapList(aBuilder, aOther)
, mEffectsBounds(aOther.mEffectsBounds)
, mHandleOpacity(aOther.mHandleOpacity)
{
MOZ_COUNT_CTOR(nsDisplaySVGEffects);
}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
return false;
}
gfxRect BBoxInUserSpace() const;
gfxPoint UserSpaceOffset() const;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override;
protected:
bool ValidateSVGFrame();
// relative to mFrame
nsRect mEffectsBounds;
// True if we need to handle css opacity in this display item.
bool mHandleOpacity;
};
/**
* A display item to paint a stacking context with mask and clip effects
* set by the stacking context root frame's style.
*/
class nsDisplayMask : public nsDisplaySVGEffects {
public:
typedef mozilla::layers::ImageLayer ImageLayer;
nsDisplayMask(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, bool aHandleOpacity,
const ActiveScrolledRoot* aActiveScrolledRoot);
nsDisplayMask(nsDisplayListBuilder* aBuilder,
const nsDisplayMask& aOther)
: nsDisplaySVGEffects(aBuilder, aOther)
, mDestRects(aOther.mDestRects)
{}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayMask();
#endif
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
MOZ_COUNT_CTOR(nsDisplayMask);
return new (aBuilder) nsDisplayMask(aBuilder, *this);
}
NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK)
virtual bool CanMerge(const nsDisplayItem* aItem) const override;
virtual void Merge(const nsDisplayItem* aItem) override
{
nsDisplayWrapList::Merge(aItem);
const nsDisplayMask* other = static_cast<const nsDisplayMask*>(aItem);
mEffectsBounds.UnionRect(mEffectsBounds,
other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayMaskGeometry(this, aBuilder);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override;
#ifdef MOZ_DUMP_PAINTING
void PrintEffects(nsACString& aTo);
#endif
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx,
LayerManager* aManager);
/*
* Paint mask onto aMaskContext in mFrame's coordinate space and
* return whether the mask layer was painted successfully.
*/
bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
const nsTArray<nsRect>& GetDestRects()
{
return mDestRects;
}
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual mozilla::Maybe<nsRect> GetClipWithRespectToASR(
nsDisplayListBuilder* aBuilder,
const ActiveScrolledRoot* aASR) const override;
private:
// According to mask property and the capability of aManager, determine
// whether we can paint the mask onto a dedicate mask layer.
bool CanPaintOnMaskLayer(LayerManager* aManager);
nsTArray<nsRect> mDestRects;
};
/**
* A display item to paint a stacking context with filter effects set by the
* stacking context root frame's style.
*/
class nsDisplayFilter : public nsDisplaySVGEffects {
public:
nsDisplayFilter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, bool aHandleOpacity);
nsDisplayFilter(nsDisplayListBuilder* aBuilder,
const nsDisplayFilter& aOther)
: nsDisplaySVGEffects(aBuilder, aOther)
, mEffectsBounds(aOther.mEffectsBounds)
{}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayFilter();
#endif
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
MOZ_COUNT_CTOR(nsDisplayFilter);
return new (aBuilder) nsDisplayFilter(aBuilder, *this);
}
NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER)
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// Items for the same content element should be merged into a single
// compositing group.
return HasSameTypeAndClip(aItem) && HasSameContent(aItem);
}
virtual void Merge(const nsDisplayItem* aItem) override
{
nsDisplayWrapList::Merge(aItem);
const nsDisplayFilter* other = static_cast<const nsDisplayFilter*>(aItem);
mEffectsBounds.UnionRect(mEffectsBounds,
other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
*aSnap = false;
return mEffectsBounds + ToReferenceFrame();
}
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayFilterGeometry(this, aBuilder);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override;
#ifdef MOZ_DUMP_PAINTING
void PrintEffects(nsACString& aTo);
#endif
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx,
LayerManager* aManager);
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
private:
// relative to mFrame
nsRect mEffectsBounds;
};
/* A display item that applies a transformation to all of its descendant
* elements. This wrapper should only be used if there is a transform applied
* to the root element.
*
* The reason that a "bounds" rect is involved in transform calculations is
* because CSS-transforms allow percentage values for the x and y components
* of <translation-value>s, where percentages are percentages of the element's
* border box.
*
* INVARIANT: The wrapped frame is transformed or we supplied a transform getter
* function.
* INVARIANT: The wrapped frame is non-null.
*/
class nsDisplayTransform: public nsDisplayItem
{
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
2014-08-29 18:47:30 +00:00
typedef mozilla::gfx::Point3D Point3D;
/*
* Avoid doing UpdateBounds() during construction.
*/
class StoreList : public nsDisplayWrapList {
public:
StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList) :
nsDisplayWrapList(aBuilder, aFrame, aList) {}
StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayItem* aItem) :
nsDisplayWrapList(aBuilder, aFrame, aItem) {}
virtual ~StoreList() {}
virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override {
// For extending 3d rendering context, the bounds would be
// updated by DoUpdateBoundsPreserves3D(), not here.
if (!mFrame->Extend3DContext()) {
nsDisplayWrapList::UpdateBounds(aBuilder);
}
}
void ForceUpdateBounds(nsDisplayListBuilder* aBuilder) {
nsDisplayWrapList::UpdateBounds(aBuilder);
}
virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
for (nsDisplayItem *i = mList.GetBottom(); i; i = i->GetAbove()) {
i->DoUpdateBoundsPreserves3D(aBuilder);
}
nsDisplayWrapList::UpdateBounds(aBuilder);
}
};
public:
enum PrerenderDecision {
NoPrerender,
FullPrerender,
PartialPrerender
};
/**
* Returns a matrix (in pixels) for the current frame. The matrix should be relative to
* the current frame's coordinate space.
*
* @param aFrame The frame to compute the transform for.
* @param aAppUnitsPerPixel The number of app units per graphics unit.
*/
typedef Matrix4x4 (* ComputeTransformFunction)(nsIFrame* aFrame, float aAppUnitsPerPixel);
/* Constructor accepts a display list, empties it, and wraps it up. It also
* ferries the underlying frame to the nsDisplayItem constructor.
*/
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
uint32_t aIndex = 0, bool aAllowAsyncAnimation = false);
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayItem *aItem, const nsRect& aChildrenVisibleRect,
uint32_t aIndex = 0);
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
ComputeTransformFunction aTransformGetter, uint32_t aIndex = 0);
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
const Matrix4x4& aTransform, uint32_t aIndex = 0);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayTransform()
{
MOZ_COUNT_DTOR(nsDisplayTransform);
}
#endif
virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
{
mHasBounds = false;
if (IsTransformSeparator()) {
mStoredList.ForceUpdateBounds(aBuilder);
return;
}
mStoredList.UpdateBounds(aBuilder);
UpdateBoundsFor3D(aBuilder);
}
virtual void Destroy(nsDisplayListBuilder* aBuilder) override
{
mStoredList.GetChildren()->DeleteAll(aBuilder);
nsDisplayItem::Destroy(aBuilder);
}
2012-07-15 04:16:47 +00:00
NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM)
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override
{
if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty())
return nsRect();
bool snap;
return GetBounds(aBuilder, &snap);
}
virtual nsDisplayList* GetChildren() const override
{
return mStoredList.GetChildren();
}
virtual void SetActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot) override
{
nsDisplayItem::SetActiveScrolledRoot(aActiveScrolledRoot);
mStoredList.SetActiveScrolledRoot(aActiveScrolledRoot);
}
virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames) override;
virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder,
bool* aSnap) const override;
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
bool* aSnap) const override;
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder *aBuilder) const override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override;
virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
nsRegion *aVisibleRegion) override;
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
return false;
}
virtual uint32_t GetPerFrameKey() const override {
return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override
{
// We don't need to compute an invalidation region since we have LayerTreeInvalidation
}
virtual const nsIFrame* ReferenceFrameForChildren() const override {
// If we were created using a transform-getter, then we don't
// belong to a transformed frame, and aren't a reference frame
// for our children.
if (!mTransformGetter) {
return mFrame;
}
return nsDisplayItem::ReferenceFrameForChildren();
}
AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const override {
return mAnimatedGeometryRootForScrollMetadata;
}
virtual const nsRect& GetVisibleRectForChildren() const override
{
return mChildrenVisibleRect;
}
enum {
INDEX_MAX = UINT32_MAX >> TYPE_BITS
};
/**
* We include the perspective matrix from our containing block for the
* purposes of visibility calculations, but we exclude it from the transform
* we set on the layer (for rendering), since there will be an
* nsDisplayPerspective created for that.
*/
const Matrix4x4& GetTransform() const;
Matrix4x4 GetTransformForRendering();
/**
* Return the transform that is aggregation of all transform on the
* preserves3d chain.
*/
const Matrix4x4& GetAccumulatedPreserved3DTransform(nsDisplayListBuilder* aBuilder);
float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint);
/**
* TransformRect takes in as parameters a rectangle (in aFrame's coordinate
* space) and returns the smallest rectangle (in aFrame's coordinate space)
* containing the transformed image of that rectangle. That is, it takes
* the four corners of the rectangle, transforms them according to the
* matrix associated with the specified frame, then returns the smallest
* rectangle containing the four transformed points.
*
* @param untransformedBounds The rectangle (in app units) to transform.
* @param aFrame The frame whose transformation should be applied. This
* function raises an assertion if aFrame is null or doesn't have a
* transform applied to it.
* @param aOrigin The origin of the transform relative to aFrame's local
* coordinate space.
* @param aBoundsOverride (optional) Rather than using the frame's computed
* bounding rect as frame bounds, use this rectangle instead. Pass
* nullptr (or nothing at all) to use the default.
*/
static nsRect TransformRect(const nsRect &aUntransformedBounds,
const nsIFrame* aFrame,
const nsRect* aBoundsOverride = nullptr);
/* UntransformRect is like TransformRect, except that it inverts the
* transform.
*/
static bool UntransformRect(const nsRect &aTransformedBounds,
const nsRect &aChildBounds,
const nsIFrame* aFrame,
nsRect *aOutRect);
bool UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
nsRect* aOutRect) const;
2014-08-29 18:47:30 +00:00
static Point3D GetDeltaToTransformOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride);
/*
* Returns true if aFrame has perspective applied from its containing
* block.
* Returns the matrix to append to apply the persective (taking
* perspective-origin into account), relative to aFrames coordinate
* space).
* aOutMatrix is assumed to be the identity matrix, and isn't explicitly
* cleared.
*/
static bool ComputePerspectiveMatrix(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
Matrix4x4& aOutMatrix);
struct FrameTransformProperties
{
FrameTransformProperties(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride);
FrameTransformProperties(RefPtr<const nsCSSValueSharedList>&&
aTransformList,
const Point3D& aToTransformOrigin)
: mFrame(nullptr)
, mTransformList(mozilla::Move(aTransformList))
, mToTransformOrigin(aToTransformOrigin)
{}
const nsIFrame* mFrame;
const RefPtr<const nsCSSValueSharedList> mTransformList;
2014-08-29 18:47:30 +00:00
const Point3D mToTransformOrigin;
};
/**
* Given a frame with the -moz-transform property or an SVG transform,
* returns the transformation matrix for that frame.
*
* @param aFrame The frame to get the matrix from.
* @param aOrigin Relative to which point this transform should be applied.
* @param aAppUnitsPerPixel The number of app units per graphics unit.
* @param aBoundsOverride [optional] If this is nullptr (the default), the
* computation will use the value of TransformReferenceBox(aFrame).
* Otherwise, it will use the value of aBoundsOverride. This is
* mostly for internal use and in most cases you will not need to
* specify a value.
* @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
* by aOrigin. This translation is applied *before* the CSS transform.
* @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
* include the transform of any ancestors participating in the same
* 3d rendering context.
* @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
* perspective transform from the containing block if applicable.
*/
enum {
OFFSET_BY_ORIGIN = 1 << 0,
INCLUDE_PRESERVE3D_ANCESTORS = 1 << 1,
INCLUDE_PERSPECTIVE = 1 << 2,
};
static Matrix4x4 GetResultingTransformMatrix(const nsIFrame* aFrame,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride = nullptr);
static Matrix4x4 GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride = nullptr);
/**
* Decide whether we should prerender some or all of the contents of the
* transformed frame even when it's not completely visible (yet).
* Return FullPrerender if the entire contents should be prerendered,
* PartialPrerender if some but not all of the contents should be prerendered,
* or NoPrerender if only the visible area should be rendered.
* |aDirtyRect| is updated to the area that should be prerendered.
*/
static PrerenderDecision ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
nsRect* aDirtyRect);
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
bool MayBeAnimated(nsDisplayListBuilder* aBuilder) const;
virtual void WriteDebugInfo(std::stringstream& aStream) override;
// Force the layer created for this item not to extend 3D context.
// See nsIFrame::BuildDisplayListForStackingContext()
void SetNoExtendContext() { mNoExtendContext = true; }
virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
MOZ_ASSERT(mFrame->Combines3DTransformWithAncestors() ||
IsTransformSeparator());
// Updating is not going through to child 3D context.
ComputeBounds(aBuilder);
}
/**
* This function updates bounds for items with a frame establishing
* 3D rendering context.
*
* \see nsDisplayItem::DoUpdateBoundsPreserves3D()
*/
void UpdateBoundsFor3D(nsDisplayListBuilder* aBuilder) {
if (!mFrame->Extend3DContext() ||
mFrame->Combines3DTransformWithAncestors() ||
IsTransformSeparator()) {
// Not an establisher of a 3D rendering context.
return;
}
// Always start updating from an establisher of a 3D rendering context.
nsDisplayListBuilder::AutoAccumulateRect accRect(aBuilder);
nsDisplayListBuilder::AutoAccumulateTransform accTransform(aBuilder);
accTransform.StartRoot();
ComputeBounds(aBuilder);
mBounds = aBuilder->GetAccumulatedRect();
mHasBounds = true;
}
/**
* This item is an additional item as the boundary between parent
* and child 3D rendering context.
* \see nsIFrame::BuildDisplayListForStackingContext().
*/
bool IsTransformSeparator() { return mIsTransformSeparator; }
/**
* This item is the boundary between parent and child 3D rendering
* context.
*/
bool IsLeafOf3DContext() {
return (IsTransformSeparator() ||
(!mFrame->Extend3DContext() &&
mFrame->Combines3DTransformWithAncestors()));
}
/**
* The backing frame of this item participates a 3D rendering
* context.
*/
bool IsParticipating3DContext() {
return mFrame->Extend3DContext() ||
mFrame->Combines3DTransformWithAncestors();
}
private:
void ComputeBounds(nsDisplayListBuilder* aBuilder);
void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
void Init(nsDisplayListBuilder* aBuilder);
static Matrix4x4 GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride);
StoreList mStoredList;
mutable Matrix4x4 mTransform;
// Accumulated transform of ancestors on the preserves-3d chain.
Matrix4x4 mTransformPreserves3D;
ComputeTransformFunction mTransformGetter;
RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForChildren;
RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForScrollMetadata;
nsRect mChildrenVisibleRect;
uint32_t mIndex;
mutable nsRect mBounds;
// True for mBounds is valid.
mutable bool mHasBounds;
// Be forced not to extend 3D context. Since we don't create a
// transform item, a container layer, for every frames in a
// preserves3d context, the transform items of a child preserves3d
// context may extend the parent context not intented if the root of
// the child preserves3d context doesn't create a transform item.
// With this flags, we force the item not extending 3D context.
bool mNoExtendContext;
// This item is a separator between 3D rendering contexts, and
// mTransform have been presetted by the constructor.
bool mIsTransformSeparator;
// True if mTransformPreserves3D have been initialized.
bool mTransformPreserves3DInited;
// True if async animation of the transform is allowed.
bool mAllowAsyncAnimation;
};
/* A display item that applies a perspective transformation to a single
* nsDisplayTransform child item. We keep this as a separate item since the
* perspective-origin is relative to an ancestor of the transformed frame, and
* APZ can scroll the child separately.
*/
class nsDisplayPerspective : public nsDisplayItem
{
typedef mozilla::gfx::Point3D Point3D;
public:
NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE)
nsDisplayPerspective(nsDisplayListBuilder* aBuilder, nsIFrame* aTransformFrame,
nsIFrame* aPerspectiveFrame,
nsDisplayList* aList);
virtual uint32_t GetPerFrameKey() const override {
return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override
{
return mList.HitTest(aBuilder, aRect, aState, aOutFrames);
}
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
return mList.GetBounds(aBuilder, aSnap);
}
virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
{
mList.UpdateBounds(aBuilder);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override
{}
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override
{
return mList.GetOpaqueRegion(aBuilder, aSnap);
}
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override
{
return mList.IsUniform(aBuilder);
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override
{
if (!mList.GetChildren()->GetTop()) {
return false;
}
return mList.GetChildren()->GetTop()->ShouldBuildLayerEvenIfInvisible(aBuilder);
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override
{
mList.RecomputeVisibility(aBuilder, aVisibleRegion);
return true;
}
virtual nsDisplayList* GetSameCoordinateSystemChildren() const override
{
return mList.GetChildren();
}
virtual nsDisplayList* GetChildren() const override
{
return mList.GetChildren();
}
virtual void SetActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot) override
{
nsDisplayItem::SetActiveScrolledRoot(aActiveScrolledRoot);
mList.SetActiveScrolledRoot(aActiveScrolledRoot);
}
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override
{
return mList.GetComponentAlphaBounds(aBuilder);
}
nsIFrame* TransformFrame() { return mTransformFrame; }
virtual nsIFrame* FrameForInvalidation() const override { return mTransformFrame; }
virtual int32_t ZIndex() const override;
virtual void
DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
if (mList.GetChildren()->GetTop()) {
static_cast<nsDisplayTransform*>(mList.GetChildren()->GetTop())->DoUpdateBoundsPreserves3D(aBuilder);
}
}
virtual void Destroy(nsDisplayListBuilder* aBuilder) override
{
mList.GetChildren()->DeleteAll(aBuilder);
nsDisplayItem::Destroy(aBuilder);
}
private:
nsDisplayWrapList mList;
nsIFrame* mTransformFrame;
uint32_t mIndex;
};
/**
* This class adds basic support for limiting the rendering (in the inline axis
* of the writing mode) to the part inside the specified edges. It's a base
* class for the display item classes that do the actual work.
* The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
* of the frame's scrollable overflow rectangle and are the amount to suppress
* on each side.
*
* Setting none, both or only one edge is allowed.
* The values must be non-negative.
* The default value for both edges is zero, which means everything is painted.
*/
class nsCharClipDisplayItem : public nsDisplayItem {
public:
nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame), mVisIStartEdge(0), mVisIEndEdge(0) {}
explicit nsCharClipDisplayItem(nsIFrame* aFrame)
: nsDisplayItem(aFrame), mVisIStartEdge(0), mVisIEndEdge(0) {}
virtual void RestoreState() override
{
nsDisplayItem::RestoreState();
mIsFrameSelected.reset();
}
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) const override;
struct ClipEdges {
ClipEdges(const nsDisplayItem& aItem,
nscoord aVisIStartEdge, nscoord aVisIEndEdge) {
nsRect r = aItem.Frame()->GetScrollableOverflowRect() +
aItem.ToReferenceFrame();
if (aItem.Frame()->GetWritingMode().IsVertical()) {
mVisIStart = aVisIStartEdge > 0 ? r.y + aVisIStartEdge : nscoord_MIN;
mVisIEnd =
aVisIEndEdge > 0 ? std::max(r.YMost() - aVisIEndEdge, mVisIStart)
: nscoord_MAX;
} else {
mVisIStart = aVisIStartEdge > 0 ? r.x + aVisIStartEdge : nscoord_MIN;
mVisIEnd =
aVisIEndEdge > 0 ? std::max(r.XMost() - aVisIEndEdge, mVisIStart)
: nscoord_MAX;
}
}
void Intersect(nscoord* aVisIStart, nscoord* aVisISize) const {
nscoord end = *aVisIStart + *aVisISize;
*aVisIStart = std::max(*aVisIStart, mVisIStart);
*aVisISize = std::max(std::min(end, mVisIEnd) - *aVisIStart, 0);
}
nscoord mVisIStart;
nscoord mVisIEnd;
};
ClipEdges Edges() const {
return ClipEdges(*this, mVisIStartEdge, mVisIEndEdge);
}
static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) {
DisplayItemType t = aItem->GetType();
return (t == DisplayItemType::TYPE_TEXT)
? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr;
}
// Lengths measured from the visual inline start and end sides
// (i.e. left and right respectively in horizontal writing modes,
// regardless of bidi directionality; top and bottom in vertical modes).
nscoord mVisIStartEdge;
nscoord mVisIEndEdge;
// Cached result of mFrame->IsSelected(). Only initialized when needed.
mutable mozilla::Maybe<bool> mIsFrameSelected;
};
class FlattenedDisplayItemIterator
{
public:
FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList)
: mBuilder(aBuilder)
, mNext(aList->GetBottom())
{
ResolveFlattening();
}
nsDisplayItem* GetNext()
{
nsDisplayItem* next = mNext;
// Advance mNext to the following item
if (next) {
mNext = mNext->GetAbove();
ResolveFlattening();
}
return next;
}
nsDisplayItem* PeekNext()
{
return mNext;
}
private:
bool AtEndOfNestedList()
{
return !mNext && mStack.Length() > 0;
}
bool ShouldFlattenNextItem()
{
return mNext && mNext->ShouldFlattenAway(mBuilder);
}
void ResolveFlattening()
{
// Handle the case where we reach the end of a nested list, or the current
// item should start a new nested list. Repeat this until we find an actual
// item, or the very end of the outer list.
while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
if (AtEndOfNestedList()) {
// Pop the last item off the stack.
mNext = mStack.LastElement();
mStack.RemoveElementAt(mStack.Length() - 1);
// We stored the item that was flattened, so advance to the next.
mNext = mNext->GetAbove();
} else {
// This item wants to be flattened. Store the current item on the stack,
// and use the first item in the child list instead.
mStack.AppendElement(mNext);
nsDisplayList* childItems = mNext->GetSameCoordinateSystemChildren();
mNext = childItems->GetBottom();
}
}
}
nsDisplayListBuilder* mBuilder;
nsDisplayItem* mNext;
AutoTArray<nsDisplayItem*, 10> mStack;
};
/**
* A display item that for webrender to handle SVG
*/
class nsDisplaySVGWrapper : public nsDisplayWrapList {
public:
NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER)
nsDisplaySVGWrapper(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplaySVGWrapper();
#endif
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
};
namespace mozilla {
class PaintTelemetry
{
public:
enum class Metric {
DisplayList,
Layerization,
Rasterization,
COUNT,
};
class AutoRecord
{
public:
explicit AutoRecord(Metric aMetric);
~AutoRecord();
TimeStamp GetStart() const {
return mStart;
}
private:
Metric mMetric;
mozilla::TimeStamp mStart;
};
class AutoRecordPaint
{
public:
AutoRecordPaint();
~AutoRecordPaint();
private:
mozilla::TimeStamp mStart;
};
private:
static uint32_t sPaintLevel;
static uint32_t sMetricLevel;
static mozilla::EnumeratedArray<Metric, Metric::COUNT, double> sMetrics;
};
} // namespace mozilla
#endif /*NSDISPLAYLIST_H_*/