Back out changeset 153237ff0f46 (bug 688619) due to some late-breaking comments.

--HG--
extra : rebase_source : d422ab65b4f73b1eb13b05db4b03d83b1b803c69
This commit is contained in:
Justin Lebar 2011-10-05 21:01:49 -04:00
parent 22132081c6
commit 0cdb327f71
2 changed files with 100 additions and 81 deletions

View File

@ -57,6 +57,8 @@ using namespace mozilla::layers;
namespace mozilla {
namespace {
/**
* This is the userdata we associate with a layer manager.
*/
@ -80,14 +82,12 @@ public:
/**
* Tracks which frames have layers associated with them.
*/
nsTHashtable<FrameLayerBuilder::DisplayItemDataEntry> mFramesWithLayers;
nsTHashtable<nsPtrHashKey<nsIFrame> > mFramesWithLayers;
bool mInvalidateAllLayers;
/** Layer manager we belong to, we hold a reference to this object. */
nsRefPtr<LayerManager> mLayerManager;
};
namespace {
static void DestroyRegion(void* aPropertyValue)
{
delete static_cast<nsRegion*>(aPropertyValue);
@ -470,40 +470,39 @@ FrameLayerBuilder::DisplayItemDataEntry::HasNonEmptyContainerLayer()
return PR_FALSE;
}
/* static */ nsTArray<FrameLayerBuilder::DisplayItemData>*
FrameLayerBuilder::GetDisplayItemDataArrayForFrame(nsIFrame* aFrame)
/* static */ void
FrameLayerBuilder::InternalDestroyDisplayItemData(nsIFrame* aFrame,
void* aPropertyValue,
bool aRemoveFromFramesWithLayers)
{
FrameProperties props = aFrame->Properties();
LayerManager *manager =
reinterpret_cast<LayerManager*>(props.Get(LayerManagerProperty()));
if (!manager)
return nsnull;
nsRefPtr<LayerManager> managerRef;
nsTArray<DisplayItemData>* array =
reinterpret_cast<nsTArray<DisplayItemData>*>(&aPropertyValue);
NS_ASSERTION(!array->IsEmpty(), "Empty arrays should not be stored");
LayerManagerData *data = static_cast<LayerManagerData*>
(manager->GetUserData(&gLayerManagerUserData));
NS_ASSERTION(data, "out of sync?");
if (!data)
return nsnull;
if (aRemoveFromFramesWithLayers) {
LayerManager* manager = array->ElementAt(0).mLayer->Manager();
LayerManagerData* data = static_cast<LayerManagerData*>
(manager->GetUserData(&gLayerManagerUserData));
NS_ASSERTION(data, "Frame with layer should have been recorded");
data->mFramesWithLayers.RemoveEntry(aFrame);
if (data->mFramesWithLayers.Count() == 0) {
// Destroying our user data will consume a reference from the layer
// manager. But don't actually release until we've released all the layers
// in the DisplayItemData array below!
managerRef = manager;
manager->RemoveUserData(&gLayerManagerUserData);
}
}
DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
NS_ASSERTION(entry, "out of sync?");
if (!entry)
return nsnull;
return &entry->mData;
array->~nsTArray<DisplayItemData>();
}
/* static */ void
FrameLayerBuilder::RemoveFrameFromLayerManager(nsIFrame* aFrame,
void* aPropertyValue)
FrameLayerBuilder::DestroyDisplayItemData(nsIFrame* aFrame,
void* aPropertyValue)
{
LayerManager *manager = reinterpret_cast<LayerManager*>(aPropertyValue);
LayerManagerData *data = static_cast<LayerManagerData*>
(manager->GetUserData(&gLayerManagerUserData));
data->mFramesWithLayers.RemoveEntry(aFrame);
if (data->mFramesWithLayers.Count() == 0) {
manager->RemoveUserData(&gLayerManagerUserData);
}
InternalDestroyDisplayItemData(aFrame, aPropertyValue, PR_TRUE);
}
void
@ -607,7 +606,7 @@ SetNoContainerLayer(nsIFrame* aFrame)
}
/* static */ PLDHashOperator
FrameLayerBuilder::UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
FrameLayerBuilder::UpdateDisplayItemDataForFrame(nsPtrHashKey<nsIFrame>* aEntry,
void* aUserArg)
{
FrameLayerBuilder* builder = static_cast<FrameLayerBuilder*>(aUserArg);
@ -618,8 +617,16 @@ FrameLayerBuilder::UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
if (!newDisplayItems) {
// This frame was visible, but isn't anymore.
bool found;
props.Remove(LayerManagerProperty(), &found);
void* prop = props.Remove(DisplayItemDataProperty(), &found);
NS_ASSERTION(found, "How can the frame property be missing?");
// Pass PR_FALSE to not remove from mFramesWithLayers, we'll remove it
// by returning PL_DHASH_REMOVE below.
// Note that DestroyDisplayItemData would delete the user data
// for the retained layer manager if it removed the last entry from
// mFramesWithLayers, but we won't. That's OK because our caller
// is DidEndTransaction, which would recreate the user data
// anyway.
InternalDestroyDisplayItemData(f, prop, PR_FALSE);
SetNoContainerLayer(f);
return PL_DHASH_REMOVE;
}
@ -640,8 +647,16 @@ FrameLayerBuilder::UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
SetNoContainerLayer(f);
}
// We need to remove and re-add the DisplayItemDataProperty in
// case the nsTArray changes the value of its mHdr.
void* propValue = props.Remove(DisplayItemDataProperty());
NS_ASSERTION(propValue, "mFramesWithLayers out of sync");
PR_STATIC_ASSERT(sizeof(nsTArray<DisplayItemData>) == sizeof(void*));
nsTArray<DisplayItemData>* array =
reinterpret_cast<nsTArray<DisplayItemData>*>(&propValue);
// Steal the list of display item layers
aEntry->mData.SwapElements(newDisplayItems->mData);
array->SwapElements(newDisplayItems->mData);
props.Set(DisplayItemDataProperty(), propValue);
// Don't need to process this frame again
builder->mNewDisplayItemData.RawRemoveEntry(newDisplayItems);
return PL_DHASH_NEXT;
@ -657,12 +672,17 @@ FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
// Remember that this frame has display items in retained layers
NS_ASSERTION(!data->mFramesWithLayers.GetEntry(f),
"We shouldn't get here if we're already in mFramesWithLayers");
DisplayItemDataEntry *newEntry = data->mFramesWithLayers.PutEntry(f);
NS_ASSERTION(!props.Get(LayerManagerProperty()),
data->mFramesWithLayers.PutEntry(f);
NS_ASSERTION(!props.Get(DisplayItemDataProperty()),
"mFramesWithLayers out of sync");
newEntry->mData.SwapElements(aEntry->mData);
props.Set(LayerManagerProperty(), data->mLayerManager);
void* propValue;
nsTArray<DisplayItemData>* array =
new (&propValue) nsTArray<DisplayItemData>();
// Steal the list of display item layers
array->SwapElements(aEntry->mData);
// Save it
props.Set(DisplayItemDataProperty(), propValue);
if (f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) {
props.Set(ThebesLayerInvalidRegionProperty(), new nsRegion());
@ -673,10 +693,12 @@ FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
bool
FrameLayerBuilder::HasRetainedLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
{
nsTArray<DisplayItemData> *array = GetDisplayItemDataArrayForFrame(aFrame);
if (!array)
void* propValue = aFrame->Properties().Get(DisplayItemDataProperty());
if (!propValue)
return PR_FALSE;
nsTArray<DisplayItemData>* array =
(reinterpret_cast<nsTArray<DisplayItemData>*>(&propValue));
for (PRUint32 i = 0; i < array->Length(); ++i) {
if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
Layer* layer = array->ElementAt(i).mLayer;
@ -697,10 +719,12 @@ FrameLayerBuilder::GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
if (!mRetainingManager || mInvalidateAllLayers)
return nsnull;
nsTArray<DisplayItemData> *array = GetDisplayItemDataArrayForFrame(aFrame);
if (!array)
void* propValue = aFrame->Properties().Get(DisplayItemDataProperty());
if (!propValue)
return nsnull;
nsTArray<DisplayItemData>* array =
(reinterpret_cast<nsTArray<DisplayItemData>*>(&propValue));
for (PRUint32 i = 0; i < array->Length(); ++i) {
if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
Layer* layer = array->ElementAt(i).mLayer;
@ -1930,10 +1954,12 @@ FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
Layer*
FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
{
nsTArray<DisplayItemData>* array = GetDisplayItemDataArrayForFrame(aFrame);
if (!array)
void* propValue = aFrame->Properties().Get(DisplayItemDataProperty());
if (!propValue)
return nsnull;
nsTArray<DisplayItemData>* array =
(reinterpret_cast<nsTArray<DisplayItemData>*>(&propValue));
for (PRUint32 i = 0; i < array->Length(); ++i) {
if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
Layer* layer = array->ElementAt(i).mLayer;

View File

@ -279,6 +279,18 @@ public:
*/
Layer* GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
/**
* 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(nsPtrHashKey<nsIFrame>* aEntry,
void* aClosure)
{
return UpdateDisplayItemDataForFrame(aEntry, nsnull);
}
/**
* Try to determine whether the ThebesLayer aLayer paints an opaque
* single color everywhere it's visible in aRect.
@ -288,12 +300,11 @@ public:
ThebesLayer* aLayer, const nsRect& aRect);
/**
* Destroy any stored LayerManagerProperty and the associated data for
* aFrame.
* Destroy any stored DisplayItemDataProperty for aFrame.
*/
static void DestroyDisplayItemDataFor(nsIFrame* aFrame)
{
aFrame->Properties().Delete(LayerManagerProperty());
aFrame->Properties().Delete(DisplayItemDataProperty());
}
LayerManager* GetRetainingLayerManager() { return mRetainingManager; }
@ -410,10 +421,18 @@ protected:
LayerState mLayerState;
};
static void RemoveFrameFromLayerManager(nsIFrame* aFrame, void* aPropertyValue);
static void InternalDestroyDisplayItemData(nsIFrame* aFrame,
void* aPropertyValue,
bool aRemoveFromFramesWithLayers);
static void DestroyDisplayItemData(nsIFrame* aFrame, void* aPropertyValue);
NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerProperty,
RemoveFrameFromLayerManager)
/**
* For DisplayItemDataProperty, the property value *is* an
* nsTArray<DisplayItemData>, not a pointer to an array. This works
* because sizeof(nsTArray<T>) == sizeof(void*).
*/
NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(DisplayItemDataProperty,
DestroyDisplayItemData)
/**
* We accumulate DisplayItemData elements in a hashtable during
@ -423,45 +442,19 @@ protected:
class DisplayItemDataEntry : public nsPtrHashKey<nsIFrame> {
public:
DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey<nsIFrame>(key) {}
DisplayItemDataEntry(DisplayItemDataEntry &toCopy) :
nsPtrHashKey<nsIFrame>(toCopy.mKey)
DisplayItemDataEntry(const DisplayItemDataEntry &toCopy) :
nsPtrHashKey<nsIFrame>(toCopy.mKey), mData(toCopy.mData)
{
// This isn't actually a copy-constructor; notice that it steals toCopy's
// array. Be careful.
mData.SwapElements(toCopy.mData);
NS_ERROR("Should never be called, since we ALLOW_MEMMOVE");
}
bool HasNonEmptyContainerLayer();
nsAutoTArray<DisplayItemData, 1> mData;
nsTArray<DisplayItemData> mData;
enum { ALLOW_MEMMOVE = false };
enum { ALLOW_MEMMOVE = PR_TRUE };
};
// LayerManagerData needs to see DisplayItemDataEntry.
friend class LayerManagerData;
/*
* 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.
*/
static nsTArray<DisplayItemData>* GetDisplayItemDataArrayForFrame(nsIFrame *aFrame);
/**
* 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)
{
return UpdateDisplayItemDataForFrame(aEntry, nsnull);
}
/**
* We store one of these for each display item associated with a
* ThebesLayer, in a hashtable that maps each ThebesLayer to an array
@ -510,7 +503,7 @@ protected:
void RemoveThebesItemsForLayerSubtree(Layer* aLayer);
static PLDHashOperator UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
static PLDHashOperator UpdateDisplayItemDataForFrame(nsPtrHashKey<nsIFrame>* aEntry,
void* aUserArg);
static PLDHashOperator StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
void* aUserArg);