зеркало из https://github.com/mozilla/pjs.git
b=391583, DoesARGBImageDataHaveAlpha is slow, r=stuart,a=me
This commit is contained in:
Родитель
1572e3189c
Коммит
e7ae74d226
|
@ -258,9 +258,22 @@ public:
|
|||
*/
|
||||
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels) = 0;
|
||||
|
||||
#ifdef MOZ_CAIRO_GFX
|
||||
/**
|
||||
* GetSurface
|
||||
* Return the Thebes gfxASurface in aSurface.
|
||||
*
|
||||
* aSurface will be AddRef'd (as with most getters), so
|
||||
* getter_AddRefs should be used.
|
||||
*/
|
||||
NS_IMETHOD GetSurface(gfxASurface **aSurface) = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SetHasNoAlpha
|
||||
*
|
||||
* Hint to the image that all the pixels are fully opaque, even if
|
||||
* the original format requested a 1-bit or 8-bit alpha mask
|
||||
*/
|
||||
virtual void SetHasNoAlpha() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIImage, NS_IIMAGE_IID)
|
||||
|
|
|
@ -551,4 +551,3 @@ NS_IMETHODIMP gfxImageFrame::GetInterface(const nsIID & aIID, void * *result)
|
|||
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
|
|
@ -606,3 +606,16 @@ nsThebesImage::ShouldUseImageSurfaces()
|
|||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// A hint from the image decoders that this image has no alpha, even
|
||||
// though we created is ARGB32. This changes our format to RGB24,
|
||||
// which in turn will cause us to Optimize() to RGB24. Has no effect
|
||||
// after Optimize() is called, though in all cases it will be just a
|
||||
// performance win -- the pixels are still correct and have the A byte
|
||||
// set to 0xff.
|
||||
void
|
||||
nsThebesImage::SetHasNoAlpha()
|
||||
{
|
||||
if (mFormat == gfxASurface::ImageFormatARGB32)
|
||||
mFormat = gfxASurface::ImageFormatRGB24;
|
||||
}
|
||||
|
|
|
@ -103,6 +103,8 @@ public:
|
|||
return mImageSurface;
|
||||
}
|
||||
|
||||
void SetHasNoAlpha();
|
||||
|
||||
protected:
|
||||
static PRBool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight) {
|
||||
NS_ASSERTION(aWidth > 0, "invalid image width");
|
||||
|
|
|
@ -134,12 +134,6 @@ public:
|
|||
virtual gfxFontGroup *CreateFontGroup(const nsAString& aFamilies,
|
||||
const gfxFontStyle *aStyle) = 0;
|
||||
|
||||
/* Returns PR_TRUE if the given block of ARGB32 data really has alpha, otherwise PR_FALSE */
|
||||
static PRBool DoesARGBImageDataHaveAlpha(PRUint8* data,
|
||||
PRUint32 width,
|
||||
PRUint32 height,
|
||||
PRUint32 stride);
|
||||
|
||||
void GetPrefFonts(const char *aLangGroup, nsString& array, PRBool aAppendUnicode = PR_TRUE);
|
||||
|
||||
/**
|
||||
|
|
|
@ -181,26 +181,6 @@ gfxPlatform::SetUseGlitz(PRBool use)
|
|||
gGlitzState = (use ? 1 : 0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxPlatform::DoesARGBImageDataHaveAlpha(PRUint8* data,
|
||||
PRUint32 width,
|
||||
PRUint32 height,
|
||||
PRUint32 stride)
|
||||
{
|
||||
PRUint32 *r;
|
||||
|
||||
for (PRUint32 j = 0; j < height; j++) {
|
||||
r = (PRUint32*) (data + stride*j);
|
||||
for (PRUint32 i = 0; i < width; i++) {
|
||||
if ((*r++ & 0xff000000) != 0xff000000) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
gfxPlatform::OptimizeImage(gfxImageSurface *aSurface)
|
||||
{
|
||||
|
@ -208,17 +188,6 @@ gfxPlatform::OptimizeImage(gfxImageSurface *aSurface)
|
|||
|
||||
gfxASurface::gfxImageFormat realFormat = aSurface->Format();
|
||||
|
||||
if (realFormat == gfxASurface::ImageFormatARGB32) {
|
||||
// this might not really need alpha; figure that out
|
||||
if (!DoesARGBImageDataHaveAlpha(aSurface->Data(),
|
||||
surfaceSize.width,
|
||||
surfaceSize.height,
|
||||
aSurface->Stride()))
|
||||
{
|
||||
realFormat = gfxASurface::ImageFormatRGB24;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> optSurface = CreateOffscreenSurface(surfaceSize, realFormat);
|
||||
|
||||
if (!optSurface)
|
||||
|
|
|
@ -119,16 +119,6 @@ already_AddRefed<gfxWindowsSurface>
|
|||
gfxWindowsSurface::OptimizeToDDB(HDC dc, const gfxIntSize& size, gfxImageFormat format)
|
||||
{
|
||||
gfxImageFormat realFormat = format;
|
||||
if (realFormat == ImageFormatARGB32) {
|
||||
cairo_surface_t *isurf = cairo_win32_surface_get_image(CairoSurface());
|
||||
if (isurf && !gfxPlatform::DoesARGBImageDataHaveAlpha(cairo_image_surface_get_data(isurf),
|
||||
cairo_image_surface_get_width(isurf),
|
||||
cairo_image_surface_get_height(isurf),
|
||||
cairo_image_surface_get_stride(isurf)))
|
||||
{
|
||||
realFormat = ImageFormatRGB24;
|
||||
}
|
||||
}
|
||||
|
||||
if (realFormat != ImageFormatRGB24)
|
||||
return nsnull;
|
||||
|
|
|
@ -77,6 +77,9 @@ mailing address.
|
|||
#include "prlog.h"
|
||||
#include "GIF2.h"
|
||||
|
||||
#include "nsIImage.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
||||
#include "nsGIFDecoder2.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
@ -320,6 +323,7 @@ void nsGIFDecoder2::EndGIF()
|
|||
void nsGIFDecoder2::BeginImageFrame()
|
||||
{
|
||||
mImageFrame = nsnull; // clear out our current frame reference
|
||||
mFrameHasNoAlpha = PR_TRUE;
|
||||
|
||||
if (!mGIFStruct.images_decoded) {
|
||||
// Send a onetime OnDataAvailable (Display Refresh) for the first frame
|
||||
|
@ -350,6 +354,11 @@ void nsGIFDecoder2::EndImageFrame()
|
|||
// timeout for the image until here to help ensure that we have the whole
|
||||
// image frame decoded before we go off and try to display another frame.
|
||||
mImageFrame->SetTimeout(mGIFStruct.delay_time);
|
||||
|
||||
if (mFrameHasNoAlpha) {
|
||||
nsCOMPtr<nsIImage> img(do_GetInterface(mImageFrame));
|
||||
img->SetHasNoAlpha();
|
||||
}
|
||||
}
|
||||
mImageContainer->EndFrameDecode(mGIFStruct.images_decoded, mGIFStruct.delay_time);
|
||||
|
||||
|
@ -442,12 +451,14 @@ void nsGIFDecoder2::HaveDecodedRow(
|
|||
} else {
|
||||
PRUint8* rowBufIndex = aRowBufPtr;
|
||||
PRUint32* rgbRowIndex = (PRUint32*)mRGBLine;
|
||||
PRBool rowHasNoAlpha = PR_TRUE;
|
||||
|
||||
const PRInt32 tpixel =
|
||||
mGIFStruct.is_transparent ? mGIFStruct.tpixel : -1;
|
||||
|
||||
while (rowBufIndex != mGIFStruct.rowend) {
|
||||
if (*rowBufIndex >= cmapsize || *rowBufIndex == tpixel) {
|
||||
rowHasNoAlpha = PR_FALSE;
|
||||
*rgbRowIndex++ = 0x00000000;
|
||||
++rowBufIndex;
|
||||
continue;
|
||||
|
@ -462,6 +473,8 @@ void nsGIFDecoder2::HaveDecodedRow(
|
|||
}
|
||||
for (int i=0; i<aDuplicateCount; i++)
|
||||
mImageFrame->SetImageData(mRGBLine, bpr, (aRowNumber+i)*bpr);
|
||||
if (!rowHasNoAlpha)
|
||||
mFrameHasNoAlpha = PR_FALSE;
|
||||
}
|
||||
|
||||
mCurrentRow = aRowNumber + aDuplicateCount - 1;
|
||||
|
|
|
@ -102,6 +102,7 @@ private:
|
|||
PRUint8 mCurrentPass;
|
||||
PRUint8 mLastFlushedPass;
|
||||
PRPackedBool mGIFOpen;
|
||||
PRPackedBool mFrameHasNoAlpha;
|
||||
|
||||
gif_struct mGIFStruct;
|
||||
};
|
||||
|
|
|
@ -119,6 +119,8 @@ void nsPNGDecoder::CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
|
|||
|
||||
if (mObserver)
|
||||
mObserver->OnStartFrame(nsnull, mFrame);
|
||||
|
||||
mFrameHasNoAlpha = PR_TRUE;
|
||||
}
|
||||
|
||||
// set timeout and frame disposal method for the current frame
|
||||
|
@ -648,6 +650,7 @@ row_callback(png_structp png_ptr, png_bytep new_row,
|
|||
PRUint32 imageDataLength, bpr = width * sizeof(PRUint32);
|
||||
decoder->mFrame->GetImageData(&imageData, &imageDataLength);
|
||||
PRUint32 *cptr32 = (PRUint32*)(imageData + (row_num*bpr));
|
||||
PRBool rowHasNoAlpha = PR_TRUE;
|
||||
|
||||
if (decoder->mTransform) {
|
||||
if (decoder->mCMSLine) {
|
||||
|
@ -679,6 +682,8 @@ row_callback(png_structp png_ptr, png_bytep new_row,
|
|||
{
|
||||
for (PRUint32 x=iwidth; x>0; --x) {
|
||||
*cptr32++ = GFX_PACKED_PIXEL(line[3]?0xFF:0x00, line[0], line[1], line[2]);
|
||||
if (line[3] == 0)
|
||||
rowHasNoAlpha = PR_FALSE;
|
||||
line += 4;
|
||||
}
|
||||
}
|
||||
|
@ -688,12 +693,17 @@ row_callback(png_structp png_ptr, png_bytep new_row,
|
|||
{
|
||||
for (PRUint32 x=width; x>0; --x) {
|
||||
*cptr32++ = GFX_PACKED_PIXEL(line[3], line[0], line[1], line[2]);
|
||||
if (line[3] != 0xff)
|
||||
rowHasNoAlpha = PR_FALSE;
|
||||
line += 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rowHasNoAlpha)
|
||||
decoder->mFrameHasNoAlpha = PR_FALSE;
|
||||
|
||||
nsIntRect r(0, row_num, width, 1);
|
||||
nsCOMPtr<nsIImage> img(do_GetInterface(decoder->mFrame));
|
||||
img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
|
||||
|
@ -714,6 +724,10 @@ frame_info_callback(png_structp png_ptr, png_uint_32 frame_num)
|
|||
if (!(decoder->apngFlags & FRAME_HIDDEN)) {
|
||||
PRInt32 timeout;
|
||||
decoder->mFrame->GetTimeout(&timeout);
|
||||
if (decoder->mFrameHasNoAlpha) {
|
||||
nsCOMPtr<nsIImage> img(do_GetInterface(decoder->mFrame));
|
||||
img->SetHasNoAlpha();
|
||||
}
|
||||
decoder->mImage->EndFrameDecode(frame_num, timeout);
|
||||
decoder->mObserver->OnStopFrame(nsnull, decoder->mFrame);
|
||||
}
|
||||
|
@ -753,6 +767,10 @@ end_callback(png_structp png_ptr, png_infop info_ptr)
|
|||
if (!(decoder->apngFlags & FRAME_HIDDEN)) {
|
||||
PRInt32 timeout;
|
||||
decoder->mFrame->GetTimeout(&timeout);
|
||||
if (decoder->mFrameHasNoAlpha) {
|
||||
nsCOMPtr<nsIImage> img(do_GetInterface(decoder->mFrame));
|
||||
img->SetHasNoAlpha();
|
||||
}
|
||||
decoder->mImage->EndFrameDecode(decoder->mPNG->num_frames_read, timeout);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ public:
|
|||
PRUint8 apngFlags;
|
||||
PRUint8 mChannels;
|
||||
PRPackedBool mError;
|
||||
PRPackedBool mFrameHasNoAlpha;
|
||||
};
|
||||
|
||||
#endif // nsPNGDecoder_h__
|
||||
|
|
|
@ -52,6 +52,7 @@ LIBXUL_LIBRARY = 1
|
|||
REQUIRES = xpcom \
|
||||
gfx \
|
||||
imglib2 \
|
||||
thebes \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsXBMDecoder.cpp
|
||||
|
|
|
@ -47,19 +47,14 @@
|
|||
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIImage.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
||||
#include "imgILoad.h"
|
||||
|
||||
#include "nsIProperties.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
|
||||
#define GFXFORMAT gfxIFormats::BGR_A1
|
||||
#else
|
||||
#define USE_RGB
|
||||
#define GFXFORMAT gfxIFormats::RGB_A1
|
||||
#endif
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXBMDecoder, imgIDecoder)
|
||||
|
||||
nsXBMDecoder::nsXBMDecoder() : mBuf(nsnull), mPos(nsnull), mAlphaRow(nsnull)
|
||||
|
@ -92,12 +87,18 @@ NS_IMETHODIMP nsXBMDecoder::Init(imgILoad *aLoad)
|
|||
|
||||
mCurRow = mBufSize = mWidth = mHeight = 0;
|
||||
mState = RECV_HEADER;
|
||||
mHasNoAlpha = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXBMDecoder::Close()
|
||||
{
|
||||
if (mHasNoAlpha) {
|
||||
nsCOMPtr<nsIImage> img(do_GetInterface(mFrame));
|
||||
img->SetHasNoAlpha();
|
||||
}
|
||||
|
||||
mObserver->OnStopContainer(nsnull, mImage);
|
||||
mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
|
||||
mObserver = nsnull;
|
||||
|
@ -185,7 +186,7 @@ nsresult nsXBMDecoder::ProcessData(const char* aData, PRUint32 aCount) {
|
|||
mImage->Init(mWidth, mHeight, mObserver);
|
||||
mObserver->OnStartContainer(nsnull, mImage);
|
||||
|
||||
nsresult rv = mFrame->Init(0, 0, mWidth, mHeight, GFXFORMAT, 24);
|
||||
nsresult rv = mFrame->Init(0, 0, mWidth, mHeight, gfxIFormats::RGB_A1, 24);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -240,6 +241,7 @@ nsresult nsXBMDecoder::ProcessData(const char* aData, PRUint32 aCount) {
|
|||
PRUint32 abpr;
|
||||
mFrame->GetAlphaBytesPerRow(&abpr);
|
||||
PRBool hiByte = PR_TRUE;
|
||||
PRBool chunkHasNoAlpha = PR_TRUE;
|
||||
|
||||
do {
|
||||
PRUint32 pixel = strtoul(mPos, &endPtr, 0);
|
||||
|
@ -273,6 +275,8 @@ nsresult nsXBMDecoder::ProcessData(const char* aData, PRUint32 aCount) {
|
|||
for (int i = 0; i < alphas; i++) {
|
||||
const PRUint8 val = ((pixel & (1 << i)) >> i) ? 255 : 0;
|
||||
*ar++ = (val << 24) | 0;
|
||||
if (val == 0)
|
||||
chunkHasNoAlpha = PR_FALSE;
|
||||
}
|
||||
|
||||
mCurCol = PR_MIN(mCurCol + 8, mWidth);
|
||||
|
@ -297,6 +301,9 @@ nsresult nsXBMDecoder::ProcessData(const char* aData, PRUint32 aCount) {
|
|||
if (*mPos == ',')
|
||||
mPos++;
|
||||
} while ((mState == RECV_DATA) && *mPos);
|
||||
|
||||
if (!chunkHasNoAlpha)
|
||||
mHasNoAlpha = PR_FALSE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -90,6 +90,7 @@ private:
|
|||
|
||||
PRPackedBool mIsCursor;
|
||||
PRPackedBool mIsX10; // X10 flavor XBM?
|
||||
PRPackedBool mHasNoAlpha;
|
||||
|
||||
enum {
|
||||
RECV_HEADER,
|
||||
|
|
Загрузка…
Ссылка в новой задаче