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 | #include "src/gpu/effects/GrXfermodeFragmentProcessor.h" |
24 | #endif |
25 | |
26 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
27 | |
28 | class SkProcCoeffXfermode : public SkXfermode { |
29 | public: |
30 | SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {} |
31 | |
32 | void xfer32(SkPMColor dst[], const SkPMColor src[], int count, |
33 | const SkAlpha aa[]) const override { |
34 | SkASSERT(dst && src && count >= 0); |
35 | |
36 | SkRasterPipeline_<256> p; |
37 | |
38 | SkRasterPipeline_MemoryCtx dst_ctx = { (void*)dst, 0 }, |
39 | src_ctx = { (void*)src, 0 }, |
40 | aa_ctx = { (void*)aa, 0 }; |
41 | |
42 | p.append_load (kN32_SkColorType, &src_ctx); |
43 | p.append_load_dst(kN32_SkColorType, &dst_ctx); |
44 | |
45 | if (SkBlendMode_ShouldPreScaleCoverage(fMode, /*rgb_coverage=*/false)) { |
46 | if (aa) { |
47 | p.append(SkRasterPipeline::scale_u8, &aa_ctx); |
48 | } |
49 | SkBlendMode_AppendStages(fMode, &p); |
50 | } else { |
51 | SkBlendMode_AppendStages(fMode, &p); |
52 | if (aa) { |
53 | p.append(SkRasterPipeline::lerp_u8, &aa_ctx); |
54 | } |
55 | } |
56 | |
57 | p.append_store(kN32_SkColorType, &dst_ctx); |
58 | p.run(0, 0, count,1); |
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 | |