Commit 1316de19 authored by pavlov%pavlov.net's avatar pavlov%pavlov.net
Browse files

additional speedups from bug 331298. r=vlad

parent 9fe39c19
Loading
Loading
Loading
Loading
+9 −25
Original line number Diff line number Diff line
@@ -501,46 +501,30 @@ int nsGIFDecoder2::HaveDecodedRow(
                                           bpr, (aRowNumber+i)*bpr);
      }
    } else {
      PRUint8* rgbRowIndex = decoder->mRGBLine;
      PRUint8* rowBufIndex = aRowBufPtr;

#if defined(MOZ_CAIRO_GFX)
      PRUint32 *rgbRowIndex = (PRUint32*)decoder->mRGBLine;
      while (rowBufIndex != decoder->mGIFStruct->rowend) {
        if (*rowBufIndex >= cmapsize ||
            ((format == gfxIFormats::RGB_A1 || format == gfxIFormats::BGR_A1) &&
             (*rowBufIndex == decoder->mGIFStruct->tpixel))) {
          *rgbRowIndex++ = 0;
          *rgbRowIndex++ = 0;
          *rgbRowIndex++ = 0;
          *rgbRowIndex++ = 0;
          *rgbRowIndex++ = 0x00000000;
          ++rowBufIndex;
          continue;
        }

        const PRUint32 colorIndex = *rowBufIndex * 3;
        const PRUint8 r = cmap[colorIndex];     // red
        const PRUint8 g = cmap[colorIndex + 1]; // green
        const PRUint8 b = cmap[colorIndex + 2]; // blue
#ifdef IS_LITTLE_ENDIAN
        // BGRX
        *rgbRowIndex++ = b;
        *rgbRowIndex++ = g;
        *rgbRowIndex++ = r;
        *rgbRowIndex++ = 0xFF;
#else
        // XRGB
        *rgbRowIndex++ = 0xFF;
        *rgbRowIndex++ = r;
        *rgbRowIndex++ = g;
        *rgbRowIndex++ = b;
#endif
        PRUint32 colorIndex = *rowBufIndex * 3;
        *rgbRowIndex++ = (0xFF << 24) |
          (cmap[colorIndex] << 16) |
          (cmap[colorIndex+1] << 8) |
          (cmap[colorIndex+2]);
        ++rowBufIndex;
      }
      for (int i=0; i<aDuplicateCount; i++)
        decoder->mImageFrame->SetImageData(decoder->mRGBLine, bpr, (aRowNumber+i)*bpr);


#else
      PRUint8* rgbRowIndex = decoder->mRGBLine;
      switch (format) {
        case gfxIFormats::RGB:
        case gfxIFormats::BGR:
+43 −33
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Stuart Parmenter <pavlov@netscape.com>
 *   Stuart Parmenter <stuart@mozilla.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -47,6 +47,8 @@
#include "nspr.h"
#include "nsCRT.h"
#include "ImageLogging.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"

#include "jerror.h"

@@ -93,7 +95,9 @@ nsJPEGDecoder::nsJPEGDecoder()
  mFillState = READING_BACK;

  mSamples = nsnull;
#ifndef MOZ_CAIRO_GFX
  mRGBRow = nsnull;
#endif

  mBytesToSkip = 0;
  
@@ -115,8 +119,10 @@ nsJPEGDecoder::~nsJPEGDecoder()
    PR_Free(mBuffer);
  if (mBackBuffer)
    PR_Free(mBackBuffer);
#ifndef MOZ_CAIRO_GFX
  if (mRGBRow)
    PR_Free(mRGBRow);
#endif
}


@@ -363,9 +369,11 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
                                           JPOOL_IMAGE,
                                           row_stride, 1);

#if defined(MOZ_CAIRO_GFX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(XP_MAC) || defined(XP_MACOSX) || defined(MOZ_WIDGET_PHOTON)
#ifndef MOZ_CAIRO_GFX
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(XP_MAC) || defined(XP_MACOSX) || defined(MOZ_WIDGET_PHOTON)
    // allocate buffer to do byte flipping / padding
    mRGBRow = (PRUint8*) PR_MALLOC(row_stride);
#endif
#endif

    mState = JPEG_START_DECOMPRESS;
