diff options
author | 2016-04-13 04:54:36 -0700 | |
---|---|---|
committer | 2016-04-13 04:54:36 -0700 | |
commit | dada4dd9cf03e42369ca5b38086dba77f01a68e6 (patch) | |
tree | 2f2c671b1e6498d016f9aa77753e81014ab596cd /src/effects/SkMatrixConvolutionImageFilter.cpp | |
parent | 58700da76b3823de878dde82fee11b80daf7fe18 (diff) |
Switch SkMatrixConvolutionImageFilter over to new onFilterImage interface
TBR=reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1877343002
Review URL: https://codereview.chromium.org/1877343002
Diffstat (limited to 'src/effects/SkMatrixConvolutionImageFilter.cpp')
-rw-r--r-- | src/effects/SkMatrixConvolutionImageFilter.cpp | 175 |
1 files changed, 100 insertions, 75 deletions
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp index 3104336628..51e3b6faa7 100644 --- a/src/effects/SkMatrixConvolutionImageFilter.cpp +++ b/src/effects/SkMatrixConvolutionImageFilter.cpp @@ -8,13 +8,16 @@ #include "SkMatrixConvolutionImageFilter.h" #include "SkBitmap.h" #include "SkColorPriv.h" -#include "SkDevice.h" #include "SkReadBuffer.h" +#include "SkSpecialImage.h" +#include "SkSpecialSurface.h" #include "SkWriteBuffer.h" #include "SkRect.h" #include "SkUnPreMultiply.h" #if SK_SUPPORT_GPU +#include "GrContext.h" +#include "GrDrawContext.h" #include "effects/GrMatrixConvolutionEffect.h" #endif @@ -242,18 +245,19 @@ void SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src, // FIXME: This should be refactored to SkImageFilterUtils for // use by other filters. For now, we assume the input is always // premultiplied and unpremultiply it -static SkBitmap unpremultiplyBitmap(SkImageFilter::Proxy* proxy, const SkBitmap& src) +static SkBitmap unpremultiply_bitmap(const SkBitmap& src) { SkAutoLockPixels alp(src); if (!src.getPixels()) { return SkBitmap(); } - SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.height())); - if (!device) { + + const SkImageInfo info = SkImageInfo::MakeN32(src.width(), src.height(), src.alphaType()); + SkBitmap result; + if (!result.tryAllocPixels(info)) { return SkBitmap(); } - SkBitmap result = device->accessBitmap(false); - SkAutoLockPixels alp_result(result); + SkAutoLockPixels resultLock(result); for (int y = 0; y < src.height(); ++y) { const uint32_t* srcRow = src.getAddr32(0, y); uint32_t* dstRow = result.getAddr32(0, y); @@ -264,46 +268,103 @@ static SkBitmap unpremultiplyBitmap(SkImageFilter::Proxy* proxy, const SkBitmap& return result; } -bool SkMatrixConvolutionImageFilter::onFilterImageDeprecated(Proxy* proxy, - const SkBitmap& source, - const Context& ctx, - SkBitmap* result, - SkIPoint* offset) const { - SkBitmap src = source; - SkIPoint srcOffset = SkIPoint::Make(0, 0); - if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) { - return false; +#if SK_SUPPORT_GPU + +static GrTextureDomain::Mode convert_tilemodes(SkMatrixConvolutionImageFilter::TileMode tileMode) { + switch (tileMode) { + case SkMatrixConvolutionImageFilter::kClamp_TileMode: + return GrTextureDomain::kClamp_Mode; + case SkMatrixConvolutionImageFilter::kRepeat_TileMode: + return GrTextureDomain::kRepeat_Mode; + case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode: + return GrTextureDomain::kDecal_Mode; + default: + SkASSERT(false); } + return GrTextureDomain::kIgnore_Mode; +} - if (src.colorType() != kN32_SkColorType) { - return false; +#endif + +sk_sp<SkSpecialImage> SkMatrixConvolutionImageFilter::onFilterImage(SkSpecialImage* source, + const Context& ctx, + SkIPoint* offset) const { + SkIPoint inputOffset = SkIPoint::Make(0, 0); + sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset)); + if (!input) { + return nullptr; } SkIRect bounds; - if (!this->applyCropRectDeprecated(this->mapContext(ctx), proxy, src, &srcOffset, - &bounds, &src)) { - return false; + input = this->applyCropRect(this->mapContext(ctx), input.get(), &inputOffset, &bounds); + if (!input) { + return nullptr; } - if (!fConvolveAlpha && !src.isOpaque()) { - src = unpremultiplyBitmap(proxy, src); +#if SK_SUPPORT_GPU + // Note: if the kernel is too big, the GPU path falls back to SW + if (source->isTextureBacked() && + fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE) { + GrContext* context = source->getContext(); + + sk_sp<GrTexture> inputTexture(input->asTextureRef(context)); + SkASSERT(inputTexture); + + offset->fX = bounds.left(); + offset->fY = bounds.top(); + bounds.offset(-inputOffset); + + // SRGBTODO: handle sRGB here + sk_sp<GrFragmentProcessor> fp(GrMatrixConvolutionEffect::Create( + inputTexture.get(), + bounds, + fKernelSize, + fKernel, + fGain, + fBias, + fKernelOffset, + convert_tilemodes(fTileMode), + fConvolveAlpha)); + if (!fp) { + return nullptr; + } + + return DrawWithFP(context, std::move(fp), bounds, source->internal_getProxy()); } +#endif - SkAutoLockPixels alp(src); - if (!src.getPixels()) { - return false; + SkBitmap inputBM; + + if (!input->getROPixels(&inputBM)) { + return nullptr; } - SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); - if (!device) { - return false; + if (inputBM.colorType() != kN32_SkColorType) { + return nullptr; } - *result = device->accessBitmap(false); - SkAutoLockPixels alp_result(*result); + + if (!fConvolveAlpha && !inputBM.isOpaque()) { + inputBM = unpremultiply_bitmap(inputBM); + } + + SkAutoLockPixels alp(inputBM); + if (!inputBM.getPixels()) { + return nullptr; + } + + const SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(), + inputBM.alphaType()); + + SkBitmap dst; + if (!dst.tryAllocPixels(info)) { + return nullptr; + } + + SkAutoLockPixels dstLock(dst); offset->fX = bounds.fLeft; offset->fY = bounds.fTop; - bounds.offset(-srcOffset); + bounds.offset(-inputOffset); SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fKernelOffset.fX, bounds.top() + fKernelOffset.fY, bounds.width() - fKernelSize.fWidth + 1, @@ -315,12 +376,14 @@ bool SkMatrixConvolutionImageFilter::onFilterImageDeprecated(Proxy* proxy, interior.left(), interior.bottom()); SkIRect right = SkIRect::MakeLTRB(interior.right(), interior.top(), bounds.right(), interior.bottom()); - filterBorderPixels(src, result, top, bounds); - filterBorderPixels(src, result, left, bounds); - filterInteriorPixels(src, result, interior, bounds); - filterBorderPixels(src, result, right, bounds); - filterBorderPixels(src, result, bottom, bounds); - return true; + this->filterBorderPixels(inputBM, &dst, top, bounds); + this->filterBorderPixels(inputBM, &dst, left, bounds); + this->filterInteriorPixels(inputBM, &dst, interior, bounds); + this->filterBorderPixels(inputBM, &dst, right, bounds); + this->filterBorderPixels(inputBM, &dst, bottom, bounds); + return SkSpecialImage::MakeFromRaster(source->internal_getProxy(), + SkIRect::MakeWH(bounds.width(), bounds.height()), + dst); } SkIRect SkMatrixConvolutionImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm, @@ -343,44 +406,6 @@ bool SkMatrixConvolutionImageFilter::affectsTransparentBlack() const { return true; } -#if SK_SUPPORT_GPU - -static GrTextureDomain::Mode convert_tilemodes( - SkMatrixConvolutionImageFilter::TileMode tileMode) { - switch (tileMode) { - case SkMatrixConvolutionImageFilter::kClamp_TileMode: - return GrTextureDomain::kClamp_Mode; - case SkMatrixConvolutionImageFilter::kRepeat_TileMode: - return GrTextureDomain::kRepeat_Mode; - case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode: - return GrTextureDomain::kDecal_Mode; - default: - SkASSERT(false); - } - return GrTextureDomain::kIgnore_Mode; -} - -bool SkMatrixConvolutionImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, - GrTexture* texture, - const SkMatrix&, - const SkIRect& bounds) const { - if (!fp) { - return fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE; - } - SkASSERT(fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE); - *fp = GrMatrixConvolutionEffect::Create(texture, - bounds, - fKernelSize, - fKernel, - fGain, - fBias, - fKernelOffset, - convert_tilemodes(fTileMode), - fConvolveAlpha); - return true; -} -#endif - #ifndef SK_IGNORE_TO_STRING void SkMatrixConvolutionImageFilter::toString(SkString* str) const { str->appendf("SkMatrixConvolutionImageFilter: ("); |