Bug 1079627 (Part 1) - Make image decoders hold a strong reference to their image. r=tn

This commit is contained in:
Seth Fowler 2015-01-15 15:11:35 -08:00
Родитель b6d9258843
Коммит 66b57f086b
15 изменённых файлов: 56 добавлений и 36 удалений

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

@ -38,7 +38,7 @@ GetBMPLog()
#define LINE(row) ((mBIH.height < 0) ? (-mBIH.height - (row)) : ((row) - 1))
#define PIXEL_OFFSET(row, col) (LINE(row) * mBIH.width + col)
nsBMPDecoder::nsBMPDecoder(RasterImage& aImage)
nsBMPDecoder::nsBMPDecoder(RasterImage* aImage)
: Decoder(aImage)
, mPos(0)
, mLOH(WIN_V3_HEADER_LENGTH)

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

@ -23,7 +23,7 @@ class nsBMPDecoder : public Decoder
{
public:
explicit nsBMPDecoder(RasterImage& aImage);
explicit nsBMPDecoder(RasterImage* aImage);
~nsBMPDecoder();
// Specifies whether or not the BMP file will contain alpha data

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

@ -68,7 +68,7 @@ namespace image {
//////////////////////////////////////////////////////////////////////
// GIF Decoder Implementation
nsGIFDecoder2::nsGIFDecoder2(RasterImage& aImage)
nsGIFDecoder2::nsGIFDecoder2(RasterImage* aImage)
: Decoder(aImage)
, mCurrentRow(-1)
, mLastFlushedRow(-1)

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

@ -23,7 +23,7 @@ class nsGIFDecoder2 : public Decoder
{
public:
explicit nsGIFDecoder2(RasterImage& aImage);
explicit nsGIFDecoder2(RasterImage* aImage);
~nsGIFDecoder2();
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE;

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

@ -58,7 +58,7 @@ nsICODecoder::GetNumColors()
}
nsICODecoder::nsICODecoder(RasterImage& aImage)
nsICODecoder::nsICODecoder(RasterImage* aImage)
: Decoder(aImage)
{
mPos = mImageOffset = mCurrIcon = mNumIcons = mBPP = mRowBytes = 0;
@ -249,7 +249,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
}
uint16_t colorDepth = 0;
nsIntSize prefSize = mImage.GetRequestedResolution();
nsIntSize prefSize = mImage->GetRequestedResolution();
if (prefSize.width == 0 && prefSize.height == 0) {
prefSize.SizeTo(PREFICONSIZE, PREFICONSIZE);
}

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

@ -23,7 +23,7 @@ class nsICODecoder : public Decoder
{
public:
explicit nsICODecoder(RasterImage& aImage);
explicit nsICODecoder(RasterImage* aImage);
virtual ~nsICODecoder();
// Obtains the width of the icon directory entry

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

@ -15,7 +15,7 @@
namespace mozilla {
namespace image {
nsIconDecoder::nsIconDecoder(RasterImage& aImage)
nsIconDecoder::nsIconDecoder(RasterImage* aImage)
: Decoder(aImage),
mWidth(-1),
mHeight(-1),

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

@ -38,7 +38,7 @@ class nsIconDecoder : public Decoder
{
public:
explicit nsIconDecoder(RasterImage& aImage);
explicit nsIconDecoder(RasterImage* aImage);
virtual ~nsIconDecoder();
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE;

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

@ -84,7 +84,7 @@ METHODDEF(void) my_error_exit (j_common_ptr cinfo);
#define MAX_JPEG_MARKER_LENGTH (((uint32_t)1 << 16) - 1)
nsJPEGDecoder::nsJPEGDecoder(RasterImage& aImage,
nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
Decoder::DecodeStyle aDecodeStyle)
: Decoder(aImage)
, mDecodeStyle(aDecodeStyle)
@ -237,7 +237,7 @@ nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
return; // I/O suspension
}
int sampleSize = mImage.GetRequestedSampleSize();
int sampleSize = mImage->GetRequestedSampleSize();
if (sampleSize > 0) {
mInfo.scale_num = 1;
mInfo.scale_denom = sampleSize;

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

@ -52,7 +52,7 @@ struct Orientation;
class nsJPEGDecoder : public Decoder
{
public:
nsJPEGDecoder(RasterImage& aImage, Decoder::DecodeStyle aDecodeStyle);
nsJPEGDecoder(RasterImage* aImage, Decoder::DecodeStyle aDecodeStyle);
virtual ~nsJPEGDecoder();
virtual void InitInternal() MOZ_OVERRIDE;

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

@ -107,7 +107,7 @@ nsPNGDecoder::AnimFrameInfo::AnimFrameInfo(png_structp aPNG, png_infop aInfo)
const uint8_t
nsPNGDecoder::pngSignatureBytes[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
nsPNGDecoder::nsPNGDecoder(RasterImage& aImage)
nsPNGDecoder::nsPNGDecoder(RasterImage* aImage)
: Decoder(aImage),
mPNG(nullptr), mInfo(nullptr),
mCMSLine(nullptr), interlacebuf(nullptr),

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

@ -24,7 +24,7 @@ class RasterImage;
class nsPNGDecoder : public Decoder
{
public:
explicit nsPNGDecoder(RasterImage& aImage);
explicit nsPNGDecoder(RasterImage* aImage);
virtual ~nsPNGDecoder();
virtual void InitInternal() MOZ_OVERRIDE;

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

@ -20,7 +20,7 @@ using mozilla::gfx::SurfaceFormat;
namespace mozilla {
namespace image {
Decoder::Decoder(RasterImage &aImage)
Decoder::Decoder(RasterImage* aImage)
: mImage(aImage)
, mProgress(NoProgress)
, mImageData(nullptr)
@ -48,6 +48,21 @@ Decoder::~Decoder()
MOZ_ASSERT(mInvalidRect.IsEmpty(),
"Destroying Decoder without taking all its invalidations");
mInitialized = false;
if (!NS_IsMainThread()) {
// Dispatch mImage to main thread to prevent it from being destructed by the
// decode thread.
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
if (mainThread) {
// Handle ambiguous nsISupports inheritance.
RasterImage* rawImg = nullptr;
mImage.swap(rawImg);
DebugOnly<nsresult> rv =
NS_ProxyRelease(mainThread, NS_ISUPPORTS_CAST(ImageResource*, rawImg));
MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to proxy release to main thread");
}
}
}
/*
@ -181,13 +196,13 @@ Decoder::Finish(ShutdownReason aReason)
if (consoleService && errorObject && !HasDecoderError()) {
nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated: ") +
NS_ConvertUTF8toUTF16(mImage.GetURIString()));
NS_ConvertUTF8toUTF16(mImage->GetURIString()));
if (NS_SUCCEEDED(errorObject->InitWithWindowID(
msg,
NS_ConvertUTF8toUTF16(mImage.GetURIString()),
NS_ConvertUTF8toUTF16(mImage->GetURIString()),
EmptyString(), 0, 0, nsIScriptError::errorFlag,
"Image", mImage.InnerWindowID()
"Image", mImage->InnerWindowID()
))) {
consoleService->LogMessage(errorObject);
}
@ -218,11 +233,11 @@ Decoder::Finish(ShutdownReason aReason)
// Set image metadata before calling DecodingComplete, because
// DecodingComplete calls Optimize().
mImageMetadata.SetOnImage(&mImage);
mImageMetadata.SetOnImage(mImage);
if (mDecodeDone) {
MOZ_ASSERT(HasError() || mCurrentFrame, "Should have an error or a frame");
mImage.DecodingComplete(mCurrentFrame.get());
mImage->DecodingComplete(mCurrentFrame.get());
}
}
@ -369,7 +384,7 @@ Decoder::InternalAddFrame(uint32_t aFrameNum,
}
InsertOutcome outcome =
SurfaceCache::Insert(frame, ImageKey(&mImage),
SurfaceCache::Insert(frame, ImageKey(mImage.get()),
RasterSurfaceKey(imageSize.ToIntSize(),
aDecodeFlags,
aFrameNum),
@ -405,7 +420,7 @@ Decoder::InternalAddFrame(uint32_t aFrameNum,
}
mFrameCount++;
mImage.OnAddedFrame(mFrameCount, refreshArea);
mImage->OnAddedFrame(mFrameCount, refreshArea);
return ref;
}
@ -416,9 +431,9 @@ Decoder::SetSizeOnImage()
MOZ_ASSERT(mImageMetadata.HasSize(), "Should have size");
MOZ_ASSERT(mImageMetadata.HasOrientation(), "Should have orientation");
mImage.SetSize(mImageMetadata.GetWidth(),
mImageMetadata.GetHeight(),
mImageMetadata.GetOrientation());
mImage->SetSize(mImageMetadata.GetWidth(),
mImageMetadata.GetHeight(),
mImageMetadata.GetOrientation());
}
/*

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

@ -22,7 +22,7 @@ class Decoder
{
public:
explicit Decoder(RasterImage& aImage);
explicit Decoder(RasterImage* aImage);
/**
* Initialize an image decoder. Decoders may not be re-initialized.
@ -187,6 +187,11 @@ public:
ImageMetadata& GetImageMetadata() { return mImageMetadata; }
/**
* Returns a weak pointer to the image associated with this decoder.
*/
RasterImage* GetImage() const { MOZ_ASSERT(mImage); return mImage.get(); }
// Tell the decoder infrastructure to allocate a frame. By default, frame 0
// is created as an ARGB frame with no offset and with size width * height.
// If decoders need something different, they must ask for it.
@ -312,7 +317,7 @@ protected:
* Member variables.
*
*/
RasterImage &mImage;
nsRefPtr<RasterImage> mImage;
RawAccessFrameRef mCurrentFrame;
ImageMetadata mImageMetadata;
nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame.

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

@ -1458,32 +1458,32 @@ RasterImage::InitDecoder(bool aDoSizeDecode)
eDecoderType type = GetDecoderType(mSourceDataMimeType.get());
CONTAINER_ENSURE_TRUE(type != eDecoderType_unknown, NS_IMAGELIB_ERROR_NO_DECODER);
// Instantiate the appropriate decoder
// Instantiate the appropriate decoder.
switch (type) {
case eDecoderType_png:
mDecoder = new nsPNGDecoder(*this);
mDecoder = new nsPNGDecoder(this);
break;
case eDecoderType_gif:
mDecoder = new nsGIFDecoder2(*this);
mDecoder = new nsGIFDecoder2(this);
break;
case eDecoderType_jpeg:
// If we have all the data we don't want to waste cpu time doing
// a progressive decode
mDecoder = new nsJPEGDecoder(*this,
// a progressive decode.
mDecoder = new nsJPEGDecoder(this,
mHasBeenDecoded ? Decoder::SEQUENTIAL :
Decoder::PROGRESSIVE);
break;
case eDecoderType_bmp:
mDecoder = new nsBMPDecoder(*this);
mDecoder = new nsBMPDecoder(this);
break;
case eDecoderType_ico:
mDecoder = new nsICODecoder(*this);
mDecoder = new nsICODecoder(this);
break;
case eDecoderType_icon:
mDecoder = new nsIconDecoder(*this);
mDecoder = new nsIconDecoder(this);
break;
default:
NS_ABORT_IF_FALSE(0, "Shouldn't get here!");
MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
}
// Initialize the decoder