summaryrefslogtreecommitdiff
path: root/vcl/skia/salbmp.cxx
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2019-12-04 18:01:47 +0100
committerLuboš Luňák <l.lunak@collabora.com>2019-12-06 14:26:45 +0100
commit8fede4e7870579251c58823566c88476df2038b0 (patch)
tree888a42fd265447827dba661456d4b383a9f8de80 /vcl/skia/salbmp.cxx
parentcd46c8710b2eb244572670d78fec1f0dcb4a577f (diff)
make all Skia drawing GPU-backed, if possible
This primarily means using SkiaHelper::createSkSurface(), which will create a GPU-backed SkSurface if Vulkan is used, and it is used in place of temporary SkBitmap instances, which are always raster-based. Change-Id: I3fe35866f962030f464d5c1d1c4bf518c20ee9af Reviewed-on: https://gerrit.libreoffice.org/84562 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl/skia/salbmp.cxx')
-rw-r--r--vcl/skia/salbmp.cxx164
1 files changed, 94 insertions, 70 deletions
diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx
index fb0c3608028d..d7fc3f6905c6 100644
--- a/vcl/skia/salbmp.cxx
+++ b/vcl/skia/salbmp.cxx
@@ -27,6 +27,9 @@
#include <SkCanvas.h>
#include <SkImage.h>
#include <SkPixelRef.h>
+#include <SkSurface.h>
+
+#include <skia/utils.hxx>
#ifdef DBG_UTIL
#include <fstream>
@@ -43,15 +46,18 @@ static bool isValidBitCount(sal_uInt16 nBitCount)
|| (nBitCount == 32);
}
-SkiaSalBitmap::SkiaSalBitmap(const SkImage& image)
+SkiaSalBitmap::SkiaSalBitmap(const sk_sp<SkImage>& image)
{
- if (Create(Size(image.width(), image.height()), 32, BitmapPalette()))
+ if (Create(Size(image->width(), image->height()), 32, BitmapPalette()))
{
SkCanvas canvas(mBitmap);
// TODO makeNonTextureImage() ?
SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha
- canvas.drawImage(&image, 0, 0, &paint);
+ canvas.drawImage(image, 0, 0, &paint);
+ // Also set up the cached image, often it will be immediately read again.
+ // TODO Maybe do the image -> bitmap conversion on demand?
+ mImage = image;
}
}
@@ -291,9 +297,12 @@ bool SkiaSalBitmap::ConvertToGreyscale()
return false;
}
-const SkBitmap& SkiaSalBitmap::GetSkBitmap() const
+SkBitmap SkiaSalBitmap::GetAsSkBitmap() const
{
- if (mBuffer && mBitmap.drawsNothing())
+ if (!mBitmap.drawsNothing())
+ return mBitmap;
+ SkBitmap bitmap;
+ if (mBuffer)
{
if (mBitCount == 24)
{
@@ -311,12 +320,12 @@ const SkBitmap& SkiaSalBitmap::GetSkBitmap() const
*dest++ = 0xff;
}
}
- if (!const_cast<SkBitmap&>(mBitmap).installPixels(
+ if (!bitmap.installPixels(
SkImageInfo::MakeS32(mSize.Width(), mSize.Height(), kOpaque_SkAlphaType),
data.release(), mSize.Width() * 4,
[](void* addr, void*) { delete[] static_cast<sal_uInt8*>(addr); }, nullptr))
abort();
- SAL_INFO("vcl.skia", "skbitmap(" << this << ")");
+ bitmap.setImmutable();
}
else
{
@@ -327,90 +336,105 @@ const SkBitmap& SkiaSalBitmap::GetSkBitmap() const
= convertDataBitCount(mBuffer.get(), mSize.Width(), mSize.Height(), mBitCount,
mScanlineSize, mPalette, GET_FORMAT);
#undef GET_FORMAT
- if (!const_cast<SkBitmap&>(mBitmap).installPixels(
+ if (!bitmap.installPixels(
SkImageInfo::MakeS32(mSize.Width(), mSize.Height(), kOpaque_SkAlphaType),
data.release(), mSize.Width() * 4,
[](void* addr, void*) { delete[] static_cast<sal_uInt8*>(addr); }, nullptr))
abort();
- SAL_INFO("vcl.skia", "skbitmap(" << this << ")");
+ bitmap.setImmutable();
}
}
- return mBitmap;
+ return bitmap;
+}
+
+const sk_sp<SkImage>& SkiaSalBitmap::GetSkImage() const
+{
+ if (mImage)
+ return mImage;
+ sk_sp<SkSurface> surface = SkiaHelper::createSkSurface(mSize);
+ assert(surface);
+ SkPaint paint;
+ paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha
+ surface->getCanvas()->drawBitmap(GetAsSkBitmap(), 0, 0, &paint);
+ const_cast<sk_sp<SkImage>&>(mImage) = surface->makeImageSnapshot();
+ SAL_INFO("vcl.skia", "getskimage(" << this << ")");
+ return mImage;
}
-const SkBitmap& SkiaSalBitmap::GetAlphaSkBitmap() const
+const sk_sp<SkImage>& SkiaSalBitmap::GetAlphaSkImage() const
{
- if (mAlphaBitmap.drawsNothing())
+ if (mAlphaImage)
+ return mAlphaImage;
+ SkBitmap alphaBitmap;
+ if (mBuffer && mBitCount <= 8)
{
- if (mBuffer && mBitCount <= 8)
+ assert(mBuffer.get());
+ verify();
+ std::unique_ptr<sal_uInt8[]> data
+ = convertDataBitCount(mBuffer.get(), mSize.Width(), mSize.Height(), mBitCount,
+ mScanlineSize, mPalette, BitConvert::A8);
+ if (!alphaBitmap.installPixels(
+ SkImageInfo::MakeA8(mSize.Width(), mSize.Height()), data.release(), mSize.Width(),
+ [](void* addr, void*) { delete[] static_cast<sal_uInt8*>(addr); }, nullptr))
+ abort();
+ alphaBitmap.setImmutable();
+ }
+ else
+ {
+ SkBitmap originalBitmap = GetAsSkBitmap();
+ // To make things more interesting, some LO code creates masks as 24bpp,
+ // so we first need to convert to 8bit to be able to convert that to 8bit alpha.
+ SkBitmap* convertedBitmap = nullptr;
+ const SkBitmap* bitmap8 = &originalBitmap;
+ if (originalBitmap.colorType() != kGray_8_SkColorType)
{
- assert(mBuffer.get());
- verify();
- std::unique_ptr<sal_uInt8[]> data
- = convertDataBitCount(mBuffer.get(), mSize.Width(), mSize.Height(), mBitCount,
- mScanlineSize, mPalette, BitConvert::A8);
- if (!const_cast<SkBitmap&>(mAlphaBitmap)
- .installPixels(
- SkImageInfo::MakeA8(mSize.Width(), mSize.Height()), data.release(),
- mSize.Width(),
- [](void* addr, void*) { delete[] static_cast<sal_uInt8*>(addr); },
- nullptr))
+ convertedBitmap = new SkBitmap;
+ if (!convertedBitmap->tryAllocPixels(SkImageInfo::Make(
+ mSize.Width(), mSize.Height(), kGray_8_SkColorType, kOpaque_SkAlphaType)))
abort();
- SAL_INFO("vcl.skia", "skalphabitmap(" << this << ")");
- }
- else
- {
- GetSkBitmap(); // make sure we have mBitmap, in case (mBuffer && mBitCount > 8)
- // To make things more interesting, some LO code creates masks as 24bpp,
- // so we first need to convert to 8bit to be able to convert that to 8bit alpha.
- SkBitmap* convertedBitmap = nullptr;
- const SkBitmap* bitmap8 = &mBitmap;
- if (mBitmap.colorType() != kGray_8_SkColorType)
- {
- convertedBitmap = new SkBitmap;
- if (!convertedBitmap->tryAllocPixels(SkImageInfo::Make(
- mSize.Width(), mSize.Height(), kGray_8_SkColorType, kOpaque_SkAlphaType)))
- abort();
- SkCanvas canvas(*convertedBitmap);
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc); // copy and convert depth
- canvas.drawBitmap(mBitmap, 0, 0, &paint);
- bitmap8 = convertedBitmap;
- }
- // Skia uses a bitmap as an alpha channel only if it's set as kAlpha_8_SkColorType.
- // But in SalBitmap::Create() it's not quite clear if the 8-bit image will be used
- // as a mask or as a real bitmap. So mBitmap is always kGray_8_SkColorType for 8bpp
- // and mAlphaBitmap is kAlpha_8_SkColorType that can be used as a mask.
- // Make mAlphaBitmap share mBitmap's data.
- const_cast<SkBitmap&>(mAlphaBitmap)
- .setInfo(bitmap8->info().makeColorType(kAlpha_8_SkColorType), bitmap8->rowBytes());
- const_cast<SkBitmap&>(mAlphaBitmap)
- .setPixelRef(sk_ref_sp(bitmap8->pixelRef()), bitmap8->pixelRefOrigin().x(),
- bitmap8->pixelRefOrigin().y());
- delete convertedBitmap;
- SAL_INFO("vcl.skia", "skalphabitmap(" << this << ")");
- return mAlphaBitmap;
+ SkCanvas canvas(*convertedBitmap);
+ SkPaint paint;
+ paint.setBlendMode(SkBlendMode::kSrc); // copy and convert depth
+ canvas.drawBitmap(originalBitmap, 0, 0, &paint);
+ convertedBitmap->setImmutable();
+ bitmap8 = convertedBitmap;
}
+ // Skia uses a bitmap as an alpha channel only if it's set as kAlpha_8_SkColorType.
+ // But in SalBitmap::Create() it's not quite clear if the 8-bit image will be used
+ // as a mask or as a real bitmap. So mBitmap is always kGray_8_SkColorType for 8bpp
+ // and alphaBitmap is kAlpha_8_SkColorType that can be used as a mask.
+ // Make alphaBitmap share bitmap8's data.
+ alphaBitmap.setInfo(
+ bitmap8->info().makeColorType(kAlpha_8_SkColorType).makeAlphaType(kPremul_SkAlphaType),
+ bitmap8->rowBytes());
+ alphaBitmap.setPixelRef(sk_ref_sp(bitmap8->pixelRef()), bitmap8->pixelRefOrigin().x(),
+ bitmap8->pixelRefOrigin().y());
+ delete convertedBitmap;
+ alphaBitmap.setImmutable();
}
- return mAlphaBitmap;
+ sk_sp<SkSurface> surface = SkiaHelper::createSkSurface(mSize, kAlpha_8_SkColorType);
+ assert(surface);
+ // https://bugs.chromium.org/p/skia/issues/detail?id=9692
+ // Raster kAlpha_8_SkColorType surfaces need empty contents for SkBlendMode::kSrc.
+ if (!surface->getCanvas()->getGrContext())
+ surface->getCanvas()->clear(SkColorSetARGB(0x00, 0x00, 0x00, 0x00));
+ SkPaint paint;
+ paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha
+ surface->getCanvas()->drawBitmap(alphaBitmap, 0, 0, &paint);
+ const_cast<sk_sp<SkImage>&>(mAlphaImage) = surface->makeImageSnapshot();
+ SAL_INFO("vcl.skia", "getalphaskbitmap(" << this << ")");
+ return mAlphaImage;
}
-// Reset the cached bitmap allocated in GetSkBitmap().
+// Reset the cached images allocated in GetSkImage().
void SkiaSalBitmap::ResetCachedBitmap()
{
- mAlphaBitmap.reset();
- if (mBuffer)
- mBitmap.reset();
+ mAlphaImage.reset();
+ mImage.reset();
}
#ifdef DBG_UTIL
-void SkiaSalBitmap::dump(const char* file) const
-{
- sk_sp<SkImage> image = SkImage::MakeFromBitmap(GetSkBitmap());
- sk_sp<SkData> data = image->encodeToData();
- std::ofstream ostream(file, std::ios::binary);
- ostream.write(static_cast<const char*>(data->data()), data->size());
-}
+void SkiaSalBitmap::dump(const char* file) const { SkiaHelper::dump(GetSkImage(), file); }
void SkiaSalBitmap::verify() const
{