Index: src/effects/SkMorphologyImageFilter.cpp |
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp |
index 204f4f3a628e426338ffa8dc9269333f0490dc8a..6abd1fc2365eac1e99f16d43632940411cd5a638 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 |