OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "effects/GrXfermodeFragmentProcessor.h" | 8 #include "effects/GrXfermodeFragmentProcessor.h" |
9 | 9 |
10 #include "GrFragmentProcessor.h" | 10 #include "GrFragmentProcessor.h" |
11 #include "effects/GrConstColorProcessor.h" | 11 #include "effects/GrConstColorProcessor.h" |
12 #include "gl/GrGLBlend.h" | 12 #include "gl/GrGLSLBlend.h" |
13 #include "gl/builders/GrGLProgramBuilder.h" | 13 #include "gl/builders/GrGLProgramBuilder.h" |
14 #include "SkGr.h" | |
14 | 15 |
15 | 16 class ComposeTwoFragmentProcessor : public GrFragmentProcessor { |
16 class GrComposeTwoFragmentProcessor : public GrFragmentProcessor { | |
17 public: | 17 public: |
18 GrComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragme ntProcessor* dst, | 18 ComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragment Processor* dst, |
19 SkXfermode::Mode mode) | 19 SkXfermode::Mode mode) |
20 : fMode(mode) { | 20 : fMode(mode) { |
21 // Only coefficient xfer modes are supported | 21 this->initClassID<ComposeTwoFragmentProcessor>(); |
22 SkASSERT(SkXfermode::kLastCoeffMode >= mode); | |
23 this->initClassID<GrComposeTwoFragmentProcessor>(); | |
24 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(src); | 22 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(src); |
25 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(dst); | 23 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(dst); |
26 SkASSERT(0 == shaderAChildIndex); | 24 SkASSERT(0 == shaderAChildIndex); |
27 SkASSERT(1 == shaderBChildIndex); | 25 SkASSERT(1 == shaderBChildIndex); |
28 } | 26 } |
29 | 27 |
30 const char* name() const override { return "ComposeShader"; } | 28 const char* name() const override { return "ComposeTwo"; } |
31 | 29 |
32 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override { | 30 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override { |
33 b->add32(fMode); | 31 b->add32(fMode); |
34 } | 32 } |
35 | 33 |
36 SkXfermode::Mode getMode() const { return fMode; } | 34 SkXfermode::Mode getMode() const { return fMode; } |
37 | 35 |
38 protected: | 36 protected: |
39 bool onIsEqual(const GrFragmentProcessor& other) const override { | 37 bool onIsEqual(const GrFragmentProcessor& other) const override { |
40 const GrComposeTwoFragmentProcessor& cs = other.cast<GrComposeTwoFragmen tProcessor>(); | 38 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentPro cessor>(); |
41 return fMode == cs.fMode; | 39 return fMode == cs.fMode; |
42 } | 40 } |
43 | 41 |
44 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 42 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
45 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 43 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
46 } | 44 } |
47 | 45 |
48 private: | 46 private: |
49 GrGLFragmentProcessor* onCreateGLInstance() const override; | 47 GrGLFragmentProcessor* onCreateGLInstance() const override; |
50 | 48 |
51 SkXfermode::Mode fMode; | 49 SkXfermode::Mode fMode; |
52 | 50 |
53 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | 51 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
54 | 52 |
55 typedef GrFragmentProcessor INHERITED; | 53 typedef GrFragmentProcessor INHERITED; |
56 }; | 54 }; |
57 | 55 |
58 ///////////////////////////////////////////////////////////////////// | 56 ///////////////////////////////////////////////////////////////////// |
59 | 57 |
60 class GrGLComposeTwoFragmentProcessor : public GrGLFragmentProcessor { | 58 class GLComposeTwoFragmentProcessor : public GrGLFragmentProcessor { |
61 public: | 59 public: |
62 GrGLComposeTwoFragmentProcessor(const GrProcessor& processor) {} | 60 GLComposeTwoFragmentProcessor(const GrProcessor& processor) {} |
63 | 61 |
64 void emitCode(EmitArgs&) override; | 62 void emitCode(EmitArgs&) override; |
65 | 63 |
66 private: | 64 private: |
67 typedef GrGLFragmentProcessor INHERITED; | 65 typedef GrGLFragmentProcessor INHERITED; |
68 }; | 66 }; |
69 | 67 |
70 ///////////////////////////////////////////////////////////////////// | 68 ///////////////////////////////////////////////////////////////////// |
71 | 69 |
72 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrComposeTwoFragmentProcessor); | 70 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor); |
73 | 71 |
74 const GrFragmentProcessor* GrComposeTwoFragmentProcessor::TestCreate(GrProcessor TestData* d) { | 72 const GrFragmentProcessor* ComposeTwoFragmentProcessor::TestCreate(GrProcessorTe stData* d) { |
75 // Create two random frag procs. | 73 // Create two random frag procs. |
76 SkAutoTUnref<const GrFragmentProcessor> fpA(GrProcessorUnitTest::CreateChild FP(d)); | 74 SkAutoTUnref<const GrFragmentProcessor> fpA(GrProcessorUnitTest::CreateChild FP(d)); |
77 SkAutoTUnref<const GrFragmentProcessor> fpB(GrProcessorUnitTest::CreateChild FP(d)); | 75 SkAutoTUnref<const GrFragmentProcessor> fpB(GrProcessorUnitTest::CreateChild FP(d)); |
78 | 76 |
79 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>( | 77 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>( |
80 d->fRandom->nextRangeU(0, SkXfermode::kLastCoeffMode)); | 78 d->fRandom->nextRangeU(0, SkXfermode::kLastMode)); |
81 return SkNEW_ARGS(GrComposeTwoFragmentProcessor, (fpA, fpB, mode)); | 79 return new ComposeTwoFragmentProcessor(fpA, fpB, mode); |
82 } | 80 } |
83 | 81 |
84 GrGLFragmentProcessor* GrComposeTwoFragmentProcessor::onCreateGLInstance() const { | 82 GrGLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLInstance() const{ |
85 return SkNEW_ARGS(GrGLComposeTwoFragmentProcessor, (*this)); | 83 return new GLComposeTwoFragmentProcessor(*this); |
86 } | 84 } |
87 | 85 |
88 ///////////////////////////////////////////////////////////////////// | 86 ///////////////////////////////////////////////////////////////////// |
89 | 87 |
90 void GrGLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) { | 88 void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) { |
91 | 89 |
92 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); | 90 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); |
93 const GrComposeTwoFragmentProcessor& cs = args.fFp.cast<GrComposeTwoFragment Processor>(); | 91 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProc essor>(); |
94 | 92 |
95 // Store alpha of input color and un-premultiply the input color by its alph a. We will | 93 // Store alpha of input color and un-premultiply the input color by its alph a. We will |
96 // re-multiply by this alpha after blending the output colors of the two chi ld procs. | 94 // re-multiply by this alpha after blending the output colors of the two chi ld procs. |
97 // This is because we don't want the paint's alpha to affect either child pr oc's output | 95 // This is because we don't want the paint's alpha to affect either child pr oc's output |
98 // before the blend; we want to apply the paint's alpha AFTER the blend. Thi s mirrors the | 96 // before the blend; we want to apply the paint's alpha AFTER the blend. Thi s mirrors the |
99 // software implementation of SkComposeShader. | 97 // software implementation of SkComposeShader. |
100 const char* opaqueInput = nullptr; | 98 const char* opaqueInput = nullptr; |
101 const char* inputAlpha = nullptr; | 99 const char* inputAlpha = nullptr; |
102 if (args.fInputColor) { | 100 if (args.fInputColor) { |
103 inputAlpha = "inputAlpha"; | 101 inputAlpha = "inputAlpha"; |
(...skipping 11 matching lines...) Expand all Loading... | |
115 | 113 |
116 SkString outputColorDst(args.fOutputColor); | 114 SkString outputColorDst(args.fOutputColor); |
117 outputColorDst.append("_dst"); | 115 outputColorDst.append("_dst"); |
118 fsBuilder->codeAppendf("vec4 %s;\n", outputColorDst.c_str()); | 116 fsBuilder->codeAppendf("vec4 %s;\n", outputColorDst.c_str()); |
119 this->emitChild(1, opaqueInput, outputColorDst.c_str(), args); | 117 this->emitChild(1, opaqueInput, outputColorDst.c_str(), args); |
120 | 118 |
121 // emit blend code | 119 // emit blend code |
122 SkXfermode::Mode mode = cs.getMode(); | 120 SkXfermode::Mode mode = cs.getMode(); |
123 fsBuilder->codeAppend("{"); | 121 fsBuilder->codeAppend("{"); |
124 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mo de)); | 122 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mo de)); |
125 GrGLBlend::AppendPorterDuffBlend(fsBuilder, outputColorSrc.c_str(), | 123 GrGLSLBlend::AppendMode(fsBuilder, outputColorSrc.c_str(), |
126 outputColorDst.c_str(), args.fOutputColor, mode); | 124 outputColorDst.c_str(), args.fOutputColor, mode); |
127 fsBuilder->codeAppend("}"); | 125 fsBuilder->codeAppend("}"); |
128 | 126 |
129 // re-multiply the output color by the input color's alpha | 127 // re-multiply the output color by the input color's alpha |
130 if (inputAlpha) { | 128 if (inputAlpha) { |
131 fsBuilder->codeAppendf("%s *= %s;", args.fOutputColor, inputAlpha); | 129 fsBuilder->codeAppendf("%s *= %s;", args.fOutputColor, inputAlpha); |
132 } | 130 } |
133 } | 131 } |
134 | 132 |
135 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors( | 133 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors( |
136 const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXferm ode::Mode mode) { | 134 const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXferm ode::Mode mode) { |
137 if (SkXfermode::kLastCoeffMode < mode) { | |
138 return nullptr; | |
139 } | |
140 switch (mode) { | 135 switch (mode) { |
141 case SkXfermode::kClear_Mode: | 136 case SkXfermode::kClear_Mode: |
142 return GrConstColorProcessor::Create(GrColor_TRANS_BLACK, | 137 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, |
143 GrConstColorProcessor::kIgnore_ InputMode); | 138 GrConstColorProcessor::kIgnore_ InputMode); |
144 break; | |
145 case SkXfermode::kSrc_Mode: | 139 case SkXfermode::kSrc_Mode: |
146 return SkRef(src); | 140 return SkRef(src); |
147 break; | |
148 case SkXfermode::kDst_Mode: | 141 case SkXfermode::kDst_Mode: |
149 return SkRef(dst); | 142 return SkRef(dst); |
150 break; | |
151 default: | 143 default: |
152 return new GrComposeTwoFragmentProcessor(src, dst, mode); | 144 return new ComposeTwoFragmentProcessor(src, dst, mode); |
153 } | 145 } |
154 } | 146 } |
147 | |
148 ////////////////////////////////////////////////////////////////////////////// | |
149 | |
150 class ComposeOneFragmentProcessor : public GrFragmentProcessor { | |
151 public: | |
152 enum Child { | |
153 kDst_Child, | |
154 kSrc_Child, | |
155 }; | |
156 | |
157 ComposeOneFragmentProcessor(const GrFragmentProcessor* dst, SkXfermode::Mode mode, Child child) | |
158 : fMode(mode) | |
159 , fChild(child) { | |
160 this->initClassID<ComposeTwoFragmentProcessor>(); | |
egdaniel
2015/09/15 20:59:28
ComposeOneFrag
bsalomon
2015/09/15 21:12:07
eek... nice catch.
| |
161 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst); | |
162 SkASSERT(0 == dstIndex); | |
163 } | |
164 | |
165 const char* name() const override { return "ComposeOne"; } | |
166 | |
167 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override { | |
168 b->add32(fMode | (fChild << 16)); | |
egdaniel
2015/09/15 20:59:28
worth asserting that kLastMode (or whatever it is
bsalomon
2015/09/15 21:12:07
Done.
| |
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_GrColorComponentFlag s, 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::kWillNo t_ReadInput; | |
202 if (kDst_Child == fChild) { | |
203 if (SkXfermode::kZero_Coeff != srcCoeff || GrBlendCoeffRefsSrc(d stCoeff)) { | |
204 readsInput = GrInvariantOutput::kWill_ReadInput; | |
205 } | |
206 } else { | |
207 if (SkXfermode::kZero_Coeff != dstCoeff || GrBlendCoeffRefsDst(s rcCoeff)) { | |
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 GrGLFragmentProcessor* onCreateGLInstance() 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 GrGLFragmentProcessor { | |
231 public: | |
232 GLComposeOneFragmentProcessor(const GrProcessor& processor) {} | |
233 | |
234 void emitCode(EmitArgs& args) override { | |
235 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder (); | |
236 SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mod e(); | |
237 ComposeOneFragmentProcessor::Child child = | |
238 args.fFp.cast<ComposeOneFragmentProcessor>().child(); | |
239 // declare _dstColor and emit the code for the two child | |
240 fsBuilder->codeAppendf("vec4 _child;"); | |
241 this->emitChild(0, nullptr, "_child", args); | |
242 | |
243 const char* inputColor = args.fInputColor; | |
244 // We don't try to optimize for this case at all | |
245 if (!inputColor) { | |
246 fsBuilder->codeAppendf("const vec4 ones = vec4(1);"); | |
247 inputColor = "ones"; | |
248 } | |
249 | |
250 // emit blend code | |
251 fsBuilder->codeAppend("{"); | |
252 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeNam e(mode)); | |
253 if (ComposeOneFragmentProcessor::kDst_Child == child) { | |
254 GrGLSLBlend::AppendMode(fsBuilder, inputColor, "_child", args.fOutpu tColor, mode); | |
255 } else { | |
256 GrGLSLBlend::AppendMode(fsBuilder, "_child", inputColor, args.fOutpu tColor, mode); | |
257 } | |
258 fsBuilder->codeAppend("}"); | |
259 } | |
260 | |
261 private: | |
262 typedef GrGLFragmentProcessor INHERITED; | |
263 }; | |
264 | |
265 ///////////////////////////////////////////////////////////////////// | |
266 | |
267 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor); | |
268 | |
269 const GrFragmentProcessor* ComposeOneFragmentProcessor::TestCreate(GrProcessorTe stData* d) { | |
270 // Create one random frag procs. | |
271 // For now, we'll prevent either children from being a shader with children to prevent the | |
272 // possibility of an arbitrarily large tree of procs. | |
273 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChild FP(d)); | |
274 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>( | |
275 d->fRandom->nextRangeU(0, SkXfermode::kLastMode)); | |
276 ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ? | |
277 ComposeOneFragmentProcessor::kDst_Child : | |
278 ComposeOneFragmentProcessor::kSrc_Child; | |
279 return new ComposeOneFragmentProcessor(dst, mode, child); | |
280 } | |
281 | |
282 GrGLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLInstance() const { | |
283 return new GLComposeOneFragmentProcessor(*this); | |
284 } | |
285 | |
286 ////////////////////////////////////////////////////////////////////////////// | |
287 | |
288 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromDstProcessor( | |
289 const GrFragmentProcessor* dst, SkXfermode::Mode mode) { | |
290 switch (mode) { | |
291 case SkXfermode::kClear_Mode: | |
292 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, | |
293 GrConstColorProcessor::kIgnore_ InputMode); | |
294 case SkXfermode::kSrc_Mode: | |
295 return nullptr; | |
296 default: | |
297 return new ComposeOneFragmentProcessor(dst, mode, | |
298 ComposeOneFragmentProcessor:: kDst_Child); | |
299 } | |
300 } | |
301 | |
302 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromSrcProcessor( | |
303 const GrFragmentProcessor* src, SkXfermode::Mode mode) { | |
304 switch (mode) { | |
305 case SkXfermode::kClear_Mode: | |
306 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, | |
307 GrConstColorProcessor::kIgnore_ InputMode); | |
308 case SkXfermode::kDst_Mode: | |
309 return nullptr; | |
310 default: | |
311 return new ComposeOneFragmentProcessor(src, mode, | |
312 ComposeOneFragmentProcessor:: kSrc_Child); | |
313 } | |
314 } | |
OLD | NEW |