Switch SkXfermodeImagerFilter over to new onFilterImage interface
authorrobertphillips <robertphillips@google.com>
Fri, 15 Apr 2016 19:47:42 +0000 (12:47 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 15 Apr 2016 19:47:42 +0000 (12:47 -0700)
TBR=reed@google.com

GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1894643002

Review URL: https://codereview.chromium.org/1894643002

include/effects/SkXfermodeImageFilter.h
src/effects/SkXfermodeImageFilter.cpp

index 6344227..96d4fef 100644 (file)
@@ -18,7 +18,7 @@ class SK_API SkXfermodeImageFilter : public SkImageFilter {
      * This filter takes an xfermode, and uses it to composite the foreground
      * over the background.  If foreground or background is NULL, the input
      * bitmap (src) is used instead.
-      */
+     */
 
 public:
     static sk_sp<SkImageFilter> Make(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> background,
@@ -53,18 +53,19 @@ public:
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkXfermodeImageFilter)
 
-    bool onFilterImageDeprecated(Proxy* proxy,
-                                 const SkBitmap& src,
-                                 const Context& ctx,
-                                 SkBitmap* dst,
-                                 SkIPoint* offset) const override;
+protected:
+    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
+                                        SkIPoint* offset) const override;
+
 #if SK_SUPPORT_GPU
-    bool canFilterImageGPU() const override;
-    bool filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, const Context& ctx,
-                                  SkBitmap* result, SkIPoint* offset) const override;
+    sk_sp<SkSpecialImage> filterImageGPU(SkSpecialImage* source,
+                                         sk_sp<SkSpecialImage> background,
+                                         const SkIPoint& backgroundOffset,
+                                         sk_sp<SkSpecialImage> foreground,
+                                         const SkIPoint& foregroundOffset,
+                                         const SkIRect& bounds) const;
 #endif
 
-protected:
     SkXfermodeImageFilter(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> inputs[2],
                           const CropRect* cropRect);
     void flatten(SkWriteBuffer&) const override;
index 330f839..af58a64 100644 (file)
@@ -6,10 +6,12 @@
  */
 
 #include "SkXfermodeImageFilter.h"
+
 #include "SkCanvas.h"
-#include "SkDevice.h"
 #include "SkColorPriv.h"
 #include "SkReadBuffer.h"
+#include "SkSpecialImage.h"
+#include "SkSpecialSurface.h"
 #include "SkWriteBuffer.h"
 #include "SkXfermode.h"
 #if SK_SUPPORT_GPU
@@ -35,14 +37,13 @@ SkXfermodeImageFilter::SkXfermodeImageFilter(sk_sp<SkXfermode> mode,
                                              sk_sp<SkImageFilter> inputs[2],
                                              const CropRect* cropRect)
     : INHERITED(inputs, 2, cropRect)
