• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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