diff options
author | Mike Reed <reed@google.com> | 2016-09-26 20:40:57 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-09-26 20:53:19 +0000 |
commit | 10ff5bfa789b6b602464e8511fdf676c6f5b1bd4 (patch) | |
tree | 1eb96e7533f882aa935b5d62132f4205bfedd2c9 | |
parent | 29111a3e71f59b26c1feebf6b30db5c68a27d5a9 (diff) |
Revert "replace Arithmetic xfermode with imagefilter"
This reverts commit Ia3f3b721854c516f3b7f8c44f71f40a8a2eeb9b4.
Reason for revert: need to guard the no-gpu codepath
Original issue's description:
> replace Arithmetic xfermode with imagefilter
>
> chrome pre-cl: https://codereview.chromium.org/2369023002/
>
> BUG=skia:
>
> GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2595
>
> Change-Id: Ia3f3b721854c516f3b7f8c44f71f40a8a2eeb9b4
> Reviewed-on: https://skia-review.googlesource.com/2595
> Commit-Queue: Mike Reed <reed@google.com>
> Reviewed-by: Florin Malita <fmalita@chromium.org>
> Reviewed-by: Robert Phillips <robertphillips@google.com>
>
TBR=robertphillips@google.com,fmalita@chromium.org,fmalita@google.com,reed@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Change-Id: I761799b594a0379c6bf356e6abc73552c3d19480
Reviewed-on: https://skia-review.googlesource.com/2661
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
-rw-r--r-- | bench/XfermodeBench.cpp | 16 | ||||
-rw-r--r-- | gm/aaxfermodes.cpp | 29 | ||||
-rw-r--r-- | gm/arithmode.cpp | 2 | ||||
-rw-r--r-- | gm/imagefiltersgraph.cpp | 3 | ||||
-rw-r--r-- | gm/xfermodeimagefilter.cpp | 5 | ||||
-rw-r--r-- | gm/xfermodes.cpp | 44 | ||||
-rw-r--r-- | include/effects/SkArithmeticMode.h | 4 | ||||
-rw-r--r-- | include/effects/SkXfermodeImageFilter.h | 12 | ||||
-rw-r--r-- | src/effects/SkArithmeticMode.cpp | 2 | ||||
-rw-r--r-- | src/effects/SkArithmeticModePriv.h | 42 | ||||
-rw-r--r-- | src/effects/SkXfermodeImageFilter.cpp | 256 | ||||
-rw-r--r-- | src/ports/SkGlobalInitialization_default.cpp | 2 |
12 files changed, 112 insertions, 305 deletions
diff --git a/bench/XfermodeBench.cpp b/bench/XfermodeBench.cpp index 60879d603e..7d00f411bd 100644 --- a/bench/XfermodeBench.cpp +++ b/bench/XfermodeBench.cpp @@ -6,6 +6,7 @@ */ #include "Benchmark.h" +#include "SkArithmeticMode.h" #include "SkCanvas.h" #include "SkPaint.h" #include "SkRandom.h" @@ -22,6 +23,12 @@ public: fName.printf("Xfermode_%s%s", SkXfermode::ModeName(mode), aa ? "_aa" : ""); } + XfermodeBench(sk_sp<SkXfermode> xferMode, const char* name, bool aa) { + fXfermode = xferMode; + fAA = aa; + fName.printf("Xfermode_%s%s", name, aa ? "_aa" : ""); + } + protected: const char* onGetName() override { return fName.c_str(); } @@ -128,4 +135,13 @@ BENCH(SkXfermode::kSaturation_Mode) BENCH(SkXfermode::kColor_Mode) BENCH(SkXfermode::kLuminosity_Mode) +DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, false), \ + "arithmetic", false); ) +DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, true), \ + "arithmetic_enforce_pm", false); ) +DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, false), \ + "arithmetic", true); ) +DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, true), \ + "arithmetic_enforce_pm", true); ) + DEF_BENCH(return new XferCreateBench;) diff --git a/gm/aaxfermodes.cpp b/gm/aaxfermodes.cpp index 678a8379e3..78f7d3e324 100644 --- a/gm/aaxfermodes.cpp +++ b/gm/aaxfermodes.cpp @@ -39,11 +39,13 @@ enum Shape { kLast_Shape = kConcave_Shape }; +namespace skiagm { + /** * Verifies AA works properly on all Xfermodes, including arithmetic, with both opaque and unknown * src colors. */ -class AAXfermodesGM : public skiagm::GM { +class AAXfermodesGM : public GM { public: AAXfermodesGM() {} @@ -118,9 +120,6 @@ protected: canvas->translate(0, kSubtitleSpacing + kShapeSpacing/2); for (size_t m = 0; m <= SkXfermode::kLastCoeffMode; m++) { - if (firstMode + m > SkXfermode::kLastMode) { - break; - } SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(firstMode + m); canvas->save(); @@ -211,7 +210,7 @@ protected: if (maxSum > 255) { SkPaint dimPaint; dimPaint.setAntiAlias(false); - dimPaint.setXfermodeMode(SkXfermode::kDstIn_Mode); + dimPaint.setXfermode(SkXfermode::Make(SkXfermode::kDstIn_Mode)); if (255 != paint->getAlpha()) { // Dim the src and dst colors. dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0); @@ -228,10 +227,16 @@ protected: } void drawShape(SkCanvas* canvas, Shape shape, const SkPaint& paint, SkXfermode::Mode mode) { - SkASSERT(mode <= SkXfermode::kLastMode); SkPaint shapePaint(paint); shapePaint.setAntiAlias(kSquare_Shape != shape); - shapePaint.setXfermodeMode(mode); + + sk_sp<SkXfermode> xfermode; + if (mode <= SkXfermode::kLastMode) { + xfermode = SkXfermode::Make(mode); + } else { + xfermode = SkArithmeticMode::Make(+1.0f, +0.25f, -0.5f, +0.1f); + } + shapePaint.setXfermode(std::move(xfermode)); switch (shape) { case kSquare_Shape: @@ -268,6 +273,12 @@ private: SkPath fOval; SkPath fConcave; - typedef skiagm::GM INHERITED; + typedef GM INHERITED; }; -DEF_GM( return new AAXfermodesGM; ) + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new AAXfermodesGM; } +static GMRegistry reg(MyFactory); + +} diff --git a/gm/arithmode.cpp b/gm/arithmode.cpp index f98fbf7057..70661a0fba 100644 --- a/gm/arithmode.cpp +++ b/gm/arithmode.cpp @@ -15,7 +15,6 @@ #define WW 100 #define HH 32 -#ifdef SK_SUPPORT_LEGACY_ARITHMETICMODE static SkBitmap make_bm() { SkBitmap bm; bm.allocN32Pixels(WW, HH); @@ -161,4 +160,3 @@ private: /////////////////////////////////////////////////////////////////////////////// DEF_GM( return new ArithmodeGM; ) -#endif diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp index 980398967a..0f3dcd10c9 100644 --- a/gm/imagefiltersgraph.cpp +++ b/gm/imagefiltersgraph.cpp @@ -7,6 +7,7 @@ #include "gm.h" +#include "SkArithmeticMode.h" #include "SkBlurImageFilter.h" #include "SkColorFilter.h" #include "SkColorFilterImageFilter.h" @@ -89,7 +90,7 @@ protected: SkPaint paint; paint.setImageFilter( - SkXfermodeImageFilter::MakeArithmetic(0, 1, 1, 0, true, + SkXfermodeImageFilter::Make(SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0), std::move(matrixFilter), std::move(offsetFilter), nullptr)); diff --git a/gm/xfermodeimagefilter.cpp b/gm/xfermodeimagefilter.cpp index a0677c796a..0ff0ea9dd1 100644 --- a/gm/xfermodeimagefilter.cpp +++ b/gm/xfermodeimagefilter.cpp @@ -7,6 +7,7 @@ #include "gm.h" #include "sk_tool_utils.h" +#include "SkArithmeticMode.h" #include "SkImage.h" #include "SkImageSource.h" #include "SkOffsetImageFilter.h" @@ -96,7 +97,9 @@ protected: } } // Test arithmetic mode as image filter - paint.setImageFilter(SkXfermodeImageFilter::MakeArithmetic(0, 1, 1, 0, true, background)); + paint.setImageFilter(SkXfermodeImageFilter::Make( + SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0), + background)); DrawClippedBitmap(canvas, fBitmap, paint, x, y); x += fBitmap.width() + MARGIN; if (x + fBitmap.width() > WIDTH) { diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp index 8fbbdbec6a..68d267bd22 100644 --- a/gm/xfermodes.cpp +++ b/gm/xfermodes.cpp @@ -11,6 +11,31 @@ #include "SkXfermode.h" #include "SkPM4f.h" +#include "SkArithmeticMode.h" + +#define kCustomShift 16 +#define kCustomMask (~0xFFFF) + +enum CustomModes { + kArithmetic_CustomMode = 1 << kCustomShift, +}; + +static sk_sp<SkXfermode> make_custom(int customMode) { + switch (customMode) { + case kArithmetic_CustomMode: { + const SkScalar k1 = 0.25; + const SkScalar k2 = 0.75; + const SkScalar k3 = 0.75; + const SkScalar k4 = -0.25; + return SkArithmeticMode::Make(k1, k2, k3, k4); + } + default: + break; + } + SkASSERT(false); + return nullptr; +} + enum SrcType { //! A WxH image with a rectangle in the lower right. kRectangleImage_SrcType = 0x01, @@ -73,6 +98,8 @@ const struct { { SkXfermode::kSaturation_Mode, "Saturation", kBasic_SrcType }, { SkXfermode::kColor_Mode, "Color", kBasic_SrcType }, { SkXfermode::kLuminosity_Mode, "Luminosity", kBasic_SrcType }, + + { SkXfermode::Mode(0xFFFF), "Arithmetic", kBasic_SrcType + kArithmetic_CustomMode }, }; static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst, @@ -118,7 +145,7 @@ class XfermodesGM : public skiagm::GM { * uses the implied shape of the drawing command and these modes * demonstrate that. */ - void draw_mode(SkCanvas* canvas, SkXfermode::Mode mode, SrcType srcType, + void draw_mode(SkCanvas* canvas, sk_sp<SkXfermode> mode, SrcType srcType, SkScalar x, SkScalar y) { SkPaint p; SkMatrix m; @@ -126,7 +153,7 @@ class XfermodesGM : public skiagm::GM { m.setTranslate(x, y); canvas->drawBitmap(fSrcB, x, y, &p); - p.setXfermodeMode(mode); + p.setXfermode(std::move(mode)); switch (srcType) { case kSmallTransparentImage_SrcType: { m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y); @@ -214,7 +241,7 @@ protected: } SkISize onISize() override { - return SkISize::Make(1990, 570); + return SkISize::Make(1990, 660); } void onDraw(SkCanvas* canvas) override { @@ -242,7 +269,14 @@ protected: if ((gModes[i].fSourceTypeMask & sourceType) == 0) { continue; } - SkRect r{ x, y, x+w, y+h }; + sk_sp<SkXfermode> mode; + if (gModes[i].fSourceTypeMask & kCustomMask) { + mode = make_custom(gModes[i].fSourceTypeMask & kCustomMask); + } else { + mode = SkXfermode::Make(gModes[i].fMode); + } + SkRect r; + r.set(x, y, x+w, y+h); SkPaint p; p.setStyle(SkPaint::kFill_Style); @@ -250,7 +284,7 @@ protected: canvas->drawRect(r, p); canvas->saveLayer(&r, nullptr); - draw_mode(canvas, gModes[i].fMode, static_cast<SrcType>(sourceType), + draw_mode(canvas, std::move(mode), static_cast<SrcType>(sourceType), r.fLeft, r.fTop); canvas->restore(); diff --git a/include/effects/SkArithmeticMode.h b/include/effects/SkArithmeticMode.h index 81b9f85394..b160dc7e9b 100644 --- a/include/effects/SkArithmeticMode.h +++ b/include/effects/SkArithmeticMode.h @@ -12,8 +12,6 @@ #include "SkScalar.h" #include "SkXfermode.h" -#ifdef SK_SUPPORT_LEGACY_ARITHMETICMODE - class SK_API SkArithmeticMode { public: /** @@ -40,5 +38,3 @@ private: }; #endif - -#endif diff --git a/include/effects/SkXfermodeImageFilter.h b/include/effects/SkXfermodeImageFilter.h index 6066b8d2e0..e39157550c 100644 --- a/include/effects/SkXfermodeImageFilter.h +++ b/include/effects/SkXfermodeImageFilter.h @@ -26,18 +26,6 @@ public: return Make(std::move(mode), std::move(background), nullptr, nullptr); } - static sk_sp<SkImageFilter> MakeArithmetic(float k1, float k2, float k3, float k4, - bool enforcePMColor, - sk_sp<SkImageFilter> background, - sk_sp<SkImageFilter> foreground, - const SkImageFilter::CropRect* cropRect); - static sk_sp<SkImageFilter> MakeArithmetic(float k1, float k2, float k3, float k4, - bool enforcePMColor, - sk_sp<SkImageFilter> background) { - return MakeArithmetic(k1, k2, k3, k4, enforcePMColor, std::move(background), - nullptr, nullptr); - } - #ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR static SkImageFilter* Create(SkXfermode* mode, SkImageFilter* background, SkImageFilter* foreground = NULL, diff --git a/src/effects/SkArithmeticMode.cpp b/src/effects/SkArithmeticMode.cpp index 876f34b430..b8aa36853a 100644 --- a/src/effects/SkArithmeticMode.cpp +++ b/src/effects/SkArithmeticMode.cpp @@ -5,7 +5,7 @@ * found in the LICENSE file. */ -#include "SkArithmeticModePriv.h" +#include "SkArithmeticMode.h" #include "SkColorPriv.h" #include "SkNx.h" #include "SkRasterPipeline.h" diff --git a/src/effects/SkArithmeticModePriv.h b/src/effects/SkArithmeticModePriv.h deleted file mode 100644 index 04bd90eebe..0000000000 --- a/src/effects/SkArithmeticModePriv.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkArithmeticModePriv_DEFINED -#define SkArithmeticModePriv_DEFINED - -#include "SkArithmeticMode.h" - -#ifndef SK_SUPPORT_LEGACY_ARITHMETICMODE - -class SK_API SkArithmeticMode { -public: - /** - * result = clamp[k1 * src * dst + k2 * src + k3 * dst + k4] - * - * k1=k2=k3=0, k4=1.0 results in returning opaque white - * k1=k3=k4=0, k2=1.0 results in returning the src - * k1=k2=k4=0, k3=1.0 results in returning the dst - */ - static sk_sp<SkXfermode> Make(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, - bool enforcePMColor = true); -#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR - static SkXfermode* Create(SkScalar k1, SkScalar k2, - SkScalar k3, SkScalar k4, - bool enforcePMColor = true) { - return Make(k1, k2, k3, k4, enforcePMColor).release(); - } -#endif - - SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP(); - -private: - SkArithmeticMode(); // can't be instantiated -}; - -#endif - -#endif diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp index 655c48ce21..c602a4a1aa 100644 --- a/src/effects/SkXfermodeImageFilter.cpp +++ b/src/effects/SkXfermodeImageFilter.cpp @@ -20,12 +20,11 @@ #include "effects/GrConstColorProcessor.h" #include "effects/GrTextureDomain.h" #include "effects/GrSimpleTextureEffect.h" -#include "SkArithmeticMode_gpu.h" #include "SkGr.h" #include "SkGrPriv.h" #endif -class SkXfermodeImageFilter_Base : public SkImageFilter { +class SK_API SkXfermodeImageFilter_Base : public SkImageFilter { public: SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> inputs[2], const CropRect* cropRect); @@ -49,8 +48,6 @@ protected: void flatten(SkWriteBuffer&) const override; - virtual void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const; - virtual sk_sp<GrFragmentProcessor> makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const; private: sk_sp<SkXfermode> fMode; @@ -141,33 +138,31 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* SkASSERT(canvas); canvas->clear(0x0); // can't count on background to fully clear the background + canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); + SkPaint paint; + paint.setXfermodeMode(SkXfermode::kSrc_Mode); + if (background) { - SkPaint paint; - paint.setXfermodeMode(SkXfermode::kSrc_Mode); background->draw(canvas, SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY), &paint); } - this->drawForeground(canvas, foreground.get(), foregroundBounds); - - return surf->makeImageSnapshot(); -} - -void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img, - const SkIRect& fgBounds) const { - SkPaint paint; paint.setXfermode(fMode); - if (img) { - img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint); + + if (foreground) { + foreground->draw(canvas, + SkIntToScalar(foregroundOffset.fX), SkIntToScalar(foregroundOffset.fY), + &paint); } - SkAutoCanvasRestore acr(canvas, true); - canvas->clipRect(SkRect::Make(fgBounds), SkCanvas::kDifference_Op); - paint.setColor(0); + canvas->clipRect(SkRect::Make(foregroundBounds), SkCanvas::kDifference_Op); + paint.setColor(SK_ColorTRANSPARENT); canvas->drawPaint(paint); + + return surf->makeImageSnapshot(); } #ifndef SK_IGNORE_TO_STRING @@ -254,7 +249,21 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU( paint.addColorFragmentProcessor(std::move(foregroundFP)); - sk_sp<GrFragmentProcessor> xferFP = this->makeFGFrag(bgFP); + // A null fMode is interpreted to mean kSrcOver_Mode (to match raster). + SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get())); + if (!mode) { + // It would be awesome to use SkXfermode::Create here but it knows better + // than us and won't return a kSrcOver_Mode SkXfermode. That means we + // have to get one the hard way. + struct ProcCoeff rec; + rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode); + SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC); + + mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode)); + } + + sk_sp<GrFragmentProcessor> xferFP( + mode->makeFragmentProcessorForImageFilter(std::move(bgFP))); // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed if (xferFP) { @@ -285,220 +294,13 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU( sk_ref_sp(drawContext->getColorSpace())); } -sk_sp<GrFragmentProcessor> -SkXfermodeImageFilter_Base::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const { - // A null fMode is interpreted to mean kSrcOver_Mode (to match raster). - SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get())); - if (!mode) { - // It would be awesome to use SkXfermode::Create here but it knows better - // than us and won't return a kSrcOver_Mode SkXfermode. That means we - // have to get one the hard way. - struct ProcCoeff rec; - rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode); - SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC); - - mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode)); - } - return mode->makeFragmentProcessorForImageFilter(std::move(bgFP)); -} - #endif /////////////////////////////////////////////////////////////////////////////////////////////////// -class SkArithmeticImageFilter : public SkXfermodeImageFilter_Base { -public: - SkArithmeticImageFilter(float k1, float k2, float k3, float k4, bool enforcePMColor, - sk_sp<SkImageFilter> inputs[2], const CropRect* cropRect) - : SkXfermodeImageFilter_Base(nullptr, inputs, cropRect) - , fK{ k1, k2, k3, k4 } - , fEnforcePMColor(enforcePMColor) - {} - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticImageFilter) - -protected: - void flatten(SkWriteBuffer& buffer) const override { - this->INHERITED::flatten(buffer); - for (int i = 0; i < 4; ++i) { - buffer.writeScalar(fK[i]); - } - buffer.writeBool(fEnforcePMColor); - } - void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const override; - sk_sp<GrFragmentProcessor> makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const override; - -private: - const float fK[4]; - const bool fEnforcePMColor; - - friend class SkXfermodeImageFilter; - - typedef SkXfermodeImageFilter_Base INHERITED; -}; - -sk_sp<SkFlattenable> SkArithmeticImageFilter::CreateProc(SkReadBuffer& buffer) { - SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2); - - // skip the mode (srcover) our parent-class wrote - sk_sp<SkXfermode> mode(buffer.readXfermode()); - SkASSERT(nullptr == mode); - - float k[4]; - for (int i = 0; i < 4; ++i) { - k[i] = buffer.readScalar(); - } - const bool enforcePMColor = buffer.readBool(); - return SkXfermodeImageFilter::MakeArithmetic(k[0], k[1], k[2], k[3], enforcePMColor, - common.getInput(0), common.getInput(1), - &common.cropRect()); -} - -#include "SkNx.h" - -static Sk4f pin(float min, const Sk4f& val, float max) { - return Sk4f::Max(min, Sk4f::Min(val, max)); -} - -template<bool EnforcePMColor> void arith_span(const float k[], SkPMColor dst[], - const SkPMColor src[], int count) { - const Sk4f k1 = k[0] * (1/255.0f), - k2 = k[1], - k3 = k[2], - k4 = k[3] * 255.0f + 0.5f; - - for (int i = 0; i < count; i++) { - Sk4f s = SkNx_cast<float>(Sk4b::Load(src+i)), - d = SkNx_cast<float>(Sk4b::Load(dst+i)), - r = pin(0, k1*s*d + k2*s + k3*d + k4, 255); - if (EnforcePMColor) { - Sk4f a = SkNx_shuffle<3,3,3,3>(r); - r = Sk4f::Min(a, r); - } - SkNx_cast<uint8_t>(r).store(dst+i); - } -} - -// apply mode to src==transparent (0) -template<bool EnforcePMColor> void arith_transparent(const float k[], SkPMColor dst[], int count) { - const Sk4f k3 = k[2], - k4 = k[3] * 255.0f + 0.5f; - - for (int i = 0; i < count; i++) { - Sk4f d = SkNx_cast<float>(Sk4b::Load(dst+i)), - r = pin(0, k3*d + k4, 255); - if (EnforcePMColor) { - Sk4f a = SkNx_shuffle<3,3,3,3>(r); - r = Sk4f::Min(a, r); - } - SkNx_cast<uint8_t>(r).store(dst+i); - } -} - -static bool intersect(SkPixmap* dst, SkPixmap* src, SkIPoint srcOffset) { - SkIRect dstR = SkIRect::MakeWH(dst->width(), dst->height()); - SkIRect srcR = SkIRect::MakeXYWH(srcOffset.x(), srcOffset.y(), src->width(), src->height()); - SkIRect sect; - if (!sect.intersect(dstR, srcR)) { - return false; - } - *dst = SkPixmap(dst->info().makeWH(sect.width(), sect.height()), - dst->addr(sect.fLeft, sect.fTop), - dst->rowBytes()); - *src = SkPixmap(src->info().makeWH(sect.width(), sect.height()), - src->addr(SkTMax(0, -srcOffset.x()), SkTMax(0, -srcOffset.y())), - src->rowBytes()); - return true; -} - -void SkArithmeticImageFilter::drawForeground(SkCanvas* canvas, SkSpecialImage* img, - const SkIRect& fgBounds) const { - SkPixmap dst; - if (!canvas->peekPixels(&dst)) { - return; - } - - if (img) { - SkBitmap srcBM; - SkPixmap src; - if (!img->getROPixels(&srcBM)) { - return; - } - srcBM.lockPixels(); - if (!srcBM.peekPixels(&src)) { - return; - } - - auto proc = fEnforcePMColor ? arith_span<true> : arith_span<false>; - const SkMatrix& ctm = canvas->getTotalMatrix(); - SkASSERT(ctm.getType() <= SkMatrix::kTranslate_Mask); - SkIPoint offset { - fgBounds.fLeft + SkScalarRoundToInt(ctm.getTranslateX()), - fgBounds.fTop + SkScalarRoundToInt(ctm.getTranslateY()), - }; - SkPixmap tmpDst = dst; - if (intersect(&tmpDst, &src, offset)) { - for (int y = 0; y < tmpDst.height(); ++y) { - proc(fK, tmpDst.writable_addr32(0, y), src.addr32(0, y), tmpDst.width()); - } - } - } - - // Now apply the mode with transparent-color to the outside of the fg image - SkRegion outside(SkIRect::MakeWH(dst.width(), dst.height())); - outside.op(fgBounds, SkRegion::kDifference_Op); - auto proc = fEnforcePMColor ? arith_transparent<true> : arith_transparent<false>; - for (SkRegion::Iterator iter(outside); !iter.done(); iter.next()) { - const SkIRect r = iter.rect(); - for (int y = r.fTop; y < r.fBottom; ++y) { - proc(fK, dst.writable_addr32(r.fLeft, y), r.width()); - } - } -} - -sk_sp<GrFragmentProcessor> -SkArithmeticImageFilter::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const { - return GrArithmeticFP::Make(fK[0], fK[1], fK[2], fK[3], fEnforcePMColor, std::move(bgFP)); -} - -sk_sp<SkImageFilter> SkXfermodeImageFilter::MakeArithmetic(float k1, float k2, float k3, float k4, - bool enforcePMColor, - sk_sp<SkImageFilter> background, - sk_sp<SkImageFilter> foreground, - const SkImageFilter::CropRect* crop) { - if (!SkScalarIsFinite(k1) || !SkScalarIsFinite(k2) || - !SkScalarIsFinite(k3) || !SkScalarIsFinite(k4)) { - return nullptr; - } - - // are we nearly some other "std" mode? - int mode = -1; // illegal mode - if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) && - SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { - mode = SkXfermode::kSrc_Mode; - } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && - SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) { - mode = SkXfermode::kDst_Mode; - } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && - SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { - mode = SkXfermode::kClear_Mode; - } - if (mode >= 0) { - return SkXfermodeImageFilter::Make(SkXfermode::Make((SkXfermode::Mode)mode), - std::move(background), std::move(foreground), crop); - } - - sk_sp<SkImageFilter> inputs[2] = { std::move(background), std::move(foreground) }; - return sk_sp<SkImageFilter>(new SkArithmeticImageFilter(k1, k2, k3, k4, enforcePMColor, - inputs, crop)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermodeImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter_Base) // manually register the legacy serialized name "SkXfermodeImageFilter" SkFlattenable::Register("SkXfermodeImageFilter", SkXfermodeImageFilter_Base::CreateProc, SkFlattenable::kSkImageFilter_Type); - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index 499e9bfed3..be41422f16 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -8,7 +8,7 @@ #include "Sk1DPathEffect.h" #include "Sk2DPathEffect.h" #include "SkAlphaThresholdFilter.h" -#include "../../src/effects/SkArithmeticModePriv.h" +#include "SkArithmeticMode.h" #include "SkArcToPathEffect.h" #include "SkBitmapSourceDeserializer.h" #include "SkBlurDrawLooper.h" |