diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-10-09 15:20:43 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-10-12 15:09:27 +0200 |
commit | 6036b2486cdc5ba8eac8636b2e087658e3550586 (patch) | |
tree | 0801f1f507629c8319315662ccab33e7fc5f47b1 | |
parent | a879daa45f40fd84373a92242e098eaf6a493508 (diff) |
implement fast bitmap variant for CopyScanline()
JPEG reads RGB, but e.g. with Skia the default bitmap format is BGRA.
Change-Id: Iad1a9e99f286b03db0fa683c14d70b8ad48d3d9d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104120
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r-- | vcl/inc/bmpfast.hxx | 5 | ||||
-rw-r--r-- | vcl/source/gdi/bmpacc.cxx | 20 | ||||
-rw-r--r-- | vcl/source/gdi/bmpfast.cxx | 97 |
3 files changed, 114 insertions, 8 deletions
diff --git a/vcl/inc/bmpfast.hxx b/vcl/inc/bmpfast.hxx index f9a1f891bb47..ebdb431fc941 100644 --- a/vcl/inc/bmpfast.hxx +++ b/vcl/inc/bmpfast.hxx @@ -21,6 +21,7 @@ #define INCLUDED_VCL_INC_BMPFAST_HXX #include <vcl/dllapi.h> +#include <vcl/Scanline.hxx> class BitmapWriteAccess; class BitmapReadAccess; @@ -34,6 +35,10 @@ struct SalTwoRect; VCL_DLLPUBLIC bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const SalTwoRect& rTwoRect ); +bool ImplFastCopyScanline( long nY, BitmapBuffer& rDst, const BitmapBuffer& rSrc); +bool ImplFastCopyScanline( long nY, BitmapBuffer& rDst, ConstScanline aSrcScanline, + ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize); + bool ImplFastBitmapBlending( BitmapWriteAccess const & rDst, const BitmapReadAccess& rSrc, const BitmapReadAccess& rMask, const SalTwoRect& rTwoRect ); diff --git a/vcl/source/gdi/bmpacc.cxx b/vcl/source/gdi/bmpacc.cxx index a406951cd7f7..3994f9c1889a 100644 --- a/vcl/source/gdi/bmpacc.cxx +++ b/vcl/source/gdi/bmpacc.cxx @@ -24,6 +24,7 @@ #include <salbmp.hxx> #include <svdata.hxx> #include <salinst.hxx> +#include <bmpfast.hxx> #include <string.h> #include <sal/log.hxx> @@ -344,11 +345,14 @@ void BitmapWriteAccess::CopyScanline( long nY, const BitmapReadAccess& rReadAcc } else { - // TODO: use fastbmp infrastructure - Scanline pScanline = GetScanline( nY ); - Scanline pScanlineRead = rReadAcc.GetScanline(nY); - for( long nX = 0, nWidth = std::min( mpBuffer->mnWidth, rReadAcc.Width() ); nX < nWidth; nX++ ) - SetPixelOnData( pScanline, nX, rReadAcc.GetPixelFromData( pScanlineRead, nX ) ); + long nWidth = std::min( mpBuffer->mnWidth, rReadAcc.Width() ); + if(!ImplFastCopyScanline( nY, *ImplGetBitmapBuffer(), *rReadAcc.ImplGetBitmapBuffer())) + { + Scanline pScanline = GetScanline( nY ); + Scanline pScanlineRead = rReadAcc.GetScanline(nY); + for( long nX = 0; nX < nWidth; nX++ ) + SetPixelOnData( pScanline, nX, rReadAcc.GetPixelFromData( pScanlineRead, nX ) ); + } } } @@ -371,13 +375,13 @@ void BitmapWriteAccess::CopyScanline( long nY, ConstScanline aSrcScanline, memcpy(GetScanline(nY), aSrcScanline, nCount); else { + if(ImplFastCopyScanline( nY, *ImplGetBitmapBuffer(), aSrcScanline, nSrcScanlineFormat, nSrcScanlineSize )) + return; + DBG_ASSERT( nFormat != ScanlineFormat::N8BitTcMask && nFormat != ScanlineFormat::N32BitTcMask, "No support for pixel formats with color masks yet!" ); - - // TODO: use fastbmp infrastructure FncGetPixel pFncGetPixel; - switch( nFormat ) { case ScanlineFormat::N1BitMsbPal: pFncGetPixel = GetPixelForN1BitMsbPal; break; diff --git a/vcl/source/gdi/bmpfast.cxx b/vcl/source/gdi/bmpfast.cxx index 9ee00b7bdd40..1fe9a9ae543a 100644 --- a/vcl/source/gdi/bmpfast.cxx +++ b/vcl/source/gdi/bmpfast.cxx @@ -457,6 +457,103 @@ bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc, return false; } +static inline ConstScanline ImplGetScanline( const BitmapBuffer& rBuf, long nY ) +{ + if( rBuf.mnFormat & ScanlineFormat::TopDown ) + return rBuf.mpBits + nY * rBuf.mnScanlineSize; + else + return rBuf.mpBits + (rBuf.mnHeight - 1 - nY) * rBuf.mnScanlineSize; +} + +static inline Scanline ImplGetScanline( BitmapBuffer& rBuf, long nY ) +{ + return const_cast<Scanline>(ImplGetScanline( const_cast<const BitmapBuffer&>(rBuf), nY )); +} + +template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT> +static bool ImplCopyToScanline( long nY, BitmapBuffer& rDst, TrueColorPixelPtr<SRCFMT>& rSrcLine, long nSrcWidth ) +{ + TrueColorPixelPtr<DSTFMT> aDstType; + aDstType.SetRawPtr( ImplGetScanline( rDst, nY )); + ImplConvertLine( aDstType, rSrcLine, std::min( nSrcWidth, rDst.mnWidth )); + return true; +} + +template <ScanlineFormat SRCFMT> +static bool ImplCopyFromScanline( long nY, BitmapBuffer& rDst, ConstScanline aSrcScanline, long nSrcWidth ) +{ + TrueColorPixelPtr<SRCFMT> aSrcType; + aSrcType.SetRawPtr( const_cast<Scanline>( aSrcScanline )); + // select the matching instantiation for the destination's bitmap format + switch( RemoveScanline( rDst.mnFormat )) + { + case ScanlineFormat::N24BitTcBgr: + return ImplCopyToScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcType, nSrcWidth ); + case ScanlineFormat::N24BitTcRgb: + return ImplCopyToScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcType, nSrcWidth ); + + case ScanlineFormat::N32BitTcAbgr: + return ImplCopyToScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcType, nSrcWidth ); + case ScanlineFormat::N32BitTcArgb: + return ImplCopyToScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcType, nSrcWidth ); + case ScanlineFormat::N32BitTcBgra: + return ImplCopyToScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcType, nSrcWidth ); + case ScanlineFormat::N32BitTcRgba: + return ImplCopyToScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcType, nSrcWidth ); + default: + break; + } + return false; + +} + +bool ImplFastCopyScanline( long nY, BitmapBuffer& rDst, ConstScanline aSrcScanline, + ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize) +{ + if( rDst.mnHeight <= nY ) + return false; + + const ScanlineFormat nSrcFormat = RemoveScanline(nSrcScanlineFormat); + const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat); + + // special handling of trivial cases + if( nSrcFormat == nDstFormat ) + { + memcpy( ImplGetScanline( rDst, nY ), aSrcScanline, std::min<long>(nSrcScanlineSize, rDst.mnScanlineSize)); + return true; + } + + // select the matching instantiation for the source's bitmap format + switch( nSrcFormat ) + { + case ScanlineFormat::N24BitTcBgr: + return ImplCopyFromScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 ); + case ScanlineFormat::N24BitTcRgb: + return ImplCopyFromScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 ); + + case ScanlineFormat::N32BitTcAbgr: + return ImplCopyFromScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 ); + case ScanlineFormat::N32BitTcArgb: + return ImplCopyFromScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 ); + case ScanlineFormat::N32BitTcBgra: + return ImplCopyFromScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 ); + case ScanlineFormat::N32BitTcRgba: + return ImplCopyFromScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 ); + default: + break; + } + return false; +} + +bool ImplFastCopyScanline( long nY, BitmapBuffer& rDst, const BitmapBuffer& rSrc) +{ + if( nY >= rDst.mnHeight ) + return false; + if( rSrc.maPalette != rDst.maPalette ) + return false; + return ImplFastCopyScanline( nY, rDst, ImplGetScanline( rSrc, nY ), rSrc.mnFormat, rSrc.mnScanlineSize); +} + template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT> //,sal_uLong MSKFMT> static bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine, BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer, |