Back out 965fe5b195ab (bug 962670) for leaking

This commit is contained in:
Phil Ringnalda 2014-03-06 20:36:28 -08:00
parent 32b0dc613c
commit b932e52022
5 changed files with 39 additions and 233 deletions

View File

@ -26,7 +26,6 @@
#include "nsSize.h" // for nsIntSize
#include "nsTArray.h" // for nsTArray
#include "mozilla/Atomics.h"
#include "mozilla/WeakPtr.h"
#include "nsThreadUtils.h"
#include "mozilla/gfx/2D.h"
#include "nsDataHashtable.h"
@ -381,7 +380,7 @@ struct RemoteImageData {
* updates the shared state to point to the new image and the old image
* is immediately released (not true in Normal or Asynchronous modes).
*/
class ImageContainer : public SupportsWeakPtr<ImageContainer> {
class ImageContainer {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
public:

View File

@ -922,24 +922,8 @@ RasterImage::GetFrame(uint32_t aWhichFrame,
nsIntRect framerect = frame->GetRect();
if (framerect.x == 0 && framerect.y == 0 &&
framerect.width == mSize.width &&
framerect.height == mSize.height) {
framerect.height == mSize.height)
frame->GetSurface(getter_AddRefs(framesurf));
if (!framesurf && !frame->IsSinglePixel()) {
// No reason to be optimized away here - the OS threw out the data
if (!(aFlags & FLAG_SYNC_DECODE))
return nullptr;
// Unconditionally call ForceDiscard() here because GetSurface can only
// return null when we can forcibly discard and redecode. There are two
// other cases where GetSurface() can return null - when it is a single
// pixel image, which we check before getting here, or when this is an
// indexed image, in which case we shouldn't be in this function at all.
// The only remaining possibility is that SetDiscardable() was called on
// this imgFrame, which implies the image can be redecoded.
ForceDiscard();
return GetFrame(aWhichFrame, aFlags);
}
}
// The image doesn't have a surface because it's been optimized away. Create
// one.
@ -963,15 +947,7 @@ RasterImage::GetCurrentImage()
}
nsRefPtr<gfxASurface> imageSurface = GetFrame(FRAME_CURRENT, FLAG_NONE);
if (!imageSurface) {
// The OS threw out some or all of our buffer. Start decoding again.
// GetFrame will only return null in the case that the image was
// discarded. We already checked that the image is decoded, so other
// error paths are not possible.
ForceDiscard();
RequestDecodeCore(ASYNCHRONOUS);
return nullptr;
}
NS_ENSURE_TRUE(imageSurface, nullptr);
if (!mImageContainer) {
mImageContainer = LayerManager::CreateImageContainer();
@ -1005,10 +981,6 @@ RasterImage::GetImageContainer(LayerManager* aManager, ImageContainer **_retval)
mStatusTracker->OnUnlockedDraw();
}
if (!mImageContainer) {
mImageContainer = mImageContainerCache;
}
if (mImageContainer) {
*_retval = mImageContainer;
NS_ADDREF(*_retval);
@ -1023,13 +995,6 @@ RasterImage::GetImageContainer(LayerManager* aManager, ImageContainer **_retval)
*_retval = mImageContainer;
NS_ADDREF(*_retval);
// We only need to be careful about holding on to the image when it is
// discardable by the OS.
if (CanForciblyDiscardAndRedecode()) {
mImageContainerCache = mImageContainer->asWeakPtr();
mImageContainer = nullptr;
}
return NS_OK;
}
@ -1427,12 +1392,6 @@ RasterImage::DecodingComplete()
// We don't optimize the frame for multipart images because we reuse
// the frame.
if ((GetNumFrames() == 1) && !mMultipart) {
// CanForciblyDiscard is used instead of CanForciblyDiscardAndRedecode
// because we know decoding is complete at this point and this is not
// an animation
if (DiscardingEnabled() && CanForciblyDiscard()) {
mFrameBlender.RawGetFrame(0)->SetDiscardable();
}
rv = mFrameBlender.RawGetFrame(0)->Optimize();
NS_ENSURE_SUCCESS(rv, rv);
}
@ -2134,6 +2093,13 @@ RasterImage::ShutdownDecoder(eShutdownIntent aIntent)
// Figure out what kind of decode we were doing before we get rid of our decoder
bool wasSizeDecode = mDecoder->IsSizeDecode();
// Unlock the last frame (if we have any). Our invariant is that, while we
// have a decoder open, the last frame is always locked.
if (GetNumFrames() > 0) {
imgFrame *curframe = mFrameBlender.RawGetFrame(GetNumFrames() - 1);
curframe->UnlockImageData();
}
// Finalize the decoder
// null out mDecoder, _then_ check for errors on the close (otherwise the
// error routine might re-invoke ShutdownDecoder)
@ -2146,13 +2112,6 @@ RasterImage::ShutdownDecoder(eShutdownIntent aIntent)
mInDecoder = false;
mFinishing = false;
// Unlock the last frame (if we have any). Our invariant is that, while we
// have a decoder open, the last frame is always locked.
if (GetNumFrames() > 0) {
imgFrame *curframe = mFrameBlender.RawGetFrame(GetNumFrames() - 1);
curframe->UnlockImageData();
}
// Kill off our decode request, if it's pending. (If not, this call is
// harmless.)
DecodePool::StopDecoding(this);
@ -2718,17 +2677,6 @@ RasterImage::Draw(gfxContext *aContext,
return NS_OK; // Getting the frame (above) touches the image and kicks off decoding
}
nsRefPtr<gfxASurface> surf;
if (!frame->IsSinglePixel()) {
frame->GetSurface(getter_AddRefs(surf));
if (!surf) {
// The OS threw out some or all of our buffer. Start decoding again.
ForceDiscard();
WantDecodedFrames();
return NS_OK;
}
}
DrawWithPreDownscaleIfNeeded(frame, aContext, aFilter, aUserSpaceToImageSpace, aFill, aSubimage, aFlags);
if (mDecoded && !mDrawStartTime.IsNull()) {

View File

@ -659,9 +659,6 @@ private: // data
// Cached value for GetImageContainer.
nsRefPtr<mozilla::layers::ImageContainer> mImageContainer;
// If not cached in mImageContainer, this might have our image container
WeakPtr<mozilla::layers::ImageContainer> mImageContainerCache;
#ifdef DEBUG
uint32_t mFramesNotified;
#endif

View File

@ -12,7 +12,6 @@
#include "gfx2DGlue.h"
#include "gfxPlatform.h"
#include "gfxUtils.h"
#include "gfxAlphaRecovery.h"
static bool gDisableOptimize = false;
@ -36,48 +35,6 @@ using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::image;
static cairo_user_data_key_t kVolatileBuffer;
static void
VolatileBufferRelease(void *vbuf)
{
delete static_cast<VolatileBufferPtr<unsigned char>*>(vbuf);
}
gfxImageSurface *
LockedImageSurface::CreateSurface(VolatileBuffer *vbuf,
const gfxIntSize& size,
gfxImageFormat format)
{
VolatileBufferPtr<unsigned char> *vbufptr =
new VolatileBufferPtr<unsigned char>(vbuf);
MOZ_ASSERT(!vbufptr->WasBufferPurged(), "Expected image data!");
long stride = gfxImageSurface::ComputeStride(size, format);
gfxImageSurface *img = new gfxImageSurface(*vbufptr, size, stride, format);
if (!img || img->CairoStatus()) {
delete img;
delete vbufptr;
return nullptr;
}
img->SetData(&kVolatileBuffer, vbufptr, VolatileBufferRelease);
return img;
}
TemporaryRef<VolatileBuffer>
LockedImageSurface::AllocateBuffer(const gfxIntSize& size,
gfxImageFormat format)
{
long stride = gfxImageSurface::ComputeStride(size, format);
RefPtr<VolatileBuffer> buf = new VolatileBuffer();
if (buf->Init(stride * size.height,
1 << gfxAlphaRecovery::GoodAlignmentLog2()))
return buf;
return nullptr;
}
// Returns true if an image of aWidth x aHeight is allowed and legal.
static bool AllowedImageSize(int32_t aWidth, int32_t aHeight)
{
@ -151,7 +108,6 @@ imgFrame::imgFrame() :
mFormatChanged(false),
mCompositingFailed(false),
mNonPremult(false),
mDiscardable(false),
mInformedDiscardTracker(false),
mDirty(false)
{
@ -218,17 +174,12 @@ nsresult imgFrame::Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
}
#endif
// For other platforms, space for the image surface is first allocated in
// a volatile buffer and then wrapped by a LockedImageSurface.
// This branch is also used on Windows if we're not using device surfaces
// or if we couldn't create one.
if (!mImageSurface) {
mVBuf = LockedImageSurface::AllocateBuffer(mSize, mFormat);
if (!mVBuf) {
return NS_ERROR_OUT_OF_MEMORY;
}
mImageSurface = LockedImageSurface::CreateSurface(mVBuf, mSize, mFormat);
}
// For other platforms we create the image surface first and then
// possibly wrap it in a device surface. This branch is also used
// on Windows if we're not using device surfaces or if we couldn't
// create one.
if (!mImageSurface)
mImageSurface = new gfxImageSurface(gfxIntSize(mSize.width, mSize.height), mFormat);
if (!mImageSurface || mImageSurface->CairoStatus()) {
mImageSurface = nullptr;
@ -300,7 +251,6 @@ nsresult imgFrame::Optimize()
mSinglePixel = true;
// blow away the older surfaces (if they exist), to release their memory
mVBuf = nullptr;
mImageSurface = nullptr;
mOptSurface = nullptr;
#ifdef USE_WIN_SURFACE
@ -350,7 +300,6 @@ nsresult imgFrame::Optimize()
mOptSurface = gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface, mFormat);
if (mOptSurface) {
mVBuf = nullptr;
mImageSurface = nullptr;
#ifdef USE_WIN_SURFACE
mWinSurface = nullptr;
@ -534,13 +483,10 @@ uint32_t imgFrame::GetImageBytesPerRow() const
if (mImageSurface)
return mImageSurface->Stride();
if (mVBuf)
return gfxImageSurface::ComputeStride(mSize, mFormat);
if (mPaletteDepth)
return mSize.width;
NS_ERROR("GetImageBytesPerRow called with mImageSurface == null, mVBuf == null and mPaletteDepth == 0");
NS_ERROR("GetImageBytesPerRow called with mImageSurface == null and mPaletteDepth == 0");
return 0;
}
@ -623,42 +569,28 @@ nsresult imgFrame::LockImageData()
if (mPalettedImageData)
return NS_OK;
if (!mImageSurface) {
if (mVBuf) {
VolatileBufferPtr<uint8_t> ref(mVBuf);
if (ref.WasBufferPurged())
return NS_ERROR_FAILURE;
if ((mOptSurface || mSinglePixel) && !mImageSurface) {
// Recover the pixels
mImageSurface = new gfxImageSurface(gfxIntSize(mSize.width, mSize.height),
gfxImageFormat::ARGB32);
if (!mImageSurface || mImageSurface->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
mImageSurface = LockedImageSurface::CreateSurface(mVBuf, mSize, mFormat);
if (!mImageSurface || mImageSurface->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
} else if (mOptSurface || mSinglePixel) {
// Recover the pixels
mVBuf = LockedImageSurface::AllocateBuffer(mSize, mFormat);
if (!mVBuf) {
return NS_ERROR_OUT_OF_MEMORY;
}
gfxContext context(mImageSurface);
context.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel)
context.SetDeviceColor(mSinglePixelColor);
else
context.SetSource(mOptSurface);
context.Paint();
mImageSurface = LockedImageSurface::CreateSurface(mVBuf, mSize, mFormat);
if (!mImageSurface || mImageSurface->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
gfxContext context(mImageSurface);
context.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel)
context.SetDeviceColor(mSinglePixelColor);
else
context.SetSource(mOptSurface);
context.Paint();
mOptSurface = nullptr;
mOptSurface = nullptr;
#ifdef USE_WIN_SURFACE
mWinSurface = nullptr;
mWinSurface = nullptr;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nullptr;
mQuartzSurface = nullptr;
#endif
}
}
// We might write to the bits in this image surface, so we need to make the
@ -671,12 +603,6 @@ nsresult imgFrame::LockImageData()
mWinSurface->Flush();
#endif
#ifdef XP_MACOSX
if (!mQuartzSurface && !ShouldUseImageSurfaces()) {
mQuartzSurface = new gfxQuartzImageSurface(mImageSurface);
}
#endif
return NS_OK;
}
@ -732,13 +658,6 @@ nsresult imgFrame::UnlockImageData()
mQuartzSurface->Flush();
#endif
if (mVBuf && mDiscardable) {
mImageSurface = nullptr;
#ifdef XP_MACOSX
mQuartzSurface = nullptr;
#endif
}
return NS_OK;
}
@ -778,12 +697,6 @@ void imgFrame::ApplyDirtToSurfaces()
}
}
void imgFrame::SetDiscardable()
{
MOZ_ASSERT(mLockCount, "Expected to be locked when SetDiscardable is called");
mDiscardable = true;
}
int32_t imgFrame::GetRawTimeout() const
{
return mTimeout;
@ -882,8 +795,8 @@ imgFrame::SizeOfExcludingThisWithComputedFallbackIfHeap(gfxMemoryLocation aLocat
#endif
#ifdef XP_MACOSX
if (mQuartzSurface && aLocation == gfxMemoryLocation::IN_PROCESS_HEAP) {
n += aMallocSizeOf(mQuartzSurface);
}
n += mSize.width * mSize.height * 4;
} else
#endif
if (mImageSurface && aLocation == mImageSurface->GetMemoryLocation()) {
size_t n2 = 0;
@ -896,11 +809,6 @@ imgFrame::SizeOfExcludingThisWithComputedFallbackIfHeap(gfxMemoryLocation aLocat
n += n2;
}
if (mVBuf && aLocation == gfxMemoryLocation::IN_PROCESS_HEAP) {
n += aMallocSizeOf(mVBuf);
n += mVBuf->HeapSizeOfExcludingThis(aMallocSizeOf);
}
if (mOptSurface && aLocation == mOptSurface->GetMemoryLocation()) {
size_t n2 = 0;
if (aLocation == gfxMemoryLocation::IN_PROCESS_HEAP &&

View File

@ -9,7 +9,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Mutex.h"
#include "mozilla/VolatileBuffer.h"
#include "nsRect.h"
#include "nsPoint.h"
#include "nsSize.h"
@ -25,21 +24,6 @@
#include "imgIContainer.h"
#include "gfxColor.h"
/*
* This creates a gfxImageSurface which will unlock the buffer on destruction
*/
class LockedImageSurface
{
public:
static gfxImageSurface *
CreateSurface(mozilla::VolatileBuffer *vbuf,
const gfxIntSize& size,
gfxImageFormat format);
static mozilla::TemporaryRef<mozilla::VolatileBuffer>
AllocateBuffer(const gfxIntSize& size, gfxImageFormat format);
};
class imgFrame
{
public:
@ -88,16 +72,14 @@ public:
nsresult UnlockImageData();
void ApplyDirtToSurfaces();
void SetDiscardable();
nsresult GetSurface(gfxASurface **aSurface)
nsresult GetSurface(gfxASurface **aSurface) const
{
*aSurface = ThebesSurface();
NS_IF_ADDREF(*aSurface);
return NS_OK;
}
nsresult GetPattern(gfxPattern **aPattern)
nsresult GetPattern(gfxPattern **aPattern) const
{
if (mSinglePixel)
*aPattern = new gfxPattern(mSinglePixelColor);
@ -107,12 +89,7 @@ public:
return NS_OK;
}
bool IsSinglePixel()
{
return mSinglePixel;
}
gfxASurface* ThebesSurface()
gfxASurface* ThebesSurface() const
{
if (mOptSurface)
return mOptSurface;
@ -123,27 +100,7 @@ public:
if (mQuartzSurface)
return mQuartzSurface;
#endif
if (mImageSurface)
return mImageSurface;
if (mVBuf) {
mozilla::VolatileBufferPtr<uint8_t> ref(mVBuf);
if (ref.WasBufferPurged())
return nullptr;
gfxImageSurface *sur =
LockedImageSurface::CreateSurface(mVBuf, mSize, mFormat);
#if defined(XP_MACOSX)
return new gfxQuartzImageSurface(sur);
#else
return sur;
#endif
}
// We can return null here if we're single pixel optimized
// or a paletted image. However, one has to check for paletted
// image data first before attempting to get a surface, so
// this is only valid for single pixel optimized images
MOZ_ASSERT(mSinglePixel, "No image surface and not a single pixel!");
return nullptr;
return mImageSurface;
}
size_t SizeOfExcludingThisWithComputedFallbackIfHeap(
@ -210,8 +167,6 @@ private: // data
/** Indicates how many readers currently have locked this frame */
int32_t mLockCount;
mozilla::RefPtr<mozilla::VolatileBuffer> mVBuf;
gfxImageFormat mFormat;
uint8_t mPaletteDepth;
int8_t mBlendMethod;
@ -219,7 +174,6 @@ private: // data
bool mFormatChanged;
bool mCompositingFailed;
bool mNonPremult;
bool mDiscardable;
/** Have we called DiscardTracker::InformAllocation()? */
bool mInformedDiscardTracker;