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 "nsRegion.h"
#include "nsIFrame.h"
#include "nsDisplayListInvalidation.h"
class nsDisplayListBuilder;
class nsDisplayList;
@ -26,6 +27,7 @@ class ThebesLayer;
}
class FrameLayerBuilder;
class LayerManagerData;
enum LayerState {
LAYER_NONE,
@ -48,8 +50,9 @@ public:
};
/**
* The FrameLayerBuilder belongs to an nsDisplayListBuilder and is
* responsible for converting display lists into layer trees.
* 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
@ -120,18 +123,14 @@ public:
void DidBeginRetainedLayerTransaction(LayerManager* aManager);
/**
* Call this just before we end a transaction on aManager. If aManager
* is not the retained layer manager then it must be a temporary layer
* manager that will not be used again.
* Call this just before we end a transaction.
*/
void WillEndTransaction(LayerManager* aManager);
void WillEndTransaction();
/**
* Call this after we end a transaction on aManager. If aManager
* is not the retained layer manager then it must be a temporary layer
* manager that will not be used again.
* Call this after we end a transaction.
*/
void DidEndTransaction(LayerManager* aManager);
void DidEndTransaction();
struct ContainerParameters {
ContainerParameters() :
@ -212,33 +211,8 @@ public:
* region.
*/
Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
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
* the next paint.
@ -279,18 +253,18 @@ public:
/**
* 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,
nsDisplayItem* aItem,
LayerState aLayerState);
/**
* Record aFrame as a frame that is rendered by an item on aLayer.
*/
void AddLayerDisplayItemForFrame(Layer* aLayer,
nsIFrame* aFrame,
uint32_t aDisplayItemKey,
LayerState aLayerState);
LayerState aLayerState,
const nsPoint& aTopLeft,
LayerManager* aManager = nullptr);
/**
* Record aItem as a display item that is rendered by the ThebesLayer
@ -303,25 +277,25 @@ public:
nsDisplayItem* aItem,
const Clip& aClip,
nsIFrame* aContainerLayerFrame,
LayerState aLayerState);
/**
* 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);
LayerState aLayerState,
const nsPoint& aTopLeft);
/**
* 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);
Layer* GetOldLayerFor(nsDisplayItem* aItem, nsDisplayItemGeometry** aOldGeometry = 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.
@ -356,11 +330,15 @@ public:
* 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);
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.
*/
void SaveLastPaintOffset(ThebesLayer* aLayer);
@ -471,16 +449,48 @@ protected:
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<Layer> mLayer;
nsRefPtr<LayerManager> mInactiveManager;
nsAutoTArray<nsIFrame*, 2> mFrameList;
nsAutoPtr<nsDisplayItemGeometry> mGeometry;
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);
NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
RemoveFrameFromLayerManager)
@ -493,21 +503,23 @@ protected:
public:
DisplayItemDataEntry(const nsIFrame *key)
: nsPtrHashKey<nsIFrame>(key)
{}
{
MOZ_COUNT_CTOR(DisplayItemDataEntry);
}
DisplayItemDataEntry(DisplayItemDataEntry &toCopy)
: nsPtrHashKey<nsIFrame>(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);
mInvalidRegion.swap(toCopy.mInvalidRegion);
mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
}
~DisplayItemDataEntry() { MOZ_COUNT_DTOR(DisplayItemDataEntry); }
bool HasNonEmptyContainerLayer();
nsAutoTArray<DisplayItemData, 1> mData;
nsRefPtr<RefCountedRegion> mInvalidRegion;
nsAutoTArray<nsRefPtr<DisplayItemData>, 1> mData;
uint32_t mContainerLayerGeneration;
enum { ALLOW_MEMMOVE = false };
@ -516,6 +528,12 @@ protected:
// 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);
@ -526,7 +544,16 @@ protected:
* Note that the pointer returned here is only valid so long as you don't
* 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
@ -535,10 +562,7 @@ protected:
* aClosure is ignored.
*/
static PLDHashOperator RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
void* aClosure)
{
return UpdateDisplayItemDataForFrame(aEntry, nullptr);
}
void* aClosure);
/**
* We store one of these for each display item associated with a
@ -556,10 +580,19 @@ protected:
{
}
~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<LayerManager> mInactiveLayer;
Clip mClip;
uint32_t mContainerLayerGeneration;
bool mInactiveLayer;
};
/**
@ -604,6 +637,8 @@ public:
return mThebesLayerItems.GetEntry(aLayer);
}
static PLDHashOperator ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry,
void* aUserArg);
protected:
void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer,
bool aRemoveThebesItems,
@ -636,6 +671,11 @@ protected:
* 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.

View File

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

View File

@ -770,6 +770,12 @@ public:
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
* areas covered by this display item. These need to retain enough information
@ -1999,6 +2005,18 @@ public:
{
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)
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder);

View File

@ -40,17 +40,6 @@ public:
*/
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
*/

View File

@ -7978,14 +7978,6 @@ nsFrame::SetParent(nsIFrame* aParent)
} else {
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

View File

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

View File

@ -138,10 +138,6 @@ typedef uint64_t nsFrameState;
// continuation, e.g. a bidi continuation.
#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
// elsewhere. The frame may want to send a notification when it is
// 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.
#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.
#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.
r.Round();
nsRefPtr<Layer> layer =
(aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem));
(aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
if (!layer) {

View File

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

View File

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