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/base/SkOnce.h"
11 #include "src/base/SkMathPriv.h"
12 #include "src/core/SkBlendModePriv.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 defined(SK_GANESH)
20 #include "src/gpu/ganesh/GrFragmentProcessor.h"
21 #include "src/gpu/ganesh/effects/GrCustomXfermode.h"
22 #include "src/gpu/ganesh/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(SkRasterPipelineOp::scale_u8, &aa_ctx);
47 }
48 SkBlendMode_AppendStages(fMode, &p);
49 } else {
50 SkBlendMode_AppendStages(fMode, &p);
51 if (aa) {
52 p.append(SkRasterPipelineOp::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 static SkOnce once[kSkBlendModeCount];
116 static SkXfermode* cached[kSkBlendModeCount];
117
118 once[(int)mode]([mode] {
119 if (auto xfermode = SkOpts::create_xfermode(mode)) {
120 cached[(int)mode] = xfermode;
121 } else {
122 cached[(int)mode] = new SkProcCoeffXfermode(mode);
123 }
124 });
125 return sk_ref_sp(cached[(int)mode]);
126 }
127
128 ///////////////////////////////////////////////////////////////////////////////////////////////////
129
IsOpaque(SkBlendMode mode,SrcColorOpacity opacityType)130 bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
131 SkBlendModeCoeff src, dst;
132 if (!SkBlendMode_AsCoeff(mode, &src, &dst)) {
133 return false;
134 }
135
136 switch (src) {
137 case SkBlendModeCoeff::kDA:
138 case SkBlendModeCoeff::kDC:
139 case SkBlendModeCoeff::kIDA:
140 case SkBlendModeCoeff::kIDC:
141 return false;
142 default:
143 break;
144 }
145
146 switch (dst) {
147 case SkBlendModeCoeff::kZero:
148 return true;
149 case SkBlendModeCoeff::kISA:
150 return kOpaque_SrcColorOpacity == opacityType;
151 case SkBlendModeCoeff::kSA:
152 return kTransparentBlack_SrcColorOpacity == opacityType ||
153 kTransparentAlpha_SrcColorOpacity == opacityType;
154 case SkBlendModeCoeff::kSC:
155 return kTransparentBlack_SrcColorOpacity == opacityType;
156 default:
157 return false;
158 }
159 }
160
161 #if defined(SK_GANESH)
SkBlendMode_AsXPFactory(SkBlendMode mode)162 const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
163 if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) {
164 const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
165 SkASSERT(result);
166 return result;
167 }
168
169 SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
170 return GrCustomXfermode::Get(mode);
171 }
172 #endif
173