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 "SkColorPriv.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 20 #if SK_SUPPORT_GPU 21 #include "GrFragmentProcessor.h" 22 #include "effects/GrCustomXfermode.h" 23 #include "effects/GrPorterDuffXferProcessor.h" 24 #include "effects/GrXfermodeFragmentProcessor.h" 25 #endif 26 27 /////////////////////////////////////////////////////////////////////////////////////////////////// 28 29 class SkProcCoeffXfermode : public SkXfermode { 30 public: 31 SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {} 32 33 void xfer32(SkPMColor dst[], const SkPMColor src[], int count, 34 const SkAlpha aa[]) const override { 35 SkASSERT(dst && src && count >= 0); 36 37 SkRasterPipeline_<256> p; 38 39 if (kN32_SkColorType == kBGRA_8888_SkColorType) { 40 p.append(SkRasterPipeline::load_bgra_dst, &dst); 41 p.append(SkRasterPipeline::load_bgra , &src); 42 } else { 43 p.append(SkRasterPipeline::load_8888_dst, &dst); 44 p.append(SkRasterPipeline::load_8888, &src); 45 } 46 47 SkBlendMode_AppendStagesNoClamp(fMode, &p); 48 if (aa) { 49 p.append(SkRasterPipeline::lerp_u8, &aa); 50 } 51 SkBlendMode_AppendClampIfNeeded(fMode, &p); 52 53 if (kN32_SkColorType == kBGRA_8888_SkColorType) { 54 p.append(SkRasterPipeline::store_bgra, &dst); 55 } else { 56 p.append(SkRasterPipeline::store_8888, &dst); 57 } 58 p.run(0, 0, count); 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