935747bccdcdb171a4417bd6b7cbf4073175913e
[platform/upstream/libSkiaSharp.git] / src / gpu / effects / GrXfermodeFragmentProcessor.cpp
1 /*
2 * Copyright 2015 Google Inc.
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 "effects/GrXfermodeFragmentProcessor.h"
9
10 #include "GrFragmentProcessor.h"
11 #include "GrInvariantOutput.h"
12 #include "effects/GrConstColorProcessor.h"
13 #include "glsl/GrGLSLFragmentProcessor.h"
14 #include "glsl/GrGLSLBlend.h"
15 #include "glsl/GrGLSLFragmentShaderBuilder.h"
16 #include "SkGrPriv.h"
17
18 class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
19 public:
20     ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst,
21                                 SkXfermode::Mode mode)
22         : fMode(mode) {
23         this->initClassID<ComposeTwoFragmentProcessor>();
24         SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
25         SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
26         SkASSERT(0 == shaderAChildIndex);
27         SkASSERT(1 == shaderBChildIndex);
28     }
29
30     const char* name() const override { return "ComposeTwo"; }
31
32     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
33         b->add32(fMode);
34     }
35
36     SkXfermode::Mode getMode() const { return fMode; }
37
38 protected:
39     bool onIsEqual(const GrFragmentProcessor& other) const override {
40         const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
41         return fMode == cs.fMode;
42     }
43
44     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
45         inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
46     }
47
48 private:
49     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
50
51     SkXfermode::Mode fMode;
52
53     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
54
55     typedef GrFragmentProcessor INHERITED;
56 };
57
58 /////////////////////////////////////////////////////////////////////
59
60 class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
61 public:
62     void emitCode(EmitArgs&) override;
63
64 private:
65     typedef GrGLSLFragmentProcessor INHERITED;
66 };
67
68 /////////////////////////////////////////////////////////////////////
69
70 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
71
72 sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
73     // Create two random frag procs.
74     sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
75     sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
76
77     SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
78         d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
79     return sk_sp<GrFragmentProcessor>(
80         new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
81 }
82
83 GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
84     return new GLComposeTwoFragmentProcessor;
85 }
86
87 /////////////////////////////////////////////////////////////////////
88
89 void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
90
91     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
92     const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
93
94     const char* inputColor = nullptr;
95     if (args.fInputColor) {
96         inputColor = "inputColor";
97         fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
98     }
99
100     // declare outputColor and emit the code for each of the two children
101     SkString srcColor("xfer_src");
102     this->emitChild(0, inputColor, &srcColor, args);
103
104     SkString dstColor("xfer_dst");
105     this->emitChild(1, inputColor, &dstColor, args);
106
107     // emit blend code
108     SkXfermode::Mode mode = cs.getMode();
109     fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
110     GrGLSLBlend::AppendMode(fragBuilder,
111                             srcColor.c_str(),
112                             dstColor.c_str(),
113                             args.fOutputColor,
114                             mode);
115
116     // re-multiply the output color by the input color's alpha
117     if (args.fInputColor) {
118         fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
119     }
120 }
121
122 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
123          sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
124     switch (mode) {
125         case SkXfermode::kClear_Mode:
126             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
127                                                GrConstColorProcessor::kIgnore_InputMode);
128         case SkXfermode::kSrc_Mode:
129             return src;
130         case SkXfermode::kDst_Mode:
131             return dst;
132         default:
133             return sk_sp<GrFragmentProcessor>(
134                 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), mode));
135     }
136 }
137
138 //////////////////////////////////////////////////////////////////////////////
139
140 class ComposeOneFragmentProcessor : public GrFragmentProcessor {
141 public:
142     enum Child {
143         kDst_Child,
144         kSrc_Child,
145     };
146
147     ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode, Child child)
148         : fMode(mode)
149         , fChild(child) {
150         this->initClassID<ComposeOneFragmentProcessor>();
151         SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(std::move(dst));
152         SkASSERT(0 == dstIndex);
153     }
154
155     const char* name() const override { return "ComposeOne"; }
156
157     SkString dumpInfo() const override {
158         SkString str;
159
160         for (int i = 0; i < this->numChildProcessors(); ++i) {
161             str.append(this->childProcessor(i).dumpInfo());
162         }
163         return str;
164     }
165
166     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
167         GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLastMode);
168         b->add32(fMode | (fChild << 16));
169     }
170
171     SkXfermode::Mode mode() const { return fMode; }
172
173     Child child() const { return fChild; }
174
175 protected:
176     bool onIsEqual(const GrFragmentProcessor& that) const override {
177         return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
178     }
179
180     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
181         SkXfermode::Coeff skSrcCoeff, skDstCoeff;
182         if (SkXfermode::ModeAsCoeff(fMode, &skSrcCoeff, &skDstCoeff)) {
183             GrBlendCoeff srcCoeff = SkXfermodeCoeffToGrBlendCoeff(skSrcCoeff);
184             GrBlendCoeff dstCoeff = SkXfermodeCoeffToGrBlendCoeff(skDstCoeff);
185             GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlags, false);
186             this->childProcessor(0).computeInvariantOutput(&childOutput);
187             GrColor blendColor;
188             GrColorComponentFlags blendFlags;
189             if (kDst_Child == fChild) {
190                 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
191                                                inout->color(), inout->validFlags(),
192                                                childOutput.color(), childOutput.validFlags(),
193                                                &blendColor, &blendFlags);
194             } else {
195                 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
196                                                childOutput.color(), childOutput.validFlags(),
197                                                inout->color(), inout->validFlags(),
198                                                &blendColor, &blendFlags);
199             }
200             // will the shader code reference the input color?
201             GrInvariantOutput::ReadInput readsInput = GrInvariantOutput::kWillNot_ReadInput;
202             if (kDst_Child == fChild) {
203                 if (kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff)) {
204                     readsInput = GrInvariantOutput::kWill_ReadInput;
205                 }
206             } else {
207                 if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoeff)) {
208                     readsInput = GrInvariantOutput::kWill_ReadInput;
209                 }
210             }
211             inout->setToOther(blendFlags, blendColor, readsInput);
212         } else {
213             inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
214         }
215     }
216
217 private:
218     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
219
220     SkXfermode::Mode    fMode;
221     Child               fChild;
222
223     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
224
225     typedef GrFragmentProcessor INHERITED;
226 };
227
228 //////////////////////////////////////////////////////////////////////////////
229
230 class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
231 public:
232     void emitCode(EmitArgs& args) override {
233         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
234         SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
235         ComposeOneFragmentProcessor::Child child =
236             args.fFp.cast<ComposeOneFragmentProcessor>().child();
237         SkString childColor("child");
238         this->emitChild(0, nullptr, &childColor, args);
239
240         const char* inputColor = args.fInputColor;
241         // We don't try to optimize for this case at all
242         if (!inputColor) {
243             fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
244             inputColor = "ones";
245         }
246
247         // emit blend code
248         fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
249         const char* childStr = childColor.c_str();
250         if (ComposeOneFragmentProcessor::kDst_Child == child) {
251             GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
252         } else {
253             GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
254         }
255     }
256
257 private:
258     typedef GrGLSLFragmentProcessor INHERITED;
259 };
260
261 /////////////////////////////////////////////////////////////////////
262
263 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
264
265 sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
266     // Create one random frag procs.
267     // For now, we'll prevent either children from being a shader with children to prevent the
268     // possibility of an arbitrarily large tree of procs.
269     sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
270     SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
271         d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
272     ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ?
273         ComposeOneFragmentProcessor::kDst_Child :
274         ComposeOneFragmentProcessor::kSrc_Child;
275     return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
276 }
277
278 GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
279     return new GLComposeOneFragmentProcessor;
280 }
281
282 //////////////////////////////////////////////////////////////////////////////
283
284 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
285     sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
286     switch (mode) {
287         case SkXfermode::kClear_Mode:
288             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
289                                                  GrConstColorProcessor::kIgnore_InputMode);
290         case SkXfermode::kSrc_Mode:
291             return nullptr;
292         default:
293             return sk_sp<GrFragmentProcessor>(
294                 new ComposeOneFragmentProcessor(std::move(dst), mode,
295                                                 ComposeOneFragmentProcessor::kDst_Child));
296     }
297 }
298
299 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
300     sk_sp<GrFragmentProcessor> src, SkXfermode::Mode mode) {
301     switch (mode) {
302         case SkXfermode::kClear_Mode:
303             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
304                                                  GrConstColorProcessor::kIgnore_InputMode);
305         case SkXfermode::kDst_Mode:
306             return nullptr;
307         default:
308             return sk_sp<GrFragmentProcessor>(
309                 new ComposeOneFragmentProcessor(src, mode,
310                                                 ComposeOneFragmentProcessor::kSrc_Child));
311     }
312 }