diff options
-rw-r--r-- | gm/morphology.cpp | 22 | ||||
-rw-r--r-- | include/effects/SkMorphologyImageFilter.h | 58 | ||||
-rw-r--r-- | src/effects/SkMorphologyImageFilter.cpp | 329 |
3 files changed, 186 insertions, 223 deletions
diff --git a/gm/morphology.cpp b/gm/morphology.cpp index 3fb11d82d1..c3326f9397 100644 --- a/gm/morphology.cpp +++ b/gm/morphology.cpp @@ -17,15 +17,14 @@ class MorphologyGM : public GM { public: MorphologyGM() { this->setBGColor(0xFF000000); - fOnce = false; } protected: - virtual SkString onShortName() { + SkString onShortName() override { return SkString("morphology"); } - void make_bitmap() { + void onOnceBeforeDraw() override { fBitmap.allocN32Pixels(135, 135); SkCanvas canvas(fBitmap); canvas.clear(0x0); @@ -40,7 +39,7 @@ protected: canvas.drawText(str2, strlen(str2), 10, 110, paint); } - virtual SkISize onISize() { + SkISize onISize() override { return SkISize::Make(WIDTH, HEIGHT); } @@ -53,11 +52,7 @@ protected: canvas->restore(); } - virtual void onDraw(SkCanvas* canvas) { - if (!fOnce) { - make_bitmap(); - fOnce = true; - } + void onDraw(SkCanvas* canvas) override { struct { int fWidth, fHeight; int fRadiusX, fRadiusY; @@ -87,20 +82,19 @@ protected: nullptr, cr))->unref(); } - drawClippedBitmap(canvas, paint, i * 140, j * 140); + this->drawClippedBitmap(canvas, paint, i * 140, j * 140); } } } private: - typedef GM INHERITED; SkBitmap fBitmap; - bool fOnce; + + typedef GM INHERITED; }; ////////////////////////////////////////////////////////////////////////////// -static GM* MyFactory(void*) { return new MorphologyGM; } -static GMRegistry reg(MyFactory); +DEF_GM(return new MorphologyGM;) } diff --git a/include/effects/SkMorphologyImageFilter.h b/include/effects/SkMorphologyImageFilter.h index f4f12605df..b449b19e61 100644 --- a/include/effects/SkMorphologyImageFilter.h +++ b/include/effects/SkMorphologyImageFilter.h @@ -5,7 +5,6 @@ * found in the LICENSE file. */ - #ifndef SkMorphologyImageFilter_DEFINED #define SkMorphologyImageFilter_DEFINED @@ -13,6 +12,7 @@ #include "SkImageFilter.h" #include "SkSize.h" +/////////////////////////////////////////////////////////////////////////////// class SK_API SkMorphologyImageFilter : public SkImageFilter { public: SkRect computeFastBounds(const SkRect& src) const override; @@ -31,45 +31,38 @@ public: protected: SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect); - bool filterImageGeneric(Proc procX, Proc procY, - Proxy*, const SkBitmap& src, const Context&, - SkBitmap* result, SkIPoint* offset) const; + sk_sp<SkSpecialImage> filterImageGeneric(bool dilate, + SkSpecialImage* source, + const Context&, + SkIPoint* offset) const; void flatten(SkWriteBuffer&) const override; -#if SK_SUPPORT_GPU - bool canFilterImageGPU() const override { return true; } - bool filterImageGPUGeneric(bool dilate, Proxy* proxy, const SkBitmap& src, - const Context& ctm, SkBitmap* result, - SkIPoint* offset) const; -#endif - SkISize radius() const { return fRadius; } + SkISize radius() const { return fRadius; } private: - SkISize fRadius; + SkISize fRadius; typedef SkImageFilter INHERITED; }; +/////////////////////////////////////////////////////////////////////////////// class SK_API SkDilateImageFilter : public SkMorphologyImageFilter { public: - static SkImageFilter* Create(int radiusX, int radiusY, SkImageFilter* input = NULL, - const CropRect* cropRect = NULL) { + static SkImageFilter* Create(int radiusX, int radiusY, + SkImageFilter* input = nullptr, + const CropRect* cropRect = nullptr) { if (radiusX < 0 || radiusY < 0) { - return NULL; + return nullptr; } return new SkDilateImageFilter(radiusX, radiusY, input, cropRect); } - bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, - SkBitmap* result, SkIPoint* offset) const override; - -#if SK_SUPPORT_GPU - bool filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, const Context&, - SkBitmap* result, SkIPoint* offset) const override; -#endif - SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDilateImageFilter) +protected: + sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&, + SkIPoint* offset) const override; + private: SkDilateImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect) : INHERITED(radiusX, radiusY, input, cropRect) {} @@ -77,28 +70,25 @@ private: typedef SkMorphologyImageFilter INHERITED; }; +/////////////////////////////////////////////////////////////////////////////// class SK_API SkErodeImageFilter : public SkMorphologyImageFilter { public: static SkImageFilter* Create(int radiusX, int radiusY, - SkImageFilter* input = NULL, - const CropRect* cropRect = NULL) { + SkImageFilter* input = nullptr, + const CropRect* cropRect = nullptr) { if (radiusX < 0 || radiusY < 0) { - return NULL; + return nullptr; } return new SkErodeImageFilter(radiusX, radiusY, input, cropRect); } - bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, - SkBitmap* result, SkIPoint* offset) const override; - -#if SK_SUPPORT_GPU - bool filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, const Context&, - SkBitmap* result, SkIPoint* offset) const override; -#endif - SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkErodeImageFilter) +protected: + sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&, + SkIPoint* offset) const override; + private: SkErodeImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect) : INHERITED(radiusX, radiusY, input, cropRect) {} diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index 204f4f3a62..6abd1fc236 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -6,13 +6,15 @@ */ #include "SkMorphologyImageFilter.h" + #include "SkBitmap.h" #include "SkColorPriv.h" -#include "SkDevice.h" #include "SkOpts.h" #include "SkReadBuffer.h" #include "SkRect.h" +#include "SkSpecialImage.h" #include "SkWriteBuffer.h" + #if SK_SUPPORT_GPU #include "GrContext.h" #include "GrDrawContext.h" @@ -30,7 +32,8 @@ SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect) - : INHERITED(1, &input, cropRect), fRadius(SkISize::Make(radiusX, radiusY)) { + : INHERITED(1, &input, cropRect) + , fRadius(SkISize::Make(radiusX, radiusY)) { } void SkMorphologyImageFilter::flatten(SkWriteBuffer& buffer) const { @@ -39,107 +42,20 @@ void SkMorphologyImageFilter::flatten(SkWriteBuffer& buffer) const { buffer.writeInt(fRadius.fHeight); } -static void callProcX(SkMorphologyImageFilter::Proc procX, const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds) -{ - procX(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), +static void call_proc_X(SkMorphologyImageFilter::Proc procX, + const SkPixmap& src, SkBitmap* dst, + int radiusX, const SkIRect& bounds) { + procX(src.addr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), radiusX, bounds.width(), bounds.height(), src.rowBytesAsPixels(), dst->rowBytesAsPixels()); } -static void callProcY(SkMorphologyImageFilter::Proc procY, const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds) -{ - procY(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), +static void call_proc_Y(SkMorphologyImageFilter::Proc procY, + const SkPMColor* src, int srcRowBytesAsPixels, SkBitmap* dst, + int radiusY, const SkIRect& bounds) { + procY(src, dst->getAddr32(0, 0), radiusY, bounds.height(), bounds.width(), - src.rowBytesAsPixels(), dst->rowBytesAsPixels()); -} - -bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc procX, - SkMorphologyImageFilter::Proc procY, - Proxy* proxy, - const SkBitmap& source, - const Context& ctx, - SkBitmap* dst, - SkIPoint* offset) const { - SkBitmap src = source; - SkIPoint srcOffset = SkIPoint::Make(0, 0); - if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) { - return false; - } - - if (src.colorType() != kN32_SkColorType) { - return false; - } - - SkIRect bounds; - if (!this->applyCropRectDeprecated(this->mapContext(ctx), proxy, src, &srcOffset, - &bounds, &src)) { - return false; - } - - SkAutoLockPixels alp(src); - if (!src.getPixels()) { - return false; - } - - SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), - SkIntToScalar(this->radius().height())); - ctx.ctm().mapVectors(&radius, 1); - int width = SkScalarFloorToInt(radius.fX); - int height = SkScalarFloorToInt(radius.fY); - - if (width < 0 || height < 0) { - return false; - } - - SkIRect srcBounds = bounds; - srcBounds.offset(-srcOffset); - - if (width == 0 && height == 0) { - src.extractSubset(dst, srcBounds); - offset->fX = bounds.left(); - offset->fY = bounds.top(); - return true; - } - - SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); - if (!device) { - return false; - } - *dst = device->accessBitmap(false); - SkAutoLockPixels alp_dst(*dst); - - if (width > 0 && height > 0) { - SkAutoTUnref<SkBaseDevice> tempDevice(proxy->createDevice(dst->width(), dst->height())); - if (!tempDevice) { - return false; - } - SkBitmap temp = tempDevice->accessBitmap(false); - SkAutoLockPixels alp_temp(temp); - callProcX(procX, src, &temp, width, srcBounds); - SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height()); - callProcY(procY, temp, dst, height, tmpBounds); - } else if (width > 0) { - callProcX(procX, src, dst, width, srcBounds); - } else if (height > 0) { - callProcY(procY, src, dst, height, srcBounds); - } - offset->fX = bounds.left(); - offset->fY = bounds.top(); - return true; -} - -bool SkErodeImageFilter::onFilterImageDeprecated(Proxy* proxy, - const SkBitmap& source, const Context& ctx, - SkBitmap* dst, SkIPoint* offset) const { - return this->filterImageGeneric(SkOpts::erode_x, SkOpts::erode_y, - proxy, source, ctx, dst, offset); -} - -bool SkDilateImageFilter::onFilterImageDeprecated(Proxy* proxy, - const SkBitmap& source, const Context& ctx, - SkBitmap* dst, SkIPoint* offset) const { - return this->filterImageGeneric(SkOpts::dilate_x, SkOpts::dilate_y, - proxy, source, ctx, dst, offset); + srcRowBytesAsPixels, dst->rowBytesAsPixels()); } SkRect SkMorphologyImageFilter::computeFastBounds(const SkRect& src) const { @@ -384,7 +300,8 @@ GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, int radius, MorphologyType type) : INHERITED(texture, direction, radius) - , fType(type), fUseRange(false) { + , fType(type) + , fUseRange(false) { this->initClassID<GrMorphologyEffect>(); } @@ -394,7 +311,8 @@ GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, MorphologyType type, float range[2]) : INHERITED(texture, direction, radius) - , fType(type), fUseRange(true) { + , fType(type) + , fUseRange(true) { this->initClassID<GrMorphologyEffect>(); fRange[0] = range[0]; fRange[1] = range[1]; @@ -441,18 +359,16 @@ const GrFragmentProcessor* GrMorphologyEffect::TestCreate(GrProcessorTestData* d return GrMorphologyEffect::Create(d->fTextures[texIdx], dir, radius, type); } -namespace { - -void apply_morphology_rect(GrDrawContext* drawContext, - const GrClip& clip, - GrTexture* texture, - const SkIRect& srcRect, - const SkIRect& dstRect, - int radius, - GrMorphologyEffect::MorphologyType morphType, - float bounds[2], - Gr1DKernelEffect::Direction direction) { +static void apply_morphology_rect(GrDrawContext* drawContext, + const GrClip& clip, + GrTexture* texture, + const SkIRect& srcRect, + const SkIRect& dstRect, + int radius, + GrMorphologyEffect::MorphologyType morphType, + float bounds[2], + Gr1DKernelEffect::Direction direction) { GrPaint paint; paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, direction, @@ -464,14 +380,14 @@ void apply_morphology_rect(GrDrawContext* drawContext, SkRect::Make(srcRect)); } -void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, - const GrClip& clip, - GrTexture* texture, - const SkIRect& srcRect, - const SkIRect& dstRect, - int radius, - GrMorphologyEffect::MorphologyType morphType, - Gr1DKernelEffect::Direction direction) { +static void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, + const GrClip& clip, + GrTexture* texture, + const SkIRect& srcRect, + const SkIRect& dstRect, + int radius, + GrMorphologyEffect::MorphologyType morphType, + Gr1DKernelEffect::Direction direction) { GrPaint paint; paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, direction, @@ -482,14 +398,14 @@ void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, SkRect::Make(srcRect)); } -void apply_morphology_pass(GrDrawContext* drawContext, - const GrClip& clip, - GrTexture* texture, - const SkIRect& srcRect, - const SkIRect& dstRect, - int radius, - GrMorphologyEffect::MorphologyType morphType, - Gr1DKernelEffect::Direction direction) { +static void apply_morphology_pass(GrDrawContext* drawContext, + const GrClip& clip, + GrTexture* texture, + const SkIRect& srcRect, + const SkIRect& dstRect, + int radius, + GrMorphologyEffect::MorphologyType morphType, + Gr1DKernelEffect::Direction direction) { float bounds[2] = { 0.0f, 1.0f }; SkIRect lowerSrcRect = srcRect, lowerDstRect = dstRect; SkIRect middleSrcRect = srcRect, middleDstRect = dstRect; @@ -528,12 +444,11 @@ void apply_morphology_pass(GrDrawContext* drawContext, } } -bool apply_morphology(const SkBitmap& input, - const SkIRect& rect, - GrMorphologyEffect::MorphologyType morphType, - SkISize radius, - SkBitmap* dst) { - SkAutoTUnref<GrTexture> srcTexture(SkRef(input.getTexture())); +static sk_sp<SkSpecialImage> apply_morphology(SkSpecialImage* input, + const SkIRect& rect, + GrMorphologyEffect::MorphologyType morphType, + SkISize radius) { + SkAutoTUnref<GrTexture> srcTexture(SkRef(input->peekTexture())); SkASSERT(srcTexture); GrContext* context = srcTexture->getContext(); @@ -549,15 +464,17 @@ bool apply_morphology(const SkBitmap& input, desc.fConfig = kSkia8888_GrPixelConfig; SkIRect srcRect = rect; + SkASSERT(radius.width() > 0 || radius.height() > 0); + if (radius.fWidth > 0) { GrTexture* scratch = context->textureProvider()->createApproxTexture(desc); - if (nullptr == scratch) { - return false; + if (!scratch) { + return nullptr; } SkAutoTUnref<GrDrawContext> dstDrawContext( context->drawContext(scratch->asRenderTarget())); if (!dstDrawContext) { - return false; + return nullptr; } apply_morphology_pass(dstDrawContext, clip, srcTexture, @@ -575,13 +492,13 @@ bool apply_morphology(const SkBitmap& input, } if (radius.fHeight > 0) { GrTexture* scratch = context->textureProvider()->createApproxTexture(desc); - if (nullptr == scratch) { - return false; + if (!scratch) { + return nullptr; } SkAutoTUnref<GrDrawContext> dstDrawContext( context->drawContext(scratch->asRenderTarget())); if (!dstDrawContext) { - return false; + return nullptr; } apply_morphology_pass(dstDrawContext, clip, srcTexture, @@ -590,28 +507,30 @@ bool apply_morphology(const SkBitmap& input, srcTexture.reset(scratch); } - GrWrapTextureInBitmap(srcTexture, rect.width(), rect.height(), false, dst); - return true; -} -}; + return SkSpecialImage::MakeFromGpu(input->internal_getProxy(), + SkIRect::MakeWH(rect.width(), rect.height()), + kNeedNewImageUniqueID_SpecialImage, + srcTexture); +} +#endif -bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, - Proxy* proxy, - const SkBitmap& src, - const Context& ctx, - SkBitmap* result, - SkIPoint* offset) const { - SkBitmap input = src; - SkIPoint srcOffset = SkIPoint::Make(0, 0); - if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &input, &srcOffset)) { - return false; +sk_sp<SkSpecialImage> SkMorphologyImageFilter::filterImageGeneric(bool dilate, + 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, input, &srcOffset, - &bounds, &input)) { - return false; + input = this->applyCropRect(this->mapContext(ctx), input.get(), &inputOffset, &bounds); + if (!input) { + return nullptr; } + SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), SkIntToScalar(this->radius().height())); ctx.ctm().mapVectors(&radius, 1); @@ -619,38 +538,98 @@ bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, int height = SkScalarFloorToInt(radius.fY); if (width < 0 || height < 0) { - return false; + return nullptr; } SkIRect srcBounds = bounds; - srcBounds.offset(-srcOffset); - if (width == 0 && height == 0) { - input.extractSubset(result, srcBounds); + srcBounds.offset(-inputOffset); + + if (0 == width && 0 == height) { offset->fX = bounds.left(); offset->fY = bounds.top(); - return true; + return input->makeSubset(srcBounds); + } + +#if SK_SUPPORT_GPU + if (input->peekTexture()) { + auto type = dilate ? GrMorphologyEffect::kDilate_MorphologyType + : GrMorphologyEffect::kErode_MorphologyType; + sk_sp<SkSpecialImage> result(apply_morphology(input.get(), srcBounds, type, + SkISize::Make(width, height))); + if (result) { + offset->fX = bounds.left(); + offset->fY = bounds.top(); + } + return result; + } +#endif + + SkPixmap inputPixmap; + + if (!input->peekPixels(&inputPixmap)) { + return nullptr; } - GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDilate_MorphologyType - : GrMorphologyEffect::kErode_MorphologyType; - if (!apply_morphology(input, srcBounds, type, SkISize::Make(width, height), result)) { - return false; + if (inputPixmap.colorType() != kN32_SkColorType) { + return nullptr; + } + + SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), + inputPixmap.colorType(), inputPixmap.alphaType()); + + SkBitmap dst; + if (!dst.tryAllocPixels(info)) { + return nullptr; + } + + SkAutoLockPixels dstLock(dst); + + SkMorphologyImageFilter::Proc procX, procY; + + if (dilate) { + procX = SkOpts::dilate_x; + procY = SkOpts::dilate_y; + } else { + procX = SkOpts::erode_x; + procY = SkOpts::erode_y; + } + + if (width > 0 && height > 0) { + SkBitmap tmp; + if (!tmp.tryAllocPixels(info)) { + return nullptr; + } + + SkAutoLockPixels tmpLock(tmp); + + call_proc_X(procX, inputPixmap, &tmp, width, srcBounds); + SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height()); + call_proc_Y(procY, + tmp.getAddr32(tmpBounds.left(), tmpBounds.top()), tmp.rowBytesAsPixels(), + &dst, height, tmpBounds); + } else if (width > 0) { + call_proc_X(procX, inputPixmap, &dst, width, srcBounds); + } else if (height > 0) { + call_proc_Y(procY, + inputPixmap.addr32(srcBounds.left(), srcBounds.top()), + inputPixmap.rowBytesAsPixels(), + &dst, height, srcBounds); } offset->fX = bounds.left(); offset->fY = bounds.top(); - return true; + + return SkSpecialImage::MakeFromRaster(source->internal_getProxy(), + SkIRect::MakeWH(bounds.width(), bounds.height()), + dst); } -bool SkDilateImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, - const Context& ctx, - SkBitmap* result, SkIPoint* offset) const { - return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); +sk_sp<SkSpecialImage> SkDilateImageFilter::onFilterImage(SkSpecialImage* source, const Context& ctx, + SkIPoint* offset) const { + return this->filterImageGeneric(true, source, ctx, offset); } -bool SkErodeImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, - const Context& ctx, - SkBitmap* result, SkIPoint* offset) const { - return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); +sk_sp<SkSpecialImage> SkErodeImageFilter::onFilterImage(SkSpecialImage* source, const Context& ctx, + SkIPoint* offset) const { + return this->filterImageGeneric(false, source, ctx, offset); } -#endif |