[Libreoffice-commits] core.git: vcl/inc vcl/skia
LuboÅ¡ LuÅák (via logerrit)
logerrit at kemper.freedesktop.org
Tue Dec 15 15:04:02 UTC 2020
vcl/inc/skia/salbmp.hxx | 1 +
vcl/skia/salbmp.cxx | 35 +++++++++++++++++++++++++----------
2 files changed, 26 insertions(+), 10 deletions(-)
New commits:
commit 0e5b473a63409da2cdae4f4c60a91fcc93755ba5
Author: Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Dec 15 12:59:25 2020 +0100
Commit: Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Dec 15 16:03:27 2020 +0100
do not free SkiaSalBitmap buffer if a read access points to it
When conserving memory in raster mode, SkiaSalBitmap may decide
to drop the pixel buffer if SkImage is created from it, since
having both wastes memory and converting between them is cheap.
But if there is still a Bitmap::ScopedReadAccess existing
for the bitmap (e.g. VclCanvasBitmap keeps it as a member),
then dropping the pixel buffer would make the data pointed to
by the read access invalid.
Technically this patch should distinguish between info and read
accesses, as info accesses do not point to pixels, but this is
simpler and hopefully doesn't make a difference in practice.
Change-Id: I307170ad4651b849feda0cf224976ca5a87e5207
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107752
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak at collabora.com>
diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx
index 9edb1d620e3a..ec8d4f3c7b82 100644
--- a/vcl/inc/skia/salbmp.hxx
+++ b/vcl/inc/skia/salbmp.hxx
@@ -177,6 +177,7 @@ private:
// Erase() is delayed, just sets these two instead of filling the buffer.
bool mEraseColorSet = false;
Color mEraseColor;
+ int mAnyAccessCount = 0; // number of any kind of AcquireAccess() that have not been released
#ifdef DBG_UTIL
int mWriteAccessCount = 0; // number of write AcquireAccess() that have not been released
#endif
diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx
index 096a667e9382..119f4acda526 100644
--- a/vcl/skia/salbmp.cxx
+++ b/vcl/skia/salbmp.cxx
@@ -68,6 +68,7 @@ SkiaSalBitmap::SkiaSalBitmap(const sk_sp<SkImage>& image)
mBitCount = 32;
mSize = mPixelsSize = Size(image->width(), image->height());
ComputeScanlineSize();
+ mAnyAccessCount = 0;
#ifdef DBG_UTIL
mWriteAccessCount = 0;
#endif
@@ -76,15 +77,13 @@ SkiaSalBitmap::SkiaSalBitmap(const sk_sp<SkImage>& image)
bool SkiaSalBitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal)
{
+ assert(mAnyAccessCount == 0);
ResetAllData();
if (!isValidBitCount(nBitCount))
return false;
mPalette = rPal;
mBitCount = nBitCount;
mSize = mPixelsSize = rSize;
-#ifdef DBG_UTIL
- mWriteAccessCount = 0;
-#endif
if (!ComputeScanlineSize())
{
mBitCount = 0;
@@ -150,6 +149,7 @@ bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, SalGraphics* pGraphics)
bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount)
{
+ assert(mAnyAccessCount == 0);
const SkiaSalBitmap& src = static_cast<const SkiaSalBitmap&>(rSalBmp);
mImage = src.mImage;
mAlphaImage = src.mAlphaImage;
@@ -162,9 +162,6 @@ bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount)
mScaleQuality = src.mScaleQuality;
mEraseColorSet = src.mEraseColorSet;
mEraseColor = src.mEraseColor;
-#ifdef DBG_UTIL
- mWriteAccessCount = 0;
-#endif
if (nNewBitCount != src.GetBitCount())
{
// This appears to be unused(?). Implement this just in case, but be lazy
@@ -188,6 +185,7 @@ void SkiaSalBitmap::Destroy()
#ifdef DBG_UTIL
assert(mWriteAccessCount == 0);
#endif
+ assert(mAnyAccessCount == 0);
ResetAllData();
}
@@ -226,7 +224,10 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode)
buffer->mnHeight = mSize.Height();
buffer->mnBitCount = mBitCount;
buffer->maPalette = mPalette;
- buffer->mpBits = mBuffer.get();
+ if (nMode != BitmapAccessMode::Info)
+ buffer->mpBits = mBuffer.get();
+ else
+ buffer->mpBits = nullptr;
if (mPixelsSize == mSize)
buffer->mnScanlineSize = mScanlineSize;
else
@@ -266,6 +267,7 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode)
abort();
}
buffer->mnFormat |= ScanlineFormat::TopDown;
+ ++mAnyAccessCount;
#ifdef DBG_UTIL
if (nMode == BitmapAccessMode::Write)
++mWriteAccessCount;
@@ -285,11 +287,13 @@ void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode)
ResetToBuffer();
InvalidateChecksum();
}
+ assert(mAnyAccessCount > 0);
+ --mAnyAccessCount;
// Are there any more ground movements underneath us ?
assert(pBuffer->mnWidth == mSize.Width());
assert(pBuffer->mnHeight == mSize.Height());
assert(pBuffer->mnBitCount == mBitCount);
- assert(pBuffer->mpBits == mBuffer.get());
+ assert(pBuffer->mpBits == mBuffer.get() || nMode == BitmapAccessMode::Info);
verify();
delete pBuffer;
}
@@ -456,6 +460,9 @@ bool SkiaSalBitmap::InterpretAs8Bit()
bool SkiaSalBitmap::Erase(const Color& color)
{
+#ifdef DBG_UTIL
+ assert(mWriteAccessCount == 0);
+#endif
// Optimized variant, just remember the color and apply it when needed,
// which may save having to do format conversions (e.g. GetSkImage()
// may directly erase the SkImage).
@@ -473,6 +480,9 @@ void SkiaSalBitmap::EraseInternal(const Color& color)
bool SkiaSalBitmap::AlphaBlendWith(const SalBitmap& rSalBmp)
{
+#ifdef DBG_UTIL
+ assert(mWriteAccessCount == 0);
+#endif
const SkiaSalBitmap* otherBitmap = dynamic_cast<const SkiaSalBitmap*>(&rSalBmp);
if (!otherBitmap)
return false;
@@ -720,7 +730,7 @@ const sk_sp<SkImage>& SkiaSalBitmap::GetSkImage() const
thisPtr->mImage = image;
// The data is now stored both in the SkImage and in our mBuffer, so drop the buffer
// if conserving memory. It'll be converted back by EnsureBitmapData() if needed.
- if (ConserveMemory())
+ if (ConserveMemory() && mAnyAccessCount == 0)
{
SAL_INFO("vcl.skia.trace", "getskimage(" << this << "): dropping buffer");
thisPtr->ResetToSkImage(mImage);
@@ -869,7 +879,7 @@ const sk_sp<SkImage>& SkiaSalBitmap::GetAlphaSkImage() const
// The data is now stored both in the SkImage and in our mBuffer, so drop the buffer
// if conserving memory and the conversion back would be simple (it'll be converted back
// by EnsureBitmapData() if needed).
- if (ConserveMemory() && mBitCount == 8 && mPalette.IsGreyPalette8Bit())
+ if (ConserveMemory() && mBitCount == 8 && mPalette.IsGreyPalette8Bit() && mAnyAccessCount == 0)
{
SAL_INFO("vcl.skia.trace", "getalphaskimage(" << this << "): dropping buffer");
SkiaSalBitmap* thisPtr = const_cast<SkiaSalBitmap*>(this);
@@ -1155,6 +1165,9 @@ void SkiaSalBitmap::EnsureBitmapData()
void SkiaSalBitmap::EnsureBitmapUniqueData()
{
+#ifdef DBG_UTIL
+ assert(mWriteAccessCount == 0);
+#endif
EnsureBitmapData();
assert(mPixelsSize == mSize);
if (mBuffer.use_count() > 1)
@@ -1182,6 +1195,7 @@ void SkiaSalBitmap::ResetToBuffer()
void SkiaSalBitmap::ResetToSkImage(sk_sp<SkImage> image)
{
+ assert(mAnyAccessCount == 0); // can't reset mBuffer if there's a read access pointing to it
SkiaZone zone;
mBuffer.reset();
mImage = image;
@@ -1191,6 +1205,7 @@ void SkiaSalBitmap::ResetToSkImage(sk_sp<SkImage> image)
void SkiaSalBitmap::ResetAllData()
{
+ assert(mAnyAccessCount == 0);
SkiaZone zone;
mBuffer.reset();
mImage.reset();
More information about the Libreoffice-commits
mailing list