aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/effects/SkAlphaThresholdFilter.cpp
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2016-04-12 11:02:25 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-04-12 11:02:25 -0700
commitaf9b8c804643952d5ff3deed62f1355319b72f72 (patch)
treec62ac7137c52816b7f012d5174f92885f2c5b217 /src/effects/SkAlphaThresholdFilter.cpp
parent0a74c9d86c7a2fb32184c109170d1946a2cff02d (diff)
Switch AlphaThresholdFilter over to new onFilterImage interface
This CL also alters the raster path in two ways: it now respects the sRGB/linear distinction of its input it now respects the clip TBR=reed@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1879643003 Review URL: https://codereview.chromium.org/1879643003
Diffstat (limited to 'src/effects/SkAlphaThresholdFilter.cpp')
-rw-r--r--src/effects/SkAlphaThresholdFilter.cpp226
1 files changed, 143 insertions, 83 deletions
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