Bug 539356 - Part 9e - FrameLayerBuilder changes for display list invalidation. r=roc

* * *
imported patch move-by-correctly
This commit is contained in:
Matt Woodrow 2012-08-29 17:47:15 +12:00
parent f49711f24b
commit 4e75c1edde
11 changed files with 918 additions and 761 deletions

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@
#include "nsTArray.h" #include "nsTArray.h"
#include "nsRegion.h" #include "nsRegion.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsDisplayListInvalidation.h"
class nsDisplayListBuilder; class nsDisplayListBuilder;
class nsDisplayList; class nsDisplayList;
@ -26,6 +27,7 @@ class ThebesLayer;
} }
class FrameLayerBuilder; class FrameLayerBuilder;
class LayerManagerData;
enum LayerState { enum LayerState {
LAYER_NONE, LAYER_NONE,
@ -48,8 +50,9 @@ public:
}; };
/** /**
* The FrameLayerBuilder belongs to an nsDisplayListBuilder and is * The FrameLayerBuilder is responsible for converting display lists
* responsible for converting display lists into layer trees. * into layer trees. Every LayerManager needs a unique FrameLayerBuilder
* to build layers.
* *
* The most important API in this class is BuildContainerLayerFor. This * The most important API in this class is BuildContainerLayerFor. This
* method takes a display list as input and constructs a ContainerLayer * method takes a display list as input and constructs a ContainerLayer
@ -120,18 +123,14 @@ public:
void DidBeginRetainedLayerTransaction(LayerManager* aManager); void DidBeginRetainedLayerTransaction(LayerManager* aManager);
/** /**
* Call this just before we end a transaction on aManager. If aManager * Call this just before we end a transaction.
* is not the retained layer manager then it must be a temporary layer
* manager that will not be used again.
*/ */
void WillEndTransaction(LayerManager* aManager); void WillEndTransaction();
/** /**
* Call this after we end a transaction on aManager. If aManager * Call this after we end a transaction.
* is not the retained layer manager then it must be a temporary layer
* manager that will not be used again.
*/ */
void DidEndTransaction(LayerManager* aManager); void DidEndTransaction();
struct ContainerParameters { struct ContainerParameters {
ContainerParameters() : ContainerParameters() :
@ -212,33 +211,8 @@ public:
* region. * region.
*/ */
Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder, Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
nsDisplayItem* aItem); nsDisplayItem* aItem);
/**
* Call this during invalidation if aFrame has
* the NS_FRAME_HAS_CONTAINER_LAYER state bit. Only the nearest
* ancestor frame of the damaged frame that has
* NS_FRAME_HAS_CONTAINER_LAYER needs to be invalidated this way.
* It is assumed that aRect does NOT have the frame's transforms applied.
*/
static void InvalidateThebesLayerContents(nsIFrame* aFrame,
const nsRect& aRect);
/**
* For any descendant frame of aFrame (including across documents) that
* has an associated container layer, invalidate all the contents of
* all ThebesLayer children of the container. Useful when aFrame is
* being moved and we need to invalidate everything in aFrame's subtree.
*/
static void InvalidateThebesLayersInSubtree(nsIFrame* aFrame);
/**
* As InvalidateThebesLayersInSubtree, but don't trust frame geometry
* (e.g. because appunits-per-dev-pixel changed).
*/
static void InvalidateThebesLayersInSubtreeWithUntrustedFrameGeometry(nsIFrame* aFrame);
/** /**
* Call this to force all retained layers to be discarded and recreated at * Call this to force all retained layers to be discarded and recreated at
* the next paint. * the next paint.
@ -279,18 +253,18 @@ public:
/** /**
* Record aItem as a display item that is rendered by aLayer. * 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.
*/ */
void AddLayerDisplayItem(Layer* aLayer, void AddLayerDisplayItem(Layer* aLayer,
nsDisplayItem* aItem, nsDisplayItem* aItem,
LayerState aLayerState); LayerState aLayerState,
const nsPoint& aTopLeft,
/** LayerManager* aManager = nullptr);
* Record aFrame as a frame that is rendered by an item on aLayer.
*/
void AddLayerDisplayItemForFrame(Layer* aLayer,
nsIFrame* aFrame,
uint32_t aDisplayItemKey,
LayerState aLayerState);
/** /**
* Record aItem as a display item that is rendered by the ThebesLayer * Record aItem as a display item that is rendered by the ThebesLayer
@ -303,25 +277,25 @@ public:
nsDisplayItem* aItem, nsDisplayItem* aItem,
const Clip& aClip, const Clip& aClip,
nsIFrame* aContainerLayerFrame, nsIFrame* aContainerLayerFrame,
LayerState aLayerState); LayerState aLayerState,
const nsPoint& aTopLeft);
/**
* 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.
*/
Layer* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey);
/** /**
* Calls GetOldLayerForFrame on the underlying frame of the display item, * Calls GetOldLayerForFrame on the underlying frame of the display item,
* and each subsequent merged frame if no layer is found for the underlying * and each subsequent merged frame if no layer is found for the underlying
* frame. * frame.
*/ */
Layer* GetOldLayerFor(nsDisplayItem* aItem); Layer* GetOldLayerFor(nsDisplayItem* aItem, nsDisplayItemGeometry** aOldGeometry = nullptr);
static Layer* GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey); 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 * Try to determine whether the ThebesLayer aLayer paints an opaque
* single color everywhere it's visible in aRect. * single color everywhere it's visible in aRect.
@ -356,11 +330,15 @@ public:
* into a retained layer. * into a retained layer.
* Returns false if it was rendered into a temporary layer manager and then * Returns false if it was rendered into a temporary layer manager and then
* into a retained layer. * 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); static bool HasRetainedLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey, LayerManager* aManager);
/** /**
* Save transform that was in aLayer when we last painted. It must be an integer * 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. * translation.
*/ */
void SaveLastPaintOffset(ThebesLayer* aLayer); void SaveLastPaintOffset(ThebesLayer* aLayer);
@ -471,16 +449,48 @@ protected:
class DisplayItemData { class DisplayItemData {
public: public:
DisplayItemData(Layer* aLayer, uint32_t aKey, LayerState aLayerState, uint32_t aGeneration); DisplayItemData(Layer* aLayer, uint32_t aKey, LayerState aLayerState, uint32_t aGeneration);
DisplayItemData()
: mUsed(false)
{}
DisplayItemData(DisplayItemData &toCopy);
~DisplayItemData(); ~DisplayItemData();
NS_INLINE_DECL_REFCOUNTING(DisplayItemData)
void AddFrame(nsIFrame* aFrame)
{
mFrameList.AppendElement(aFrame);
}
bool FrameListMatches(nsDisplayItem* aOther);
nsRefPtr<Layer> mLayer; nsRefPtr<Layer> mLayer;
nsRefPtr<LayerManager> mInactiveManager;
nsAutoTArray<nsIFrame*, 2> mFrameList;
nsAutoPtr<nsDisplayItemGeometry> mGeometry;
uint32_t mDisplayItemKey; uint32_t mDisplayItemKey;
uint32_t mContainerLayerGeneration; uint32_t mContainerLayerGeneration;
LayerState mLayerState; 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); 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);
NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty, NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
RemoveFrameFromLayerManager) RemoveFrameFromLayerManager)
@ -493,21 +503,23 @@ protected:
public: public:
DisplayItemDataEntry(const nsIFrame *key) DisplayItemDataEntry(const nsIFrame *key)
: nsPtrHashKey<nsIFrame>(key) : nsPtrHashKey<nsIFrame>(key)
{} {
MOZ_COUNT_CTOR(DisplayItemDataEntry);
}
DisplayItemDataEntry(DisplayItemDataEntry &toCopy) DisplayItemDataEntry(DisplayItemDataEntry &toCopy)
: nsPtrHashKey<nsIFrame>(toCopy.mKey) : nsPtrHashKey<nsIFrame>(toCopy.mKey)
{ {
MOZ_COUNT_CTOR(DisplayItemDataEntry);
// This isn't actually a copy-constructor; notice that it steals toCopy's // This isn't actually a copy-constructor; notice that it steals toCopy's
// array and invalid region. Be careful. // array and invalid region. Be careful.
mData.SwapElements(toCopy.mData); mData.SwapElements(toCopy.mData);
mInvalidRegion.swap(toCopy.mInvalidRegion);
mContainerLayerGeneration = toCopy.mContainerLayerGeneration; mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
} }
~DisplayItemDataEntry() { MOZ_COUNT_DTOR(DisplayItemDataEntry); }
bool HasNonEmptyContainerLayer(); bool HasNonEmptyContainerLayer();
nsAutoTArray<DisplayItemData, 1> mData; nsAutoTArray<nsRefPtr<DisplayItemData>, 1> mData;
nsRefPtr<RefCountedRegion> mInvalidRegion;
uint32_t mContainerLayerGeneration; uint32_t mContainerLayerGeneration;
enum { ALLOW_MEMMOVE = false }; enum { ALLOW_MEMMOVE = false };
@ -516,6 +528,12 @@ protected:
// LayerManagerData needs to see DisplayItemDataEntry. // LayerManagerData needs to see DisplayItemDataEntry.
friend class LayerManagerData; 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. // Flash the area within the context clip if paint flashing is enabled.
static void FlashPaint(gfxContext *aContext); static void FlashPaint(gfxContext *aContext);
@ -526,7 +544,16 @@ protected:
* Note that the pointer returned here is only valid so long as you don't * Note that the pointer returned here is only valid so long as you don't
* poke the LayerManagerData's mFramesWithLayers hashtable. * poke the LayerManagerData's mFramesWithLayers hashtable.
*/ */
static nsTArray<DisplayItemData>* GetDisplayItemDataArrayForFrame(nsIFrame *aFrame); nsTArray<nsRefPtr<DisplayItemData> >* 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(nsDisplayItem* aItem, LayerManager* aManager);
/** /**
* A useful hashtable iteration function that removes the * A useful hashtable iteration function that removes the
@ -535,10 +562,7 @@ protected:
* aClosure is ignored. * aClosure is ignored.
*/ */
static PLDHashOperator RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry, static PLDHashOperator RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
void* aClosure) void* aClosure);
{
return UpdateDisplayItemDataForFrame(aEntry, nullptr);
}
/** /**
* We store one of these for each display item associated with a * We store one of these for each display item associated with a
@ -556,10 +580,19 @@ protected:
{ {
} }
~ClippedDisplayItem();
nsDisplayItem* mItem; 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<LayerManager> mInactiveLayer;
Clip mClip; Clip mClip;
uint32_t mContainerLayerGeneration; uint32_t mContainerLayerGeneration;
bool mInactiveLayer;
}; };
/** /**
@ -604,6 +637,8 @@ public:
return mThebesLayerItems.GetEntry(aLayer); return mThebesLayerItems.GetEntry(aLayer);
} }
static PLDHashOperator ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry,
void* aUserArg);
protected: protected:
void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer, void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer,
bool aRemoveThebesItems, bool aRemoveThebesItems,
@ -636,6 +671,11 @@ protected:
* The root prescontext for the display list builder reference frame * The root prescontext for the display list builder reference frame
*/ */
nsRootPresContext* mRootPresContext; nsRootPresContext* mRootPresContext;
/**
* The display list builder being used.
*/
nsDisplayListBuilder* mDisplayListBuilder;
/** /**
* A map from frames to a list of (display item key, layer) pairs that * 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. * describes what layers various parts of the frame are assigned to.

View File

@ -1064,12 +1064,12 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
} }
layerManager->SetRoot(root); layerManager->SetRoot(root);
layerBuilder->WillEndTransaction(layerManager); layerBuilder->WillEndTransaction();
bool temp = aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap()); bool temp = aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer,
aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT); aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT);
aBuilder->SetIsCompositingCheap(temp); aBuilder->SetIsCompositingCheap(temp);
layerBuilder->DidEndTransaction(layerManager); layerBuilder->DidEndTransaction();
if (aFlags & PAINT_FLUSH_LAYERS) { if (aFlags & PAINT_FLUSH_LAYERS) {
FrameLayerBuilder::InvalidateAllLayers(layerManager); FrameLayerBuilder::InvalidateAllLayers(layerManager);

View File

@ -770,6 +770,12 @@ public:
return GetUnderlyingFrame()->GetContentRectRelativeToSelf() + ToReferenceFrame(); return GetUnderlyingFrame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
} }
/**
* Checks if the frame(s) owning this display item have been marked as invalid,
* and needing repainting.
*/
virtual bool IsInvalid() { return mFrame ? mFrame->IsInvalid() : false; }
/** /**
* Creates and initializes an nsDisplayItemGeometry object that retains the current * Creates and initializes an nsDisplayItemGeometry object that retains the current
* areas covered by this display item. These need to retain enough information * areas covered by this display item. These need to retain enough information
@ -1999,6 +2005,18 @@ public:
{ {
aFrames->AppendElements(mMergedFrames); aFrames->AppendElements(mMergedFrames);
} }
virtual bool IsInvalid()
{
if (mFrame->IsInvalid()) {
return true;
}
for (uint32_t i = 0; i < mMergedFrames.Length(); i++) {
if (mMergedFrames[i]->IsInvalid()) {
return true;
}
}
return false;
}
NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST) NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder); virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder);

View File

@ -40,17 +40,6 @@ public:
*/ */
virtual void MoveBy(const nsPoint& aOffset) = 0; virtual void MoveBy(const nsPoint& aOffset) = 0;
/**
* The appunits per dev pixel for the item's frame.
*/
nscoord mAppUnitsPerDevPixel;
/**
* The offset (in pixels) of the TopLeft() of the ThebesLayer
* this display item was drawn into.
*/
nsIntPoint mPaintOffset;
/** /**
* Bounds of the display item * Bounds of the display item
*/ */

