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
28class SkProcCoeffXfermode : public SkXfermode {
29public:
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
61private:
62 const SkBlendMode fMode;
63
64 typedef SkXfermode INHERITED;
65};
66
67const 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
80sk_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
109bool 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
142const 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