| 1 | /* | 
|---|
| 2 | * Copyright 2006 The Android Open Source Project | 
|---|
| 3 | * | 
|---|
| 4 | * Use of this source code is governed by a BSD-style license that can be | 
|---|
| 5 | * found in the LICENSE file. | 
|---|
| 6 | */ | 
|---|
| 7 |  | 
|---|
| 8 | #include "include/core/SkString.h" | 
|---|
| 9 | #include "include/private/SkColorData.h" | 
|---|
| 10 | #include "include/private/SkOnce.h" | 
|---|
| 11 | #include "src/core/SkBlendModePriv.h" | 
|---|
| 12 | #include "src/core/SkMathPriv.h" | 
|---|
| 13 | #include "src/core/SkOpts.h" | 
|---|
| 14 | #include "src/core/SkRasterPipeline.h" | 
|---|
| 15 | #include "src/core/SkReadBuffer.h" | 
|---|
| 16 | #include "src/core/SkWriteBuffer.h" | 
|---|
| 17 | #include "src/core/SkXfermodePriv.h" | 
|---|
| 18 |  | 
|---|
| 19 | #if SK_SUPPORT_GPU | 
|---|
| 20 | #include "src/gpu/GrFragmentProcessor.h" | 
|---|
| 21 | #include "src/gpu/effects/GrCustomXfermode.h" | 
|---|
| 22 | #include "src/gpu/effects/GrPorterDuffXferProcessor.h" | 
|---|
| 23 | #include "src/gpu/effects/GrXfermodeFragmentProcessor.h" | 
|---|
| 24 | #endif | 
|---|
| 25 |  | 
|---|
| 26 | /////////////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 27 |  | 
|---|
| 28 | class SkProcCoeffXfermode : public SkXfermode { | 
|---|
| 29 | public: | 
|---|
| 30 | SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {} | 
|---|
| 31 |  | 
|---|
| 32 | void xfer32(SkPMColor dst[], const SkPMColor src[], int count, | 
|---|
| 33 | const SkAlpha aa[]) const override { | 
|---|
| 34 | SkASSERT(dst && src && count >= 0); | 
|---|
| 35 |  | 
|---|
| 36 | SkRasterPipeline_<256> p; | 
|---|
| 37 |  | 
|---|
| 38 | SkRasterPipeline_MemoryCtx dst_ctx = { (void*)dst, 0 }, | 
|---|
| 39 | src_ctx = { (void*)src, 0 }, | 
|---|
| 40 | aa_ctx = { (void*)aa,  0 }; | 
|---|
| 41 |  | 
|---|
| 42 | p.append_load    (kN32_SkColorType, &src_ctx); | 
|---|
| 43 | p.append_load_dst(kN32_SkColorType, &dst_ctx); | 
|---|
| 44 |  | 
|---|
| 45 | if (SkBlendMode_ShouldPreScaleCoverage(fMode, /*rgb_coverage=*/false)) { | 
|---|
| 46 | if (aa) { | 
|---|
| 47 | p.append(SkRasterPipeline::scale_u8, &aa_ctx); | 
|---|
| 48 | } | 
|---|
| 49 | SkBlendMode_AppendStages(fMode, &p); | 
|---|
| 50 | } else { | 
|---|
| 51 | SkBlendMode_AppendStages(fMode, &p); | 
|---|
| 52 | if (aa) { | 
|---|
| 53 | p.append(SkRasterPipeline::lerp_u8, &aa_ctx); | 
|---|
| 54 | } | 
|---|
| 55 | } | 
|---|
| 56 |  | 
|---|
| 57 | p.append_store(kN32_SkColorType, &dst_ctx); | 
|---|
| 58 | p.run(0, 0, count,1); | 
|---|
| 59 | } | 
|---|
| 60 |  | 
|---|
| 61 | private: | 
|---|
| 62 | const SkBlendMode fMode; | 
|---|
| 63 |  | 
|---|
| 64 | typedef SkXfermode INHERITED; | 
|---|
| 65 | }; | 
|---|
| 66 |  | 
|---|
| 67 | const char* SkBlendMode_Name(SkBlendMode mode) { | 
|---|
| 68 | SkASSERT((unsigned) mode <= (unsigned)SkBlendMode::kLastMode); | 
|---|
| 69 | const char* gModeStrings[] = { | 
|---|
| 70 | "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", | 
|---|
| 71 | "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", | 
|---|
| 72 | "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", | 
|---|
| 73 | "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", | 
|---|
| 74 | "Multiply", "Hue", "Saturation", "Color", "Luminosity" | 
|---|
| 75 | }; | 
|---|
| 76 | return gModeStrings[(int)mode]; | 
|---|
| 77 | static_assert(SK_ARRAY_COUNT(gModeStrings) == (size_t)SkBlendMode::kLastMode + 1, "mode_count"); | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) { | 
|---|
| 81 | if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) { | 
|---|
| 82 | // report error | 
|---|
| 83 | return nullptr; | 
|---|
| 84 | } | 
|---|
| 85 |  | 
|---|
| 86 | // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover | 
|---|
| 87 | // so we can just return nullptr from the factory. | 
|---|
| 88 | if (SkBlendMode::kSrcOver == mode) { | 
|---|
| 89 | return nullptr; | 
|---|
| 90 | } | 
|---|
| 91 |  | 
|---|
| 92 | const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1; | 
|---|
| 93 |  | 
|---|
| 94 | static SkOnce        once[COUNT_BLENDMODES]; | 
|---|
| 95 | static SkXfermode* cached[COUNT_BLENDMODES]; | 
|---|
| 96 |  | 
|---|
| 97 | once[(int)mode]([mode] { | 
|---|
| 98 | if (auto xfermode = SkOpts::create_xfermode(mode)) { | 
|---|
| 99 | cached[(int)mode] = xfermode; | 
|---|
| 100 | } else { | 
|---|
| 101 | cached[(int)mode] = new SkProcCoeffXfermode(mode); | 
|---|
| 102 | } | 
|---|
| 103 | }); | 
|---|
| 104 | return sk_ref_sp(cached[(int)mode]); | 
|---|
| 105 | } | 
|---|
| 106 |  | 
|---|
| 107 | /////////////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 108 |  | 
|---|
| 109 | bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) { | 
|---|
| 110 | SkBlendModeCoeff src, dst; | 
|---|
| 111 | if (!SkBlendMode_AsCoeff(mode, &src, &dst)) { | 
|---|
| 112 | return false; | 
|---|
| 113 | } | 
|---|
| 114 |  | 
|---|
| 115 | switch (src) { | 
|---|
| 116 | case SkBlendModeCoeff::kDA: | 
|---|
| 117 | case SkBlendModeCoeff::kDC: | 
|---|
| 118 | case SkBlendModeCoeff::kIDA: | 
|---|
| 119 | case SkBlendModeCoeff::kIDC: | 
|---|
| 120 | return false; | 
|---|
| 121 | default: | 
|---|
| 122 | break; | 
|---|
| 123 | } | 
|---|
| 124 |  | 
|---|
| 125 | switch (dst) { | 
|---|
| 126 | case SkBlendModeCoeff::kZero: | 
|---|
| 127 | return true; | 
|---|
| 128 | case SkBlendModeCoeff::kISA: | 
|---|
| 129 | return kOpaque_SrcColorOpacity == opacityType; | 
|---|
| 130 | case SkBlendModeCoeff::kSA: | 
|---|
| 131 | return kTransparentBlack_SrcColorOpacity == opacityType || | 
|---|
| 132 | kTransparentAlpha_SrcColorOpacity == opacityType; | 
|---|
| 133 | case SkBlendModeCoeff::kSC: | 
|---|
| 134 | return kTransparentBlack_SrcColorOpacity == opacityType; | 
|---|
| 135 | default: | 
|---|
| 136 | return false; | 
|---|
| 137 | } | 
|---|
| 138 | return false; | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | #if SK_SUPPORT_GPU | 
|---|
| 142 | const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) { | 
|---|
| 143 | if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) { | 
|---|
| 144 | const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode); | 
|---|
| 145 | SkASSERT(result); | 
|---|
| 146 | return result; | 
|---|
| 147 | } | 
|---|
| 148 |  | 
|---|
| 149 | SkASSERT(GrCustomXfermode::IsSupportedMode(mode)); | 
|---|
| 150 | return GrCustomXfermode::Get(mode); | 
|---|
| 151 | } | 
|---|
| 152 | #endif | 
|---|
| 153 |  | 
|---|
| 154 |  | 
|---|