diff options
-rw-r--r-- | include/effects/SkDisplacementMapEffect.h | 15 | ||||
-rw-r--r-- | src/effects/SkDisplacementMapEffect.cpp | 389 |
2 files changed, 197 insertions, 207 deletions
diff --git a/include/effects/SkDisplacementMapEffect.h b/include/effects/SkDisplacementMapEffect.h index a5b81e8585..4b6f321a22 100644 --- a/include/effects/SkDisplacementMapEffect.h +++ b/include/effects/SkDisplacementMapEffect.h @@ -9,7 +9,6 @@ #define SkDisplacementMapEffect_DEFINED #include "SkImageFilter.h" -#include "SkBitmap.h" class SK_API SkDisplacementMapEffect : public SkImageFilter { public: @@ -31,26 +30,18 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDisplacementMapEffect) - bool onFilterImageDeprecated(Proxy* proxy, - const SkBitmap& src, - const Context& ctx, - SkBitmap* dst, - SkIPoint* offset) const override; SkRect computeFastBounds(const SkRect& src) const override; virtual SkIRect onFilterBounds(const SkIRect& src, const SkMatrix&, MapDirection) const override; SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override; -#if SK_SUPPORT_GPU - bool canFilterImageGPU() const override { return true; } - bool filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, const Context& ctx, - SkBitmap* result, SkIPoint* offset) const override; -#endif - SK_TO_STRING_OVERRIDE() protected: + sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&, + SkIPoint* offset) const override; + SkDisplacementMapEffect(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, SkScalar scale, SkImageFilter* inputs[2], diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index 6debea16e4..db0a59a1b9 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -6,8 +6,10 @@ */ #include "SkDisplacementMapEffect.h" -#include "SkDevice.h" + +#include "SkBitmap.h" #include "SkReadBuffer.h" +#include "SkSpecialImage.h" #include "SkWriteBuffer.h" #include "SkUnPreMultiply.h" #include "SkColorPriv.h" @@ -57,13 +59,12 @@ template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>( template<SkDisplacementMapEffect::ChannelSelectorType typeX, SkDisplacementMapEffect::ChannelSelectorType typeY> void computeDisplacement(const SkVector& scale, SkBitmap* dst, - SkBitmap* displ, const SkIPoint& offset, - SkBitmap* src, - const SkIRect& bounds) -{ + const SkBitmap& displ, const SkIPoint& offset, + const SkBitmap& src, + const SkIRect& bounds) { static const SkScalar Inv8bit = SkScalarInvert(255); - const int srcW = src->width(); - const int srcH = src->height(); + const int srcW = src.width(); + const int srcH = src.height(); const SkVector scaleForColor = SkVector::Make(SkScalarMul(scale.fX, Inv8bit), SkScalarMul(scale.fY, Inv8bit)); const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - SkScalarMul(scale.fX, SK_ScalarHalf), @@ -71,8 +72,7 @@ void computeDisplacement(const SkVector& scale, SkBitmap* dst, const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); SkPMColor* dstPtr = dst->getAddr32(0, 0); for (int y = bounds.top(); y < bounds.bottom(); ++y) { - const SkPMColor* displPtr = displ->getAddr32(bounds.left() + offset.fX, - y + offset.fY); + const SkPMColor* displPtr = displ.getAddr32(bounds.left() + offset.fX, y + offset.fY); for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) { const SkScalar displX = SkScalarMul(scaleForColor.fX, SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj.fX; @@ -82,7 +82,7 @@ void computeDisplacement(const SkVector& scale, SkBitmap* dst, const int srcX = x + SkScalarTruncToInt(displX); const int srcY = y + SkScalarTruncToInt(displY); *dstPtr++ = ((srcX < 0) || (srcX >= srcW) || (srcY < 0) || (srcY >= srcH)) ? - 0 : *(src->getAddr32(srcX, srcY)); + 0 : *(src.getAddr32(srcX, srcY)); } } } @@ -90,10 +90,9 @@ void computeDisplacement(const SkVector& scale, SkBitmap* dst, template<SkDisplacementMapEffect::ChannelSelectorType typeX> void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, const SkVector& scale, SkBitmap* dst, - SkBitmap* displ, const SkIPoint& offset, - SkBitmap* src, - const SkIRect& bounds) -{ + const SkBitmap& displ, const SkIPoint& offset, + const SkBitmap& src, + const SkIRect& bounds) { switch (yChannelSelector) { case SkDisplacementMapEffect::kR_ChannelSelectorType: computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>( @@ -120,10 +119,9 @@ void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSe void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, const SkVector& scale, SkBitmap* dst, - SkBitmap* displ, const SkIPoint& offset, - SkBitmap* src, - const SkIRect& bounds) -{ + const SkBitmap& displ, const SkIPoint& offset, + const SkBitmap& src, + const SkIRect& bounds) { switch (xChannelSelector) { case SkDisplacementMapEffect::kR_ChannelSelectorType: computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>( @@ -185,11 +183,10 @@ SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSel SkScalar scale, SkImageFilter* inputs[2], const CropRect* cropRect) - : INHERITED(2, inputs, cropRect) - , fXChannelSelector(xChannelSelector) - , fYChannelSelector(yChannelSelector) - , fScale(scale) -{ + : INHERITED(2, inputs, cropRect) + , fXChannelSelector(xChannelSelector) + , fYChannelSelector(yChannelSelector) + , fScale(scale) { } SkDisplacementMapEffect::~SkDisplacementMapEffect() { @@ -211,59 +208,191 @@ void SkDisplacementMapEffect::flatten(SkWriteBuffer& buffer) const { buffer.writeScalar(fScale); } -bool SkDisplacementMapEffect::onFilterImageDeprecated(Proxy* proxy, - const SkBitmap& src, - const Context& ctx, - SkBitmap* dst, - SkIPoint* offset) const { - SkBitmap displ = src, color = src; - SkIPoint colorOffset = SkIPoint::Make(0, 0), displOffset = SkIPoint::Make(0, 0); - if (!this->filterInputDeprecated(1, proxy, src, ctx, &color, &colorOffset) || - !this->filterInputDeprecated(0, proxy, src, ctx, &displ, &displOffset)) { - return false; +#if SK_SUPPORT_GPU +class GrDisplacementMapEffect : public GrFragmentProcessor { +public: + static GrFragmentProcessor* Create( + SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, SkVector scale, + GrTexture* displacement, const SkMatrix& offsetMatrix, GrTexture* color, + const SkISize& colorDimensions) { + return new GrDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, displacement, + offsetMatrix, color, colorDimensions); } - if ((displ.colorType() != kN32_SkColorType) || - (color.colorType() != kN32_SkColorType)) { - return false; + + virtual ~GrDisplacementMapEffect(); + + SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const { + return fXChannelSelector; + } + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const { + return fYChannelSelector; } + const SkVector& scale() const { return fScale; } + + const char* name() const override { return "DisplacementMap"; } + const GrTextureDomain& domain() const { return fDomain; } + +private: + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; + + void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; + + bool onIsEqual(const GrFragmentProcessor&) const override; + + void onComputeInvariantOutput(GrInvariantOutput* inout) const override; + + GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, + const SkVector& scale, + GrTexture* displacement, const SkMatrix& offsetMatrix, + GrTexture* color, + const SkISize& colorDimensions); + + GR_DECLARE_FRAGMENT_PROCESSOR_TEST; + + GrCoordTransform fDisplacementTransform; + GrTextureAccess fDisplacementAccess; + GrCoordTransform fColorTransform; + GrTextureDomain fDomain; + GrTextureAccess fColorAccess; + SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; + SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; + SkVector fScale; + + typedef GrFragmentProcessor INHERITED; +}; +#endif + +sk_sp<SkSpecialImage> SkDisplacementMapEffect::onFilterImage(SkSpecialImage* source, + const Context& ctx, + SkIPoint* offset) const { + SkIPoint colorOffset = SkIPoint::Make(0, 0); + sk_sp<SkSpecialImage> color(this->filterInput(1, source, ctx, &colorOffset)); + if (!color) { + return nullptr; + } + + SkIPoint displOffset = SkIPoint::Make(0, 0); + sk_sp<SkSpecialImage> displ(this->filterInput(0, source, ctx, &displOffset)); + if (!displ) { + return nullptr; + } + + const SkIRect srcBounds = SkIRect::MakeXYWH(colorOffset.x(), colorOffset.y(), + color->width(), color->height()); + + // Both paths do bounds checking on color pixel access, we don't need to + // pad the color bitmap to bounds here. SkIRect bounds; - // Since computeDisplacement does bounds checking on color pixel access, we don't need to pad - // the color bitmap to bounds here. - SkIRect srcBounds = color.bounds(); - srcBounds.offset(colorOffset); if (!this->applyCropRect(ctx, srcBounds, &bounds)) { - return false; + return nullptr; } + SkIRect displBounds; - if (!this->applyCropRectDeprecated(ctx, proxy, displ, &displOffset, &displBounds, &displ)) { - return false; + displ = this->applyCropRect(ctx, displ.get(), &displOffset, &displBounds); + if (!displ) { + return nullptr; } + if (!bounds.intersect(displBounds)) { - return false; - } - SkAutoLockPixels alp_displacement(displ), alp_color(color); - if (!displ.getPixels() || !color.getPixels()) { - return false; + return nullptr; } - SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); - if (!device) { - return false; - } - *dst = device->accessBitmap(false); - SkAutoLockPixels alp_dst(*dst); + const SkIRect colorBounds = bounds.makeOffset(-colorOffset.x(), -colorOffset.y()); SkVector scale = SkVector::Make(fScale, fScale); ctx.ctm().mapVectors(&scale, 1); - SkIRect colorBounds = bounds; - colorBounds.offset(-colorOffset); - computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst, - &displ, colorOffset - displOffset, &color, colorBounds); +#if SK_SUPPORT_GPU + if (source->isTextureBacked()) { + GrContext* context = source->getContext(); + + sk_sp<GrTexture> colorTexture(color->asTextureRef(context)); + sk_sp<GrTexture> displTexture(displ->asTextureRef(context)); + if (!colorTexture || !displTexture) { + return nullptr; + } + + GrSurfaceDesc desc; + desc.fFlags = kRenderTarget_GrSurfaceFlag; + desc.fWidth = bounds.width(); + desc.fHeight = bounds.height(); + desc.fConfig = kSkia8888_GrPixelConfig; + + SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc)); + if (!dst) { + return nullptr; + } + + GrPaint paint; + SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displTexture.get()); + offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displOffset.fX), + SkIntToScalar(colorOffset.fY - displOffset.fY)); + + paint.addColorFragmentProcessor( + GrDisplacementMapEffect::Create(fXChannelSelector, + fYChannelSelector, + scale, + displTexture.get(), + offsetMatrix, + colorTexture.get(), + SkISize::Make(color->width(), + color->height())))->unref(); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); + SkMatrix matrix; + matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y())); + + SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget())); + if (!drawContext) { + return nullptr; + } + + drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(colorBounds)); + + offset->fX = bounds.left(); + offset->fY = bounds.top(); + return SkSpecialImage::MakeFromGpu(source->internal_getProxy(), + SkIRect::MakeWH(bounds.width(), bounds.height()), + kNeedNewImageUniqueID_SpecialImage, + dst); + } +#endif + + SkBitmap colorBM, displBM; + + if (!color->getROPixels(&colorBM) || !displ->getROPixels(&displBM)) { + return nullptr; + } + + if ((colorBM.colorType() != kN32_SkColorType) || + (displBM.colorType() != kN32_SkColorType)) { + return nullptr; + } + + SkAutoLockPixels colorLock(colorBM), displLock(displBM); + if (!colorBM.getPixels() || !displBM.getPixels()) { + return nullptr; + } + + SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(), + colorBM.alphaType()); + + SkBitmap dst; + if (!dst.tryAllocPixels(info)) { + return nullptr; + } + + SkAutoLockPixels dstLock(dst); + + computeDisplacement(fXChannelSelector, fYChannelSelector, scale, &dst, + displBM, colorOffset - displOffset, colorBM, colorBounds); offset->fX = bounds.left(); offset->fY = bounds.top(); - return true; + return SkSpecialImage::MakeFromRaster(source->internal_getProxy(), + SkIRect::MakeWH(bounds.width(), bounds.height()), + dst); } SkRect SkDisplacementMapEffect::computeFastBounds(const SkRect& src) const { @@ -326,144 +455,14 @@ private: /////////////////////////////////////////////////////////////////////////////// -class GrDisplacementMapEffect : public GrFragmentProcessor { -public: - static GrFragmentProcessor* Create( - SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, - SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, SkVector scale, - GrTexture* displacement, const SkMatrix& offsetMatrix, GrTexture* color, - const SkISize& colorDimensions) { - return new GrDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, displacement, - offsetMatrix, color, colorDimensions); - } - - virtual ~GrDisplacementMapEffect(); - - SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const - { return fXChannelSelector; } - SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const - { return fYChannelSelector; } - const SkVector& scale() const { return fScale; } - - const char* name() const override { return "DisplacementMap"; } - const GrTextureDomain& domain() const { return fDomain; } - -private: - GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { - return new GrGLDisplacementMapEffect; - } - - void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { - GrGLDisplacementMapEffect::GenKey(*this, caps, b); - } - - bool onIsEqual(const GrFragmentProcessor&) const override; - - void onComputeInvariantOutput(GrInvariantOutput* inout) const override; - - GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, - SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, - const SkVector& scale, - GrTexture* displacement, const SkMatrix& offsetMatrix, - GrTexture* color, - const SkISize& colorDimensions); - - GR_DECLARE_FRAGMENT_PROCESSOR_TEST; - - GrCoordTransform fDisplacementTransform; - GrTextureAccess fDisplacementAccess; - GrCoordTransform fColorTransform; - GrTextureDomain fDomain; - GrTextureAccess fColorAccess; - SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; - SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; - SkVector fScale; - - typedef GrFragmentProcessor INHERITED; -}; - -bool SkDisplacementMapEffect::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, - const Context& ctx, - SkBitmap* result, SkIPoint* offset) const { - SkBitmap colorBM = src; - SkIPoint colorOffset = SkIPoint::Make(0, 0); - if (!this->filterInputGPUDeprecated(1, proxy, src, ctx, &colorBM, &colorOffset)) { - return false; - } - SkBitmap displacementBM = src; - SkIPoint displacementOffset = SkIPoint::Make(0, 0); - if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &displacementBM, &displacementOffset)) { - return false; - } - SkIRect srcBounds = colorBM.bounds(); - srcBounds.offset(colorOffset); - SkIRect bounds; - // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to - // pad the color bitmap to bounds here. - if (!this->applyCropRect(ctx, srcBounds, &bounds)) { - return false; - } - SkIRect displBounds; - if (!this->applyCropRectDeprecated(ctx, proxy, displacementBM, - &displacementOffset, &displBounds, &displacementBM)) { - return false; - } - if (!bounds.intersect(displBounds)) { - return false; - } - GrTexture* color = colorBM.getTexture(); - GrTexture* displacement = displacementBM.getTexture(); - GrContext* context = color->getContext(); - - GrSurfaceDesc desc; - desc.fFlags = kRenderTarget_GrSurfaceFlag; - desc.fWidth = bounds.width(); - desc.fHeight = bounds.height(); - desc.fConfig = kSkia8888_GrPixelConfig; - - SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc)); - - if (!dst) { - return false; - } - - SkVector scale = SkVector::Make(fScale, fScale); - ctx.ctm().mapVectors(&scale, 1); - - GrPaint paint; - // SRGBTODO: AllowSRGBInputs? - SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement); - offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX), - SkIntToScalar(colorOffset.fY - displacementOffset.fY)); - - paint.addColorFragmentProcessor( - GrDisplacementMapEffect::Create(fXChannelSelector, - fYChannelSelector, - scale, - displacement, - offsetMatrix, - color, - colorBM.dimensions()))->unref(); - paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); - SkIRect colorBounds = bounds; - colorBounds.offset(-colorOffset); - SkMatrix matrix; - matrix.setTranslate(-SkIntToScalar(colorBounds.x()), - -SkIntToScalar(colorBounds.y())); - - SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget())); - if (!drawContext) { - return false; - } - - drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(colorBounds)); - offset->fX = bounds.left(); - offset->fY = bounds.top(); - GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result); - return true; +GrGLSLFragmentProcessor* GrDisplacementMapEffect::onCreateGLSLInstance() const { + return new GrGLDisplacementMapEffect; } -/////////////////////////////////////////////////////////////////////////////// +void GrDisplacementMapEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, + GrProcessorKeyBuilder* b) const { + GrGLDisplacementMapEffect::GenKey(*this, caps, b); +} GrDisplacementMapEffect::GrDisplacementMapEffect( SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, |