@@ -506,8 +514,30 @@ nsJPEGDecoder::OutputScanlines()
  PRUint32 top = mInfo.output_scanline;
  PRBool rv = PR_TRUE;

  PRUint32 bpr;
  mFrame->GetImageBytesPerRow(&bpr);

  // Note! row_stride here must match the row_stride in
  // nsJPEGDecoder::WriteFrom
#if defined(MOZ_CAIRO_GFX) || defined(XP_MAC) || defined(XP_MACOSX)
  const int row_stride = mInfo.output_width << 2; // * 4
#else
  const int row_stride = mInfo.output_width * 3;
#endif

#if defined(MOZ_CAIRO_GFX)
  // we're thebes. we can write stuff directly to the data
  PRUint8 *imageData;
  PRUint32 imageDataLength;
  mFrame->GetImageData(&imageData, &imageDataLength);
  nsCOMPtr<nsIImage> img(do_GetInterface(mFrame));
  nsIntRect r(0, 0, mInfo.output_width, 1);
#endif

  while ((mInfo.output_scanline < mInfo.output_height)) {
#ifndef MOZ_CAIRO_GFX
      JSAMPROW samples;
#endif

      /* Request one scanline.  Returns 0 or 1 scanlines. */
      int ns = jpeg_read_scanlines(&mInfo, mSamples, 1);
@@ -518,31 +548,20 @@ nsJPEGDecoder::OutputScanlines()
      }

#if defined(MOZ_CAIRO_GFX)
      PRUint8 *ptrOutputBuf = mRGBRow;

      PRUint32 offset = (mInfo.output_scanline - 1) * bpr;
      PRUint32 *ptrOutputBuf = (PRUint32*)(imageData + offset);
      JSAMPLE *j1 = mSamples[0];
      for (PRUint32 i=0; i < mInfo.output_width; ++i) {
        const PRUint8 r = *j1++;
        const PRUint8 g = *j1++;
        const PRUint8 b = *j1++;
#ifdef IS_LITTLE_ENDIAN
        // BGRX
        *ptrOutputBuf++ = b;
        *ptrOutputBuf++ = g;
        *ptrOutputBuf++ = r;
        *ptrOutputBuf++ = 0xFF;
#else
        // XRGB
        *ptrOutputBuf++ = 0xFF;
        *ptrOutputBuf++ = r;
        *ptrOutputBuf++ = g;
        *ptrOutputBuf++ = b;
#endif
        PRUint8 r = *j1++;
        PRUint8 g = *j1++;
        PRUint8 b = *j1++;
        *ptrOutputBuf++ = (0xFF << 24) | (r << 16) | (g << 8) | b;
      }
      r.y = mInfo.output_scanline;
      img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
#else

      samples = mRGBRow;

#elif defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
      PRUint8 *ptrOutputBuf = mRGBRow;

      JSAMPLE *j1 = mSamples[0];
@@ -571,20 +590,11 @@ nsJPEGDecoder::OutputScanlines()
      samples = mSamples[0];
#endif

      // Note! row_stride here must match the row_stride in
      // nsJPEGDecoder::WriteFrom
#if defined(MOZ_CAIRO_GFX) || defined(XP_MAC) || defined(XP_MACOSX)
      int row_stride = mInfo.output_width * 4;
#else
      int row_stride = mInfo.output_width * 3;
#endif

      PRUint32 bpr;
      mFrame->GetImageBytesPerRow(&bpr);
      mFrame->SetImageData(
        samples,             // data
        row_stride,          // length
        (mInfo.output_scanline-1) * bpr); // offset
