Bug 579276. Part 1: Change layer/layermanager user data API to use keys and values. r=cjones,sr=vlad

This commit is contained in:
Robert O'Callahan 2010-09-02 21:18:39 +12:00
Родитель b505f86231
Коммит c649008789
4 изменённых файлов: 140 добавлений и 40 удалений

Просмотреть файл

@ -514,7 +514,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (!mResetLayer && aOldLayer &&
aOldLayer->GetUserData() == &gWebGLLayerUserData) {
aOldLayer->HasUserData(&gWebGLLayerUserData)) {
NS_ADDREF(aOldLayer);
if (mInvalidated) {
aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
@ -528,7 +528,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
NS_WARNING("CreateCanvasLayer returned null!");
return nsnull;
}
canvasLayer->SetUserData(&gWebGLLayerUserData);
canvasLayer->SetUserData(&gWebGLLayerUserData, nsnull);
CanvasLayer::Data data;

Просмотреть файл

@ -4154,7 +4154,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer,
return nsnull;
if (!mResetLayer && aOldLayer &&
aOldLayer->GetUserData() == &g2DContextLayerUserData) {
aOldLayer->HasUserData(&g2DContextLayerUserData)) {
NS_ADDREF(aOldLayer);
// XXX Need to just update the changed area here
aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
@ -4166,7 +4166,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer,
NS_WARNING("CreateCanvasLayer returned null!");
return nsnull;
}
canvasLayer->SetUserData(&g2DContextLayerUserData);
canvasLayer->SetUserData(&g2DContextLayerUserData, nsnull);
CanvasLayer::Data data;

Просмотреть файл

@ -83,6 +83,14 @@ class SpecificLayerAttributes;
virtual const char* Name() const { return n; } \
virtual LayerType GetType() const { return e; }
/**
* Base class for userdata objects attached to layers and layer managers.
*/
class THEBES_API LayerUserData {
public:
virtual ~LayerUserData() {}
};
/*
* Motivation: For truly smooth animation and video playback, we need to
* be able to compose frames and render them on a dedicated thread (i.e.
@ -109,6 +117,52 @@ class SpecificLayerAttributes;
* BasicLayerManager for such an implementation.
*/
/**
* Helper class to manage user data for layers and LayerManagers.
*/
class THEBES_API LayerUserDataSet {
public:
LayerUserDataSet() : mKey(nsnull) {}
void Set(void* aKey, LayerUserData* aValue)
{
NS_ASSERTION(!mKey || mKey == aKey,
"Multiple LayerUserData objects not supported");
mKey = aKey;
mValue = aValue;
}
/**
* This can be used anytime. Ownership passes to the caller!
*/
LayerUserData* Remove(void* aKey)
{
if (mKey == aKey) {
mKey = nsnull;
LayerUserData* d = mValue.forget();
return d;
}
return nsnull;
}
/**
* This getter can be used anytime.
*/
PRBool Has(void* aKey)
{
return mKey == aKey;
}
/**
* This getter can be used anytime. Ownership is retained by this object.
*/
LayerUserData* Get(void* aKey)
{
return mKey == aKey ? mValue.get() : nsnull;
}
private:
void* mKey;
nsAutoPtr<LayerUserData> mValue;
};
/**
* A LayerManager controls a tree of layers. All layers in the tree
* must use the same LayerManager.
@ -142,7 +196,7 @@ public:
LAYERS_D3D9
};
LayerManager() : mUserData(nsnull), mDestroyed(PR_FALSE)
LayerManager() : mDestroyed(PR_FALSE)
{
InitLog();
}
@ -267,10 +321,28 @@ public:
*/
virtual LayersBackend GetBackendType() = 0;
// This setter and getter can be used anytime. The user data is initially
// null.
void SetUserData(void* aData) { mUserData = aData; }
void* GetUserData() { return mUserData; }
/**
* This setter can be used anytime. The user data for all keys is
* initially null. Ownership pases to the layer manager.
*/
void SetUserData(void* aKey, LayerUserData* aData)
{ mUserData.Set(aKey, aData); }
/**
* This can be used anytime. Ownership passes to the caller!
*/
nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
{ nsAutoPtr<LayerUserData> d(mUserData.Remove(aKey)); return d; }
/**
* This getter can be used anytime.
*/
PRBool HasUserData(void* aKey)
{ return mUserData.Has(aKey); }
/**
* This getter can be used anytime. Ownership is retained by the layer
* manager.
*/
LayerUserData* GetUserData(void* aKey)
{ return mUserData.Get(aKey); }
// We always declare the following logging symbols, because it's
// extremely tricky to conditionally declare them. However, for
@ -305,7 +377,7 @@ public:
protected:
nsRefPtr<Layer> mRoot;
void* mUserData;
LayerUserDataSet mUserData;
PRPackedBool mDestroyed;
// Print interesting information about this into aTo. Internally
@ -460,10 +532,28 @@ public:
// quality.
PRBool CanUseOpaqueSurface();
// This setter and getter can be used anytime. The user data is initially
// null.
void SetUserData(void* aData) { mUserData = aData; }
void* GetUserData() { return mUserData; }
/**
* This setter can be used anytime. The user data for all keys is
* initially null. Ownership pases to the layer manager.
*/
void SetUserData(void* aKey, LayerUserData* aData)
{ mUserData.Set(aKey, aData); }
/**
* This can be used anytime. Ownership passes to the caller!
*/
nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
{ nsAutoPtr<LayerUserData> d(mUserData.Remove(aKey)); return d; }
/**
* This getter can be used anytime.
*/
PRBool HasUserData(void* aKey)
{ return mUserData.Has(aKey); }
/**
* This getter can be used anytime. Ownership is retained by the layer
* manager.
*/
LayerUserData* GetUserData(void* aKey)
{ return mUserData.Get(aKey); }
/**
* Dynamic downcast to a Thebes layer. Returns null if this is not
@ -519,7 +609,6 @@ protected:
mNextSibling(nsnull),
mPrevSibling(nsnull),
mImplData(aImplData),
mUserData(nsnull),
mOpacity(1.0),
mUseClipRect(PR_FALSE),
mIsOpaqueContent(PR_FALSE)
@ -539,7 +628,7 @@ protected:
Layer* mNextSibling;
Layer* mPrevSibling;
void* mImplData;
void* mUserData;
LayerUserDataSet mUserData;
nsIntRegion mVisibleRegion;
gfx3DMatrix mTransform;
float mOpacity;

Просмотреть файл

@ -57,14 +57,19 @@ namespace {
/**
* This is the userdata we associate with a layer manager.
*/
class LayerManagerData {
class LayerManagerData : public LayerUserData {
public:
LayerManagerData() :
mInvalidateAllThebesContent(PR_FALSE),
mInvalidateAllLayers(PR_FALSE)
{
MOZ_COUNT_CTOR(LayerManagerData);
mFramesWithLayers.Init();
}
~LayerManagerData() {
MOZ_COUNT_DTOR(LayerManagerData);
}
/**
* Tracks which frames have layers associated with them.
@ -304,18 +309,26 @@ protected:
/**
* The address of gThebesDisplayItemLayerUserData is used as the user
* data pointer for ThebesLayers created by FrameLayerBuilder.
* data key for ThebesLayers created by FrameLayerBuilder.
* It identifies ThebesLayers used to draw non-layer content, which are
* therefore eligible for recycling. We want display items to be able to
* create their own dedicated ThebesLayers in BuildLayer, if necessary,
* and we wouldn't want to accidentally recycle those.
* The user data is null.
*/
static PRUint8 gThebesDisplayItemLayerUserData;
PRUint8 gThebesDisplayItemLayerUserData;
/**
* The address of gColorLayerUserData is used as the user
* data pointer for ColorLayers
* data key for ColorLayers created by FrameLayerBuilder.
* The user data is null.
*/
static PRUint8 gColorLayerUserData;
PRUint8 gColorLayerUserData;
/**
* The address of gLayerManagerUserData is used as the user
* data key for retained LayerManagers managed by FrameLayerBuilder.
* The user data is a LayerManagerData.
*/
PRUint8 gLayerManagerUserData;
} // anonymous namespace
@ -342,12 +355,11 @@ FrameLayerBuilder::InternalDestroyDisplayItemData(nsIFrame* aFrame,
if (aRemoveFromFramesWithLayers) {
LayerManager* manager = array->ElementAt(0).mLayer->Manager();
LayerManagerData* data = static_cast<LayerManagerData*>
(manager->GetUserData());
(manager->GetUserData(&gLayerManagerUserData));
NS_ASSERTION(data, "Frame with layer should have been recorded");
data->mFramesWithLayers.RemoveEntry(aFrame);
if (data->mFramesWithLayers.Count() == 0) {
delete data;
manager->SetUserData(nsnull);
manager->RemoveUserData(&gLayerManagerUserData);
// Consume the reference we added when we set the user data
// in DidEndTransaction. But don't actually release until we've
// released all the layers in the DisplayItemData array below!
@ -371,7 +383,7 @@ FrameLayerBuilder::WillBeginRetainedLayerTransaction(LayerManager* aManager)
{
mRetainingManager = aManager;
LayerManagerData* data = static_cast<LayerManagerData*>
(aManager->GetUserData());
(aManager->GetUserData(&gLayerManagerUserData));
if (data) {
mInvalidateAllThebesContent = data->mInvalidateAllThebesContent;
mInvalidateAllLayers = data->mInvalidateAllLayers;
@ -420,13 +432,13 @@ FrameLayerBuilder::WillEndTransaction(LayerManager* aManager)
// correctly and the NS_FRAME_HAS_CONTAINER_LAYER bits will be set
// correctly.
LayerManagerData* data = static_cast<LayerManagerData*>
(mRetainingManager->GetUserData());
(mRetainingManager->GetUserData(&gLayerManagerUserData));
if (data) {
// Update all the frames that used to have layers.
data->mFramesWithLayers.EnumerateEntries(UpdateDisplayItemDataForFrame, this);
} else {
data = new LayerManagerData();
mRetainingManager->SetUserData(data);
mRetainingManager->SetUserData(&gLayerManagerUserData, data);
// Addref mRetainingManager. We'll release it when 'data' is
// removed.
NS_ADDREF(mRetainingManager);
@ -595,7 +607,7 @@ ContainerState::CreateOrRecycleColorLayer()
if (!layer)
return nsnull;
// Mark this layer as being used for Thebes-painting display items
layer->SetUserData(&gColorLayerUserData);
layer->SetUserData(&gColorLayerUserData, nsnull);
}
return layer.forget();
}
@ -637,7 +649,7 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
if (!layer)
return nsnull;
// Mark this layer as being used for Thebes-painting display items
layer->SetUserData(&gThebesDisplayItemLayerUserData);
layer->SetUserData(&gThebesDisplayItemLayerUserData, nsnull);
}
// Set up transform so that 0,0 in the Thebes layer corresponds to the
@ -965,7 +977,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
// Update that layer's clip and visible rects.
NS_ASSERTION(ownLayer->Manager() == mManager, "Wrong manager");
NS_ASSERTION(ownLayer->GetUserData() != &gThebesDisplayItemLayerUserData,
NS_ASSERTION(!ownLayer->HasUserData(&gLayerManagerUserData),
"We shouldn't have a FrameLayerBuilder-managed layer here!");
// It has its own layer. Update that layer's clip and visible rects.
if (aClipRect) {
@ -1119,10 +1131,9 @@ ContainerState::CollectOldLayers()
{
for (Layer* layer = mContainerLayer->GetFirstChild(); layer;
layer = layer->GetNextSibling()) {
void* data = layer->GetUserData();
if (data == &gColorLayerUserData) {
if (layer->HasUserData(&gColorLayerUserData)) {
mRecycledColorLayers.AppendElement(static_cast<ColorLayer*>(layer));
} else if (data == &gThebesDisplayItemLayerUserData) {
} else if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
NS_ASSERTION(layer->AsThebesLayer(), "Wrong layer type");
mRecycledThebesLayers.AppendElement(static_cast<ThebesLayer*>(layer));
}
@ -1203,7 +1214,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
Layer* oldLayer = GetOldLayerFor(aContainerFrame, containerDisplayItemKey);
if (oldLayer) {
NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager");
if (oldLayer->GetUserData() == &gThebesDisplayItemLayerUserData) {
if (oldLayer->HasUserData(&gThebesDisplayItemLayerUserData)) {
// The old layer for this item is actually our ThebesLayer
// because we rendered its layer into that ThebesLayer. So we
// don't actually have a retained container layer.
@ -1276,7 +1287,7 @@ FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
Layer* layer = GetOldLayerFor(f, aItem->GetPerFrameKey());
if (!layer)
return nsnull;
if (layer->GetUserData() == &gThebesDisplayItemLayerUserData) {
if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
// This layer was created to render Thebes-rendered content for this
// display item. The display item should not use it for its own
// layer rendering.
@ -1352,7 +1363,7 @@ FrameLayerBuilder::InvalidateThebesLayersInSubtree(nsIFrame* aFrame)
FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager)
{
LayerManagerData* data = static_cast<LayerManagerData*>
(aManager->GetUserData());
(aManager->GetUserData(&gLayerManagerUserData));
if (data) {
data->mInvalidateAllThebesContent = PR_TRUE;
}
@ -1362,7 +1373,7 @@ FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager)
FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
{
LayerManagerData* data = static_cast<LayerManagerData*>
(aManager->GetUserData());
(aManager->GetUserData(&gLayerManagerUserData));
if (data) {
data->mInvalidateAllLayers = PR_TRUE;
}
@ -1380,9 +1391,9 @@ FrameLayerBuilder::HasDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
(reinterpret_cast<nsTArray<DisplayItemData>*>(&propValue));
for (PRUint32 i = 0; i < array->Length(); ++i) {
if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
void* layerUserData = array->ElementAt(i).mLayer->GetUserData();
if (layerUserData != &gColorLayerUserData &&
layerUserData != &gThebesDisplayItemLayerUserData)
Layer* layer = array->ElementAt(i).mLayer;
if (!layer->HasUserData(&gColorLayerUserData) &&
!layer->HasUserData(&gThebesDisplayItemLayerUserData))
return PR_TRUE;
}
}