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