Bug 769021; fix a memory leak with mask sharing. r=khuey

This commit is contained in:
Nicholas Cameron 2012-09-04 13:02:56 +12:00
parent f3c3989fbe
commit 120146b67e
3 changed files with 57 additions and 21 deletions

View File

@ -3296,28 +3296,24 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aCl
gfxMatrix imageTransform = maskTransform;
imageTransform.Scale(mParameters.mXScale, mParameters.mYScale);
nsAutoPtr<MaskLayerImageCache::MaskLayerImageKey> newKey(
new MaskLayerImageCache::MaskLayerImageKey(aLayer->Manager()->GetBackendType()));
// copy and transform the rounded rects
nsTArray<MaskLayerImageCache::PixelRoundedRect> roundedRects;
for (uint32_t i = 0; i < newData.mRoundedClipRects.Length(); ++i) {
roundedRects.AppendElement(
newKey->mRoundedClipRects.AppendElement(
MaskLayerImageCache::PixelRoundedRect(newData.mRoundedClipRects[i],
mContainerFrame->PresContext()));
roundedRects[i].ScaleAndTranslate(imageTransform);
newKey->mRoundedClipRects[i].ScaleAndTranslate(imageTransform);
}
// check to see if we can reuse a mask image
const MaskLayerImageCache::MaskLayerImageKey* key =
new MaskLayerImageCache::MaskLayerImageKey(roundedRects, aLayer->Manager()->GetBackendType());
const MaskLayerImageCache::MaskLayerImageKey* lookupKey = key;
const MaskLayerImageCache::MaskLayerImageKey* lookupKey = newKey;
// check to see if we can reuse a mask image
nsRefPtr<ImageContainer> container =
GetMaskLayerImageCache()->FindImageFor(&lookupKey);
if (container) {
// track the returned key for the mask image
delete key;
key = lookupKey;
} else {
if (!container) {
// no existing mask image, so build a new one
nsRefPtr<gfxASurface> surface =
aLayer->Manager()->CreateOptimalMaskSurface(surfaceSize);
@ -3348,7 +3344,7 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aCl
static_cast<CairoImage*>(image.get())->SetData(data);
container->SetCurrentImageInTransaction(image);
GetMaskLayerImageCache()->PutImage(key, container);
GetMaskLayerImageCache()->PutImage(newKey.forget(), container);
}
maskLayer->SetContainer(container);
@ -3358,7 +3354,7 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aCl
userData->mScaleX = newData.mScaleX;
userData->mScaleY = newData.mScaleY;
userData->mRoundedClipRects.SwapElements(newData.mRoundedClipRects);
userData->mImageKey = key;
userData->mImageKey = lookupKey;
aLayer->SetMaskLayer(maskLayer);
SetClipCount(thebesData, aRoundedRectClipCount);

View File

@ -12,10 +12,13 @@ namespace mozilla {
MaskLayerImageCache::MaskLayerImageCache()
{
MOZ_COUNT_CTOR(MaskLayerImageCache);
mMaskImageContainers.Init();
}
MaskLayerImageCache::~MaskLayerImageCache()
{}
{
MOZ_COUNT_DTOR(MaskLayerImageCache);
}
/* static */ PLDHashOperator

View File

@ -50,10 +50,24 @@ public:
aPresContext->AppUnitsToGfxUnits(aRRect.mRect.width),
aPresContext->AppUnitsToGfxUnits(aRRect.mRect.height))
{
MOZ_COUNT_CTOR(PixelRoundedRect);
NS_FOR_CSS_HALF_CORNERS(corner) {
mRadii[corner] = aPresContext->AppUnitsToGfxUnits(aRRect.mRadii[corner]);
}
}
PixelRoundedRect(const PixelRoundedRect& aPRR)
: mRect(aPRR.mRect)
{
MOZ_COUNT_CTOR(PixelRoundedRect);
NS_FOR_CSS_HALF_CORNERS(corner) {
mRadii[corner] = aPRR.mRadii[corner];
}
}
~PixelRoundedRect()
{
MOZ_COUNT_DTOR(PixelRoundedRect);
}
// Applies the scale and translate components of aTransform.
// It is an error to pass a matrix which does more than just scale
@ -99,6 +113,9 @@ public:
gfxRect mRect;
// Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h
gfxFloat mRadii[8];
private:
PixelRoundedRect() MOZ_DELETE;
};
/**
@ -111,14 +128,27 @@ public:
* pointers to a key object (the +1 being from the hashtable entry), but this
* invariant may be temporarily broken.
*/
class MaskLayerImageKey
struct MaskLayerImageKey
{
public:
MaskLayerImageKey(const nsTArray<PixelRoundedRect>& aRoundedClipRects, layers::LayersBackend aBackend)
MaskLayerImageKey(layers::LayersBackend aBackend)
: mBackend(aBackend)
, mLayerCount(0)
, mRoundedClipRects(aRoundedClipRects)
{}
, mRoundedClipRects()
{
MOZ_COUNT_CTOR(MaskLayerImageKey);
}
MaskLayerImageKey(const MaskLayerImageKey& aKey)
: mBackend(aKey.mBackend)
, mLayerCount(aKey.mLayerCount)
, mRoundedClipRects(aKey.mRoundedClipRects)
{
MOZ_COUNT_CTOR(MaskLayerImageKey);
}
~MaskLayerImageKey()
{
MOZ_COUNT_DTOR(MaskLayerImageKey);
}
void AddRef() const { ++mLayerCount; }
void Release() const
@ -172,12 +202,19 @@ protected:
typedef const MaskLayerImageKey& KeyType;
typedef const MaskLayerImageKey* KeyTypePointer;
MaskLayerImageEntry(KeyTypePointer aKey) : mKey(aKey) {}
MaskLayerImageEntry(KeyTypePointer aKey) : mKey(aKey)
{
MOZ_COUNT_CTOR(MaskLayerImageEntry);
}
MaskLayerImageEntry(const MaskLayerImageEntry& aOther)
: mKey(aOther.mKey.get())
{
NS_ERROR("ALLOW_MEMMOVE == true, should never be called");
}
~MaskLayerImageEntry()
{
MOZ_COUNT_DTOR(MaskLayerImageEntry);
}
// KeyEquals(): does this entry match this key?
bool KeyEquals(KeyTypePointer aKey) const