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 #endif
24
25 ///////////////////////////////////////////////////////////////////////////////////////////////////
26
27 class SkProcCoeffXfermode : public SkXfermode {
28 public:
SkProcCoeffXfermode(SkBlendMode mode)29 SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
30
xfer32(SkPMColor dst[],const SkPMColor src[],int count,const SkAlpha aa[]) const31 void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
32 const SkAlpha aa[]) const override {
33 SkASSERT(dst && src && count >= 0);
34
35 SkRasterPipeline_<256> p;
36
37 SkRasterPipeline_MemoryCtx dst_ctx = { (void*)dst, 0 },
38 src_ctx = { (void*)src, 0 },
39 aa_ctx = { (void*)aa, 0 };
40
41 p.append_load (kN32_SkColorType, &src_ctx);
42 p.append_load_dst(kN32_SkColorType, &dst_ctx);
43
44 if (SkBlendMode_ShouldPreScaleCoverage(fMode, /*rgb_coverage=*/false)) {
45 if (aa) {
46 p.append(SkRasterPipeline::scale_u8, &aa_ctx);
47 }
48 SkBlendMode_AppendStages(fMode, &p);
49 } else {
50 SkBlendMode_AppendStages(fMode, &p);
51 if (aa) {
52 p.append(SkRasterPipeline::lerp_u8, &aa_ctx);
53 }
54 }
55
56 p.append_store(kN32_SkColorType, &dst_ctx);
57 p.run(0, 0, count,1);
58 }
59
60 private:
61 const SkBlendMode fMode;
62
63 using INHERITED = SkXfermode;
64 };
65
SkBlendMode_Name(SkBlendMode bm)66 const char* SkBlendMode_Name(SkBlendMode bm) {
67 switch (bm) {
68 case SkBlendMode::kClear: return "Clear";
69 case SkBlendMode::kSrc: return "Src";
70 case SkBlendMode::kDst: return "Dst";
71 case SkBlendMode::kSrcOver: return "SrcOver";
72 case SkBlendMode::kDstOver: return "DstOver";
73 case SkBlendMode::kSrcIn: return "SrcIn";
74 case SkBlendMode::kDstIn: return "DstIn";
75 case SkBlendMode::kSrcOut: return "SrcOut";
76 case SkBlendMode::kDstOut: return "DstOut";
77 case SkBlendMode::kSrcATop: return "SrcATop";
78 case SkBlendMode::kDstATop: return "DstATop";
79 case SkBlendMode::kXor: return "Xor";
80 case SkBlendMode::kPlus: return "Plus";
81 case SkBlendMode::kModulate: return "Modulate";
82 case SkBlendMode::kScreen: return "Screen";
83
84 case SkBlendMode::kOverlay: return "Overlay";
85 case SkBlendMode::kDarken: return "Darken";
86 case SkBlendMode::kLighten: return "Lighten";
87 case SkBlendMode::kColorDodge: return "ColorDodge";
88 case SkBlendMode::kColorBurn: return "ColorBurn";
89 case SkBlendMode::kHardLight: return "HardLight";
90 case SkBlendMode::kSoftLight: return "SoftLight";
91 case SkBlendMode::kDifference: return "Difference";
92 case SkBlendMode::kExclusion: return "Exclusion";
93 case SkBlendMode::kMultiply: return "Multiply";
94
95 case SkBlendMode::kHue: return "Hue";
96 case SkBlendMode::kSaturation: return "Saturation";
97 case SkBlendMode::kColor: return "Color";
98 case SkBlendMode::kLuminosity: return "Luminosity";
99 }
100 SkUNREACHABLE;
101 }
102
Make(SkBlendMode mode)103 sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
104 if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) {
105 // report error
106 return nullptr;
107 }
108
109 // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
110 // so we can just return nullptr from the factory.
111 if (SkBlendMode::kSrcOver == mode) {
112 return nullptr;
113 }
114
115 const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
116
117 static SkOnce once[COUNT_BLENDMODES];
118 static SkXfermode* cached[COUNT_BLENDMODES];
119
120 once[(int)mode]([mode] {
121 if (auto xfermode = SkOpts::create_xfermode(mode)) {
122 cached[(int)mode] = xfermode;
123 } else {
124 cached[(int)mode] = new SkProcCoeffXfermode(mode);
125 }
126 });
127 return sk_ref_sp(cached[(int)mode]);
128 }
129
130 ///////////////////////////////////////////////////////////////////////////////////////////////////
131
IsOpaque(SkBlendMode mode,SrcColorOpacity opacityType)132 bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
133 SkBlendModeCoeff src, dst;
134 if (!SkBlendMode_AsCoeff(mode, &src, &dst)) {
135 return false;
136 }
137
138 switch (src) {
139 case SkBlendModeCoeff::kDA:
140 case SkBlendModeCoeff::kDC:
141 case SkBlendModeCoeff::kIDA:
142 case SkBlendModeCoeff::kIDC:
143 return false;
144 default:
145 break;
146 }
147
148 switch (dst) {
149 case SkBlendModeCoeff::kZero:
150 return true;
151 case SkBlendModeCoeff::kISA:
152 return kOpaque_SrcColorOpacity == opacityType;
153 case SkBlendModeCoeff::kSA:
154 return kTransparentBlack_SrcColorOpacity == opacityType ||
155 kTransparentAlpha_SrcColorOpacity == opacityType;
156 case SkBlendModeCoeff::kSC:
157 return kTransparentBlack_SrcColorOpacity == opacityType;
158 default:
159 return false;
160 }
161 return false;
162 }
163
164 #if SK_SUPPORT_GPU
SkBlendMode_AsXPFactory(SkBlendMode mode)165 const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
166 if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) {
167 const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
168 SkASSERT(result);
169 return result;
170 }
171
172 SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
173 return GrCustomXfermode::Get(mode);
174 }
175 #endif
176