summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-10-09 15:20:43 +0200
committerLuboš Luňák <l.lunak@collabora.com>2020-10-12 15:09:27 +0200
commit6036b2486cdc5ba8eac8636b2e087658e3550586 (patch)
tree0801f1f507629c8319315662ccab33e7fc5f47b1
parenta879daa45f40fd84373a92242e098eaf6a493508 (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.hxx5
-rw-r--r--vcl/source/gdi/bmpacc.cxx20
-rw-r--r--vcl/source/gdi/bmpfast.cxx97
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,