зеркало из https://github.com/mozilla/gecko-dev.git
Bug 579276. Part 1: Change layer/layermanager user data API to use keys and values. r=cjones,sr=vlad
This commit is contained in:
Родитель
b505f86231
Коммит
c649008789
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче