mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 716140 - Preallocate frames before going into a decoder. r=seth
--HG-- extra : rebase_source : 6445356bc4a01ac2890eca855103e58bda772095
This commit is contained in:
parent
c6cdce35eb
commit
7d7f4428f7
@ -139,7 +139,11 @@ nsBMPDecoder::FinishInternal()
|
||||
nsIntRect r(0, 0, mBIH.width, GetHeight());
|
||||
PostInvalidation(r);
|
||||
|
||||
PostFrameStop();
|
||||
if (mUseAlphaData) {
|
||||
PostFrameStop(RasterImage::kFrameHasAlpha);
|
||||
} else {
|
||||
PostFrameStop(RasterImage::kFrameOpaque);
|
||||
}
|
||||
PostDecodeDone();
|
||||
}
|
||||
}
|
||||
@ -193,7 +197,6 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
if (!aCount || !mCurLine)
|
||||
return;
|
||||
|
||||
nsresult rv;
|
||||
if (mPos < BFH_INTERNAL_LENGTH) { /* In BITMAPFILEHEADER */
|
||||
uint32_t toCopy = BFH_INTERNAL_LENGTH - mPos;
|
||||
if (toCopy > aCount)
|
||||
@ -308,34 +311,19 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t imageLength;
|
||||
if (mBIH.compression == BI_RLE8 || mBIH.compression == BI_RLE4 ||
|
||||
mBIH.compression == BI_ALPHABITFIELDS) {
|
||||
rv = mImage.EnsureFrame(0, 0, 0, mBIH.width, real_height,
|
||||
gfxASurface::ImageFormatARGB32,
|
||||
(uint8_t**)&mImageData, &imageLength);
|
||||
} else {
|
||||
if (mBIH.compression != BI_RLE8 && mBIH.compression != BI_RLE4 &&
|
||||
mBIH.compression != BI_ALPHABITFIELDS) {
|
||||
// mRow is not used for RLE encoded images
|
||||
mRow = (uint8_t*)moz_malloc((mBIH.width * mBIH.bpp) / 8 + 4);
|
||||
// + 4 because the line is padded to a 4 bit boundary, but I don't want
|
||||
// to make exact calculations here, that's unnecessary.
|
||||
// Also, it compensates rounding error.
|
||||
if (!mRow) {
|
||||
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mUseAlphaData) {
|
||||
rv = mImage.EnsureFrame(0, 0, 0, mBIH.width, real_height,
|
||||
gfxASurface::ImageFormatARGB32,
|
||||
(uint8_t**)&mImageData, &imageLength);
|
||||
} else {
|
||||
rv = mImage.EnsureFrame(0, 0, 0, mBIH.width, real_height,
|
||||
gfxASurface::ImageFormatRGB24,
|
||||
(uint8_t**)&mImageData, &imageLength);
|
||||
PostDataError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (NS_FAILED(rv) || !mImageData) {
|
||||
if (!mImageData) {
|
||||
PostDecoderError(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
@ -343,11 +331,8 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
// Prepare for transparency
|
||||
if ((mBIH.compression == BI_RLE8) || (mBIH.compression == BI_RLE4)) {
|
||||
// Clear the image, as the RLE may jump over areas
|
||||
memset(mImageData, 0, imageLength);
|
||||
memset(mImageData, 0, mImageDataLength);
|
||||
}
|
||||
|
||||
// Tell the superclass we're starting a frame
|
||||
PostFrameStart();
|
||||
}
|
||||
|
||||
if (mColors && mPos >= mLOH) {
|
||||
|
@ -315,7 +315,8 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
mContainedDecoder = new nsPNGDecoder(mImage);
|
||||
mContainedDecoder->SetObserver(mObserver);
|
||||
mContainedDecoder->SetSizeDecode(IsSizeDecode());
|
||||
mContainedDecoder->InitSharedDecoder();
|
||||
mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength,
|
||||
mColormap, mColormapSize);
|
||||
if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE)) {
|
||||
return;
|
||||
}
|
||||
@ -384,7 +385,8 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
bmpDecoder->SetUseAlphaData(true);
|
||||
mContainedDecoder->SetObserver(mObserver);
|
||||
mContainedDecoder->SetSizeDecode(IsSizeDecode());
|
||||
mContainedDecoder->InitSharedDecoder();
|
||||
mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength,
|
||||
mColormap, mColormapSize);
|
||||
|
||||
// The ICO format when containing a BMP does not include the 14 byte
|
||||
// bitmap file header. To use the code of the BMP decoder we need to
|
||||
|
@ -37,7 +37,6 @@ nsIconDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
|
||||
// We put this here to avoid errors about crossing initialization with case
|
||||
// jumps on linux.
|
||||
uint32_t bytesToRead = 0;
|
||||
nsresult rv;
|
||||
|
||||
// Loop until the input data is gone
|
||||
while (aCount > 0) {
|
||||
@ -72,18 +71,11 @@ nsIconDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the frame and signal
|
||||
rv = mImage.EnsureFrame(0, 0, 0, mWidth, mHeight,
|
||||
gfxASurface::ImageFormatARGB32,
|
||||
&mImageData, &mImageDataLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
PostDecoderError(rv);
|
||||
if (!mImageData) {
|
||||
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the superclass we're starting a frame
|
||||
PostFrameStart();
|
||||
|
||||
// Book Keeping
|
||||
aBuffer++;
|
||||
aCount--;
|
||||
|
@ -371,10 +371,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
|
||||
/* Used to set up image size so arrays can be allocated */
|
||||
jpeg_calc_output_dimensions(&mInfo);
|
||||
|
||||
uint32_t imagelength;
|
||||
if (NS_FAILED(mImage.EnsureFrame(0, 0, 0, mInfo.image_width, mInfo.image_height,
|
||||
gfxASurface::ImageFormatRGB24,
|
||||
&mImageData, &imagelength))) {
|
||||
if (!mImageData) {
|
||||
mState = JPEG_ERROR;
|
||||
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
|
||||
PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
|
||||
@ -386,9 +383,6 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
|
||||
(" JPEGDecoderAccounting: nsJPEGDecoder::Write -- created image frame with %ux%u pixels",
|
||||
mInfo.image_width, mInfo.image_height));
|
||||
|
||||
// Tell the superclass we're starting a frame
|
||||
PostFrameStart();
|
||||
|
||||
mState = JPEG_START_DECOMPRESS;
|
||||
}
|
||||
|
||||
@ -542,7 +536,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
|
||||
void
|
||||
nsJPEGDecoder::NotifyDone()
|
||||
{
|
||||
PostFrameStop();
|
||||
PostFrameStop(RasterImage::kFrameOpaque);
|
||||
PostDecodeDone();
|
||||
}
|
||||
|
||||
|
@ -174,12 +174,7 @@ nsWBMPDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the frame and signal
|
||||
nsresult rv = mImage.EnsureFrame(0, 0, 0, mWidth, mHeight,
|
||||
gfxASurface::ImageFormatRGB24,
|
||||
(uint8_t**)&mImageData, &mImageDataLength);
|
||||
|
||||
if (NS_FAILED(rv) || !mImageData) {
|
||||
if (!mImageData) {
|
||||
PostDecoderError(NS_ERROR_FAILURE);
|
||||
mState = DecodingFailed;
|
||||
return;
|
||||
@ -193,9 +188,6 @@ nsWBMPDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the superclass we're starting a frame
|
||||
PostFrameStart();
|
||||
|
||||
mState = DecodingImageData;
|
||||
|
||||
} else if (heightReadResult == IntParseFailed) {
|
||||
|
@ -52,16 +52,24 @@ Decoder::Init()
|
||||
|
||||
// Implementation-specific initialization
|
||||
InitInternal();
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
// Initializes a decoder whose image and observer is already being used by a
|
||||
// parent decoder
|
||||
void
|
||||
Decoder::InitSharedDecoder()
|
||||
Decoder::InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength,
|
||||
uint32_t* colormap, uint32_t colormapSize)
|
||||
{
|
||||
// No re-initializing
|
||||
NS_ABORT_IF_FALSE(!mInitialized, "Can't re-initialize a decoder!");
|
||||
NS_ABORT_IF_FALSE(mObserver, "Need an observer!");
|
||||
|
||||
mImageData = imageData;
|
||||
mImageDataLength = imageDataLength;
|
||||
mColormap = colormap;
|
||||
mColormapSize = colormapSize;
|
||||
|
||||
// Implementation-specific initialization
|
||||
InitInternal();
|
||||
@ -81,35 +89,26 @@ Decoder::Write(const char* aBuffer, uint32_t aCount)
|
||||
if (HasDataError())
|
||||
return;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Preallocate a frame if we've been asked to.
|
||||
if (mNeedsNewFrame) {
|
||||
rv = AllocateFrame();
|
||||
if (NS_FAILED(rv)) {
|
||||
PostDataError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the data along to the implementation
|
||||
WriteInternal(aBuffer, aCount);
|
||||
|
||||
// If the decoder told us that it needs a new frame to proceed, let's create
|
||||
// one and call it again.
|
||||
while (mNeedsNewFrame && !HasDataError()) {
|
||||
nsresult rv;
|
||||
if (mNewFrameData.mPaletteDepth) {
|
||||
rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX,
|
||||
mNewFrameData.mOffsetY, mNewFrameData.mWidth,
|
||||
mNewFrameData.mHeight, mNewFrameData.mFormat,
|
||||
mNewFrameData.mPaletteDepth,
|
||||
&mImageData, &mImageDataLength,
|
||||
&mColormap, &mColormapSize);
|
||||
} else {
|
||||
rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX,
|
||||
mNewFrameData.mOffsetY, mNewFrameData.mWidth,
|
||||
mNewFrameData.mHeight, mNewFrameData.mFormat,
|
||||
&mImageData, &mImageDataLength);
|
||||
}
|
||||
|
||||
// Release our new frame data before talking to anyone else so they can
|
||||
// tell us if they need yet another.
|
||||
mNeedsNewFrame = false;
|
||||
nsresult rv = AllocateFrame();
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// We've now created our frame, so be sure we keep track of it correctly.
|
||||
PostFrameStart();
|
||||
|
||||
// Tell the decoder to use the data it saved when it asked for a new frame.
|
||||
WriteInternal(nullptr, 0);
|
||||
} else {
|
||||
@ -189,6 +188,37 @@ Decoder::FinishSharedDecoder()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
Decoder::AllocateFrame()
|
||||
{
|
||||
MOZ_ASSERT(mNeedsNewFrame);
|
||||
|
||||
nsresult rv;
|
||||
if (mNewFrameData.mPaletteDepth) {
|
||||
rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX,
|
||||
mNewFrameData.mOffsetY, mNewFrameData.mWidth,
|
||||
mNewFrameData.mHeight, mNewFrameData.mFormat,
|
||||
mNewFrameData.mPaletteDepth,
|
||||
&mImageData, &mImageDataLength,
|
||||
&mColormap, &mColormapSize);
|
||||
} else {
|
||||
rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX,
|
||||
mNewFrameData.mOffsetY, mNewFrameData.mWidth,
|
||||
mNewFrameData.mHeight, mNewFrameData.mFormat,
|
||||
&mImageData, &mImageDataLength);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PostFrameStart();
|
||||
}
|
||||
|
||||
// Mark ourselves as not needing another frame before talking to anyone else
|
||||
// so they can tell us if they need yet another.
|
||||
mNeedsNewFrame = false;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
Decoder::FlushInvalidations()
|
||||
{
|
||||
|
@ -34,7 +34,8 @@ public:
|
||||
*
|
||||
* Notifications Sent: TODO
|
||||
*/
|
||||
void InitSharedDecoder();
|
||||
void InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength,
|
||||
uint32_t* colormap, uint32_t colormapSize);
|
||||
|
||||
/**
|
||||
* Writes data to the decoder.
|
||||
@ -134,6 +135,18 @@ public:
|
||||
|
||||
ImageMetadata& GetImageMetadata() { return mImageMetadata; }
|
||||
|
||||
// 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.
|
||||
// This is called by decoders when they need a new frame. These decoders
|
||||
// must then save the data they have been sent but not yet processed and
|
||||
// return from WriteInternal. When the new frame is created, WriteInternal
|
||||
// will be called again with nullptr and 0 as arguments.
|
||||
void NeedNewFrame(uint32_t frameNum, uint32_t x_offset, uint32_t y_offset,
|
||||
uint32_t width, uint32_t height,
|
||||
gfxASurface::gfxImageFormat format,
|
||||
uint8_t palette_depth = 0);
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
@ -184,14 +197,9 @@ protected:
|
||||
void PostDataError();
|
||||
void PostDecoderError(nsresult aFailCode);
|
||||
|
||||
// This is called by decoders when they need a new frame. These decoders
|
||||
// must then save the data they have been sent but not yet processed and
|
||||
// return from WriteInternal. When the new frame is created, WriteInternal
|
||||
// will be called again with nullptr and 0 as arguments.
|
||||
void NeedNewFrame(uint32_t frameNum, uint32_t x_offset, uint32_t y_offset,
|
||||
uint32_t width, uint32_t height,
|
||||
gfxASurface::gfxImageFormat format,
|
||||
uint8_t palette_depth = 0);
|
||||
// Try to allocate a frame as described in mNewFrameData and return the
|
||||
// status code from that attempt. Clears mNewFrameData.
|
||||
nsresult AllocateFrame();
|
||||
|
||||
/*
|
||||
* Member variables.
|
||||
|
@ -2618,6 +2618,13 @@ RasterImage::InitDecoder(bool aDoSizeDecode)
|
||||
mDecoder->SetObserver(mDecodeRequest->mStatusTracker->GetDecoderObserver());
|
||||
mDecoder->SetSizeDecode(aDoSizeDecode);
|
||||
mDecoder->SetDecodeFlags(mFrameDecodeFlags);
|
||||
if (!aDoSizeDecode) {
|
||||
// We already have the size; tell the decoder so it can preallocate a
|
||||
// frame. By default, we create an ARGB frame with no offset. If decoders
|
||||
// need a different type, they need to ask for it themselves.
|
||||
mDecoder->NeedNewFrame(0, 0, 0, mSize.width, mSize.height,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
}
|
||||
mDecoder->Init();
|
||||
CONTAINER_ENSURE_SUCCESS(mDecoder->GetDecoderError());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user