diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-12-08 12:48:08 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-12-09 11:50:56 +0100 |
commit | b99aada53eb259a3045ced558ebc9c44d3eb722f (patch) | |
tree | f221948162f978833267d9b03444a9078f70acc0 /vcl/skia | |
parent | 991b4e032a4834779aac100607ffc13758328c4a (diff) |
faster Skia conversion to alpha for the alpha-vdev hack
SkColorFilter::Matrix() uses a matrix and some range checks, so
it's faster to just directly convert RGBA -> R in order to get
the one channel we want.
Change-Id: If7e42c13ec2a4aba5f98ada4facccac1eaf4f7a7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107409
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl/skia')
-rw-r--r-- | vcl/skia/salbmp.cxx | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 0ce99d5778e4..096a667e9382 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -754,10 +754,46 @@ const sk_sp<SkImage>& SkiaSalBitmap::GetAlphaSkImage() const if (mImage) { SkiaZone zone; - sk_sp<SkSurface> surface = SkiaHelper::createSkSurface(mSize, kAlpha_8_SkColorType); - assert(surface); - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha + bool scaling = mImage->width() != mSize.Width() || mImage->height() != mSize.Height(); + SkPixmap pixmap; + // Note: We cannot do this when 'scaling' because SkCanvas::drawImageRect() + // with kAlpha_8_SkColorType as source and destination would act as SkBlendMode::kSrcOver + // despite SkBlendMode::kSrc set (https://bugs.chromium.org/p/skia/issues/detail?id=9692). + if (mImage->peekPixels(&pixmap) && !scaling) + { + assert(pixmap.colorType() == kN32_SkColorType); + // In non-GPU mode, convert 32bit data to 8bit alpha, this is faster than + // the SkColorFilter below. Since this is the VCL alpha-vdev alpha, where + // all R,G,B are the same and in fact mean alpha, this means we simply take one + // 8bit channel from the input, and that's the output. + SkBitmap bitmap; + if (!bitmap.installPixels(pixmap)) + abort(); + SkBitmap alphaBitmap; + if (!alphaBitmap.tryAllocPixels(SkImageInfo::MakeA8(bitmap.width(), bitmap.height()))) + abort(); + if (int(bitmap.rowBytes()) == bitmap.width() * 4) + { + SkConvertRGBAToR(alphaBitmap.getAddr8(0, 0), bitmap.getAddr32(0, 0), + bitmap.width() * bitmap.height()); + } + else + { + for (tools::Long y = 0; y < bitmap.height(); ++y) + SkConvertRGBAToR(alphaBitmap.getAddr8(0, y), bitmap.getAddr32(0, y), + bitmap.width()); + } + alphaBitmap.setImmutable(); + sk_sp<SkImage> alphaImage = SkiaHelper::createSkImage(alphaBitmap); + assert(alphaImage); + SAL_INFO("vcl.skia.trace", "getalphaskimage(" << this << ") from raster image"); + // Don't bother here with ConserveMemory(), mImage -> mAlphaImage conversions should + // generally only happen with the separate-alpha-outdev hack, and those bitmaps should + // be temporary. + SkiaSalBitmap* thisPtr = const_cast<SkiaSalBitmap*>(this); + thisPtr->mAlphaImage = alphaImage; + return mAlphaImage; + } // Move the R channel value to the alpha channel. This seems to be the only // way to reinterpret data in SkImage as an alpha SkImage without accessing the pixels. // NOTE: The matrix is 4x5 organized as columns (i.e. each line is a column, not a row). @@ -765,13 +801,16 @@ const sk_sp<SkImage>& SkiaSalBitmap::GetAlphaSkImage() const 0, 0, 0, 0, 0, // G column 0, 0, 0, 0, 0, // B column 1, 0, 0, 0, 0); // A column + SkPaint paint; paint.setColorFilter(SkColorFilters::Matrix(redToAlpha)); - bool scaling = mImage->width() != mSize.Width() || mImage->height() != mSize.Height(); if (scaling) { assert(!mBuffer); // This code should be only called if only mImage holds data. paint.setFilterQuality(mScaleQuality); } + sk_sp<SkSurface> surface = SkiaHelper::createSkSurface(mSize, kAlpha_8_SkColorType); + assert(surface); + paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha surface->getCanvas()->drawImageRect(mImage, SkRect::MakeWH(mImage->width(), mImage->height()), SkRect::MakeWH(mSize.Width(), mSize.Height()), &paint); |