summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2022-01-11 19:31:36 +0100
committerLuboš Luňák <l.lunak@collabora.com>2022-01-12 12:20:38 +0100
commitd39acd432df374ffdf4142c23d1c74df8821160c (patch)
tree369d64f2fe71801d8a5ef42d171e69e5e6f8d484
parentb89a26457eef67c23f5bcc1495b564fc7a86654f (diff)
do not force pixel reading in VclCanvasBitmap ctor
BitmapReadAccess is not need by most calls in the class, and creating it already in ctor forces reading of all pixels, which is expensive e.g. when fetching them from the GPU. Change-Id: Ie5da67d1c41ad798928646077b5b4c33147d0ea9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128308 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r--vcl/inc/canvasbitmap.hxx8
-rw-r--r--vcl/source/helper/canvasbitmap.cxx120
2 files changed, 81 insertions, 47 deletions
diff --git a/vcl/inc/canvasbitmap.hxx b/vcl/inc/canvasbitmap.hxx
index cb50e82bf8d9..54586a1ad60e 100644
--- a/vcl/inc/canvasbitmap.hxx
+++ b/vcl/inc/canvasbitmap.hxx
@@ -38,8 +38,10 @@ namespace vcl::unotools
BitmapEx m_aBmpEx;
::Bitmap m_aBitmap;
::Bitmap m_aAlpha;
- Bitmap::ScopedReadAccess m_pBmpAcc;
- Bitmap::ScopedReadAccess m_pAlphaAcc;
+ Bitmap::ScopedInfoAccess m_pBmpAcc;
+ Bitmap::ScopedInfoAccess m_pAlphaAcc;
+ std::optional<Bitmap::ScopedReadAccess> m_pBmpReadAcc;
+ std::optional<Bitmap::ScopedReadAccess> m_pAlphaReadAcc;
css::uno::Sequence<sal_Int8> m_aComponentTags;
css::uno::Sequence<sal_Int32> m_aComponentBitCounts;
css::rendering::IntegerBitmapLayout m_aLayout;
@@ -53,6 +55,8 @@ namespace vcl::unotools
bool m_bPalette;
SAL_DLLPRIVATE void setComponentInfo( sal_uInt32 redShift, sal_uInt32 greenShift, sal_uInt32 blueShift );
+ Bitmap::ScopedReadAccess& getBitmapReadAccess();
+ Bitmap::ScopedReadAccess& getAlphaReadAccess();
virtual ~VclCanvasBitmap() override;
diff --git a/vcl/source/helper/canvasbitmap.cxx b/vcl/source/helper/canvasbitmap.cxx
index 2eaa16223789..301237e18e43 100644
--- a/vcl/source/helper/canvasbitmap.cxx
+++ b/vcl/source/helper/canvasbitmap.cxx
@@ -94,6 +94,24 @@ void VclCanvasBitmap::setComponentInfo( sal_uInt32 redShift, sal_uInt32 greenShi
pCounts[bluePos] = bitcount(blueShift);
}
+Bitmap::ScopedReadAccess& VclCanvasBitmap::getBitmapReadAccess()
+{
+ // BitmapReadAccess is more expensive than BitmapInfoAccess,
+ // as the latter requires also pixels, which may need converted
+ // from the system format (and even fetched). Most calls here
+ // need only info access, create read access only on demand.
+ if(!m_pBmpReadAcc)
+ m_pBmpReadAcc.emplace(m_aBitmap);
+ return m_pBmpReadAcc.value();
+}
+
+Bitmap::ScopedReadAccess& VclCanvasBitmap::getAlphaReadAccess()
+{
+ if(!m_pAlphaReadAcc)
+ m_pAlphaReadAcc.emplace(m_aAlpha);
+ return m_pAlphaReadAcc.value();
+}
+
VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
m_aBmpEx( rBitmap ),
m_aBitmap( rBitmap.GetBitmap() ),
@@ -110,7 +128,7 @@ VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
if( m_aBmpEx.IsAlpha() )
{
m_aAlpha = m_aBmpEx.GetAlpha().GetBitmap();
- m_pAlphaAcc = Bitmap::ScopedReadAccess(m_aAlpha);
+ m_pAlphaAcc = Bitmap::ScopedInfoAccess(m_aAlpha);
}
m_aLayout.ScanLines = 0;
@@ -391,20 +409,23 @@ uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerB
if( !m_aBmpEx.IsAlpha() )
{
- OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
+ OSL_ENSURE(pBmpAcc,"Invalid bmp read access");
// can return bitmap data as-is
for( tools::Long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
{
- Scanline pScan = m_pBmpAcc->GetScanline(y);
+ Scanline pScan = pBmpAcc->GetScanline(y);
memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
pOutBuf += nScanlineStride;
}
}
else
{
- OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
- OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
+ Bitmap::ScopedReadAccess& pAlphaAcc = getAlphaReadAccess();
+ OSL_ENSURE(pBmpAcc,"Invalid bmp read access");
+ OSL_ENSURE(pAlphaAcc,"Invalid alpha read access");
// interleave alpha with bitmap data - note, bitcount is
// always integer multiple of 8
@@ -420,23 +441,23 @@ uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerB
// input less than a byte - copy via GetPixel()
for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
{
- *pOutScan++ = m_pBmpAcc->GetPixelIndex(y,x);
- *pOutScan++ = m_pAlphaAcc->GetPixelIndex(y,x);
+ *pOutScan++ = pBmpAcc->GetPixelIndex(y,x);
+ *pOutScan++ = pAlphaAcc->GetPixelIndex(y,x);
}
}
else
{
const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
const tools::Long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
- Scanline pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
- Scanline pScanlineAlpha = m_pAlphaAcc->GetScanline( y );
+ Scanline pScan = pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
+ Scanline pScanlineAlpha = pAlphaAcc->GetScanline( y );
// input integer multiple of byte - copy directly
for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
{
for( tools::Long i=0; i<nNonAlphaBytes; ++i )
*pOutScan++ = *pScan++;
- *pOutScan++ = m_pAlphaAcc->GetIndexFromData( pScanlineAlpha, x );
+ *pOutScan++ = pAlphaAcc->GetIndexFromData( pScanlineAlpha, x );
}
}
@@ -477,16 +498,19 @@ uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::Integer
const tools::Long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
if( !m_aBmpEx.IsAlpha() )
{
- assert(m_pBmpAcc && "Invalid bmp read access");
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
+ assert(pBmpAcc && "Invalid bmp read access");
// can return bitmap data as-is
- Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
+ Scanline pScan = pBmpAcc->GetScanline(pos.Y);
memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
}
else
{
- assert(m_pBmpAcc && "Invalid bmp read access");
- assert(m_pAlphaAcc && "Invalid alpha read access");
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
+ Bitmap::ScopedReadAccess& pAlphaAcc = getAlphaReadAccess();
+ assert(pBmpAcc && "Invalid bmp read access");
+ assert(pAlphaAcc && "Invalid alpha read access");
// interleave alpha with bitmap data - note, bitcount is
// always integer multiple of 8
@@ -496,18 +520,18 @@ uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::Integer
if( m_nBitsPerInputPixel < 8 )
{
// input less than a byte - copy via GetPixel()
- *pOutBuf++ = m_pBmpAcc->GetPixelIndex(pos.Y,pos.X);
- *pOutBuf = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
+ *pOutBuf++ = pBmpAcc->GetPixelIndex(pos.Y,pos.X);
+ *pOutBuf = pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
}
else
{
const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
- Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
+ Scanline pScan = pBmpAcc->GetScanline(pos.Y);
// input integer multiple of byte - copy directly
memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
pOutBuf += nNonAlphaBytes;
- *pOutBuf++ = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
+ *pOutBuf++ = pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
}
}
@@ -1014,7 +1038,8 @@ uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB
uno::Sequence< rendering::RGBColor > aRes(nNumColors);
rendering::RGBColor* pOut( aRes.getArray() );
- ENSURE_OR_THROW(m_pBmpAcc,
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
+ ENSURE_OR_THROW(pBmpAcc,
"Unable to get BitmapAccess");
if( m_aBmpEx.IsAlpha() )
@@ -1025,8 +1050,8 @@ uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB
// if palette, index is guaranteed to be 8 bit
const BitmapColor aCol =
m_bPalette ?
- m_pBmpAcc->GetPaletteColor(*pIn) :
- m_pBmpAcc->GetPixelFromData(pIn,0);
+ pBmpAcc->GetPaletteColor(*pIn) :
+ pBmpAcc->GetPixelFromData(pIn,0);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
@@ -1042,8 +1067,8 @@ uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB
{
const BitmapColor aCol =
m_bPalette ?
- m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
- m_pBmpAcc->GetPixelFromData(pIn, i);
+ pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
+ pBmpAcc->GetPixelFromData(pIn, i);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
@@ -1066,7 +1091,8 @@ uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToAR
uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
rendering::ARGBColor* pOut( aRes.getArray() );
- ENSURE_OR_THROW(m_pBmpAcc,
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
+ ENSURE_OR_THROW(pBmpAcc,
"Unable to get BitmapAccess");
if( m_aBmpEx.IsAlpha() )
@@ -1079,8 +1105,8 @@ uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToAR
// if palette, index is guaranteed to be 8 bit
const BitmapColor aCol =
m_bPalette ?
- m_pBmpAcc->GetPaletteColor(*pIn) :
- m_pBmpAcc->GetPixelFromData(pIn,0);
+ pBmpAcc->GetPaletteColor(*pIn) :
+ pBmpAcc->GetPixelFromData(pIn,0);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
@@ -1096,8 +1122,8 @@ uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToAR
{
const BitmapColor aCol =
m_bPalette ?
- m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
- m_pBmpAcc->GetPixelFromData(pIn, i);
+ pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
+ pBmpAcc->GetPixelFromData(pIn, i);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::ARGBColor(1.0,
@@ -1121,7 +1147,8 @@ uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPA
uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
rendering::ARGBColor* pOut( aRes.getArray() );
- ENSURE_OR_THROW(m_pBmpAcc,
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
+ ENSURE_OR_THROW(pBmpAcc,
"Unable to get BitmapAccess");
if( m_aBmpEx.IsAlpha() )
@@ -1134,8 +1161,8 @@ uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPA
// if palette, index is guaranteed to be 8 bit
const BitmapColor aCol =
m_bPalette ?
- m_pBmpAcc->GetPaletteColor(*pIn) :
- m_pBmpAcc->GetPixelFromData(pIn,0);
+ pBmpAcc->GetPaletteColor(*pIn) :
+ pBmpAcc->GetPixelFromData(pIn,0);
// TODO(F3): Convert result to sRGB color space
const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
@@ -1152,8 +1179,8 @@ uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPA
{
const BitmapColor aCol =
m_bPalette ?
- m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
- m_pBmpAcc->GetPixelFromData(pIn, i);
+ pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
+ pBmpAcc->GetPixelFromData(pIn, i);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::ARGBColor(1.0,
@@ -1175,6 +1202,7 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( con
uno::Sequence< sal_Int8 > aRes(nNumBytes);
sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
if( m_aBmpEx.IsAlpha() )
{
@@ -1187,10 +1215,10 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( con
const BitmapColor aCol2 =
m_bPalette ?
BitmapColor(
- sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
+ sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
aCol;
- m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
+ pBmpAcc->SetPixelOnData(pColors,i,aCol2);
pColors += nNonAlphaBytes;
*pColors++ = sal_uInt8(255);
}
@@ -1205,10 +1233,10 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( con
const BitmapColor aCol2 =
m_bPalette ?
BitmapColor(
- sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
+ sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
aCol;
- m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
+ pBmpAcc->SetPixelOnData(pColors,i,aCol2);
}
}
@@ -1224,6 +1252,7 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( co
uno::Sequence< sal_Int8 > aRes(nNumBytes);
sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
if( m_aBmpEx.IsAlpha() )
{
@@ -1236,10 +1265,10 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( co
const BitmapColor aCol2 =
m_bPalette ?
BitmapColor(
- sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
+ sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
aCol;
- m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
+ pBmpAcc->SetPixelOnData(pColors,i,aCol2);
pColors += nNonAlphaBytes;
*pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
}
@@ -1254,10 +1283,10 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( co
const BitmapColor aCol2 =
m_bPalette ?
BitmapColor(
- sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
+ sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
aCol;
- m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
+ pBmpAcc->SetPixelOnData(pColors,i,aCol2);
}
}
@@ -1273,6 +1302,7 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( c
uno::Sequence< sal_Int8 > aRes(nNumBytes);
sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
+ Bitmap::ScopedReadAccess& pBmpAcc = getBitmapReadAccess();
if( m_aBmpEx.IsAlpha() )
{
@@ -1286,10 +1316,10 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( c
const BitmapColor aCol2 =
m_bPalette ?
BitmapColor(
- sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
+ sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
aCol;
- m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
+ pBmpAcc->SetPixelOnData(pColors,i,aCol2);
pColors += nNonAlphaBytes;
*pColors++ = 255 - toByteColor(nAlpha);
}
@@ -1304,10 +1334,10 @@ uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( c
const BitmapColor aCol2 =
m_bPalette ?
BitmapColor(
- sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
+ sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
aCol;
- m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
+ pBmpAcc->SetPixelOnData(pColors,i,aCol2);
}
}