From: Mike Reed Date: Tue, 15 Nov 2016 21:44:34 +0000 (-0500) Subject: make SkXfermode.h go away X-Git-Tag: submit/tizen/20180928.044319~73^2~36 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d47067392848ba132d4e86ffbeebe2dcacda9534;p=platform%2Fupstream%2FlibSkiaSharp.git make SkXfermode.h go away This is step one: - make SkXfermode useless to public clients - everything they should need is in SkBlendMode.h Step two: - remove SkXfermode.h entirely (since skia core will already be using SkXfermodePriv.h) BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4534 Change-Id: If2cea9f71df92430ed6644edb98dd306c5572cbc Reviewed-on: https://skia-review.googlesource.com/4534 Commit-Queue: Mike Reed Reviewed-by: Florin Malita --- diff --git a/bench/RotatedRectBench.cpp b/bench/RotatedRectBench.cpp index f81bfb1d10..d9ee5823bf 100644 --- a/bench/RotatedRectBench.cpp +++ b/bench/RotatedRectBench.cpp @@ -6,6 +6,7 @@ */ #include "Benchmark.h" +#include "SkBlendModePriv.h" #include "SkCanvas.h" #include "SkPaint.h" @@ -144,7 +145,7 @@ private: fName.append("_alternating_transparent_and_opaque"); break; } - fName.appendf("_%s", to_lower(SkXfermode::ModeName(fMode)).c_str()); + fName.appendf("_%s", to_lower(SkBlendMode_Name(fMode)).c_str()); } bool fAA; diff --git a/bench/Xfer4fBench.cpp b/bench/Xfer4fBench.cpp index 0e99c8c3f2..5e679a826e 100644 --- a/bench/Xfer4fBench.cpp +++ b/bench/Xfer4fBench.cpp @@ -8,7 +8,7 @@ #include "Benchmark.h" #include "SkPM4f.h" #include "SkString.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" #define USE_AA (1 << 31) // merge with Xfermode::PMFlags w/o conflict diff --git a/bench/XferF16Bench.cpp b/bench/XferF16Bench.cpp index 14505fd6bf..bd44effd05 100644 --- a/bench/XferF16Bench.cpp +++ b/bench/XferF16Bench.cpp @@ -8,7 +8,7 @@ #include "Benchmark.h" #include "SkPM4f.h" #include "SkString.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" #define USE_AA (1 << 31) // merge with Xfermode::PMFlags w/o conflict diff --git a/bench/XfermodeBench.cpp b/bench/XfermodeBench.cpp index 9e148d4317..605d167296 100644 --- a/bench/XfermodeBench.cpp +++ b/bench/XfermodeBench.cpp @@ -6,18 +6,18 @@ */ #include "Benchmark.h" +#include "SkBlendModePriv.h" #include "SkCanvas.h" #include "SkPaint.h" #include "SkRandom.h" #include "SkString.h" -#include "SkXfermode.h" // Benchmark that draws non-AA rects or AA text with an SkXfermode::Mode. class XfermodeBench : public Benchmark { public: XfermodeBench(SkBlendMode mode, bool aa) : fBlendMode(mode) { fAA = aa; - fName.printf("Xfermode_%s%s", SkXfermode::ModeName(mode), aa ? "_aa" : ""); + fName.printf("Xfermode_%s%s", SkBlendMode_Name(mode), aa ? "_aa" : ""); } protected: diff --git a/gm/SkLinearBitmapPipelineGM.cpp b/gm/SkLinearBitmapPipelineGM.cpp index f6f7c9e215..13f600429f 100644 --- a/gm/SkLinearBitmapPipelineGM.cpp +++ b/gm/SkLinearBitmapPipelineGM.cpp @@ -12,7 +12,7 @@ #include "SkImage.h" #include "SkImageInfo.h" #include "SkLinearBitmapPipeline.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" #include "SkPM4fPriv.h" #include "SkShader.h" diff --git a/gm/aaxfermodes.cpp b/gm/aaxfermodes.cpp index 7106ce8174..df09a0bc9d 100644 --- a/gm/aaxfermodes.cpp +++ b/gm/aaxfermodes.cpp @@ -4,14 +4,15 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ + #include "gm.h" #include "SkArithmeticMode.h" +#include "SkBlendModePriv.h" #include "SkPath.h" #include "SkShader.h" -#include "SkXfermode.h" enum { - kXfermodeCount = SkXfermode::kLastMode + 2, // All xfermodes plus arithmetic mode. + kXfermodeCount = (int)SkBlendMode::kLastMode + 1 + 1, // extra for arith kShapeSize = 22, kShapeSpacing = 36, kShapeTypeSpacing = 4 * kShapeSpacing / 3, @@ -62,7 +63,7 @@ protected: return SkISize::Make(2 * kMargin + 2 * kXfermodeTypeSpacing - (kXfermodeTypeSpacing - (kLabelSpacing + 2 * kPaintSpacing)), 2 * kMargin + kTitleSpacing + kSubtitleSpacing + - (1 + SkXfermode::kLastCoeffMode) * kShapeSpacing); + (1 + (int)SkBlendMode::kLastCoeffMode) * kShapeSpacing); } void onOnceBeforeDraw() override { @@ -101,7 +102,7 @@ protected: canvas->translate(0, kTitleSpacing); for (size_t xfermodeSet = 0; xfermodeSet < 2; xfermodeSet++) { - size_t firstMode = (SkXfermode::kLastCoeffMode + 1) * xfermodeSet; + size_t firstMode = ((size_t)SkBlendMode::kLastCoeffMode + 1) * xfermodeSet; canvas->save(); if (kShape_Pass == drawingPass) { @@ -117,8 +118,8 @@ protected: canvas->translate(0, kSubtitleSpacing + kShapeSpacing/2); - for (size_t m = 0; m <= SkXfermode::kLastCoeffMode; m++) { - if (firstMode + m > SkXfermode::kLastMode) { + for (size_t m = 0; m <= (size_t)SkBlendMode::kLastCoeffMode; m++) { + if (firstMode + m > (size_t)SkBlendMode::kLastMode) { break; } SkBlendMode mode = static_cast(firstMode + m); @@ -191,7 +192,7 @@ protected: } void drawModeName(SkCanvas* canvas, SkBlendMode mode) { - const char* modeName = SkXfermode::ModeName(mode); + const char* modeName = SkBlendMode_Name(mode); fLabelPaint.setTextAlign(SkPaint::kRight_Align); canvas->drawText(modeName, strlen(modeName), kLabelSpacing - kShapeSize / 4, fLabelPaint.getTextSize() / 4, fLabelPaint); diff --git a/gm/gamma.cpp b/gm/gamma.cpp index 4e80bbf3b0..09f80dd327 100644 --- a/gm/gamma.cpp +++ b/gm/gamma.cpp @@ -8,6 +8,7 @@ #include "gm.h" #include "Resources.h" +#include "SkBlendModePriv.h" #include "SkGradientShader.h" #include "SkPM4fPriv.h" @@ -86,7 +87,7 @@ DEF_SIMPLE_GM(gamma, canvas, 850, 200) { SkString dstText = SkStringPrintf("%08X", dstColor); canvas->drawText(srcText.c_str(), srcText.size(), 0, sz + textPaint.getFontSpacing(), textPaint); - const char* modeName = SkXfermode::ModeName(mode); + const char* modeName = SkBlendMode_Name(mode); canvas->drawText(modeName, strlen(modeName), 0, sz + 2 * textPaint.getFontSpacing(), textPaint); canvas->drawText(dstText.c_str(), dstText.size(), 0, sz + 3 * textPaint.getFontSpacing(), diff --git a/gm/lumafilter.cpp b/gm/lumafilter.cpp index 3852d9385f..abce994c20 100644 --- a/gm/lumafilter.cpp +++ b/gm/lumafilter.cpp @@ -6,6 +6,7 @@ */ #include "gm.h" +#include "SkBlendModePriv.h" #include "SkCanvas.h" #include "SkGradientShader.h" #include "SkLumaColorFilter.h" @@ -121,7 +122,7 @@ protected: SkScalar gridStep = kSize + 2 * kInset; for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) { - draw_label(canvas, SkXfermode::ModeName(modes[i]), + draw_label(canvas, SkBlendMode_Name(modes[i]), SkPoint::Make(gridStep * (0.5f + i), 20)); } diff --git a/gm/xfermodes2.cpp b/gm/xfermodes2.cpp index 03da0d3317..4d6b5e7fe9 100644 --- a/gm/xfermodes2.cpp +++ b/gm/xfermodes2.cpp @@ -7,7 +7,7 @@ #include "gm.h" #include "SkBitmap.h" #include "SkShader.h" -#include "SkXfermode.h" +#include "SkBlendModePriv.h" #include "SkColorPriv.h" namespace skiagm { @@ -39,7 +39,7 @@ protected: const int W = 6; SkScalar x = 0, y = 0; - for (size_t m = 0; m <= SkXfermode::kLastMode; m++) { + for (size_t m = 0; m <= (size_t)SkBlendMode::kLastMode; m++) { SkBlendMode mode = static_cast(m); canvas->save(); @@ -71,7 +71,7 @@ protected: canvas->restore(); #if 1 - canvas->drawText(SkXfermode::ModeName(mode), strlen(SkXfermode::ModeName(mode)), + canvas->drawText(SkBlendMode_Name(mode), strlen(SkBlendMode_Name(mode)), x + w/2, y - labelP.getTextSize()/2, labelP); #endif x += w + SkIntToScalar(10); diff --git a/gm/xfermodes3.cpp b/gm/xfermodes3.cpp index 36702bf70e..e6ee7508ad 100644 --- a/gm/xfermodes3.cpp +++ b/gm/xfermodes3.cpp @@ -9,7 +9,7 @@ #include "SkBitmap.h" #include "SkGradientShader.h" #include "SkSurface.h" -#include "SkXfermode.h" +#include "SkBlendModePriv.h" #include "SkColorPriv.h" #if SK_SUPPORT_GPU @@ -68,10 +68,10 @@ protected: {SkPaint::kStroke_Style, SkIntToScalar(kSize) / 2}, }; for (size_t s = 0; s < SK_ARRAY_COUNT(kStrokes); ++s) { - for (size_t m = 0; m <= SkXfermode::kLastMode; ++m) { + for (size_t m = 0; m <= (size_t)SkBlendMode::kLastMode; ++m) { SkBlendMode mode = static_cast(m); - canvas->drawText(SkXfermode::ModeName(mode), - strlen(SkXfermode::ModeName(mode)), + canvas->drawText(SkBlendMode_Name(mode), + strlen(SkBlendMode_Name(mode)), SkIntToScalar(x), SkIntToScalar(y + kSize + 3) + labelP.getTextSize(), labelP); diff --git a/gn/android_framework_defines.gni b/gn/android_framework_defines.gni index 90fea2fb25..1e61d377b3 100644 --- a/gn/android_framework_defines.gni +++ b/gn/android_framework_defines.gni @@ -15,4 +15,5 @@ android_framework_defines = [ "SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT", "SK_SUPPORT_LEGACY_CLIP_REGIONOPS", "SK_SUPPORT_LEGACY_SHADER_ISABITMAP", + "SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC", ] diff --git a/gn/core.gni b/gn/core.gni index 60c7761ef5..d7f11569a8 100644 --- a/gn/core.gni +++ b/gn/core.gni @@ -442,7 +442,6 @@ skia_core_sources = [ "$_include/core/SkTypes.h", "$_include/core/SkUnPreMultiply.h", "$_include/core/SkWriter32.h", - "$_include/core/SkXfermode.h", # private "$_include/private/SkAtomics.h", diff --git a/gn/tests.gni b/gn/tests.gni index d828297b5b..d888c6a152 100644 --- a/gn/tests.gni +++ b/gn/tests.gni @@ -245,7 +245,6 @@ tests_sources = [ "$_tests/WindowRectanglesTest.cpp", "$_tests/WritePixelsTest.cpp", "$_tests/Writer32Test.cpp", - "$_tests/XfermodeTest.cpp", "$_tests/YUVCacheTest.cpp", "$_tests/YUVTest.cpp", ] diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h index 34989354cd..2d0047757b 100644 --- a/include/core/SkMaskFilter.h +++ b/include/core/SkMaskFilter.h @@ -20,7 +20,9 @@ class GrClip; class GrContext; class GrRenderTargetContext; class GrPaint; +class GrFragmentProcessor; class GrRenderTarget; +class GrTexture; class GrTextureProvider; class SkBitmap; class SkBlitter; diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h index e865e66456..59f205848a 100644 --- a/include/core/SkXfermode.h +++ b/include/core/SkXfermode.h @@ -12,6 +12,8 @@ #include "SkColor.h" #include "SkFlattenable.h" +#ifdef SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC + class GrFragmentProcessor; class GrTexture; class GrXPFactory; @@ -303,3 +305,5 @@ private: }; #endif + +#endif diff --git a/include/gpu/GrProcessorUnitTest.h b/include/gpu/GrProcessorUnitTest.h index 075581f6c1..3e9fe5e44b 100644 --- a/include/gpu/GrProcessorUnitTest.h +++ b/include/gpu/GrProcessorUnitTest.h @@ -17,6 +17,7 @@ class GrCaps; class GrContext; class GrRenderTargetContext; struct GrProcessorTestData; +class GrTexture; namespace GrProcessorUnitTest { diff --git a/include/gpu/effects/GrCustomXfermode.h b/include/gpu/effects/GrCustomXfermode.h index 8632093074..a8c868e034 100644 --- a/include/gpu/effects/GrCustomXfermode.h +++ b/include/gpu/effects/GrCustomXfermode.h @@ -8,9 +8,11 @@ #ifndef GrCustomXfermode_DEFINED #define GrCustomXfermode_DEFINED -#include "SkXfermode.h" +#include "SkBlendMode.h" +#include "SkRefCnt.h" class GrTexture; +class GrXPFactory; /** * Custom Xfer modes are used for blending when the blend mode cannot be represented using blend diff --git a/public.bzl b/public.bzl index 4e100122a1..dee0fb8ded 100644 --- a/public.bzl +++ b/public.bzl @@ -602,6 +602,7 @@ DEFINES_ALL = [ "SK_SUPPORT_LEGACY_ACCESSBITMAP", "SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT", "SK_SUPPORT_LEGACY_CLIP_REGIONOPS", + "SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC", # Temporarily Disable analytic AA for Google3 "SK_NO_ANALYTIC_AA", ] diff --git a/samplecode/SampleFilterFuzz.cpp b/samplecode/SampleFilterFuzz.cpp index 5f65c9fabc..682db9220e 100644 --- a/samplecode/SampleFilterFuzz.cpp +++ b/samplecode/SampleFilterFuzz.cpp @@ -158,7 +158,7 @@ static SkMatrix make_matrix() { } static SkBlendMode make_xfermode() { - return static_cast(R(SkXfermode::kLastMode+1)); + return static_cast(R((int)SkBlendMode::kLastMode+1)); } static SkPaint::Align make_paint_align() { diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp index 218e919da3..b17d3e3dff 100644 --- a/src/core/SkBitmapProcShader.cpp +++ b/src/core/SkBitmapProcShader.cpp @@ -8,6 +8,7 @@ #include "SkBitmapProcShader.h" #include "SkBitmapProcState.h" #include "SkBitmapProvider.h" +#include "SkXfermodePriv.h" static bool only_scale_and_translate(const SkMatrix& matrix) { unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; @@ -102,7 +103,6 @@ private: /////////////////////////////////////////////////////////////////////////////////////////////////// #include "SkLinearBitmapPipeline.h" #include "SkPM4f.h" -#include "SkXfermode.h" class LinearPipelineContext : public BitmapProcInfoContext { public: diff --git a/src/core/SkBlendModePriv.h b/src/core/SkBlendModePriv.h index 29df639842..c4628fd927 100644 --- a/src/core/SkBlendModePriv.h +++ b/src/core/SkBlendModePriv.h @@ -15,6 +15,8 @@ bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode); bool SkBlendMode_CanOverflow(SkBlendMode); bool SkBlendMode_AppendStages(SkBlendMode, SkRasterPipeline* = nullptr); +const char* SkBlendMode_Name(SkBlendMode); + #if SK_SUPPORT_GPU #include "GrXferProcessor.h" sk_sp SkBlendMode_AsXPFactory(SkBlendMode); diff --git a/src/core/SkBlitter_A8.cpp b/src/core/SkBlitter_A8.cpp index cb7d718f54..1fd4d5f0d9 100644 --- a/src/core/SkBlitter_A8.cpp +++ b/src/core/SkBlitter_A8.cpp @@ -9,7 +9,7 @@ #include "SkCoreBlitters.h" #include "SkColorPriv.h" #include "SkShader.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" SkA8_Blitter::SkA8_Blitter(const SkPixmap& device, const SkPaint& paint) : INHERITED(device) { fSrcA = paint.getAlpha(); diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp index ea0554d66e..958ad27970 100644 --- a/src/core/SkBlitter_ARGB32.cpp +++ b/src/core/SkBlitter_ARGB32.cpp @@ -9,7 +9,7 @@ #include "SkColorPriv.h" #include "SkShader.h" #include "SkUtils.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" #include "SkBlitMask.h" /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp index 2084972262..ce66580659 100644 --- a/src/core/SkBlitter_PM4f.cpp +++ b/src/core/SkBlitter_PM4f.cpp @@ -9,7 +9,7 @@ #include "SkColorPriv.h" #include "SkShader.h" #include "SkUtils.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" #include "SkBlitMask.h" #include "SkTemplates.h" #include "SkPM4f.h" diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp index 7860b7cb6c..015112a107 100644 --- a/src/core/SkBlitter_RGB16.cpp +++ b/src/core/SkBlitter_RGB16.cpp @@ -12,7 +12,7 @@ #include "SkShader.h" #include "SkUtils.h" #include "SkUtilsArm.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" #if defined(__mips_dsp) extern void blitmask_d565_opaque_mips(int width, int height, uint16_t* device, diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h index aa5deb21c1..23fca0f402 100644 --- a/src/core/SkCoreBlitters.h +++ b/src/core/SkCoreBlitters.h @@ -13,6 +13,7 @@ #include "SkBlitRow.h" #include "SkShader.h" #include "SkSmallAllocator.h" +#include "SkXfermodePriv.h" class SkRasterBlitter : public SkBlitter { public: diff --git a/src/core/SkLinearBitmapPipeline.h b/src/core/SkLinearBitmapPipeline.h index ea78489ed8..3e7be5c873 100644 --- a/src/core/SkLinearBitmapPipeline.h +++ b/src/core/SkLinearBitmapPipeline.h @@ -38,7 +38,7 @@ public: SkLinearBitmapPipeline( const SkLinearBitmapPipeline& pipeline, const SkPixmap& srcPixmap, - SkBlendMode blendMode, + SkBlendMode, const SkImageInfo& dstInfo); static bool ClonePipelineForBlitting( diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h index ccd38acc5f..1d5e333729 100644 --- a/src/core/SkOpts.h +++ b/src/core/SkOpts.h @@ -11,7 +11,7 @@ #include "SkRasterPipeline.h" #include "SkTextureCompressor.h" #include "SkTypes.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" #include struct ProcCoeff; diff --git a/src/core/SkPaintPriv.cpp b/src/core/SkPaintPriv.cpp index cbe2558c2a..ffa818c6e8 100644 --- a/src/core/SkPaintPriv.cpp +++ b/src/core/SkPaintPriv.cpp @@ -11,6 +11,7 @@ #include "SkImage.h" #include "SkPaint.h" #include "SkShader.h" +#include "SkXfermodePriv.h" static bool changes_alpha(const SkPaint& paint) { SkColorFilter* cf = paint.getColorFilter(); diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h index c49b01c5fd..25928d1ba0 100644 --- a/src/core/SkReadBuffer.h +++ b/src/core/SkReadBuffer.h @@ -23,7 +23,7 @@ #include "SkShader.h" #include "SkTHash.h" #include "SkWriteBuffer.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" class SkBitmap; class SkImage; diff --git a/src/core/SkSpriteBlitter4f.cpp b/src/core/SkSpriteBlitter4f.cpp index ddf044e455..977a2647a9 100644 --- a/src/core/SkSpriteBlitter4f.cpp +++ b/src/core/SkSpriteBlitter4f.cpp @@ -8,7 +8,7 @@ #include "SkSpriteBlitter.h" #include "SkSpanProcs.h" #include "SkTemplates.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" class Sprite_4f : public SkSpriteBlitter { public: diff --git a/src/core/SkSpriteBlitter_ARGB32.cpp b/src/core/SkSpriteBlitter_ARGB32.cpp index 1a76b1b2fe..99856a14f9 100644 --- a/src/core/SkSpriteBlitter_ARGB32.cpp +++ b/src/core/SkSpriteBlitter_ARGB32.cpp @@ -11,7 +11,7 @@ #include "SkColorPriv.h" #include "SkTemplates.h" #include "SkUtils.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp index 64ce04d851..3f3927e742 100644 --- a/src/core/SkXfermode.cpp +++ b/src/core/SkXfermode.cpp @@ -1280,6 +1280,10 @@ const char* SkXfermode::ModeName(Mode mode) { static_assert(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, "mode_count"); } +const char* SkBlendMode_Name(SkBlendMode mode) { + return SkXfermode::ModeName((SkXfermode::Mode)mode); +} + #ifndef SK_IGNORE_TO_STRING void SkProcCoeffXfermode::toString(SkString* str) const { str->append("SkProcCoeffXfermode: "); diff --git a/src/core/SkXfermode4f.cpp b/src/core/SkXfermode4f.cpp index d5bdfe5251..e9d55905a7 100644 --- a/src/core/SkXfermode4f.cpp +++ b/src/core/SkXfermode4f.cpp @@ -7,7 +7,7 @@ #include "SkPM4fPriv.h" #include "SkUtils.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" #include "Sk4x4f.h" static SkPM4f rgba_to_pmcolor_order(const SkPM4f& x) { diff --git a/src/core/SkXfermodeF16.cpp b/src/core/SkXfermodeF16.cpp index 868ee087ca..ece4a097c3 100644 --- a/src/core/SkXfermodeF16.cpp +++ b/src/core/SkXfermodeF16.cpp @@ -8,7 +8,7 @@ #include "SkHalf.h" #include "SkPM4fPriv.h" #include "SkUtils.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" static Sk4f lerp_by_coverage(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) { return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f)); diff --git a/src/core/SkXfermodePriv.h b/src/core/SkXfermodePriv.h new file mode 100644 index 0000000000..b7d85ea98f --- /dev/null +++ b/src/core/SkXfermodePriv.h @@ -0,0 +1,311 @@ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkXfermodePriv_DEFINED +#define SkXfermodePriv_DEFINED + +#include "SkBlendMode.h" +#include "SkColor.h" +#include "SkFlattenable.h" + +#ifdef SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC +#include "SkXfermode.h" +#else + +class GrFragmentProcessor; +class GrTexture; +class GrXPFactory; +class SkRasterPipeline; +class SkString; + +struct SkArithmeticParams; + +struct SkPM4f; +typedef SkPM4f (*SkXfermodeProc4f)(const SkPM4f& src, const SkPM4f& dst); + +/** \class SkXfermode + * + * SkXfermode is the base class for objects that are called to implement custom + * "transfer-modes" in the drawing pipeline. The static function Create(Modes) + * can be called to return an instance of any of the predefined subclasses as + * specified in the Modes enum. When an SkXfermode is assigned to an SkPaint, + * then objects drawn with that paint have the xfermode applied. + * + * All subclasses are required to be reentrant-safe : it must be legal to share + * the same instance between several threads. + */ +class SK_API SkXfermode : public SkFlattenable { +public: + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const; + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const; + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const; + + /** Enum of possible coefficients to describe some xfermodes + */ + enum Coeff { + kZero_Coeff, /** 0 */ + kOne_Coeff, /** 1 */ + kSC_Coeff, /** src color */ + kISC_Coeff, /** inverse src color (i.e. 1 - sc) */ + kDC_Coeff, /** dst color */ + kIDC_Coeff, /** inverse dst color (i.e. 1 - dc) */ + kSA_Coeff, /** src alpha */ + kISA_Coeff, /** inverse src alpha (i.e. 1 - sa) */ + kDA_Coeff, /** dst alpha */ + kIDA_Coeff, /** inverse dst alpha (i.e. 1 - da) */ + + kCoeffCount + }; + + /** List of predefined xfermodes. + The algebra for the modes uses the following symbols: + Sa, Sc - source alpha and color + Da, Dc - destination alpha and color (before compositing) + [a, c] - Resulting (alpha, color) values + For these equations, the colors are in premultiplied state. + If no xfermode is specified, kSrcOver is assumed. + The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those + that aren't Coeffs but have separable r,g,b computations, and finally + those that are not separable. + */ + enum Mode { + kClear_Mode, //!< [0, 0] + kSrc_Mode, //!< [Sa, Sc] + kDst_Mode, //!< [Da, Dc] + kSrcOver_Mode, //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)] + kDstOver_Mode, //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)] + kSrcIn_Mode, //!< [Sa * Da, Sc * Da] + kDstIn_Mode, //!< [Da * Sa, Dc * Sa] + kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] + kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] + kSrcATop_Mode, //!< [Da, Sc * Da + Dc * (1 - Sa)] + kDstATop_Mode, //!< [Sa, Dc * Sa + Sc * (1 - Da)] + kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)] + kPlus_Mode, //!< [Sa + Da, Sc + Dc] + kModulate_Mode, // multiplies all components (= alpha and color) + + // Following blend modes are defined in the CSS Compositing standard: + // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending + kScreen_Mode, + kLastCoeffMode = kScreen_Mode, + + kOverlay_Mode, + kDarken_Mode, + kLighten_Mode, + kColorDodge_Mode, + kColorBurn_Mode, + kHardLight_Mode, + kSoftLight_Mode, + kDifference_Mode, + kExclusion_Mode, + kMultiply_Mode, + kLastSeparableMode = kMultiply_Mode, + + kHue_Mode, + kSaturation_Mode, + kColor_Mode, + kLuminosity_Mode, + kLastMode = kLuminosity_Mode + }; + + /** + * Gets the name of the Mode as a string. + */ + static const char* ModeName(Mode); + static const char* ModeName(SkBlendMode mode) { + return ModeName(Mode(mode)); + } + + /** + * If the xfermode is one of the modes in the Mode enum, then asMode() + * returns true and sets (if not null) mode accordingly. Otherwise it + * returns false and ignores the mode parameter. + */ + virtual bool asMode(Mode* mode) const; + + /** + * The same as calling xfermode->asMode(mode), except that this also checks + * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode. + */ + static bool AsMode(const SkXfermode*, Mode* mode); + static bool AsMode(const sk_sp& xfer, Mode* mode) { + return AsMode(xfer.get(), mode); + } + + /** + * Returns true if the xfermode claims to be the specified Mode. This works + * correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus + * you can say this without checking for a null... + * + * If (SkXfermode::IsMode(paint.getXfermode(), + * SkXfermode::kDstOver_Mode)) { + * ... + * } + */ + static bool IsMode(const SkXfermode* xfer, Mode mode); + static bool IsMode(const sk_sp& xfer, Mode mode) { + return IsMode(xfer.get(), mode); + } + + /** Return an SkXfermode object for the specified mode. + */ + static sk_sp Make(SkBlendMode); + static sk_sp Make(Mode m) { return Make((SkBlendMode)m); } + + /** + * Skia maintains global xfermode objects corresponding to each BlendMode. This returns a + * ptr to that global xfermode (or null if the mode is srcover). Thus the caller may use + * the returned ptr, but it should leave its refcnt untouched. + */ + static SkXfermode* Peek(SkBlendMode mode) { + sk_sp xfer = Make(mode); + if (!xfer) { + SkASSERT(SkBlendMode::kSrcOver == mode); + return nullptr; + } + SkASSERT(!xfer->unique()); + return xfer.get(); + } + + SkBlendMode blend() const { + Mode mode; + SkAssertResult(this->asMode(&mode)); + return (SkBlendMode)mode; + } + + static SkXfermodeProc GetProc(SkBlendMode); + static SkXfermodeProc4f GetProc4f(SkBlendMode); + + /** + * If the specified mode can be represented by a pair of Coeff, then return + * true and set (if not NULL) the corresponding coeffs. If the mode is + * not representable as a pair of Coeffs, return false and ignore the + * src and dst parameters. + */ + static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst); + static bool ModeAsCoeff(SkBlendMode mode, Coeff* src, Coeff* dst) { + return ModeAsCoeff((Mode)mode, src, dst); + } + + /** + * Returns whether or not the xfer mode can support treating coverage as alpha + */ + virtual bool supportsCoverageAsAlpha() const; + + /** + * The same as calling xfermode->supportsCoverageAsAlpha(), except that this also checks if + * the xfermode is NULL, and if so, treats it as kSrcOver_Mode. + */ + static bool SupportsCoverageAsAlpha(const SkXfermode* xfer); + static bool SupportsCoverageAsAlpha(const sk_sp& xfer) { + return SupportsCoverageAsAlpha(xfer.get()); + } + + enum SrcColorOpacity { + // The src color is known to be opaque (alpha == 255) + kOpaque_SrcColorOpacity = 0, + // The src color is known to be fully transparent (color == 0) + kTransparentBlack_SrcColorOpacity = 1, + // The src alpha is known to be fully transparent (alpha == 0) + kTransparentAlpha_SrcColorOpacity = 2, + // The src color opacity is unknown + kUnknown_SrcColorOpacity = 3 + }; + + /** + * Returns whether or not the result of the draw with the xfer mode will be opaque or not. The + * input to this call is an enum describing known information about the opacity of the src color + * that will be given to the xfer mode. + */ + virtual bool isOpaque(SrcColorOpacity opacityType) const; + + /** + * The same as calling xfermode->isOpaque(...), except that this also checks if + * the xfermode is NULL, and if so, treats it as kSrcOver_Mode. + */ + static bool IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType); + static bool IsOpaque(const sk_sp& xfer, SrcColorOpacity opacityType) { + return IsOpaque(xfer.get(), opacityType); + } + static bool IsOpaque(SkBlendMode, SrcColorOpacity); + +#if SK_SUPPORT_GPU + /** Used by the SkXfermodeImageFilter to blend two colors via a GrFragmentProcessor. + The input to the returned FP is the src color. The dst color is + provided by the dst param which becomes a child FP of the returned FP. + It is legal for the function to return a null output. This indicates that + the output of the blend is simply the src color. + */ + virtual sk_sp makeFragmentProcessorForImageFilter( + sk_sp dst) const; + + /** A subclass must implement this factory function to work with the GPU backend. + The xfermode will return a factory for which the caller will get a ref. It is up + to the caller to install it. XferProcessors cannot use a background texture. + */ + virtual sk_sp asXPFactory() const; +#endif + + SK_TO_STRING_PUREVIRT() + SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() + SK_DEFINE_FLATTENABLE_TYPE(SkXfermode) + + enum D32Flags { + kSrcIsOpaque_D32Flag = 1 << 0, + kSrcIsSingle_D32Flag = 1 << 1, + kDstIsSRGB_D32Flag = 1 << 2, + }; + typedef void (*D32Proc)(SkBlendMode, uint32_t dst[], const SkPM4f src[], + int count, const SkAlpha coverage[]); + static D32Proc GetD32Proc(SkBlendMode, uint32_t flags); + + enum F16Flags { + kSrcIsOpaque_F16Flag = 1 << 0, + kSrcIsSingle_F16Flag = 1 << 1, + }; + typedef void (*F16Proc)(SkBlendMode, uint64_t dst[], const SkPM4f src[], int count, + const SkAlpha coverage[]); + static F16Proc GetF16Proc(SkBlendMode, uint32_t flags); + + enum LCDFlags { + kSrcIsOpaque_LCDFlag = 1 << 0, // else src(s) may have alpha < 1 + kSrcIsSingle_LCDFlag = 1 << 1, // else src[count] + kDstIsSRGB_LCDFlag = 1 << 2, // else l32 or f16 + }; + typedef void (*LCD32Proc)(uint32_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]); + typedef void (*LCDF16Proc)(uint64_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]); + static LCD32Proc GetLCD32Proc(uint32_t flags); + static LCDF16Proc GetLCDF16Proc(uint32_t) { return nullptr; } + + virtual bool isArithmetic(SkArithmeticParams*) const { return false; } + +protected: + SkXfermode() {} + /** The default implementation of xfer32/xfer16/xferA8 in turn call this + method, 1 color at a time (upscaled to a SkPMColor). The default + implementation of this method just returns dst. If performance is + important, your subclass should override xfer32/xfer16/xferA8 directly. + + This method will not be called directly by the client, so it need not + be implemented if your subclass has overridden xfer32/xfer16/xferA8 + */ + virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const; + +private: + enum { + kModeCount = kLastMode + 1 + }; + + typedef SkFlattenable INHERITED; +}; + +#endif + +#endif diff --git a/src/effects/SkArithmeticModePriv.h b/src/effects/SkArithmeticModePriv.h index ca469a7233..5cb1093434 100644 --- a/src/effects/SkArithmeticModePriv.h +++ b/src/effects/SkArithmeticModePriv.h @@ -10,6 +10,8 @@ #include "SkArithmeticMode.h" +class SkXfermode; + struct SkArithmeticParams { float fK[4]; bool fEnforcePMColor; diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h index ecbe558c94..bd1d7155e6 100644 --- a/src/gpu/SkGrPriv.h +++ b/src/gpu/SkGrPriv.h @@ -12,7 +12,7 @@ #include "GrBlend.h" #include "SkImageInfo.h" #include "SkMatrix.h" -#include "SkXfermode.h" +#include "SkXfermodePriv.h" class GrCaps; class GrContext; diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp index 3895f57f5d..8a54d4457a 100644 --- a/src/gpu/effects/GrCustomXfermode.cpp +++ b/src/gpu/effects/GrCustomXfermode.cpp @@ -384,8 +384,8 @@ void CustomXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory); sk_sp CustomXPFactory::TestCreate(GrProcessorTestData* d) { - int mode = d->fRandom->nextRangeU(SkXfermode::kLastCoeffMode + 1, - SkXfermode::kLastSeparableMode); + int mode = d->fRandom->nextRangeU((int)SkBlendMode::kLastCoeffMode + 1, + (int)SkBlendMode::kLastSeparableMode); return sk_sp(new CustomXPFactory(static_cast(mode))); } diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp index d511fae45d..ff95dac723 100644 --- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp +++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp @@ -227,7 +227,7 @@ GR_MAKE_BITFIELD_OPS(BlendFormula::Properties); * with and without an opaque input color. Optimization properties are deduced at compile time so we * can make runtime decisions quickly. RGB coverage is not supported. */ -static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = { +static const BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = { /*>> No coverage, input color unknown <<*/ {{ @@ -302,7 +302,7 @@ static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = { /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), }}}; -static const BlendFormula gLCDBlendTable[SkXfermode::kLastCoeffMode + 1] = { +static const BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = { /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType), /* src */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff), /* dst */ NO_DST_WRITE_FORMULA, diff --git a/src/gpu/glsl/GrGLSLBlend.cpp b/src/gpu/glsl/GrGLSLBlend.cpp index 73a145b7c3..da73b6644b 100644 --- a/src/gpu/glsl/GrGLSLBlend.cpp +++ b/src/gpu/glsl/GrGLSLBlend.cpp @@ -4,8 +4,10 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ + #include "GrGLSLBlend.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" +#include "SkXfermodePriv.h" ////////////////////////////////////////////////////////////////////////////// // Advanced (non-coeff) blend helpers diff --git a/tests/BlendTest.cpp b/tests/BlendTest.cpp index ca9e46efd3..cd5e8efba7 100644 --- a/tests/BlendTest.cpp +++ b/tests/BlendTest.cpp @@ -67,36 +67,3 @@ DEF_TEST(Blend_byte_multiply, r) { }; for (auto multiply : perfect) { REPORTER_ASSERT(r, test(multiply).diffs == 0); } } - -DEF_TEST(Blend_premul_begets_premul, r) { - // This test is quite slow, even if you have enough cores to run each mode in parallel. - if (!r->allowExtendedTest()) { - return; - } - - // No matter what xfermode we use, premul inputs should create premul outputs. - auto test_mode = [&](int m) { - SkXfermode::Mode mode = (SkXfermode::Mode)m; - if (mode == SkXfermode::kSrcOver_Mode) { - return; // TODO: can't create a SrcOver xfermode. - } - auto xfermode(SkXfermode::Make(mode)); - SkASSERT(xfermode); - // We'll test all alphas and legal color values, assuming all colors work the same. - // This is not true for non-separable blend modes, but this test still can't hurt. - for (int sa = 0; sa <= 255; sa++) { - for (int da = 0; da <= 255; da++) { - for (int s = 0; s <= sa; s++) { - for (int d = 0; d <= da; d++) { - SkPMColor src = SkPackARGB32(sa, s, s, s), - dst = SkPackARGB32(da, d, d, d); - xfermode->xfer32(&dst, &src, 1, nullptr); // To keep it simple, no AA. - if (!SkPMColorValid(dst)) { - ERRORF(r, "%08x is not premul using %s", dst, SkXfermode::ModeName(mode)); - } - }}}} - }; - - // Parallelism helps speed things up on my desktop from ~725s to ~50s. - SkTaskGroup().batch(SkXfermode::kLastMode, test_mode); -} diff --git a/tests/RecordingXfermodeTest.cpp b/tests/RecordingXfermodeTest.cpp index 32aec36f9f..db4262c7e9 100644 --- a/tests/RecordingXfermodeTest.cpp +++ b/tests/RecordingXfermodeTest.cpp @@ -12,6 +12,7 @@ #include "../include/core/SkStream.h" #include "../include/core/SkString.h" #include "../include/core/SkPictureRecorder.h" +#include "../src/core/SkBlendModePriv.h" #include // Verify that replay of a recording into a clipped canvas @@ -160,7 +161,7 @@ DEF_TEST(SkRecordingAccuracyXfermode, reporter) { if (memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize)) { numErrors++; errors.appendf("For SkXfermode %d %s: SkPictureRecorder bitmap is wrong\n", - iMode, SkXfermode::ModeName(mode)); + iMode, SkBlendMode_Name(mode)); } #endif } diff --git a/tests/SkColor4fTest.cpp b/tests/SkColor4fTest.cpp index 028b99f413..f268e5f42d 100644 --- a/tests/SkColor4fTest.cpp +++ b/tests/SkColor4fTest.cpp @@ -23,15 +23,6 @@ static bool nearly_equal(float a, float b, float tol = kTolerance) { return fabsf(a - b) <= tol; } -static bool nearly_equal(const SkPM4f a, const SkPM4f& b, float tol = kTolerance) { - for (int i = 0; i < 4; ++i) { - if (!nearly_equal(a.fVec[i], b.fVec[i], tol)) { - return false; - } - } - return true; -} - DEF_TEST(SkColor4f_FromColor, reporter) { const struct { SkColor fC; @@ -75,45 +66,3 @@ DEF_TEST(Color4f_premul, reporter) { REPORTER_ASSERT(reporter, nearly_equal(pm4.b(), c4.fA * c4.fB)); } } - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -typedef SkPM4f (*SkXfermodeProc4f)(const SkPM4f& src, const SkPM4f& dst); - -static bool compare_procs(SkXfermodeProc proc32, SkXfermodeProc4f proc4f) { - const float kTolerance = 1.0f / 255; - - const SkColor colors[] = { - 0, 0xFF000000, 0xFFFFFFFF, 0x80FF0000 - }; - - for (auto s32 : colors) { - SkPMColor s_pm32 = SkPreMultiplyColor(s32); - SkPM4f s_pm4f = SkColor4f::FromColor(s32).premul(); - for (auto d32 : colors) { - SkPMColor d_pm32 = SkPreMultiplyColor(d32); - SkPM4f d_pm4f = SkColor4f::FromColor(d32).premul(); - - SkPMColor r32 = proc32(s_pm32, d_pm32); - SkPM4f r4f = proc4f(s_pm4f, d_pm4f); - - SkPM4f r32_4f = SkPM4f::FromPMColor(r32); - if (!nearly_equal(r4f, r32_4f, kTolerance)) { - return false; - } - } - } - return true; -} - -// Check that our Proc and Proc4f return (nearly) the same results -// -DEF_TEST(Color4f_xfermode_proc4f, reporter) { - // TODO: extend xfermodes so that all cases can be tested. - // - for (int mode = (int)SkBlendMode::kClear; mode <= (int)SkBlendMode::kScreen; ++mode) { - SkXfermodeProc proc32 = SkXfermode::GetProc((SkBlendMode)mode); - SkXfermodeProc4f proc4f = SkXfermode::GetProc4f((SkBlendMode)mode); - REPORTER_ASSERT(reporter, compare_procs(proc32, proc4f)); - } -} diff --git a/tests/XfermodeTest.cpp b/tests/XfermodeTest.cpp deleted file mode 100644 index c3a4d96785..0000000000 --- a/tests/XfermodeTest.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkColor.h" -#include "SkXfermode.h" -#include "Test.h" - -#define ILLEGAL_MODE ((SkXfermode::Mode)-1) - -static void test_asMode(skiatest::Reporter* reporter) { - for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) { - auto xfer = SkXfermode::Make((SkXfermode::Mode) mode); - - SkXfermode::Mode reportedMode = ILLEGAL_MODE; - REPORTER_ASSERT(reporter, reportedMode != mode); - - // test IsMode - REPORTER_ASSERT(reporter, SkXfermode::AsMode(xfer, &reportedMode)); - REPORTER_ASSERT(reporter, reportedMode == mode); - - // repeat that test, but with asMode instead - if (xfer) { - reportedMode = (SkXfermode::Mode) -1; - REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode)); - REPORTER_ASSERT(reporter, reportedMode == mode); - } else { - REPORTER_ASSERT(reporter, SkXfermode::kSrcOver_Mode == mode); - } - } -} - -static void test_IsMode(skiatest::Reporter* reporter) { - REPORTER_ASSERT(reporter, SkXfermode::IsMode(nullptr, - SkXfermode::kSrcOver_Mode)); - - for (int i = 0; i <= SkXfermode::kLastMode; ++i) { - SkXfermode::Mode mode = (SkXfermode::Mode)i; - - auto xfer = SkXfermode::Make(mode); - REPORTER_ASSERT(reporter, SkXfermode::IsMode(xfer, mode)); - - if (SkXfermode::kSrcOver_Mode != mode) { - REPORTER_ASSERT(reporter, !SkXfermode::IsMode(nullptr, mode)); - } - } -} - -DEF_TEST(Xfermode, reporter) { - test_asMode(reporter); - test_IsMode(reporter); -}