diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkImageFilter.cpp | 44 | ||||
-rw-r--r-- | src/effects/SkAlphaThresholdFilter.cpp | 226 |
2 files changed, 184 insertions, 86 deletions
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 6cbdf625fb..af2b278e3d 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -414,7 +414,7 @@ bool SkImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, GrContext* context = srcTexture->getContext(); GrSurfaceDesc desc; - desc.fFlags = kRenderTarget_GrSurfaceFlag, + desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fWidth = bounds.width(); desc.fHeight = bounds.height(); desc.fConfig = kRGBA_8888_GrPixelConfig; @@ -452,6 +452,44 @@ bool SkImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, return false; } +#if SK_SUPPORT_GPU +sk_sp<SkSpecialImage> SkImageFilter::DrawWithFP(GrContext* context, + sk_sp<GrFragmentProcessor> fp, + const SkIRect& bounds, + SkImageFilter::Proxy* proxy) { + GrPaint paint; + paint.addColorFragmentProcessor(fp.get()); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); + + GrSurfaceDesc desc; + desc.fFlags = kRenderTarget_GrSurfaceFlag; + desc.fWidth = bounds.width(); + desc.fHeight = bounds.height(); + desc.fConfig = kRGBA_8888_GrPixelConfig; + + sk_sp<GrTexture> dst(context->textureProvider()->createApproxTexture(desc)); + if (!dst) { + return nullptr; + } + + sk_sp<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget())); + if (!drawContext) { + return nullptr; + } + + SkRect srcRect = SkRect::Make(bounds); + SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); + GrClip clip(dstRect); + drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect); + + return SkSpecialImage::MakeFromGpu(proxy, + SkIRect::MakeWH(bounds.width(), bounds.height()), + kNeedNewImageUniqueID_SpecialImage, + dst.get()); + +} +#endif + bool SkImageFilter::asAColorFilter(SkColorFilter** filterPtr) const { SkASSERT(nullptr != filterPtr); if (!this->isColorFilterNode(filterPtr)) { @@ -530,8 +568,8 @@ sk_sp<SkSpecialImage> SkImageFilter::applyCropRect(const Context& ctx, SkSpecialImage* src, SkIPoint* srcOffset, SkIRect* bounds) const { - SkIRect srcBounds; - srcBounds = SkIRect::MakeXYWH(srcOffset->fX, srcOffset->fY, src->width(), src->height()); + const SkIRect srcBounds = SkIRect::MakeXYWH(srcOffset->x(), srcOffset->y(), + src->width(), src->height()); SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_MapDirection); fCropRect.applyTo(dstBounds, ctx.ctm(), this->affectsTransparentBlack(), bounds); diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp index 0b65188e83..832fcb39e7 100644 --- a/src/effects/SkAlphaThresholdFilter.cpp +++ b/src/effects/SkAlphaThresholdFilter.cpp @@ -8,8 +8,8 @@ #include "SkAlphaThresholdFilter.h" #include "SkBitmap.h" -#include "SkDevice.h" #include "SkReadBuffer.h" +#include "SkSpecialImage.h" #include "SkWriteBuffer.h" #include "SkRegion.h" #if SK_SUPPORT_GPU @@ -19,7 +19,8 @@ class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter { public: SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold, - SkScalar outerThreshold, sk_sp<SkImageFilter> input); + SkScalar outerThreshold, sk_sp<SkImageFilter> input, + const CropRect* cropRect = nullptr); SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAlphaThresholdFilterImpl) @@ -28,11 +29,11 @@ public: protected: void flatten(SkWriteBuffer&) const override; - bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, - SkBitmap* result, SkIPoint* offset) const override; + sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&, + SkIPoint* offset) const override; + #if SK_SUPPORT_GPU - bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, - const SkIRect& bounds) const override; + sk_sp<GrTexture> createMaskTexture(GrContext*, const SkMatrix&, const SkIRect& bounds) const; #endif private: @@ -53,14 +54,17 @@ static SkScalar pin_0_1(SkScalar x) { sk_sp<SkImageFilter> SkAlphaThresholdFilter::Make(const SkRegion& region, SkScalar innerThreshold, SkScalar outerThreshold, - sk_sp<SkImageFilter> input) { + sk_sp<SkImageFilter> input, + const SkImageFilter::CropRect* cropRect) { innerThreshold = pin_0_1(innerThreshold); outerThreshold = pin_0_1(outerThreshold); if (!SkScalarIsFinite(innerThreshold) || !SkScalarIsFinite(outerThreshold)) { return nullptr; } return sk_sp<SkImageFilter>(new SkAlphaThresholdFilterImpl(region, innerThreshold, - outerThreshold, std::move(input))); + outerThreshold, + std::move(input), + cropRect)); } #if SK_SUPPORT_GPU @@ -271,66 +275,59 @@ sk_sp<SkFlattenable> SkAlphaThresholdFilterImpl::CreateProc(SkReadBuffer& buffer SkScalar outer = buffer.readScalar(); SkRegion rgn; buffer.readRegion(&rgn); - return SkAlphaThresholdFilter::Make(rgn, inner, outer, common.getInput(0)); + return SkAlphaThresholdFilter::Make(rgn, inner, outer, common.getInput(0), + &common.cropRect()); } SkAlphaThresholdFilterImpl::SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold, SkScalar outerThreshold, - sk_sp<SkImageFilter> input) - : INHERITED(&input, 1, nullptr) + sk_sp<SkImageFilter> input, + const CropRect* cropRect) + : INHERITED(&input, 1, cropRect) , fRegion(region) , fInnerThreshold(innerThreshold) , fOuterThreshold(outerThreshold) { } #if SK_SUPPORT_GPU -bool SkAlphaThresholdFilterImpl::asFragmentProcessor(GrFragmentProcessor** fp, - GrTexture* texture, - const SkMatrix& inMatrix, - const SkIRect& bounds) const { - if (fp) { - GrContext* context = texture->getContext(); - GrSurfaceDesc maskDesc; - if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { - maskDesc.fConfig = kAlpha_8_GrPixelConfig; - } else { - maskDesc.fConfig = kRGBA_8888_GrPixelConfig; - } - maskDesc.fFlags = kRenderTarget_GrSurfaceFlag; - // Add one pixel of border to ensure that clamp mode will be all zeros - // the outside. - maskDesc.fWidth = bounds.width(); - maskDesc.fHeight = bounds.height(); - SkAutoTUnref<GrTexture> maskTexture( - context->textureProvider()->createApproxTexture(maskDesc)); - if (!maskTexture) { - return false; - } +sk_sp<GrTexture> SkAlphaThresholdFilterImpl::createMaskTexture(GrContext* context, + const SkMatrix& inMatrix, + const SkIRect& bounds) const { + GrSurfaceDesc maskDesc; + if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { + maskDesc.fConfig = kAlpha_8_GrPixelConfig; + } else { + maskDesc.fConfig = kRGBA_8888_GrPixelConfig; + } + maskDesc.fFlags = kRenderTarget_GrSurfaceFlag; + // Add one pixel of border to ensure that clamp mode will be all zeros + // the outside. + maskDesc.fWidth = bounds.width(); + maskDesc.fHeight = bounds.height(); + sk_sp<GrTexture> maskTexture(context->textureProvider()->createApproxTexture(maskDesc)); + if (!maskTexture) { + return nullptr; + } - SkAutoTUnref<GrDrawContext> drawContext( - context->drawContext(maskTexture->asRenderTarget())); - if (drawContext) { - GrPaint grPaint; - grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); - SkRegion::Iterator iter(fRegion); - drawContext->clear(nullptr, 0x0, true); - - GrClip clip(SkRect::Make(SkIRect::MakeWH(bounds.width(), bounds.height()))); - while (!iter.done()) { - SkRect rect = SkRect::Make(iter.rect()); - drawContext->drawRect(clip, grPaint, inMatrix, rect); - iter.next(); - } - } + sk_sp<GrDrawContext> drawContext(context->drawContext(maskTexture->asRenderTarget())); + if (!drawContext) { + return nullptr; + } - *fp = AlphaThresholdEffect::Create(texture, - maskTexture, - fInnerThreshold, - fOuterThreshold, - bounds); + GrPaint grPaint; + grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); + SkRegion::Iterator iter(fRegion); + drawContext->clear(nullptr, 0x0, true); + + GrClip clip(SkRect::Make(SkIRect::MakeWH(bounds.width(), bounds.height()))); + while (!iter.done()) { + SkRect rect = SkRect::Make(iter.rect()); + drawContext->drawRect(clip, grPaint, inMatrix, rect); + iter.next(); } - return true; + + return maskTexture; } #endif @@ -341,50 +338,109 @@ void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const { buffer.writeRegion(fRegion); } -bool SkAlphaThresholdFilterImpl::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& src, - const Context& ctx, SkBitmap* dst, - SkIPoint* offset) const { +sk_sp<SkSpecialImage> SkAlphaThresholdFilterImpl::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; + } + + const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(), + input->width(), input->height()); + + SkIRect bounds; + if (!this->applyCropRect(ctx, inputBounds, &bounds)) { + return nullptr; + } + +#if SK_SUPPORT_GPU + if (source->isTextureBacked()) { + GrContext* context = source->getContext(); + + sk_sp<GrTexture> inputTexture(input->asTextureRef(context)); + SkASSERT(inputTexture); + + offset->fX = bounds.left(); + offset->fY = bounds.top(); - if (src.colorType() != kN32_SkColorType) { - return false; + bounds.offset(-inputOffset); + + SkMatrix matrix(ctx.ctm()); + matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); + + sk_sp<GrTexture> maskTexture(this->createMaskTexture(context, matrix, bounds)); + if (!maskTexture) { + return nullptr; + } + + // SRGBTODO: handle sRGB here + sk_sp<GrFragmentProcessor> fp(AlphaThresholdEffect::Create(inputTexture.get(), + maskTexture.get(), + fInnerThreshold, + fOuterThreshold, + bounds)); + if (!fp) { + return nullptr; + } + + return DrawWithFP(context, std::move(fp), bounds, source->internal_getProxy()); + } +#endif + + SkBitmap inputBM; + + if (!input->getROPixels(&inputBM)) { + return nullptr; } + if (inputBM.colorType() != kN32_SkColorType) { + return nullptr; + } + + SkAutoLockPixels inputLock(inputBM); + + if (!inputBM.getPixels() || inputBM.width() <= 0 || inputBM.height() <= 0) { + return nullptr; + } + + SkMatrix localInverse; if (!ctx.ctm().invert(&localInverse)) { - return false; + return nullptr; } - SkAutoLockPixels alp(src); - SkASSERT(src.getPixels()); - if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) { - return false; - } + SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(), + inputBM.alphaType()); - SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.height())); - if (!device) { - return false; + SkBitmap dst; + if (!dst.tryAllocPixels(info)) { + return nullptr; } - *dst = device->accessBitmap(false); - SkAutoLockPixels alp_dst(*dst); + + SkAutoLockPixels dstLock(dst); U8CPU innerThreshold = (U8CPU)(fInnerThreshold * 0xFF); U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF); - SkColor* sptr = src.getAddr32(0, 0); - SkColor* dptr = dst->getAddr32(0, 0); - int width = src.width(), height = src.height(); - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - const SkColor& source = sptr[y * width + x]; - SkColor output_color(source); + SkColor* dptr = dst.getAddr32(0, 0); + int dstWidth = dst.width(), dstHeight = dst.height(); + for (int y = 0; y < dstHeight; ++y) { + const SkColor* sptr = inputBM.getAddr32(bounds.fLeft, bounds.fTop+y); + + for (int x = 0; x < dstWidth; ++x) { + const SkColor& source = sptr[x]; + SkColor outputColor(source); SkPoint position; - localInverse.mapXY((SkScalar)x, (SkScalar)y, &position); + localInverse.mapXY((SkScalar)x + bounds.fLeft, (SkScalar)y + bounds.fTop, &position); if (fRegion.contains((int32_t)position.x(), (int32_t)position.y())) { if (SkColorGetA(source) < innerThreshold) { U8CPU alpha = SkColorGetA(source); - if (alpha == 0) + if (alpha == 0) { alpha = 1; + } float scale = (float)innerThreshold / alpha; - output_color = SkColorSetARGB(innerThreshold, + outputColor = SkColorSetARGB(innerThreshold, (U8CPU)(SkColorGetR(source) * scale), (U8CPU)(SkColorGetG(source) * scale), (U8CPU)(SkColorGetB(source) * scale)); @@ -392,17 +448,21 @@ bool SkAlphaThresholdFilterImpl::onFilterImageDeprecated(Proxy* proxy, const SkB } else { if (SkColorGetA(source) > outerThreshold) { float scale = (float)outerThreshold / SkColorGetA(source); - output_color = SkColorSetARGB(outerThreshold, + outputColor = SkColorSetARGB(outerThreshold, (U8CPU)(SkColorGetR(source) * scale), (U8CPU)(SkColorGetG(source) * scale), (U8CPU)(SkColorGetB(source) * scale)); } } - dptr[y * dst->width() + x] = output_color; + dptr[y * dstWidth + x] = outputColor; } } - return true; + offset->fX = bounds.left(); + offset->fY = bounds.top(); + return SkSpecialImage::MakeFromRaster(source->internal_getProxy(), + SkIRect::MakeWH(bounds.width(), bounds.height()), + dst); } #ifndef SK_IGNORE_TO_STRING |