From 0ba32b706d95c41840d0da4c12c0ef2ea43ecc0c Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 14 Apr 2009 15:12:38 -0700 Subject: [PATCH] b=484864; StretchDIBits takes too long (Do 32->24 conversion before calling StretchDIBits); r=jrmuizel --- widget/src/windows/nsWindow.cpp | 66 +++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 5672a4c095a8..818746915cf4 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -84,6 +84,9 @@ #define PAINT_USE_IMAGE_SURFACE +// do 32->24 conversion before calling StretchDIBits +#define PAINT_USE_IMAGE_SURFACE_24BPP + #ifdef WINCE_WINDOWS_MOBILE #define WINCE_HAVE_SOFTKB #include "tpcshell.h" @@ -6075,6 +6078,69 @@ PRBool nsWindow::OnPaint(HDC aDC) bi.biBitCount = 32; bi.biCompression = BI_RGB; +#ifdef PAINT_USE_IMAGE_SURFACE_24BPP + // On Windows CE/Windows Mobile, 24bpp packed-pixel sources + // seem to be far faster to blit than 32bpp (see bug 484864). + // So, convert the bits to 24bpp by stripping out the unused + // alpha byte. 24bpp DIBs also have scanlines that are 4-byte + // aligned though, so that must be taken into account. + int srcstride = surfaceSize.width*4; + int dststride = surfaceSize.width*3; + dststride = (dststride + 3) & ~3; + + // Convert in place + for (int j = 0; j < surfaceSize.height; ++j) { + unsigned int *src = (unsigned int*) (targetSurface->Data() + j*srcstride); + unsigned int *dst = (unsigned int*) (targetSurface->Data() + j*dststride); + + // go 4 pixels at a time, since each 4 pixels + // turns into 3 DWORDs when converted into BGR: + // BGRx BGRx BGRx BGRx -> BGRB GRBG RBGR + // + // However, since we're dealing with little-endian ints, this is actually: + // xRGB xrgb xRGB xrgb -> bRGB GBrg rgbR + int width_left = surfaceSize.width; + while (width_left > 4) { + unsigned int a = *src++; + unsigned int b = *src++; + unsigned int c = *src++; + unsigned int d = *src++; + + *dst++ = (a & 0x00ffffff) | (b << 24); + *dst++ = ((b & 0x00ffff00) >> 8) | (c << 16); + *dst++ = ((c & 0x00ff0000) >> 16) | (d << 8); + + width_left -= 4; + } + + // then finish up whatever number of pixels are left, + // using bytes. + unsigned char *bsrc = (unsigned char*) src; + unsigned char *bdst = (unsigned char*) dst; + switch (width_left) { + case 3: + *bdst++ = *bsrc++; + *bdst++ = *bsrc++; + *bdst++ = *bsrc++; + bsrc++; + case 2: + *bdst++ = *bsrc++; + *bdst++ = *bsrc++; + *bdst++ = *bsrc++; + bsrc++; + case 1: + *bdst++ = *bsrc++; + *bdst++ = *bsrc++; + *bdst++ = *bsrc++; + bsrc++; + case 0: + break; + } + } + + bi.biBitCount = 24; +#endif + StretchDIBits(hDC, ps.rcPaint.left, ps.rcPaint.top, surfaceSize.width, surfaceSize.height,