Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: src/gpu/effects/GrXfermodeFragmentProcessor.cpp

Issue 1334293003: Create fragment processor for performing input color blend with child processor (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: working Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698