-    , fMode(std::move(mode))
-{}
+    , fMode(std::move(mode)) {
+}
 
 sk_sp<SkFlattenable> SkXfermodeImageFilter::CreateProc(SkReadBuffer& buffer) {
     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
     sk_sp<SkXfermode> mode(buffer.readXfermode());
-    return Make(std::move(mode), common.getInput(0), common.getInput(1),
-                &common.cropRect());
+    return Make(std::move(mode), common.getInput(0), common.getInput(1), &common.cropRect());
 }
 
 void SkXfermodeImageFilter::flatten(SkWriteBuffer& buffer) const {
@@ -50,51 +51,83 @@ void SkXfermodeImageFilter::flatten(SkWriteBuffer& buffer) const {
     buffer.writeFlattenable(fMode.get());
 }
 
-bool SkXfermodeImageFilter::onFilterImageDeprecated(Proxy* proxy,
-                                                    const SkBitmap& src,
-                                                    const Context& ctx,
-                                                    SkBitmap* dst,
-                                                    SkIPoint* offset) const {
-    SkBitmap background = src, foreground = src;
+sk_sp<SkSpecialImage> SkXfermodeImageFilter::onFilterImage(SkSpecialImage* source,
+                                                           const Context& ctx,
+                                                           SkIPoint* offset) const {
     SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
-    if (!this->filterInputDeprecated(0, proxy, src, ctx, &background, &backgroundOffset)) {
-        background.reset();
-    }
+    sk_sp<SkSpecialImage> background(this->filterInput(0, source, ctx, &backgroundOffset));
+
     SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
-    if (!this->filterInputDeprecated(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
-        foreground.reset();
+    sk_sp<SkSpecialImage> foreground(this->filterInput(1, source, ctx, &foregroundOffset));
+
+    SkIRect foregroundBounds = SkIRect::EmptyIRect();
+    if (foreground) {
+        foregroundBounds = SkIRect::MakeXYWH(foregroundOffset.x(), foregroundOffset.y(),
+                                             foreground->width(), foreground->height());
     }
 
-    SkIRect foregroundBounds = foreground.bounds();
-    foregroundBounds.offset(foregroundOffset);
-    SkIRect srcBounds = background.bounds();
-    srcBounds.offset(backgroundOffset);
+    SkIRect srcBounds = SkIRect::EmptyIRect();
+    if (background) {
+        srcBounds = SkIRect::MakeXYWH(backgroundOffset.x(), backgroundOffset.y(),
+                                       background->width(), background->height());
+    }
+        
     srcBounds.join(foregroundBounds);
+    if (srcBounds.isEmpty()) {
+        return nullptr;
+    }
+
     SkIRect bounds;
     if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
-        return false;
+        return nullptr;
+    }
+
+    offset->fX = bounds.left();
+    offset->fY = bounds.top();
+
+#if SK_SUPPORT_GPU
+    if (source->isTextureBacked()) {
+        return this->filterImageGPU(source,
+                                    background, backgroundOffset, 
+                                    foreground, foregroundOffset,
+                                    bounds);
     }
+#endif
 
-    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
-    if (nullptr == device.get()) {
-        return false;
+    const SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
+                                                  kPremul_SkAlphaType);
+    sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
+    if (!surf) {
+        return nullptr;
     }
-    SkCanvas canvas(device);
-    canvas.translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
+
+    SkCanvas* canvas = surf->getCanvas();
+    SkASSERT(canvas);
+
+    canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
+
     SkPaint paint;
     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-    canvas.drawBitmap(background, SkIntToScalar(backgroundOffset.fX),
-                      SkIntToScalar(backgroundOffset.fY), &paint);
+
+    if (background) {
+        background->draw(canvas,
+                         SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
+                         &paint);
+    }
+
     paint.setXfermode(fMode);
-    canvas.drawBitmap(foreground, SkIntToScalar(foregroundOffset.fX),
-                      SkIntToScalar(foregroundOffset.fY), &paint);
-    canvas.clipRect(SkRect::Make(foregroundBounds), SkRegion::kDifference_Op);
+
+    if (foreground) {
+        foreground->draw(canvas,
+                         SkIntToScalar(foregroundOffset.fX), SkIntToScalar(foregroundOffset.fY),
+                         &paint);
+    }
+
+    canvas->clipRect(SkRect::Make(foregroundBounds), SkRegion::kDifference_Op);
     paint.setColor(SK_ColorTRANSPARENT);
-    canvas.drawPaint(paint);
-    *dst = device->accessBitmap(false);
-    offset->fX = bounds.left();
-    offset->fY = bounds.top();
-    return true;
+    canvas->drawPaint(paint);
+
+    return surf->makeImageSnapshot();
 }
 
 #ifndef SK_IGNORE_TO_STRING
@@ -121,46 +154,26 @@ void SkXfermodeImageFilter::toString(SkString* str) const {
 
 #if SK_SUPPORT_GPU
 
-bool SkXfermodeImageFilter::canFilterImageGPU() const {
-    return !this->cropRectIsSet();
-}
-
 #include "SkXfermode_proccoeff.h"
 
-bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
-                                                     const SkBitmap& src,
-                                                     const Context& ctx,
-                                                     SkBitmap* result,
-                                                     SkIPoint* offset) const {
-    GrContext* context = nullptr;
-    SkBitmap background = src;
-    SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
-    if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &background, &backgroundOffset)) {
-        background.reset();
-    }
-    GrTexture* backgroundTex = background.getTexture();
-    if (backgroundTex) {
-        context = backgroundTex->getContext();
-    }
+sk_sp<SkSpecialImage> SkXfermodeImageFilter::filterImageGPU(SkSpecialImage* source,
+                                                            sk_sp<SkSpecialImage> background,
+                                                            const SkIPoint& backgroundOffset,
+                                                            sk_sp<SkSpecialImage> foreground,
+                                                            const SkIPoint& foregroundOffset,
+                                                            const SkIRect& bounds) const {
+    SkASSERT(source->isTextureBacked());
 
-    SkBitmap foreground = src;
-    SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
-    if (!this->filterInputGPUDeprecated(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
-        foreground.reset();
-    }
-    GrTexture* foregroundTex = foreground.getTexture();
-    if (foregroundTex) {
-        context = foregroundTex->getContext();
-    }
+    GrContext* context = source->getContext();
 
-    if (!context) {
-        return false;
+    sk_sp<GrTexture> backgroundTex, foregroundTex;
+    
+    if (background) {
+        backgroundTex.reset(background->asTextureRef(context));
     }
 
-    SkIRect bounds = background.bounds().makeOffset(backgroundOffset.x(), backgroundOffset.y());
-    bounds.join(foreground.bounds().makeOffset(foregroundOffset.x(), foregroundOffset.y()));
-    if (bounds.isEmpty()) {
-        return false;
+    if (foreground) {
+        foregroundTex.reset(foreground->asTextureRef(context));
     }
 
     GrSurfaceDesc desc;
@@ -170,7 +183,7 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
     desc.fConfig = kSkia8888_GrPixelConfig;
     SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
     if (!dst) {
-        return false;
+        return nullptr;
     }
 
     GrPaint paint;
@@ -183,8 +196,9 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
         backgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX),
                                       SkIntToScalar(-backgroundOffset.fY));
         bgFP.reset(GrTextureDomainEffect::Create(
-                            backgroundTex, backgroundMatrix,
-                            GrTextureDomain::MakeTexelDomain(backgroundTex, background.bounds()),
+                            backgroundTex.get(), backgroundMatrix,
+                            GrTextureDomain::MakeTexelDomain(backgroundTex.get(),
+                                                             background->subset()),
                             GrTextureDomain::kDecal_Mode,
                             GrTextureParams::kNone_FilterMode));
     } else {
@@ -201,8 +215,9 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
         SkAutoTUnref<const GrFragmentProcessor> foregroundFP;
 
         foregroundFP.reset(GrTextureDomainEffect::Create(
-                            foregroundTex, foregroundMatrix,
-                            GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
+                            foregroundTex.get(), foregroundMatrix,
+                            GrTextureDomain::MakeTexelDomain(foregroundTex.get(), 
+                                                             foreground->subset()),
                             GrTextureDomain::kDecal_Mode,
                             GrTextureParams::kNone_FilterMode));
 
@@ -235,17 +250,17 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
 
     SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
     if (!drawContext) {
-        return false;
+        return nullptr;
     }
 
     SkMatrix matrix;
     matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
     drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(bounds));
 
-    offset->fX = bounds.left();
-    offset->fY = bounds.top();
-    GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result);
-    return true;
+    return SkSpecialImage::MakeFromGpu(source->internal_getProxy(),
+                                       SkIRect::MakeWH(bounds.width(), bounds.height()),
+                                       kNeedNewImageUniqueID_SpecialImage,
+                                       dst.get());
 }
 
 #endif