View File

@ -7978,14 +7978,6 @@ nsFrame::SetParent(nsIFrame* aParent)
} else { } else {
RemoveInPopupStateBitFromDescendants(this); RemoveInPopupStateBitFromDescendants(this);
} }
if (GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT) {
for (nsIFrame* f = aParent;
f && !(f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
f->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
}
}
} }
void void

View File

@ -264,7 +264,7 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
return nullptr; return nullptr;
CanvasLayer* oldLayer = static_cast<CanvasLayer*> CanvasLayer* oldLayer = static_cast<CanvasLayer*>
(aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem)); (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
nsRefPtr<CanvasLayer> layer = element->GetCanvasLayer(aBuilder, oldLayer, aManager); nsRefPtr<CanvasLayer> layer = element->GetCanvasLayer(aBuilder, oldLayer, aManager);
if (!layer) if (!layer)
return nullptr; return nullptr;

View File

@ -138,10 +138,6 @@ typedef uint64_t nsFrameState;
// continuation, e.g. a bidi continuation. // continuation, e.g. a bidi continuation.
#define NS_FRAME_IS_FLUID_CONTINUATION NS_FRAME_STATE_BIT(2) #define NS_FRAME_IS_FLUID_CONTINUATION NS_FRAME_STATE_BIT(2)
// This bit is set whenever the frame has one or more associated
// container layers.
#define NS_FRAME_HAS_CONTAINER_LAYER NS_FRAME_STATE_BIT(3)
// If this bit is set, then a reference to the frame is being held // If this bit is set, then a reference to the frame is being held
// elsewhere. The frame may want to send a notification when it is // elsewhere. The frame may want to send a notification when it is
// destroyed to allow these references to be cleared. // destroyed to allow these references to be cleared.
@ -253,10 +249,6 @@ typedef uint64_t nsFrameState;
// This bit acts as a loop flag for recursive paint server drawing. // This bit acts as a loop flag for recursive paint server drawing.
#define NS_FRAME_DRAWING_AS_PAINTSERVER NS_FRAME_STATE_BIT(33) #define NS_FRAME_DRAWING_AS_PAINTSERVER NS_FRAME_STATE_BIT(33)
// Frame or one of its (cross-doc) descendants may have the
// NS_FRAME_HAS_CONTAINER_LAYER bit.
#define NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT NS_FRAME_STATE_BIT(34)
// Frame's overflow area was clipped by the 'clip' property. // Frame's overflow area was clipped by the 'clip' property.
#define NS_FRAME_HAS_CLIP NS_FRAME_STATE_BIT(35) #define NS_FRAME_HAS_CLIP NS_FRAME_STATE_BIT(35)

View File

@ -1638,7 +1638,7 @@ nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
// to provide crisper and faster drawing. // to provide crisper and faster drawing.
r.Round(); r.Round();
nsRefPtr<Layer> layer = nsRefPtr<Layer> layer =
(aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem)); (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) { if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
if (!layer) { if (!layer) {

View File

@ -196,7 +196,7 @@ nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
container->SetScaleHint(scaleHint); container->SetScaleHint(scaleHint);
nsRefPtr<ImageLayer> layer = static_cast<ImageLayer*> nsRefPtr<ImageLayer> layer = static_cast<ImageLayer*>
(aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem)); (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
if (!layer) { if (!layer) {
layer = aManager->CreateImageLayer(); layer = aManager->CreateImageLayer();
if (!layer) if (!layer)

View File

@ -646,7 +646,7 @@ RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
MOZ_ASSERT(!GetRootLayer()); MOZ_ASSERT(!GetRootLayer());
nsRefPtr<Layer> layer = nsRefPtr<Layer> layer =
(aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem)); (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
if (!layer) { if (!layer) {
layer = aManager->CreateRefLayer(); layer = aManager->CreateRefLayer();
} }