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