Bug 1148582 - Recycle mask layers attached to FrameMetrics. r=mattwoodrow

--HG--
extra : rebase_source : f74699e5c40598ca8b7aa0163897c74524e32419
extra : source : be49031960aa935f2f0d6fa594251c9e1fa12536
This commit is contained in:
David Anderson 2015-06-21 12:28:10 -04:00
Родитель 55a0f8ee25
Коммит 16262c38a8
1 изменённых файлов: 46 добавлений и 10 удалений

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

@ -1088,8 +1088,14 @@ protected:
* Grab a recyclable ImageLayer for use as a mask layer for aLayer (that is a * Grab a recyclable ImageLayer for use as a mask layer for aLayer (that is a
* mask layer which has been used for aLayer before), or create one if such * mask layer which has been used for aLayer before), or create one if such
* a layer doesn't exist. * a layer doesn't exist.
*
* Since mask layers can exist either on the layer directly, or as a side-
* attachment to FrameMetrics (for ancestor scrollframe clips), we key the
* recycle operation on both the originating layer and the mask layer's
* index in the layer, if any.
*/ */
already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(Layer* aLayer, const Maybe<size_t>& aForAncestorMaskLayer); struct MaskLayerKey;
already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey);
/** /**
* Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes them * Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes them
* available for recycling. * available for recycling.
@ -1229,11 +1235,33 @@ protected:
typedef nsAutoTArray<NewLayerEntry,1> AutoLayersArray; typedef nsAutoTArray<NewLayerEntry,1> AutoLayersArray;
AutoLayersArray mNewChildLayers; AutoLayersArray mNewChildLayers;
nsTHashtable<nsRefPtrHashKey<PaintedLayer>> mPaintedLayersAvailableForRecycling; nsTHashtable<nsRefPtrHashKey<PaintedLayer>> mPaintedLayersAvailableForRecycling;
nsDataHashtable<nsPtrHashKey<Layer>, nsRefPtr<ImageLayer> >
mRecycledMaskImageLayers;
nscoord mAppUnitsPerDevPixel; nscoord mAppUnitsPerDevPixel;
bool mSnappingEnabled; bool mSnappingEnabled;
bool mFlattenToSingleLayer; bool mFlattenToSingleLayer;
struct MaskLayerKey {
MaskLayerKey() : mLayer(nullptr) {}
MaskLayerKey(Layer* aLayer, const Maybe<size_t>& aAncestorIndex)
: mLayer(aLayer),
mAncestorIndex(aAncestorIndex)
{}
PLDHashNumber Hash() const {
// Hash the layer and add the layer index to the hash.
return (NS_PTR_TO_UINT32(mLayer) >> 2)
+ (mAncestorIndex ? (*mAncestorIndex + 1) : 0);
}
bool operator ==(const MaskLayerKey& aOther) const {
return mLayer == aOther.mLayer &&
mAncestorIndex == aOther.mAncestorIndex;
}
Layer* mLayer;
Maybe<size_t> mAncestorIndex;
};
nsDataHashtable<nsGenericHashKey<MaskLayerKey>, nsRefPtr<ImageLayer>>
mRecycledMaskImageLayers;
}; };
class PaintedDisplayItemLayerUserData : public LayerUserData class PaintedDisplayItemLayerUserData : public LayerUserData
@ -1933,12 +1961,12 @@ ContainerState::CreateOrRecycleImageLayer(PaintedLayer *aPainted)
} }
already_AddRefed<ImageLayer> already_AddRefed<ImageLayer>
ContainerState::CreateOrRecycleMaskImageLayerFor(Layer* aLayer, const Maybe<size_t>& aForAncestorMaskLayer) ContainerState::CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey)
{ {
nsRefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aLayer); nsRefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aKey);
if (result && !aForAncestorMaskLayer) { if (result) {
mRecycledMaskImageLayers.Remove(aLayer); mRecycledMaskImageLayers.Remove(aKey);
aLayer->ClearExtraDumpInfo(); aKey.mLayer->ClearExtraDumpInfo();
// XXX if we use clip on mask layers, null it out here // XXX if we use clip on mask layers, null it out here
} else { } else {
// Create a new layer // Create a new layer
@ -4326,7 +4354,14 @@ ContainerState::CollectOldLayers()
if (Layer* maskLayer = layer->GetMaskLayer()) { if (Layer* maskLayer = layer->GetMaskLayer()) {
NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE, NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE,
"Could not recycle mask layer, unsupported layer type."); "Could not recycle mask layer, unsupported layer type.");
mRecycledMaskImageLayers.Put(layer, static_cast<ImageLayer*>(maskLayer)); mRecycledMaskImageLayers.Put(MaskLayerKey(layer, Nothing()), static_cast<ImageLayer*>(maskLayer));
}
for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
Layer* maskLayer = layer->GetAncestorMaskLayerAt(i);
NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE,
"Could not recycle mask layer, unsupported layer type.");
mRecycledMaskImageLayers.Put(MaskLayerKey(layer, Some(i)), static_cast<ImageLayer*>(maskLayer));
} }
} }
} }
@ -5697,7 +5732,8 @@ ContainerState::CreateMaskLayer(Layer *aLayer,
uint32_t aRoundedRectClipCount) uint32_t aRoundedRectClipCount)
{ {
// check if we can re-use the mask layer // check if we can re-use the mask layer
nsRefPtr<ImageLayer> maskLayer = CreateOrRecycleMaskImageLayerFor(aLayer, aForAncestorMaskLayer); MaskLayerKey recycleKey(aLayer, aForAncestorMaskLayer);
nsRefPtr<ImageLayer> maskLayer = CreateOrRecycleMaskImageLayerFor(recycleKey);
MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer); MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer);
MaskLayerUserData newData; MaskLayerUserData newData;