| Index: src/effects/SkDisplacementMapEffect.cpp
|
| diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
|
| index 6debea16e43b276728e02e6cd589f1a9a413ccf7..db0a59a1b964cd7e22672f043760d7f637e8fafc 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,
|
|
|