michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef FRAMELAYERBUILDER_H_ michael@0: #define FRAMELAYERBUILDER_H_ michael@0: michael@0: #include "nsTHashtable.h" michael@0: #include "nsHashKeys.h" michael@0: #include "nsTArray.h" michael@0: #include "nsRegion.h" michael@0: #include "nsIFrame.h" michael@0: #include "ImageLayers.h" michael@0: #include "DisplayItemClip.h" michael@0: #include "mozilla/layers/LayersTypes.h" michael@0: michael@0: class nsDisplayListBuilder; michael@0: class nsDisplayList; michael@0: class nsDisplayItem; michael@0: class gfxContext; michael@0: class nsDisplayItemGeometry; michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: class ContainerLayer; michael@0: class LayerManager; michael@0: class BasicLayerManager; michael@0: class ThebesLayer; michael@0: } michael@0: michael@0: class FrameLayerBuilder; michael@0: class LayerManagerData; michael@0: class ThebesLayerData; michael@0: michael@0: enum LayerState { michael@0: LAYER_NONE, michael@0: LAYER_INACTIVE, michael@0: LAYER_ACTIVE, michael@0: // Force an active layer even if it causes incorrect rendering, e.g. michael@0: // when the layer has rounded rect clips. michael@0: LAYER_ACTIVE_FORCE, michael@0: // Special layer that is metadata only. michael@0: LAYER_ACTIVE_EMPTY, michael@0: // Inactive style layer for rendering SVG effects. michael@0: LAYER_SVG_EFFECTS michael@0: }; michael@0: michael@0: class RefCountedRegion { michael@0: public: michael@0: NS_INLINE_DECL_REFCOUNTING(RefCountedRegion) michael@0: michael@0: RefCountedRegion() : mIsInfinite(false) {} michael@0: nsRegion mRegion; michael@0: bool mIsInfinite; michael@0: }; michael@0: michael@0: struct ContainerLayerParameters { michael@0: ContainerLayerParameters() : michael@0: mXScale(1), mYScale(1), mAncestorClipRect(nullptr), michael@0: mInTransformedSubtree(false), mInActiveTransformedSubtree(false), michael@0: mDisableSubpixelAntialiasingInDescendants(false) michael@0: {} michael@0: ContainerLayerParameters(float aXScale, float aYScale) : michael@0: mXScale(aXScale), mYScale(aYScale), mAncestorClipRect(nullptr), michael@0: mInTransformedSubtree(false), mInActiveTransformedSubtree(false), michael@0: mDisableSubpixelAntialiasingInDescendants(false) michael@0: {} michael@0: ContainerLayerParameters(float aXScale, float aYScale, michael@0: const nsIntPoint& aOffset, michael@0: const ContainerLayerParameters& aParent) : michael@0: mXScale(aXScale), mYScale(aYScale), mAncestorClipRect(nullptr), michael@0: mOffset(aOffset), michael@0: mInTransformedSubtree(aParent.mInTransformedSubtree), michael@0: mInActiveTransformedSubtree(aParent.mInActiveTransformedSubtree), michael@0: mDisableSubpixelAntialiasingInDescendants(aParent.mDisableSubpixelAntialiasingInDescendants) michael@0: {} michael@0: float mXScale, mYScale; michael@0: /** michael@0: * An ancestor clip rect that can be applied to restrict the visibility michael@0: * of this container. Null if none available. michael@0: */ michael@0: const nsIntRect* mAncestorClipRect; michael@0: /** michael@0: * An offset to append to the transform set on all child layers created. michael@0: */ michael@0: nsIntPoint mOffset; michael@0: michael@0: bool mInTransformedSubtree; michael@0: bool mInActiveTransformedSubtree; michael@0: bool mDisableSubpixelAntialiasingInDescendants; michael@0: /** michael@0: * When this is false, ThebesLayer coordinates are drawn to with an integer michael@0: * translation and the scale in mXScale/mYScale. michael@0: */ michael@0: bool AllowResidualTranslation() michael@0: { michael@0: // If we're in a transformed subtree, but no ancestor transform is actively michael@0: // changing, we'll use the residual translation when drawing into the michael@0: // ThebesLayer to ensure that snapping exactly matches the ideal transform. michael@0: return mInTransformedSubtree && !mInActiveTransformedSubtree; michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * The FrameLayerBuilder is responsible for converting display lists michael@0: * into layer trees. Every LayerManager needs a unique FrameLayerBuilder michael@0: * to build layers. michael@0: * michael@0: * The most important API in this class is BuildContainerLayerFor. This michael@0: * method takes a display list as input and constructs a ContainerLayer michael@0: * with child layers that render the contents of the display list. It michael@0: * records the relationship between frames and layers. michael@0: * michael@0: * That data enables us to retain layer trees. When constructing a michael@0: * ContainerLayer, we first check to see if there's an existing michael@0: * ContainerLayer for the same frame that can be recycled. If we recycle michael@0: * it, we also try to reuse its existing ThebesLayer children to render michael@0: * the display items without layers of their own. The idea is that by michael@0: * recycling layers deterministically, we can ensure that when nothing michael@0: * changes in a display list, we will reuse the existing layers without michael@0: * changes. michael@0: * michael@0: * We expose a GetLeafLayerFor method that can be called by display items michael@0: * that make their own layers (e.g. canvas and video); this method michael@0: * locates the last layer used to render the display item, if any, and michael@0: * return it as a candidate for recycling. michael@0: * michael@0: * FrameLayerBuilder sets up ThebesLayers so that 0,0 in the Thebes layer michael@0: * corresponds to the (pixel-snapped) top-left of the aAnimatedGeometryRoot. michael@0: * It sets up ContainerLayers so that 0,0 in the container layer michael@0: * corresponds to the snapped top-left of the display item reference frame. michael@0: * michael@0: * When we construct a container layer, we know the transform that will be michael@0: * applied to the layer. If the transform scales the content, we can get michael@0: * better results when intermediate buffers are used by pushing some scale michael@0: * from the container's transform down to the children. For ThebesLayer michael@0: * children, the scaling can be achieved by changing the size of the layer michael@0: * and drawing into it with increased or decreased resolution. By convention, michael@0: * integer types (nsIntPoint/nsIntSize/nsIntRect/nsIntRegion) are all in layer michael@0: * coordinates, post-scaling, whereas appunit types are all pre-scaling. michael@0: */ michael@0: class FrameLayerBuilder : public layers::LayerUserData { michael@0: public: michael@0: typedef layers::ContainerLayer ContainerLayer; michael@0: typedef layers::Layer Layer; michael@0: typedef layers::ThebesLayer ThebesLayer; michael@0: typedef layers::ImageLayer ImageLayer; michael@0: typedef layers::LayerManager LayerManager; michael@0: typedef layers::BasicLayerManager BasicLayerManager; michael@0: typedef layers::EventRegions EventRegions; michael@0: michael@0: FrameLayerBuilder() : michael@0: mRetainingManager(nullptr), michael@0: mDetectedDOMModification(false), michael@0: mInvalidateAllLayers(false), michael@0: mInLayerTreeCompressionMode(false), michael@0: mContainerLayerGeneration(0), michael@0: mMaxContainerLayerGeneration(0) michael@0: { michael@0: MOZ_COUNT_CTOR(FrameLayerBuilder); michael@0: } michael@0: ~FrameLayerBuilder() michael@0: { michael@0: MOZ_COUNT_DTOR(FrameLayerBuilder); michael@0: } michael@0: michael@0: static void Shutdown(); michael@0: michael@0: void Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager, michael@0: ThebesLayerData* aLayerData = nullptr); michael@0: michael@0: /** michael@0: * Call this to notify that we have just started a transaction on the michael@0: * retained layer manager aManager. michael@0: */ michael@0: void DidBeginRetainedLayerTransaction(LayerManager* aManager); michael@0: michael@0: /** michael@0: * Call this just before we end a transaction. michael@0: */ michael@0: void WillEndTransaction(); michael@0: michael@0: /** michael@0: * Call this after we end a transaction. michael@0: */ michael@0: void DidEndTransaction(); michael@0: michael@0: enum { michael@0: CONTAINER_NOT_CLIPPED_BY_ANCESTORS = 0x01 michael@0: }; michael@0: /** michael@0: * Build a container layer for a display item that contains a child michael@0: * list, either reusing an existing one or creating a new one. It michael@0: * sets the container layer children to layers which together render michael@0: * the contents of the display list. It reuses existing layers from michael@0: * the retained layer manager if possible. michael@0: * aContainer may be null, in which case we construct a root layer. michael@0: * This gets called by display list code. It calls BuildLayer on the michael@0: * items in the display list, making items with their own layers michael@0: * children of the new container, and assigning all other items to michael@0: * ThebesLayer children created and managed by the FrameLayerBuilder. michael@0: * Returns a layer with clip rect cleared; it is the michael@0: * caller's responsibility to add any clip rect. The visible region michael@0: * is set based on what's in the layer. michael@0: * The container layer is transformed by aTransform (if non-null), and michael@0: * the result is transformed by the scale factors in aContainerParameters. michael@0: */ michael@0: already_AddRefed michael@0: BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, michael@0: LayerManager* aManager, michael@0: nsIFrame* aContainerFrame, michael@0: nsDisplayItem* aContainerItem, michael@0: const nsDisplayList& aChildren, michael@0: const ContainerLayerParameters& aContainerParameters, michael@0: const gfx3DMatrix* aTransform, michael@0: uint32_t aFlags = 0); michael@0: michael@0: /** michael@0: * Get a retained layer for a display item that needs to create its own michael@0: * layer for rendering (i.e. under nsDisplayItem::BuildLayer). Returns michael@0: * null if no retained layer is available, which usually means that this michael@0: * display item didn't have a layer before so the caller will michael@0: * need to create one. michael@0: * Returns a layer with clip rect cleared; it is the michael@0: * caller's responsibility to add any clip rect and set the visible michael@0: * region. michael@0: */ michael@0: Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder, michael@0: nsDisplayItem* aItem); michael@0: michael@0: /** michael@0: * Call this to force all retained layers to be discarded and recreated at michael@0: * the next paint. michael@0: */ michael@0: static void InvalidateAllLayers(LayerManager* aManager); michael@0: static void InvalidateAllLayersForFrame(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Call this to determine if a frame has a dedicated (non-Thebes) layer michael@0: * for the given display item key. If there isn't one, we return null, michael@0: * otherwise we return the layer. michael@0: */ michael@0: static Layer* GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey); michael@0: michael@0: /** michael@0: * This callback must be provided to EndTransaction. The callback data michael@0: * must be the nsDisplayListBuilder containing this FrameLayerBuilder. michael@0: * This function can be called multiple times in a row to draw michael@0: * different regions. michael@0: */ michael@0: static void DrawThebesLayer(ThebesLayer* aLayer, michael@0: gfxContext* aContext, michael@0: const nsIntRegion& aRegionToDraw, michael@0: mozilla::layers::DrawRegionClip aClip, michael@0: const nsIntRegion& aRegionToInvalidate, michael@0: void* aCallbackData); michael@0: michael@0: #ifdef MOZ_DUMP_PAINTING michael@0: /** michael@0: * Dumps this FrameLayerBuilder's retained layer manager's retained michael@0: * layer tree. Defaults to dumping to stdout in non-HTML format. michael@0: */ michael@0: static void DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile = stdout, bool aDumpHtml = false); michael@0: #endif michael@0: michael@0: /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/ michael@0: /* These are only in the public section because they need michael@0: * to be called by file-scope helper functions in FrameLayerBuilder.cpp. michael@0: */ michael@0: michael@0: /** michael@0: * Record aItem as a display item that is rendered by aLayer. michael@0: * michael@0: * @param aLayer Layer that the display item will be rendered into michael@0: * @param aItem Display item to be drawn. michael@0: * @param aLayerState What LayerState the item is using. michael@0: * @param aTopLeft offset from active scrolled root to reference frame michael@0: * @param aManager If the layer is in the LAYER_INACTIVE state, michael@0: * then this is the temporary layer manager to draw with. michael@0: */ michael@0: void AddLayerDisplayItem(Layer* aLayer, michael@0: nsDisplayItem* aItem, michael@0: const DisplayItemClip& aClip, michael@0: LayerState aLayerState, michael@0: const nsPoint& aTopLeft, michael@0: BasicLayerManager* aManager, michael@0: nsAutoPtr aGeometry); michael@0: michael@0: /** michael@0: * Record aItem as a display item that is rendered by the ThebesLayer michael@0: * aLayer, with aClipRect, where aContainerLayerFrame is the frame michael@0: * for the container layer this ThebesItem belongs to. michael@0: * aItem must have an underlying frame. michael@0: * @param aTopLeft offset from active scrolled root to reference frame michael@0: */ michael@0: void AddThebesDisplayItem(ThebesLayerData* aLayer, michael@0: nsDisplayItem* aItem, michael@0: const DisplayItemClip& aClip, michael@0: nsIFrame* aContainerLayerFrame, michael@0: LayerState aLayerState, michael@0: const nsPoint& aTopLeft, michael@0: nsAutoPtr aGeometry); michael@0: michael@0: /** michael@0: * Gets the frame property descriptor for the given manager, or for the current michael@0: * widget layer manager if nullptr is passed. michael@0: */ michael@0: static const FramePropertyDescriptor* GetDescriptorForManager(LayerManager* aManager); michael@0: michael@0: /** michael@0: * Calls GetOldLayerForFrame on the underlying frame of the display item, michael@0: * and each subsequent merged frame if no layer is found for the underlying michael@0: * frame. michael@0: */ michael@0: Layer* GetOldLayerFor(nsDisplayItem* aItem, michael@0: nsDisplayItemGeometry** aOldGeometry = nullptr, michael@0: DisplayItemClip** aOldClip = nullptr, michael@0: nsTArray* aChangedFrames = nullptr, michael@0: bool *aIsInvalid = nullptr); michael@0: michael@0: static Layer* GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey); michael@0: michael@0: /** michael@0: * Destroy any stored LayerManagerDataProperty and the associated data for michael@0: * aFrame. michael@0: */ michael@0: static void DestroyDisplayItemDataFor(nsIFrame* aFrame); michael@0: michael@0: LayerManager* GetRetainingLayerManager() { return mRetainingManager; } michael@0: michael@0: /** michael@0: * Returns true if the given display item was rendered during the previous michael@0: * paint. Returns false otherwise. michael@0: */ michael@0: static bool HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey); michael@0: michael@0: class DisplayItemData; michael@0: typedef void (*DisplayItemDataCallback)(nsIFrame *aFrame, DisplayItemData* aItem); michael@0: michael@0: static void IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback); michael@0: michael@0: /** michael@0: * Save transform that was in aLayer when we last painted, and the position michael@0: * of the active scrolled root frame. It must be an integer michael@0: * translation. michael@0: */ michael@0: void SaveLastPaintOffset(ThebesLayer* aLayer); michael@0: /** michael@0: * Get the translation transform that was in aLayer when we last painted. It's either michael@0: * the transform saved by SaveLastPaintTransform, or else the transform michael@0: * that's currently in the layer (which must be an integer translation). michael@0: */ michael@0: nsIntPoint GetLastPaintOffset(ThebesLayer* aLayer); michael@0: michael@0: /** michael@0: * Return the resolution at which we expect to render aFrame's contents, michael@0: * assuming they are being painted to retained layers. This takes into account michael@0: * the resolution the contents of the ContainerLayer containing aFrame are michael@0: * being rendered at, as well as any currently-inactive transforms between michael@0: * aFrame and that container layer. michael@0: */ michael@0: static gfxSize GetThebesLayerScaleForFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair. michael@0: * michael@0: * Used when we optimize a ThebesLayer into an ImageLayer and want to retroactively update the michael@0: * DisplayItemData so we can retrieve the layer from within layout. michael@0: */ michael@0: void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer); michael@0: michael@0: NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty, michael@0: RemoveFrameFromLayerManager) michael@0: michael@0: /** michael@0: * Retained data storage: michael@0: * michael@0: * Each layer manager (widget, and inactive) stores a LayerManagerData object michael@0: * that keeps a hash-set of DisplayItemData items that were drawn into it. michael@0: * Each frame also keeps a list of DisplayItemData pointers that were michael@0: * created for that frame. DisplayItemData objects manage these lists automatically. michael@0: * michael@0: * During layer construction we update the data in the LayerManagerData object, marking michael@0: * items that are modified. At the end we sweep the LayerManagerData hash-set and remove michael@0: * all items that haven't been modified. michael@0: */ michael@0: michael@0: /** michael@0: * Retained data for a display item. michael@0: */ michael@0: class DisplayItemData MOZ_FINAL { michael@0: public: michael@0: friend class FrameLayerBuilder; michael@0: michael@0: uint32_t GetDisplayItemKey() { return mDisplayItemKey; } michael@0: Layer* GetLayer() { return mLayer; } michael@0: void Invalidate() { mIsInvalid = true; } michael@0: michael@0: private: michael@0: DisplayItemData(LayerManagerData* aParent, uint32_t aKey, Layer* aLayer, LayerState aLayerState, uint32_t aGeneration); michael@0: DisplayItemData(DisplayItemData &toCopy); michael@0: michael@0: /** michael@0: * Removes any references to this object from frames michael@0: * in mFrameList. michael@0: */ michael@0: ~DisplayItemData(); michael@0: michael@0: NS_INLINE_DECL_REFCOUNTING(DisplayItemData) michael@0: michael@0: michael@0: /** michael@0: * Associates this DisplayItemData with a frame, and adds it michael@0: * to the LayerManagerDataProperty list on the frame. michael@0: */ michael@0: void AddFrame(nsIFrame* aFrame); michael@0: void RemoveFrame(nsIFrame* aFrame); michael@0: void GetFrameListChanges(nsDisplayItem* aOther, nsTArray& aOut); michael@0: michael@0: /** michael@0: * Updates the contents of this item to a new set of data, instead of allocating a new michael@0: * object. michael@0: * Set the passed in parameters, and clears the opt layer, inactive manager, geometry michael@0: * and clip. michael@0: * Parent, frame list and display item key are assumed to be the same. michael@0: */ michael@0: void UpdateContents(Layer* aLayer, LayerState aState, michael@0: uint32_t aContainerLayerGeneration, nsDisplayItem* aItem = nullptr); michael@0: michael@0: LayerManagerData* mParent; michael@0: nsRefPtr mLayer; michael@0: nsRefPtr mOptLayer; michael@0: nsRefPtr mInactiveManager; michael@0: nsAutoTArray mFrameList; michael@0: nsAutoPtr mGeometry; michael@0: DisplayItemClip mClip; michael@0: uint32_t mDisplayItemKey; michael@0: uint32_t mContainerLayerGeneration; michael@0: LayerState mLayerState; michael@0: michael@0: /** michael@0: * Used to track if data currently stored in mFramesWithLayers (from an existing michael@0: * paint) has been updated in the current paint. michael@0: */ michael@0: bool mUsed; michael@0: bool mIsInvalid; michael@0: }; michael@0: michael@0: protected: michael@0: michael@0: friend class LayerManagerData; michael@0: michael@0: static void RemoveFrameFromLayerManager(nsIFrame* aFrame, void* aPropertyValue); michael@0: michael@0: /** michael@0: * Given a frame and a display item key that uniquely identifies a michael@0: * display item for the frame, find the layer that was last used to michael@0: * render that display item. Returns null if there is no such layer. michael@0: * This could be a dedicated layer for the display item, or a ThebesLayer michael@0: * that renders many display items. michael@0: */ michael@0: DisplayItemData* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey); michael@0: michael@0: /** michael@0: * Stores DisplayItemData associated with aFrame, stores the data in michael@0: * mNewDisplayItemData. michael@0: */ michael@0: DisplayItemData* StoreDataForFrame(nsDisplayItem* aItem, Layer* aLayer, LayerState aState); michael@0: void StoreDataForFrame(nsIFrame* aFrame, michael@0: uint32_t aDisplayItemKey, michael@0: Layer* aLayer, michael@0: LayerState aState); michael@0: michael@0: // Flash the area within the context clip if paint flashing is enabled. michael@0: static void FlashPaint(gfxContext *aContext); michael@0: michael@0: /* michael@0: * Get the DisplayItemData array associated with this frame, or null if one michael@0: * doesn't exist. michael@0: * michael@0: * Note that the pointer returned here is only valid so long as you don't michael@0: * poke the LayerManagerData's mFramesWithLayers hashtable. michael@0: */ michael@0: DisplayItemData* GetDisplayItemData(nsIFrame *aFrame, uint32_t aKey); michael@0: michael@0: /* michael@0: * Get the DisplayItemData associated with this frame / display item pair, michael@0: * using the LayerManager instead of FrameLayerBuilder. michael@0: */ michael@0: static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, michael@0: uint32_t aDisplayItemKey, michael@0: LayerManager* aManager); michael@0: static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, michael@0: uint32_t aDisplayItemKey); michael@0: static DisplayItemData* GetDisplayItemDataForManager(nsDisplayItem* aItem, LayerManager* aManager); michael@0: static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, michael@0: uint32_t aDisplayItemKey, michael@0: LayerManagerData* aData); michael@0: michael@0: static PLDHashOperator DumpDisplayItemDataForFrame(nsRefPtrHashKey* aEntry, michael@0: void* aClosure); michael@0: /** michael@0: * We store one of these for each display item associated with a michael@0: * ThebesLayer, in a hashtable that maps each ThebesLayer to an array michael@0: * of ClippedDisplayItems. (ThebesLayerItemsEntry is the hash entry michael@0: * for that hashtable.) michael@0: * These are only stored during the paint process, so that the michael@0: * DrawThebesLayer callback can figure out which items to draw for the michael@0: * ThebesLayer. michael@0: */ michael@0: struct ClippedDisplayItem { michael@0: ClippedDisplayItem(nsDisplayItem* aItem, uint32_t aGeneration) michael@0: : mItem(aItem), mContainerLayerGeneration(aGeneration) michael@0: { michael@0: } michael@0: michael@0: ~ClippedDisplayItem(); michael@0: michael@0: nsDisplayItem* mItem; michael@0: michael@0: /** michael@0: * If the display item is being rendered as an inactive michael@0: * layer, then this stores the layer manager being michael@0: * used for the inactive transaction. michael@0: */ michael@0: nsRefPtr mInactiveLayerManager; michael@0: michael@0: uint32_t mContainerLayerGeneration; michael@0: }; michael@0: michael@0: static void RecomputeVisibilityForItems(nsTArray& aItems, michael@0: nsDisplayListBuilder* aBuilder, michael@0: const nsIntRegion& aRegionToDraw, michael@0: const nsIntPoint& aOffset, michael@0: int32_t aAppUnitsPerDevPixel, michael@0: float aXScale, michael@0: float aYScale); michael@0: michael@0: void PaintItems(nsTArray& aItems, michael@0: const nsIntRect& aRect, michael@0: gfxContext* aContext, michael@0: nsRenderingContext* aRC, michael@0: nsDisplayListBuilder* aBuilder, michael@0: nsPresContext* aPresContext, michael@0: const nsIntPoint& aOffset, michael@0: float aXScale, float aYScale, michael@0: int32_t aCommonClipCount); michael@0: michael@0: /** michael@0: * We accumulate ClippedDisplayItem elements in a hashtable during michael@0: * the paint process. This is the hashentry for that hashtable. michael@0: */ michael@0: public: michael@0: class ThebesLayerItemsEntry : public nsPtrHashKey { michael@0: public: michael@0: ThebesLayerItemsEntry(const ThebesLayer *key) : michael@0: nsPtrHashKey(key), mContainerLayerFrame(nullptr), michael@0: mContainerLayerGeneration(0), michael@0: mHasExplicitLastPaintOffset(false), mCommonClipCount(0) {} michael@0: ThebesLayerItemsEntry(const ThebesLayerItemsEntry &toCopy) : michael@0: nsPtrHashKey(toCopy.mKey), mItems(toCopy.mItems) michael@0: { michael@0: NS_ERROR("Should never be called, since we ALLOW_MEMMOVE"); michael@0: } michael@0: michael@0: nsTArray mItems; michael@0: nsIFrame* mContainerLayerFrame; michael@0: // The translation set on this ThebesLayer before we started updating the michael@0: // layer tree. michael@0: nsIntPoint mLastPaintOffset; michael@0: uint32_t mContainerLayerGeneration; michael@0: bool mHasExplicitLastPaintOffset; michael@0: /** michael@0: * The first mCommonClipCount rounded rectangle clips are identical for michael@0: * all items in the layer. Computed in ThebesLayerData. michael@0: */ michael@0: uint32_t mCommonClipCount; michael@0: michael@0: enum { ALLOW_MEMMOVE = true }; michael@0: }; michael@0: michael@0: /** michael@0: * Get the ThebesLayerItemsEntry object associated with aLayer in this michael@0: * FrameLayerBuilder michael@0: */ michael@0: ThebesLayerItemsEntry* GetThebesLayerItemsEntry(ThebesLayer* aLayer) michael@0: { michael@0: return mThebesLayerItems.GetEntry(aLayer); michael@0: } michael@0: michael@0: ThebesLayerData* GetContainingThebesLayerData() michael@0: { michael@0: return mContainingThebesLayer; michael@0: } michael@0: michael@0: /** michael@0: * Attempt to build the most compressed layer tree possible, even if it means michael@0: * throwing away existing retained buffers. michael@0: */ michael@0: void SetLayerTreeCompressionMode() { mInLayerTreeCompressionMode = true; } michael@0: bool CheckInLayerTreeCompressionMode(); michael@0: michael@0: protected: michael@0: void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer, michael@0: bool aRemoveThebesItems, michael@0: bool aRemoveOwnerData); michael@0: michael@0: static PLDHashOperator ProcessRemovedDisplayItems(nsRefPtrHashKey* aEntry, michael@0: void* aUserArg); michael@0: static PLDHashOperator RestoreDisplayItemData(nsRefPtrHashKey* aEntry, michael@0: void *aUserArg); michael@0: michael@0: static PLDHashOperator RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry, michael@0: void *aUserArg); michael@0: michael@0: /** michael@0: * Returns true if the DOM has been modified since we started painting, michael@0: * in which case we should bail out and not paint anymore. This should michael@0: * never happen, but plugins can trigger it in some cases. michael@0: */ michael@0: bool CheckDOMModified(); michael@0: michael@0: /** michael@0: * The layer manager belonging to the widget that is being retained michael@0: * across paints. michael@0: */ michael@0: LayerManager* mRetainingManager; michael@0: /** michael@0: * The root prescontext for the display list builder reference frame michael@0: */ michael@0: nsRefPtr mRootPresContext; michael@0: michael@0: /** michael@0: * The display list builder being used. michael@0: */ michael@0: nsDisplayListBuilder* mDisplayListBuilder; michael@0: /** michael@0: * A map from ThebesLayers to the list of display items (plus michael@0: * clipping data) to be rendered in the layer. michael@0: */ michael@0: nsTHashtable mThebesLayerItems; michael@0: michael@0: /** michael@0: * When building layers for an inactive layer, this is where the michael@0: * inactive layer will be placed. michael@0: */ michael@0: ThebesLayerData* mContainingThebesLayer; michael@0: michael@0: /** michael@0: * Saved generation counter so we can detect DOM changes. michael@0: */ michael@0: uint32_t mInitialDOMGeneration; michael@0: /** michael@0: * Set to true if we have detected and reported DOM modification during michael@0: * the current paint. michael@0: */ michael@0: bool mDetectedDOMModification; michael@0: /** michael@0: * Indicates that the entire layer tree should be rerendered michael@0: * during this paint. michael@0: */ michael@0: bool mInvalidateAllLayers; michael@0: michael@0: bool mInLayerTreeCompressionMode; michael@0: michael@0: uint32_t mContainerLayerGeneration; michael@0: uint32_t mMaxContainerLayerGeneration; michael@0: }; michael@0: michael@0: } michael@0: michael@0: #endif /* FRAMELAYERBUILDER_H_ */