Bug 1383404 - Part 4. imgTools::DecodeImage should set the source size hint to optimize the allocation. r=tnikkel

This commit is contained in:
Andrew Osmond 2017-08-01 06:59:12 -04:00
parent af89f9b9b6
commit 9ea902f3c5
3 changed files with 39 additions and 30 deletions

View File

@ -124,8 +124,32 @@ BadImage(const char* aMessage, RefPtr<T>& aImage)
return aImage.forget();
}
static void
SetSourceSizeHint(RasterImage* aImage, uint32_t aSize)
{
// Pass anything usable on so that the RasterImage can preallocate
// its source buffer.
if (aSize == 0) {
return;
}
// Bound by something reasonable
uint32_t sizeHint = std::min<uint32_t>(aSize, 20000000);
nsresult rv = aImage->SetSourceSizeHint(sizeHint);
if (NS_FAILED(rv)) {
// Flush memory, try to get some back, and try again.
rv = nsMemory::HeapMinimize(true);
nsresult rv2 = aImage->SetSourceSizeHint(sizeHint);
// If we've still failed at this point, things are going downhill.
if (NS_FAILED(rv) || NS_FAILED(rv2)) {
NS_WARNING("About to hit OOM in imagelib!");
}
}
}
/* static */ already_AddRefed<Image>
ImageFactory::CreateAnonymousImage(const nsCString& aMimeType)
ImageFactory::CreateAnonymousImage(const nsCString& aMimeType,
uint32_t aSizeHint /* = 0 */)
{
nsresult rv;
@ -140,6 +164,7 @@ ImageFactory::CreateAnonymousImage(const nsCString& aMimeType)
return BadImage("RasterImage::Init failed", newImage);
}
SetSourceSizeHint(newImage, aSizeHint);
return newImage.forget();
}
@ -225,25 +250,7 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
newImage->SetInnerWindowID(aInnerWindowId);
uint32_t len = GetContentSize(aRequest);
// Pass anything usable on so that the RasterImage can preallocate
// its source buffer.
if (len > 0) {
// Bound by something reasonable
uint32_t sizeHint = std::min<uint32_t>(len, 20000000);
rv = newImage->SetSourceSizeHint(sizeHint);
if (NS_FAILED(rv)) {
// Flush memory, try to get some back, and try again.
rv = nsMemory::HeapMinimize(true);
nsresult rv2 = newImage->SetSourceSizeHint(sizeHint);
// If we've still failed at this point, things are going downhill.
if (NS_FAILED(rv) || NS_FAILED(rv2)) {
NS_WARNING("About to hit OOM in imagelib!");
}
}
}
SetSourceSizeHint(newImage, GetContentSize(aRequest));
return newImage.forget();
}

View File

@ -51,9 +51,10 @@ public:
* the usual image loading mechanism.
*
* @param aMimeType The mimetype of the image.
* @param aSizeHint The length of the source data for the image.
*/
static already_AddRefed<Image>
CreateAnonymousImage(const nsCString& aMimeType);
CreateAnonymousImage(const nsCString& aMimeType, uint32_t aSizeHint = 0);
/**
* Creates a new multipart/x-mixed-replace image wrapper, and initializes it

View File

@ -68,15 +68,6 @@ imgTools::DecodeImage(nsIInputStream* aInStr,
NS_ENSURE_ARG_POINTER(aInStr);
// Create a new image container to hold the decoded data.
nsAutoCString mimeType(aMimeType);
RefPtr<image::Image> image = ImageFactory::CreateAnonymousImage(mimeType);
RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
if (image->HasError()) {
return NS_ERROR_FAILURE;
}
// Prepare the input stream.
nsCOMPtr<nsIInputStream> inStream = aInStr;
if (!NS_InputStreamIsBuffered(aInStr)) {
@ -93,6 +84,16 @@ imgTools::DecodeImage(nsIInputStream* aInStr,
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(length <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
// Create a new image container to hold the decoded data.
nsAutoCString mimeType(aMimeType);
RefPtr<image::Image> image =
ImageFactory::CreateAnonymousImage(mimeType, uint32_t(length));
RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
if (image->HasError()) {
return NS_ERROR_FAILURE;
}
// Send the source data to the Image.
rv = image->OnImageDataAvailable(nullptr, nullptr, inStream, 0,
uint32_t(length));