summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2013-09-05 13:01:45 +0000
committerCaolán McNamara <caolanm@redhat.com>2013-09-06 11:20:47 +0100
commitc77ec4fe42c064adc507caa2760a99e096f8c016 (patch)
tree8e7b8dc91f83a0b2366331c2bf56fbc67ae4d403 /vcl
parent871cc47c5ea66d1c2f1cbff5d7564202192ea84c (diff)
Resolves: #i122985# Various speedups for graphic object swapping
(cherry picked from commit f18ad6132d79540431bf04f090a7472e21a23e49) Conflicts: svtools/source/filter/jpeg/jpeg.cxx svx/inc/svx/svdundo.hxx svx/source/svdraw/svdograf.cxx vcl/source/gdi/pngread.cxx Change-Id: I733551fa9447eb8f45e9163a9c0189f013b03e82
Diffstat (limited to 'vcl')
-rw-r--r--vcl/source/filter/jpeg/JpegReader.cxx36
-rw-r--r--vcl/source/gdi/pngread.cxx241
2 files changed, 228 insertions, 49 deletions
diff --git a/vcl/source/filter/jpeg/JpegReader.cxx b/vcl/source/filter/jpeg/JpegReader.cxx
index 8b87aa6d9f20..a79f5ca12a02 100644
--- a/vcl/source/filter/jpeg/JpegReader.cxx
+++ b/vcl/source/filter/jpeg/JpegReader.cxx
@@ -354,14 +354,38 @@ void JPEGReader::FillBitmap()
for( long nY = 0L; nY < nHeight; nY++ )
{
- pTmp = (sal_uInt8*) mpBuffer + nY * nAlignedWidth;
+ // #i122985# Added fast-lane implementations using CopyScanline with direct supported mem formats
+ static bool bCheckOwnReader(true);
- for( long nX = 0L; nX < nWidth; nX++ )
+ if(bCheckOwnReader)
+ {
+ // #i122985# Trying to copy the RGB data from jpeg import to make things faster. Unfortunately
+ // it has no GBR format, so RGB three-byte groups need to be 'flipped' to GBR first,
+ // then CopyScanline can use a memcpy to do the data transport. CopyScanline can also
+ // do the needed conversion from BMP_FORMAT_24BIT_TC_RGB (and it works well), but this
+ // is not faster that the old loop below using SetPixel.
+ sal_uInt8* aSource((sal_uInt8*)mpBuffer + nY * nAlignedWidth);
+ sal_uInt8* aEnd(aSource + (nWidth * 3));
+
+ for(sal_uInt8* aTmp(aSource); aTmp < aEnd; aTmp += 3)
+ {
+ ::std::swap(*aTmp, *(aTmp + 2));
+ }
+
+ mpAcc->CopyScanline(nY, aSource, BMP_FORMAT_24BIT_TC_BGR, nWidth * 3);
+ }
+ else
{
- aColor.SetRed( *pTmp++ );
- aColor.SetGreen( *pTmp++ );
- aColor.SetBlue( *pTmp++ );
- mpAcc->SetPixel( nY, nX, aColor );
+ // old version: WritePixel
+ pTmp = (sal_uInt8*) mpBuffer + nY * nAlignedWidth;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aColor.SetRed( *pTmp++ );
+ aColor.SetGreen( *pTmp++ );
+ aColor.SetBlue( *pTmp++ );
+ mpAcc->SetPixel( nY, nX, aColor );
+ }
}
}
}
diff --git a/vcl/source/gdi/pngread.cxx b/vcl/source/gdi/pngread.cxx
index 71fb345326d1..f8b4e9561c3e 100644
--- a/vcl/source/gdi/pngread.cxx
+++ b/vcl/source/gdi/pngread.cxx
@@ -123,6 +123,15 @@ private:
bool mbpHYs; // true if pysical size of pixel available
bool mbIgnoreGammaChunk;
+#ifdef DBG_UTIL
+ // do some checks in debug mode
+ sal_uInt32 mnAllocSizeScanline;
+ sal_uInt32 mnAllocSizeScanlineAlpha;
+#endif
+ // the temporary Scanline (and alpha) for direct scanline copy to Bitmap
+ sal_uInt8* mpScanline;
+ sal_uInt8* mpScanlineAlpha;
+
bool ReadNextChunk();
void ReadRemainingChunks();
@@ -178,7 +187,13 @@ PNGReaderImpl::PNGReaderImpl( SvStream& rPNGStream )
mbIDAT( false ),
mbGamma ( false ),
mbpHYs ( false ),
- mbIgnoreGammaChunk ( false )
+ mbIgnoreGammaChunk ( false ),
+#ifdef DBG_UTIL
+ mnAllocSizeScanline(0),
+ mnAllocSizeScanlineAlpha(0),
+#endif
+ mpScanline(0),
+ mpScanlineAlpha(0)
{
// prepare the PNG data stream
mnOrigStreamMode = mrPNGStream.GetNumberFormatInt();
@@ -222,6 +237,9 @@ PNGReaderImpl::~PNGReaderImpl()
delete[] mpInflateInBuf;
delete[] mpScanPrior;
delete mpZCodec;
+
+ delete[] mpScanline;
+ delete[] mpScanlineAlpha;
}
bool PNGReaderImpl::ReadNextChunk()
@@ -1290,42 +1308,123 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
}
else // no palette => truecolor
{
- if( mbAlphaChannel ) // has RGB + alpha
- { // BMP_FORMAT_32BIT_TC_RGBA
+ // #i122985# Added fast-lane implementations using CopyScanline with direct supported mem formats
+ static bool bCkeckDirectScanline(true);
+
+ if( mbAlphaChannel )
+ {
+ // has RGB + alpha
if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample
{
- if ( mpColorTable != mpDefaultColorTable )
+ // BMP_FORMAT_32BIT_TC_RGBA
+ // only use DirectScanline when we have no preview shifting stuff and accesses to content and alpha
+ const bool bDoDirectScanline(
+ bCkeckDirectScanline && !nXStart && 1 == nXAdd && !mnPreviewShift && mpAcc && mpMaskAcc);
+ const bool bCustomColorTable(mpColorTable != mpDefaultColorTable);
+
+ if(bDoDirectScanline)
{
- for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
- ImplSetAlphaPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
- mpColorTable[ pTmp[ 1 ] ],
- mpColorTable[ pTmp[ 2 ] ] ), pTmp[ 3 ] );
+ // allocate scanlines on demand, reused for next line
+ if(!mpScanline)
+ {
+#ifdef DBG_UTIL
+ mnAllocSizeScanline = maOrigSize.Width() * 3;
+#endif
+ mpScanline = new sal_uInt8[maOrigSize.Width() * 3];
+ }
+
+ if(!mpScanlineAlpha)
+ {
+#ifdef DBG_UTIL
+ mnAllocSizeScanlineAlpha = maOrigSize.Width();
+#endif
+ mpScanlineAlpha = new sal_uInt8[maOrigSize.Width()];
+ }
+ }
+
+ if(bDoDirectScanline)
+ {
+ OSL_ENSURE(mpScanline, "No Scanline allocated (!)");
+ OSL_ENSURE(mpScanlineAlpha, "No ScanlineAlpha allocated (!)");
+ OSL_ENSURE(mnAllocSizeScanline >= maOrigSize.Width() * 3, "Allocated Scanline too small (!)");
+ OSL_ENSURE(mnAllocSizeScanlineAlpha >= maOrigSize.Width(), "Allocated ScanlineAlpha too small (!)");
+ sal_uInt8* pScanline(mpScanline);
+ sal_uInt8* pScanlineAlpha(mpScanlineAlpha);
+
+ for(sal_uInt32 nX(0); nX < maOrigSize.Width(); nX++, pTmp += 4)
+ {
+ // prepare content line as BGR by reordering when copying
+ // do not forget to invert alpha (source is alpha, target is opacity)
+ if(bCustomColorTable)
+ {
+ *pScanline++ = mpColorTable[pTmp[2]];
+ *pScanline++ = mpColorTable[pTmp[1]];
+ *pScanline++ = mpColorTable[pTmp[0]];
+ *pScanlineAlpha++ = ~pTmp[3];
+ }
+ else
+ {
+ *pScanline++ = pTmp[2];
+ *pScanline++ = pTmp[1];
+ *pScanline++ = pTmp[0];
+ *pScanlineAlpha++ = ~pTmp[3];
+ }
+ }
+
+ // copy scanlines directly to bitmaps for content and alpha; use the formats which
+ // are able to copy directly to BitmapBuffer
+ mpAcc->CopyScanline(nY, mpScanline, BMP_FORMAT_24BIT_TC_BGR, maOrigSize.Width() * 3);
+ mpMaskAcc->CopyScanline(nY, mpScanlineAlpha, BMP_FORMAT_8BIT_PAL, maOrigSize.Width());
}
else
{
-// if ( nXAdd == 1 && mnPreviewShift == 0 ) // copy raw line data if possible
-// {
-// int nLineBytes = 4 * maOrigSize.Width();
-// mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_32BIT_TC_RGBA, nLineBytes );
-// pTmp += nLineBytes;
-// }
-// else
+ for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
{
- for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
- ImplSetAlphaPixel( nY, nX, BitmapColor( pTmp[0], pTmp[1], pTmp[2] ), pTmp[3] );
+ if(bCustomColorTable)
+ {
+ ImplSetAlphaPixel(
+ nY,
+ nX,
+ BitmapColor(
+ mpColorTable[ pTmp[ 0 ] ],
+ mpColorTable[ pTmp[ 1 ] ],
+ mpColorTable[ pTmp[ 2 ] ]),
+ pTmp[ 3 ]);
+ }
+ else
+ {
+ ImplSetAlphaPixel(
+ nY,
+ nX,
+ BitmapColor(
+ pTmp[0],
+ pTmp[1],
+ pTmp[2]),
+ pTmp[3]);
+ }
}
}
}
else
- { // BMP_FORMAT_64BIT_TC_RGBA
+ {
+ // BMP_FORMAT_64BIT_TC_RGBA
for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 8 )
- ImplSetAlphaPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
- mpColorTable[ pTmp[ 2 ] ],
- mpColorTable[ pTmp[ 4 ] ] ), pTmp[6] );
+ {
+ ImplSetAlphaPixel(
+ nY,
+ nX,
+ BitmapColor(
+ mpColorTable[ pTmp[ 0 ] ],
+ mpColorTable[ pTmp[ 2 ] ],
+ mpColorTable[ pTmp[ 4 ] ]),
+ pTmp[6]);
+ }
}
}
else if( mbTransparent ) // has RGB + transparency
- { // BMP_FORMAT_24BIT_TC_RGB
+ {
+ // BMP_FORMAT_24BIT_TC_RGB
+ // no support currently for DirectScanline, found no real usages in current PNGs, may be added on demand
if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample
{
for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
@@ -1334,7 +1433,7 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
sal_uInt8 nGreen = pTmp[ 1 ];
sal_uInt8 nBlue = pTmp[ 2 ];
bool bTransparent = ( ( nRed == mnTransRed )
- && ( nGreen == mnTransGreen )
+ && ( nGreen == mnTransGreen )
&& ( nBlue == mnTransBlue ) );
ImplSetTranspPixel( nY, nX, BitmapColor( mpColorTable[ nRed ],
@@ -1343,7 +1442,8 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
}
}
else
- { // BMP_FORMAT_48BIT_TC_RGB
+ {
+ // BMP_FORMAT_48BIT_TC_RGB
for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 )
{
sal_uInt8 nRed = pTmp[ 0 ];
@@ -1360,37 +1460,92 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
}
}
else // has RGB but neither alpha nor transparency
- { // BMP_FORMAT_24BIT_TC_RGB
+ {
+ // BMP_FORMAT_24BIT_TC_RGB
+ // only use DirectScanline when we have no preview shifting stuff and access to content
+ const bool bDoDirectScanline(
+ bCkeckDirectScanline && !nXStart && 1 == nXAdd && !mnPreviewShift && mpAcc);
+ const bool bCustomColorTable(mpColorTable != mpDefaultColorTable);
+
+ if(bDoDirectScanline && !mpScanline)
+ {
+ // allocate scanlines on demand, reused for next line
+#ifdef DBG_UTIL
+ mnAllocSizeScanline = maOrigSize.Width() * 3;
+#endif
+ mpScanline = new sal_uInt8[maOrigSize.Width() * 3];
+ }
+
if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample
{
- if ( mpColorTable != mpDefaultColorTable )
+ if(bDoDirectScanline)
{
- for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
- ImplSetPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
- mpColorTable[ pTmp[ 1 ] ],
- mpColorTable[ pTmp[ 2 ] ] ) );
+ OSL_ENSURE(mpScanline, "No Scanline allocated (!)");
+ OSL_ENSURE(mnAllocSizeScanline >= maOrigSize.Width() * 3, "Allocated Scanline too small (!)");
+ sal_uInt8* pScanline(mpScanline);
+
+ for(sal_uInt32 nX(0); nX < maOrigSize.Width(); nX++, pTmp += 3)
+ {
+ // prepare content line as BGR by reordering when copying
+ if(bCustomColorTable)
+ {
+ *pScanline++ = mpColorTable[pTmp[2]];
+ *pScanline++ = mpColorTable[pTmp[1]];
+ *pScanline++ = mpColorTable[pTmp[0]];
+ }
+ else
+ {
+ *pScanline++ = pTmp[2];
+ *pScanline++ = pTmp[1];
+ *pScanline++ = pTmp[0];
+ }
+ }
+
+ // copy scanline directly to bitmap for content; use the format which is able to
+ // copy directly to BitmapBuffer
+ mpAcc->CopyScanline(nY, mpScanline, BMP_FORMAT_24BIT_TC_BGR, maOrigSize.Width() * 3);
}
else
{
- if( nXAdd == 1 && mnPreviewShift == 0 ) // copy raw line data if possible
- {
- int nLineBytes = maOrigSize.Width() * 3;
- mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_24BIT_TC_RGB, nLineBytes );
- pTmp += nLineBytes;
- }
- else
+ for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
{
- for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
- ImplSetPixel( nY, nX, BitmapColor( pTmp[0], pTmp[1], pTmp[2] ) );
+ if(bCustomColorTable)
+ {
+ ImplSetPixel(
+ nY,
+ nX,
+ BitmapColor(
+ mpColorTable[ pTmp[ 0 ] ],
+ mpColorTable[ pTmp[ 1 ] ],
+ mpColorTable[ pTmp[ 2 ] ]));
+ }
+ else
+ {
+ ImplSetPixel(
+ nY,
+ nX,
+ BitmapColor(
+ pTmp[0],
+ pTmp[1],
+ pTmp[2]));
+ }
}
}
}
else
- { // BMP_FORMAT_48BIT_TC_RGB
+ {
+ // BMP_FORMAT_48BIT_TC_RGB
+ // no support currently for DirectScanline, found no real usages in current PNGs, may be added on demand
for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 )
- ImplSetPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
- mpColorTable[ pTmp[ 2 ] ],
- mpColorTable[ pTmp[ 4 ] ] ) );
+ {
+ ImplSetPixel(
+ nY,
+ nX,
+ BitmapColor(
+ mpColorTable[ pTmp[ 0 ] ],
+ mpColorTable[ pTmp[ 2 ] ],
+ mpColorTable[ pTmp[ 4 ] ]));
+ }
}
}
}