blob: 0dbb6eb5346b98542fad49ed4d2567a946f4de6f [file] [log] [blame]
wangyix809e5af2015-09-09 12:58:32 -07001/*
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 "effects/GrConstColorProcessor.h"
egdaniel574a4c12015-11-02 06:22:44 -080012#include "gl/GrGLFragmentProcessor.h"
bsalomonae4738f2015-09-15 15:33:27 -070013#include "gl/GrGLSLBlend.h"
egdaniel2d721d32015-11-11 13:06:05 -080014#include "glsl/GrGLSLFragmentShaderBuilder.h"
15#include "glsl/GrGLSLProgramBuilder.h"
bsalomonf276ac52015-10-09 13:36:42 -070016#include "SkGrPriv.h"
wangyix809e5af2015-09-09 12:58:32 -070017
bsalomonae4738f2015-09-15 15:33:27 -070018class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -070019public:
bsalomonae4738f2015-09-15 15:33:27 -070020 ComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragmentProcessor* dst,
wangyix809e5af2015-09-09 12:58:32 -070021 SkXfermode::Mode mode)
22 : fMode(mode) {
bsalomonae4738f2015-09-15 15:33:27 -070023 this->initClassID<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -070024 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(src);
25 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(dst);
26 SkASSERT(0 == shaderAChildIndex);
27 SkASSERT(1 == shaderBChildIndex);
28 }
29
bsalomonae4738f2015-09-15 15:33:27 -070030 const char* name() const override { return "ComposeTwo"; }
wangyix809e5af2015-09-09 12:58:32 -070031
32 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
33 b->add32(fMode);
34 }
35
36 SkXfermode::Mode getMode() const { return fMode; }
37
38protected:
39 bool onIsEqual(const GrFragmentProcessor& other) const override {
bsalomonae4738f2015-09-15 15:33:27 -070040 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -070041 return fMode == cs.fMode;
42 }
43
44 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
45 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
46 }
47
48private:
49 GrGLFragmentProcessor* onCreateGLInstance() const override;
50
51 SkXfermode::Mode fMode;
52
53 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
54
55 typedef GrFragmentProcessor INHERITED;
56};
57
58/////////////////////////////////////////////////////////////////////
59
bsalomonae4738f2015-09-15 15:33:27 -070060class GLComposeTwoFragmentProcessor : public GrGLFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -070061public:
bsalomonae4738f2015-09-15 15:33:27 -070062 GLComposeTwoFragmentProcessor(const GrProcessor& processor) {}
wangyix809e5af2015-09-09 12:58:32 -070063
64 void emitCode(EmitArgs&) override;
65
66private:
67 typedef GrGLFragmentProcessor INHERITED;
68};
69
70/////////////////////////////////////////////////////////////////////
71
bsalomonae4738f2015-09-15 15:33:27 -070072GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -070073
bsalomonae4738f2015-09-15 15:33:27 -070074const GrFragmentProcessor* ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
wangyix809e5af2015-09-09 12:58:32 -070075 // Create two random frag procs.
bsalomon506c8022015-09-14 13:16:26 -070076 SkAutoTUnref<const GrFragmentProcessor> fpA(GrProcessorUnitTest::CreateChildFP(d));
77 SkAutoTUnref<const GrFragmentProcessor> fpB(GrProcessorUnitTest::CreateChildFP(d));
wangyix809e5af2015-09-09 12:58:32 -070078
79 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
bsalomonae4738f2015-09-15 15:33:27 -070080 d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
81 return new ComposeTwoFragmentProcessor(fpA, fpB, mode);
wangyix809e5af2015-09-09 12:58:32 -070082}
83
bsalomonae4738f2015-09-15 15:33:27 -070084GrGLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLInstance() const{
85 return new GLComposeTwoFragmentProcessor(*this);
wangyix809e5af2015-09-09 12:58:32 -070086}
87
88/////////////////////////////////////////////////////////////////////
89
bsalomonae4738f2015-09-15 15:33:27 -070090void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
wangyix809e5af2015-09-09 12:58:32 -070091
egdaniel2d721d32015-11-11 13:06:05 -080092 GrGLSLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
bsalomonae4738f2015-09-15 15:33:27 -070093 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -070094
bsalomonf1b7a1d2015-09-28 06:26:28 -070095 const char* inputColor = nullptr;
bsalomonb5b60322015-09-14 12:26:33 -070096 if (args.fInputColor) {
bsalomonf1b7a1d2015-09-28 06:26:28 -070097 inputColor = "inputColor";
98 fsBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -070099 }
wangyix809e5af2015-09-09 12:58:32 -0700100
101 // declare outputColor and emit the code for each of the two children
bsalomon38ddbad2015-09-24 06:00:00 -0700102 SkString srcColor("src");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700103 this->emitChild(0, inputColor, &srcColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700104
bsalomon38ddbad2015-09-24 06:00:00 -0700105 SkString dstColor("dst");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700106 this->emitChild(1, inputColor, &dstColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700107
108 // emit blend code
109 SkXfermode::Mode mode = cs.getMode();
wangyix809e5af2015-09-09 12:58:32 -0700110 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700111 GrGLSLBlend::AppendMode(fsBuilder, srcColor.c_str(), dstColor.c_str(), args.fOutputColor, mode);
wangyix809e5af2015-09-09 12:58:32 -0700112
113 // re-multiply the output color by the input color's alpha
bsalomonf1b7a1d2015-09-28 06:26:28 -0700114 if (args.fInputColor) {
115 fsBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -0700116 }
wangyix809e5af2015-09-09 12:58:32 -0700117}
118
wangyix809e5af2015-09-09 12:58:32 -0700119const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors(
120 const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXfermode::Mode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700121 switch (mode) {
122 case SkXfermode::kClear_Mode:
bsalomonae4738f2015-09-15 15:33:27 -0700123 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
wangyix809e5af2015-09-09 12:58:32 -0700124 GrConstColorProcessor::kIgnore_InputMode);
wangyix809e5af2015-09-09 12:58:32 -0700125 case SkXfermode::kSrc_Mode:
wangyix809e5af2015-09-09 12:58:32 -0700126 return SkRef(src);
wangyix809e5af2015-09-09 12:58:32 -0700127 case SkXfermode::kDst_Mode:
wangyix809e5af2015-09-09 12:58:32 -0700128 return SkRef(dst);
wangyix809e5af2015-09-09 12:58:32 -0700129 default:
bsalomonae4738f2015-09-15 15:33:27 -0700130 return new ComposeTwoFragmentProcessor(src, dst, mode);
131 }
132}
133
134//////////////////////////////////////////////////////////////////////////////
135
136class ComposeOneFragmentProcessor : public GrFragmentProcessor {
137public:
138 enum Child {
139 kDst_Child,
140 kSrc_Child,
141 };
142
143 ComposeOneFragmentProcessor(const GrFragmentProcessor* dst, SkXfermode::Mode mode, Child child)
144 : fMode(mode)
145 , fChild(child) {
146 this->initClassID<ComposeOneFragmentProcessor>();
147 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst);
148 SkASSERT(0 == dstIndex);
149 }
150
151 const char* name() const override { return "ComposeOne"; }
152
153 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
154 GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLastMode);
155 b->add32(fMode | (fChild << 16));
156 }
157
158 SkXfermode::Mode mode() const { return fMode; }
159
160 Child child() const { return fChild; }
161
162protected:
163 bool onIsEqual(const GrFragmentProcessor& that) const override {
164 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
165 }
166
167 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
168 SkXfermode::Coeff skSrcCoeff, skDstCoeff;
169 if (SkXfermode::ModeAsCoeff(fMode, &skSrcCoeff, &skDstCoeff)) {
170 GrBlendCoeff srcCoeff = SkXfermodeCoeffToGrBlendCoeff(skSrcCoeff);
171 GrBlendCoeff dstCoeff = SkXfermodeCoeffToGrBlendCoeff(skDstCoeff);
172 GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlags, false);
173 this->childProcessor(0).computeInvariantOutput(&childOutput);
174 GrColor blendColor;
175 GrColorComponentFlags blendFlags;
176 if (kDst_Child == fChild) {
177 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
178 inout->color(), inout->validFlags(),
179 childOutput.color(), childOutput.validFlags(),
180 &blendColor, &blendFlags);
181 } else {
182 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
183 childOutput.color(), childOutput.validFlags(),
184 inout->color(), inout->validFlags(),
185 &blendColor, &blendFlags);
186 }
187 // will the shader code reference the input color?
188 GrInvariantOutput::ReadInput readsInput = GrInvariantOutput::kWillNot_ReadInput;
189 if (kDst_Child == fChild) {
190 if (kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff)) {
191 readsInput = GrInvariantOutput::kWill_ReadInput;
192 }
193 } else {
194 if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoeff)) {
195 readsInput = GrInvariantOutput::kWill_ReadInput;
196 }
197 }
198 inout->setToOther(blendFlags, blendColor, readsInput);
199 } else {
200 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
201 }
202 }
203
204private:
205 GrGLFragmentProcessor* onCreateGLInstance() const override;
206
207 SkXfermode::Mode fMode;
208 Child fChild;
209
210 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
211
212 typedef GrFragmentProcessor INHERITED;
213};
214
215//////////////////////////////////////////////////////////////////////////////
216
217class GLComposeOneFragmentProcessor : public GrGLFragmentProcessor {
218public:
219 GLComposeOneFragmentProcessor(const GrProcessor& processor) {}
220
221 void emitCode(EmitArgs& args) override {
egdaniel2d721d32015-11-11 13:06:05 -0800222 GrGLSLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
bsalomonae4738f2015-09-15 15:33:27 -0700223 SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
224 ComposeOneFragmentProcessor::Child child =
225 args.fFp.cast<ComposeOneFragmentProcessor>().child();
bsalomon38ddbad2015-09-24 06:00:00 -0700226 SkString childColor("child");
227 this->emitChild(0, nullptr, &childColor, args);
bsalomonae4738f2015-09-15 15:33:27 -0700228
229 const char* inputColor = args.fInputColor;
230 // We don't try to optimize for this case at all
231 if (!inputColor) {
232 fsBuilder->codeAppendf("const vec4 ones = vec4(1);");
233 inputColor = "ones";
234 }
235
236 // emit blend code
bsalomonae4738f2015-09-15 15:33:27 -0700237 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700238 const char* childStr = childColor.c_str();
bsalomonae4738f2015-09-15 15:33:27 -0700239 if (ComposeOneFragmentProcessor::kDst_Child == child) {
bsalomon38ddbad2015-09-24 06:00:00 -0700240 GrGLSLBlend::AppendMode(fsBuilder, inputColor, childStr, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700241 } else {
bsalomon38ddbad2015-09-24 06:00:00 -0700242 GrGLSLBlend::AppendMode(fsBuilder, childStr, inputColor, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700243 }
bsalomonae4738f2015-09-15 15:33:27 -0700244 }
245
246private:
247 typedef GrGLFragmentProcessor INHERITED;
248};
249
250/////////////////////////////////////////////////////////////////////
251
252GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
253
254const GrFragmentProcessor* ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
255 // Create one random frag procs.
256 // For now, we'll prevent either children from being a shader with children to prevent the
257 // possibility of an arbitrarily large tree of procs.
258 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d));
259 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
260 d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
261 ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ?
262 ComposeOneFragmentProcessor::kDst_Child :
263 ComposeOneFragmentProcessor::kSrc_Child;
264 return new ComposeOneFragmentProcessor(dst, mode, child);
265}
266
267GrGLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLInstance() const {
268 return new GLComposeOneFragmentProcessor(*this);
269}
270
271//////////////////////////////////////////////////////////////////////////////
272
273const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromDstProcessor(
274 const GrFragmentProcessor* dst, SkXfermode::Mode mode) {
275 switch (mode) {
276 case SkXfermode::kClear_Mode:
277 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
278 GrConstColorProcessor::kIgnore_InputMode);
279 case SkXfermode::kSrc_Mode:
280 return nullptr;
281 default:
282 return new ComposeOneFragmentProcessor(dst, mode,
283 ComposeOneFragmentProcessor::kDst_Child);
284 }
285}
286
287const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromSrcProcessor(
288 const GrFragmentProcessor* src, SkXfermode::Mode mode) {
289 switch (mode) {
290 case SkXfermode::kClear_Mode:
291 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
292 GrConstColorProcessor::kIgnore_InputMode);
293 case SkXfermode::kDst_Mode:
294 return nullptr;
295 default:
296 return new ComposeOneFragmentProcessor(src, mode,
297 ComposeOneFragmentProcessor::kSrc_Child);
wangyix809e5af2015-09-09 12:58:32 -0700298 }
299}