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:
SkProcCoeffXfermode(SkBlendMode mode)31 SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
32
xfer32(SkPMColor dst[],const SkPMColor src[],int count,const SkAlpha aa[]) const33 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
SkBlendMode_Name(SkBlendMode mode)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
Make(SkBlendMode mode)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
IsOpaque(SkBlendMode mode,SrcColorOpacity opacityType)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
SkBlendMode_AsXPFactory(SkBlendMode mode)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