#endif
  }

  if (top != mInfo.output_scanline) {
+2 −0
Original line number Diff line number Diff line
@@ -110,7 +110,9 @@ public:
  jstate mState;

  JSAMPARRAY mSamples;
#ifndef MOZ_CAIRO_GFX
  PRUint8*   mRGBRow;
#endif

  PRInt32 mCompletedPasses;
  PRInt32 mPasses;
+55 −81
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@
#include "nsIInputStream.h"

#include "imgIContainerObserver.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"

#include "nsColor.h"

@@ -67,7 +69,10 @@ NS_IMPL_ISUPPORTS1(nsPNGDecoder, imgIDecoder)

nsPNGDecoder::nsPNGDecoder() :
  mPNG(nsnull), mInfo(nsnull),
  colorLine(nsnull), alphaLine(nsnull),
#ifndef MOZ_CAIRO_GFX
  colorLine(nsnull),
  alphaLine(nsnull),
#endif
  interlacebuf(nsnull), ibpr(0),
  mError(PR_FALSE)
{
@@ -75,10 +80,12 @@ nsPNGDecoder::nsPNGDecoder() :

nsPNGDecoder::~nsPNGDecoder()
{
#ifndef MOZ_CAIRO_GFX
  if (colorLine)
    nsMemory::Free(colorLine);
  if (alphaLine)
    nsMemory::Free(alphaLine);
#endif
  if (interlacebuf)
    nsMemory::Free(interlacebuf);
}
@@ -348,13 +355,15 @@ info_callback(png_structp png_ptr, png_infop info_ptr)
  if (decoder->mObserver)
    decoder->mObserver->OnStartFrame(nsnull, decoder->mFrame);

  PRUint32 bpr, abpr;
  PRUint32 bpr;
  decoder->mFrame->GetImageBytesPerRow(&bpr);
#ifndef MOZ_CAIRO_GFX
  PRUint32 abpr;
  decoder->mFrame->GetAlphaBytesPerRow(&abpr);
  decoder->colorLine = (PRUint8 *)nsMemory::Alloc(bpr);
  if (channels > 3)
    decoder->alphaLine = (PRUint8 *)nsMemory::Alloc(abpr);

#endif
  if (interlace_type == PNG_INTERLACE_ADAM7) {
    if (channels > 3)
      decoder->ibpr = channels*width;
@@ -425,7 +434,17 @@ row_callback(png_structp png_ptr, png_bytep new_row,

    gfx_format format;
    decoder->mFrame->GetFormat(&format);
#ifndef MOZ_CAIRO_GFX
    PRUint8 *aptr, *cptr;
#else
    // we're thebes. we can write stuff directly to the data
    PRUint8 *imageData;
    PRUint32 imageDataLength;
    decoder->mFrame->GetImageData(&imageData, &imageDataLength);
    nsCOMPtr<nsIImage> img(do_GetInterface(decoder->mFrame));
#endif
    nsIntRect r(0, row_num, width, 1);


    // The mac specific ifdefs in the code below are there to make sure we
    // always fill in 4 byte pixels right now, which is what the mac always
@@ -437,26 +456,16 @@ row_callback(png_structp png_ptr, png_bytep new_row,
    case gfxIFormats::BGR:
      {
#if defined(MOZ_CAIRO_GFX)
        cptr = decoder->colorLine;
        PRUint32 *cptr32 = (PRUint32*)(imageData + (row_num*bpr));
        for (PRUint32 x=0; x<iwidth; x++) {
          const PRUint8 r = *line++;
          const PRUint8 g = *line++;
          const PRUint8 b = *line++;
#ifdef IS_LITTLE_ENDIAN
          // BGRX
          *cptr++ = b;
          *cptr++ = g;
          *cptr++ = r;
          *cptr++ = 0xFF;
#else
          // XRGB
          *cptr++ = 0xFF;
          *cptr++ = r;
          *cptr++ = g;
          *cptr++ = b;
#endif
          PRUint8 r = *line++;
          PRUint8 g = *line++;
          PRUint8 b = *line++;
          *cptr32++ = (0xFF << 24) | (r << 16) | (g << 8) | b;
        }
        decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
        r.y = row_num;
        img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);

#elif defined(XP_MAC) || defined(XP_MACOSX)
        cptr = decoder->colorLine;
        for (PRUint32 x=0; x<iwidth; x++) {
@@ -475,33 +484,21 @@ row_callback(png_structp png_ptr, png_bytep new_row,
    case gfxIFormats::BGR_A1:
      {
#if defined(MOZ_CAIRO_GFX)
        cptr = decoder->colorLine;
        PRUint32 *cptr32 = (PRUint32*)(imageData + (row_num*bpr));
        for (PRUint32 x=0; x<iwidth; x++) {
          if (line[3]) {
            const PRUint8 r = *line++;
            const PRUint8 g = *line++;
            const PRUint8 b = *line++;
#ifdef IS_LITTLE_ENDIAN
            *cptr++ = b;
            *cptr++ = g;
            *cptr++ = r;
            *cptr++ = 0xFF;
#else
            *cptr++ = 0xFF;
            *cptr++ = r;
            *cptr++ = g;
            *cptr++ = b;
#endif
            PRUint8 r = *line++;
            PRUint8 g = *line++;
            PRUint8 b = *line++;
            line++;
            *cptr32++ = (0xFF << 24) | (r << 16) | (g << 8) | b;
          } else {
            *cptr++ = 0;
            *cptr++ = 0;
            *cptr++ = 0;
            *cptr++ = 0;
            *cptr32++ = 0x00000000;
            line += 4;
          }
        }
        decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
        r.y = row_num;
        img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);

#else
        cptr = decoder->colorLine;
@@ -532,52 +529,30 @@ row_callback(png_structp png_ptr, png_bytep new_row,
    case gfxIFormats::RGB_A8:
    case gfxIFormats::BGR_A8:
      {
        cptr = decoder->colorLine;
        aptr = decoder->alphaLine;
#if defined(MOZ_CAIRO_GFX)
        PRUint32 *cptr32 = (PRUint32*)(imageData + (row_num*bpr));
        for (PRUint32 x=0; x<iwidth; x++) {
          const PRUint8 r = *line++;
          const PRUint8 g = *line++;
          const PRUint8 b = *line++;
          const PRUint8 a = *line++;
          if (a == 0) {
            *cptr++ = 0;
            *cptr++ = 0;
            *cptr++ = 0;
            *cptr++ = 0;
          } else if (a == 0xFF) {
#ifdef IS_LITTLE_ENDIAN
            // BGRA
            *cptr++ = b;
            *cptr++ = g;
            *cptr++ = r;
            *cptr++ = a;
#else
            // ARGB
            *cptr++ = a;
            *cptr++ = r;
            *cptr++ = b;
            *cptr++ = g;
#endif
          PRUint8 r = *line++;
          PRUint8 g = *line++;
          PRUint8 b = *line++;
          PRUint8 a = *line++;
          if (a == 0xFF) {
            *cptr32++ = (0xFF << 24) | (r << 16) | (g << 8) | b;
          } else if (a == 0x00) {
            *cptr32++ = 0x00000000;
          } else {
#ifdef IS_LITTLE_ENDIAN
            // BGRA
            FAST_DIVIDE_BY_255(*cptr++, b*a);
            FAST_DIVIDE_BY_255(*cptr++, g*a);
            FAST_DIVIDE_BY_255(*cptr++, r*a);
            *cptr++ = a;
#else
            // ARGB
            *cptr++ = a;
            FAST_DIVIDE_BY_255(*cptr++, r*a);
            FAST_DIVIDE_BY_255(*cptr++, g*a);
            FAST_DIVIDE_BY_255(*cptr++, b*a);
#endif
            FAST_DIVIDE_BY_255(r, r*a);
            FAST_DIVIDE_BY_255(g, g*a);
            FAST_DIVIDE_BY_255(b, b*a);
            *cptr32++ = (a << 24) | (r << 16) | (g << 8) | b;
          }
        }
        decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);

        r.y = row_num;
        img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
#else
        cptr = decoder->colorLine;
        aptr = decoder->alphaLine;
        for (PRUint32 x=0; x<iwidth; x++) {
#if defined(XP_MAC) || defined(XP_MACOSX)
          *cptr++ = 0;
@@ -594,7 +569,6 @@ row_callback(png_structp png_ptr, png_bytep new_row,
      break;
    }

    nsIntRect r(0, row_num, width, 1);
    decoder->mObserver->OnDataAvailable(nsnull, decoder->mFrame, &r);
  }
}
+2 −0
Original line number Diff line number Diff line
@@ -77,7 +77,9 @@ public:

  png_structp mPNG;
  png_infop mInfo;
#ifndef MOZ_CAIRO_GFX
  PRUint8 *colorLine, *alphaLine;
#endif
  PRUint8 *interlacebuf;
  PRUint32 ibpr;
  PRPackedBool mError;