/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * 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/. */ #ifndef FRAMELAYERBUILDER_H_ #define FRAMELAYERBUILDER_H_ #include "nsTHashtable.h" #include "nsHashKeys.h" #include "nsTArray.h" #include "nsRegion.h" #include "nsIFrame.h" #include "nsDisplayListInvalidation.h" #include "LayerTreeInvalidation.h" class nsDisplayListBuilder; class nsDisplayList; class nsDisplayItem; class gfxContext; class nsRootPresContext; namespace mozilla { namespace layers { class ContainerLayer; class LayerManager; class ThebesLayer; } class FrameLayerBuilder; class LayerManagerData; enum LayerState { LAYER_NONE, LAYER_INACTIVE, LAYER_ACTIVE, // Force an active layer even if it causes incorrect rendering, e.g. // when the layer has rounded rect clips. LAYER_ACTIVE_FORCE, // Special layer that is metadata only. LAYER_ACTIVE_EMPTY, // Inactive style layer for rendering SVG effects. LAYER_SVG_EFFECTS }; extern uint8_t gLayerManagerSecondary; class LayerManagerSecondary : public layers::LayerUserData { }; class RefCountedRegion : public RefCounted { public: RefCountedRegion() : mIsInfinite(false) {} nsRegion mRegion; bool mIsInfinite; }; /** * The FrameLayerBuilder is responsible for converting display lists * into layer trees. Every LayerManager needs a unique FrameLayerBuilder * to build layers. * * The most important API in this class is BuildContainerLayerFor. This * method takes a display list as input and constructs a ContainerLayer * with child layers that render the contents of the display list. It * also updates userdata for the retained layer manager, and * DisplayItemDataProperty data for frames, to record the relationship * between frames and layers. * * That data enables us to retain layer trees. When constructing a * ContainerLayer, we first check to see if there's an existing * ContainerLayer for the same frame that can be recycled. If we recycle * it, we also try to reuse its existing ThebesLayer children to render * the display items without layers of their own. The idea is that by * recycling layers deterministically, we can ensure that when nothing * changes in a display list, we will reuse the existing layers without * changes. * * We expose a GetLeafLayerFor method that can be called by display items * that make their own layers (e.g. canvas and video); this method * locates the last layer used to render the display item, if any, and * return it as a candidate for recycling. * * FrameLayerBuilder sets up ThebesLayers so that 0,0 in the Thebes layer * corresponds to the (pixel-snapped) top-left of the aActiveScrolledRoot. * It sets up ContainerLayers so that 0,0 in the container layer * corresponds to the snapped top-left of the display list reference frame. * * When we construct a container layer, we know the transform that will be * applied to the layer. If the transform scales the content, we can get * better results when intermediate buffers are used by pushing some scale * from the container's transform down to the children. For ThebesLayer * children, the scaling can be achieved by changing the size of the layer * and drawing into it with increased or decreased resolution. By convention, * integer types (nsIntPoint/nsIntSize/nsIntRect/nsIntRegion) are all in layer * coordinates, post-scaling, whereas appunit types are all pre-scaling. */ class FrameLayerBuilder : public layers::LayerUserData { public: typedef layers::ContainerLayer ContainerLayer; typedef layers::Layer Layer; typedef layers::ThebesLayer ThebesLayer; typedef layers::LayerManager LayerManager; FrameLayerBuilder() : mRetainingManager(nullptr), mDetectedDOMModification(false), mInvalidateAllLayers(false), mContainerLayerGeneration(0), mMaxContainerLayerGeneration(0) { MOZ_COUNT_CTOR(FrameLayerBuilder); mNewDisplayItemData.Init(); mThebesLayerItems.Init(); } ~FrameLayerBuilder() { MOZ_COUNT_DTOR(FrameLayerBuilder); } static void Shutdown(); void Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager); /** * Call this to notify that we have just started a transaction on the * retained layer manager aManager. */ void DidBeginRetainedLayerTransaction(LayerManager* aManager); /** * Call this just before we end a transaction. */ void WillEndTransaction(); /** * Call this after we end a transaction. */ void DidEndTransaction(); struct ContainerParameters { ContainerParameters() : mXScale(1), mYScale(1), mInTransformedSubtree(false), mInActiveTransformedSubtree(false), mDisableSubpixelAntialiasingInDescendants(false) {} ContainerParameters(float aXScale, float aYScale) : mXScale(aXScale), mYScale(aYScale), mInTransformedSubtree(false), mInActiveTransformedSubtree(false), mDisableSubpixelAntialiasingInDescendants(false) {} ContainerParameters(float aXScale, float aYScale, const nsIntPoint& aOffset, const ContainerParameters& aParent) : mXScale(aXScale), mYScale(aYScale), mOffset(aOffset), mInTransformedSubtree(aParent.mInTransformedSubtree), mInActiveTransformedSubtree(aParent.mInActiveTransformedSubtree), mDisableSubpixelAntialiasingInDescendants(aParent.mDisableSubpixelAntialiasingInDescendants) {} float mXScale, mYScale; /** * An offset to append to the transform set on all child layers created. */ nsIntPoint mOffset; bool mInTransformedSubtree; bool mInActiveTransformedSubtree; bool mDisableSubpixelAntialiasingInDescendants; /** * When this is false, ThebesLayer coordinates are drawn to with an integer * translation and the scale in mXScale/mYScale. */ bool AllowResidualTranslation() { // If we're in a transformed subtree, but no ancestor transform is actively // changing, we'll use the residual translation when drawing into the // ThebesLayer to ensure that snapping exactly matches the ideal transform. return mInTransformedSubtree && !mInActiveTransformedSubtree; } }; /** * Build a container layer for a display item that contains a child * list, either reusing an existing one or creating a new one. It * sets the container layer children to layers which together render * the contents of the display list. It reuses existing layers from * the retained layer manager if possible. * aContainer may be null, in which case we construct a root layer. * This gets called by display list code. It calls BuildLayer on the * items in the display list, making items with their own layers * children of the new container, and assigning all other items to * ThebesLayer children created and managed by the FrameLayerBuilder. * Returns a layer with clip rect cleared; it is the * caller's responsibility to add any clip rect. The visible region * is set based on what's in the layer. * The container layer is transformed by aTransform (if non-null), and * the result is transformed by the scale factors in aContainerParameters. */ already_AddRefed BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, LayerManager* aManager, nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem, const nsDisplayList& aChildren, const ContainerParameters& aContainerParameters, const gfx3DMatrix* aTransform); /** * Get a retained layer for a display item that needs to create its own * layer for rendering (i.e. under nsDisplayItem::BuildLayer). Returns * null if no retained layer is available, which usually means that this * display item didn't have a layer before so the caller will * need to create one. * Returns a layer with clip rect cleared; it is the * caller's responsibility to add any clip rect and set the visible * region. */ Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem); /** * Call this to force all retained layers to be discarded and recreated at * the next paint. */ static void InvalidateAllLayers(LayerManager* aManager); static void InvalidateAllLayersForFrame(nsIFrame *aFrame); /** * Call this to determine if a frame has a dedicated (non-Thebes) layer * for the given display item key. If there isn't one, we return null, * otherwise we return the layer. */ static Layer* GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey); /** * This callback must be provided to EndTransaction. The callback data * must be the nsDisplayListBuilder containing this FrameLayerBuilder. * This function can be called multiple times in a row to draw * different regions. */ static void DrawThebesLayer(ThebesLayer* aLayer, gfxContext* aContext, const nsIntRegion& aRegionToDraw, const nsIntRegion& aRegionToInvalidate, void* aCallbackData); #ifdef MOZ_DUMP_PAINTING /** * Dumps this FrameLayerBuilder's retained layer manager's retained * layer tree. Defaults to dumping to stdout in non-HTML format. */ static void DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile = stdout, bool aDumpHtml = false); #endif /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/ /* These are only in the public section because they need * to be called by file-scope helper functions in FrameLayerBuilder.cpp. */ /** * Record aItem as a display item that is rendered by aLayer. * * @param aLayer Layer that the display item will be rendered into * @param aItem Display item to be drawn. * @param aLayerState What LayerState the item is using. * @param aManager If the layer is in the LAYER_INACTIVE state, * then this is the temporary layer manager to draw with. */ struct Clip; void AddLayerDisplayItem(Layer* aLayer, nsDisplayItem* aItem, const Clip& aClip, LayerState aLayerState, const nsPoint& aTopLeft, LayerManager* aManager = nullptr); /** * Record aItem as a display item that is rendered by the ThebesLayer * aLayer, with aClipRect, where aContainerLayerFrame is the frame * for the container layer this ThebesItem belongs to. * aItem must have an underlying frame. */ void AddThebesDisplayItem(ThebesLayer* aLayer, nsDisplayItem* aItem, const Clip& aClip, nsIFrame* aContainerLayerFrame, LayerState aLayerState, const nsPoint& aTopLeft); /** * Set the current top-level LayerManager for the widget being * painted. */ static void SetWidgetLayerManager(LayerManager* aManager) { LayerManagerSecondary* secondary = static_cast(aManager->GetUserData(&gLayerManagerSecondary)); sWidgetManagerSecondary = !!secondary; } /** * Gets the frame property descriptor for the given manager, or for the current * widget layer manager if nullptr is passed. */ static const FramePropertyDescriptor* GetDescriptorForManager(LayerManager* aManager); /** * Get the LayerManagerData for a given frame and layer manager. If no layer manager * is passed, then the current widget layer manager is used. */ static LayerManagerData* GetManagerData(nsIFrame* aFrame, LayerManager* aManager = nullptr); /** * Set the LayerManagerData for a given frame and current widget layer manager. * This replaces any existing data for the same frame/layer manager pair. */ static void SetManagerData(nsIFrame* aFrame, LayerManagerData* aData); /** * Clears the current LayerManagerData for the given frame and current widget * layer manager. */ static void ClearManagerData(nsIFrame* aFrame); /** * Clears any references to the given LayerManagerData for the given frame * and belonging to any layer manager. */ static void ClearManagerData(nsIFrame* aFrame, LayerManagerData* aData); /** * Calls GetOldLayerForFrame on the underlying frame of the display item, * and each subsequent merged frame if no layer is found for the underlying * frame. */ Layer* GetOldLayerFor(nsDisplayItem* aItem, nsDisplayItemGeometry** aOldGeometry = nullptr, Clip** aOldClip = nullptr); static Layer* GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey); /** * If the display item was previously drawn as an inactive layer, * then return the layer manager used for the inactive transaction. * Returns nullptr if no manager could be found. */ LayerManager* GetInactiveLayerManagerFor(nsDisplayItem* aItem); /** * Try to determine whether the ThebesLayer aLayer paints an opaque * single color everywhere it's visible in aRect. * If successful, return that color, otherwise return NS_RGBA(0,0,0,0). */ nscolor FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder, ThebesLayer* aLayer, const nsRect& aRect); /** * Destroy any stored LayerManagerDataProperty and the associated data for * aFrame. */ static void DestroyDisplayItemDataFor(nsIFrame* aFrame); LayerManager* GetRetainingLayerManager() { return mRetainingManager; } /** * Returns true if the given item (which we assume here is * background-attachment:fixed) needs to be repainted as we scroll in its * document. * Returns false if it doesn't need to be repainted because the layer system * is ensuring its fixed-ness for us. */ static bool NeedToInvalidateFixedDisplayItem(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem); /** * Returns true if the given display item was rendered directly * into a retained layer. * Returns false if it was rendered into a temporary layer manager and then * into a retained layer. * * Since display items can belong to multiple retained LayerManagers, we need to * specify which LayerManager to check. */ static bool HasRetainedLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey, LayerManager* aManager); /** * Returns true if the given display item was rendered during the previous * paint. Returns false otherwise. */ static bool HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey); /** * Save transform that was in aLayer when we last painted, and the position * of the active scrolled root frame. It must be an integer * translation. */ void SaveLastPaintOffset(ThebesLayer* aLayer); /** * Get the translation transform that was in aLayer when we last painted. It's either * the transform saved by SaveLastPaintTransform, or else the transform * that's currently in the layer (which must be an integer translation). */ nsIntPoint GetLastPaintOffset(ThebesLayer* aLayer); /** * Return the resolution at which we expect to render aFrame's contents, * assuming they are being painted to retained layers. This takes into account * the resolution the contents of the ContainerLayer containing aFrame are * being rendered at, as well as any currently-inactive transforms between * aFrame and that container layer. */ static gfxSize GetThebesLayerScaleForFrame(nsIFrame* aFrame); /** * Clip represents the intersection of an optional rectangle with a * list of rounded rectangles. */ struct Clip { struct RoundedRect { nsRect mRect; // Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h nscoord mRadii[8]; RoundedRect operator+(const nsPoint& aOffset) const { RoundedRect r = *this; r.mRect += aOffset; return r; } bool operator==(const RoundedRect& aOther) const { if (!mRect.IsEqualInterior(aOther.mRect)) { return false; } NS_FOR_CSS_HALF_CORNERS(corner) { if (mRadii[corner] != aOther.mRadii[corner]) { return false; } } return true; } bool operator!=(const RoundedRect& aOther) const { return !(*this == aOther); } }; nsRect mClipRect; nsTArray mRoundedClipRects; bool mHaveClipRect; Clip() : mHaveClipRect(false) {} // Construct as the intersection of aOther and aClipItem. Clip(const Clip& aOther, nsDisplayItem* aClipItem); // Apply this |Clip| to the given gfxContext. Any saving of state // or clearing of other clips must be done by the caller. // See aBegin/aEnd note on ApplyRoundedRectsTo. void ApplyTo(gfxContext* aContext, nsPresContext* aPresContext, uint32_t aBegin = 0, uint32_t aEnd = PR_UINT32_MAX); void ApplyRectTo(gfxContext* aContext, int32_t A2D) const; // Applies the rounded rects in this Clip to aContext // Will only apply rounded rects from aBegin (inclusive) to aEnd // (exclusive) or the number of rounded rects, whichever is smaller. void ApplyRoundedRectsTo(gfxContext* aContext, int32_t A2DPRInt32, uint32_t aBegin, uint32_t aEnd) const; // Draw (fill) the rounded rects in this clip to aContext void DrawRoundedRectsTo(gfxContext* aContext, int32_t A2D, uint32_t aBegin, uint32_t aEnd) const; // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext void AddRoundedRectPathTo(gfxContext* aContext, int32_t A2D, const RoundedRect &aRoundRect) const; // Return a rectangle contained in the intersection of aRect with this // clip region. Tries to return the largest possible rectangle, but may // not succeed. nsRect ApproximateIntersect(const nsRect& aRect) const; // Returns false if aRect is definitely not clipped by a rounded corner in // this clip. Returns true if aRect is clipped by a rounded corner in this // clip or it can not be quickly determined that it is not clipped by a // rounded corner in this clip. bool IsRectClippedByRoundedCorner(const nsRect& aRect) const; // Intersection of all rects in this clip ignoring any rounded corners. nsRect NonRoundedIntersection() const; // Gets rid of any rounded corners in this clip. void RemoveRoundedCorners(); // Adds the difference between Intersect(*this + aPoint, aBounds) and // Intersect(aOther, aOtherBounds) to aDifference. void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds, const Clip& aOther, const nsRect& aOtherBounds, nsRegion* aDifference); bool operator==(const Clip& aOther) const { return mHaveClipRect == aOther.mHaveClipRect && (!mHaveClipRect || mClipRect.IsEqualInterior(aOther.mClipRect)) && mRoundedClipRects == aOther.mRoundedClipRects; } bool operator!=(const Clip& aOther) const { return !(*this == aOther); } }; NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty, RemoveFrameFromLayerManager) NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerSecondaryDataProperty, RemoveFrameFromLayerManager) protected: /** * We store an array of these for each frame that is associated with * one or more retained layers. Each DisplayItemData records the layer * used to render one of the frame's display items. */ class DisplayItemData { public: DisplayItemData(Layer* aLayer, uint32_t aKey, LayerState aLayerState, uint32_t aGeneration); DisplayItemData() : mUsed(false) {} DisplayItemData(DisplayItemData &toCopy); ~DisplayItemData(); NS_INLINE_DECL_REFCOUNTING(DisplayItemData) void AddFrame(nsIFrame* aFrame) { mFrameList.AppendElement(aFrame); } bool FrameListMatches(nsDisplayItem* aOther); nsRefPtr mLayer; nsRefPtr mInactiveManager; nsAutoTArray mFrameList; nsAutoPtr mGeometry; Clip mClip; uint32_t mDisplayItemKey; uint32_t mContainerLayerGeneration; LayerState mLayerState; /** * Used to track if data currently stored in mFramesWithLayers (from an existing * paint) is also used in the current paint and has an equivalent data object * in mNewDisplayItemData. */ bool mUsed; }; static void RemoveFrameFromLayerManager(nsIFrame* aFrame, void* aPropertyValue); /** * Given a frame and a display item key that uniquely identifies a * display item for the frame, find the layer that was last used to * render that display item. Returns null if there is no such layer. * This could be a dedicated layer for the display item, or a ThebesLayer * that renders many display items. */ DisplayItemData* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey); /** * We accumulate DisplayItemData elements in a hashtable during * the paint process, and store them in the frame property only when * paint is complete. This is the hashentry for that hashtable. */ class DisplayItemDataEntry : public nsPtrHashKey { public: DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey(key) { MOZ_COUNT_CTOR(DisplayItemDataEntry); } DisplayItemDataEntry(DisplayItemDataEntry &toCopy) : nsPtrHashKey(toCopy.mKey) { MOZ_COUNT_CTOR(DisplayItemDataEntry); // This isn't actually a copy-constructor; notice that it steals toCopy's // array and invalid region. Be careful. mData.SwapElements(toCopy.mData); mContainerLayerGeneration = toCopy.mContainerLayerGeneration; } ~DisplayItemDataEntry() { MOZ_COUNT_DTOR(DisplayItemDataEntry); } bool HasNonEmptyContainerLayer(); nsAutoTArray, 1> mData; uint32_t mContainerLayerGeneration; enum { ALLOW_MEMMOVE = false }; }; // LayerManagerData needs to see DisplayItemDataEntry. friend class LayerManagerData; /** * Stores DisplayItemData associated with aFrame, stores the data in * mNewDisplayItemData. */ void StoreDataForFrame(nsIFrame* aFrame, DisplayItemData* data); // Flash the area within the context clip if paint flashing is enabled. static void FlashPaint(gfxContext *aContext); /* * Get the DisplayItemData array associated with this frame, or null if one * doesn't exist. * * Note that the pointer returned here is only valid so long as you don't * poke the LayerManagerData's mFramesWithLayers hashtable. */ nsTArray >* GetDisplayItemDataArrayForFrame(nsIFrame *aFrame); /* * Get the DisplayItemData associated with this frame / display item pair, * using the LayerManager instead of FrameLayerBuilder. */ static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, uint32_t aDisplayItemKey, LayerManager* aManager); static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, uint32_t aDisplayItemKey); static DisplayItemData* GetDisplayItemDataForManager(nsDisplayItem* aItem, LayerManager* aManager); static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, uint32_t aDisplayItemKey, LayerManagerData* aData); /** * A useful hashtable iteration function that removes the * DisplayItemData property for the frame, clears its * NS_FRAME_HAS_CONTAINER_LAYER bit and returns PL_DHASH_REMOVE. * aClosure is ignored. */ static PLDHashOperator RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry, void* aClosure); /** * We store one of these for each display item associated with a * ThebesLayer, in a hashtable that maps each ThebesLayer to an array * of ClippedDisplayItems. (ThebesLayerItemsEntry is the hash entry * for that hashtable.) * These are only stored during the paint process, so that the * DrawThebesLayer callback can figure out which items to draw for the * ThebesLayer. * mItem always has an underlying frame. */ struct ClippedDisplayItem { ClippedDisplayItem(nsDisplayItem* aItem, const Clip& aClip, uint32_t aGeneration) : mItem(aItem), mClip(aClip), mContainerLayerGeneration(aGeneration) { } ~ClippedDisplayItem(); nsDisplayItem* mItem; /** * If the display item is being rendered as an inactive * layer, then this stores the layer manager being * used for the inactive transaction. */ nsRefPtr mInactiveLayer; Clip mClip; uint32_t mContainerLayerGeneration; }; /** * We accumulate ClippedDisplayItem elements in a hashtable during * the paint process. This is the hashentry for that hashtable. */ public: class ThebesLayerItemsEntry : public nsPtrHashKey { public: ThebesLayerItemsEntry(const ThebesLayer *key) : nsPtrHashKey(key), mContainerLayerFrame(nullptr), mContainerLayerGeneration(0), mHasExplicitLastPaintOffset(false), mCommonClipCount(0) {} ThebesLayerItemsEntry(const ThebesLayerItemsEntry &toCopy) : nsPtrHashKey(toCopy.mKey), mItems(toCopy.mItems) { NS_ERROR("Should never be called, since we ALLOW_MEMMOVE"); } nsTArray mItems; nsIFrame* mContainerLayerFrame; // The translation set on this ThebesLayer before we started updating the // layer tree. nsIntPoint mLastPaintOffset; uint32_t mContainerLayerGeneration; bool mHasExplicitLastPaintOffset; /** * The first mCommonClipCount rounded rectangle clips are identical for * all items in the layer. Computed in ThebesLayerData. */ uint32_t mCommonClipCount; enum { ALLOW_MEMMOVE = true }; }; /** * Get the ThebesLayerItemsEntry object associated with aLayer in this * FrameLayerBuilder */ ThebesLayerItemsEntry* GetThebesLayerItemsEntry(ThebesLayer* aLayer) { return mThebesLayerItems.GetEntry(aLayer); } static PLDHashOperator ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry, void* aUserArg); protected: void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer, bool aRemoveThebesItems, bool aRemoveOwnerData); static void SetAndClearInvalidRegion(DisplayItemDataEntry* aEntry); static PLDHashOperator UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry, void* aUserArg); static PLDHashOperator StoreNewDisplayItemData(DisplayItemDataEntry* aEntry, void* aUserArg); static PLDHashOperator RestoreDisplayItemData(DisplayItemDataEntry* aEntry, void *aUserArg); static PLDHashOperator RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry, void *aUserArg); /** * Returns true if the DOM has been modified since we started painting, * in which case we should bail out and not paint anymore. This should * never happen, but plugins can trigger it in some cases. */ bool CheckDOMModified(); /** * The layer manager belonging to the widget that is being retained * across paints. */ LayerManager* mRetainingManager; /** * The root prescontext for the display list builder reference frame */ nsRootPresContext* mRootPresContext; /** * The display list builder being used. */ nsDisplayListBuilder* mDisplayListBuilder; /** * A map from frames to a list of (display item key, layer) pairs that * describes what layers various parts of the frame are assigned to. */ nsTHashtable mNewDisplayItemData; /** * A map from ThebesLayers to the list of display items (plus * clipping data) to be rendered in the layer. */ nsTHashtable mThebesLayerItems; /** * Saved generation counter so we can detect DOM changes. */ uint32_t mInitialDOMGeneration; /** * Set to true if we have detected and reported DOM modification during * the current paint. */ bool mDetectedDOMModification; /** * Indicates that the entire layer tree should be rerendered * during this paint. */ bool mInvalidateAllLayers; uint32_t mContainerLayerGeneration; uint32_t mMaxContainerLayerGeneration; /** * True if the current top-level LayerManager for the widget being * painted is marked as being a 'secondary' LayerManager. */ static bool sWidgetManagerSecondary; }; } #endif /* FRAMELAYERBUILDER_H_ */