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

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: fix 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
« no previous file with comments | « src/gpu/effects/GrSimpleTextureEffect.h ('k') | src/gpu/gl/GrGLBlend.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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<ComposeOneFragmentProcessor>();
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 GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLas tMode);
169 b->add32(fMode | (fChild << 16));
170 }
171
172 SkXfermode::Mode mode() const { return fMode; }
173
174 Child child() const { return fChild; }
175
176 protected:
177 bool onIsEqual(const GrFragmentProcessor& that) const override {
178 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
179 }
180
181 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
182 SkXfermode::Coeff skSrcCoeff, skDstCoeff;
183 if (SkXfermode::ModeAsCoeff(fMode, &skSrcCoeff, &skDstCoeff)) {
184 GrBlendCoeff srcCoeff = SkXfermodeCoeffToGrBlendCoeff(skSrcCoeff);
185 GrBlendCoeff dstCoeff = SkXfermodeCoeffToGrBlendCoeff(skDstCoeff);
186 GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlag s, false);
187 this->childProcessor(0).computeInvariantOutput(&childOutput);
188 GrColor blendColor;
189 GrColorComponentFlags blendFlags;
190 if (kDst_Child == fChild) {
191 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
192 inout->color(), inout->validFlags (),
193 childOutput.color(), childOutput. validFlags(),
194 &blendColor, &blendFlags);
195 } else {
196 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
197 childOutput.color(), childOutput. validFlags(),
198 inout->color(), inout->validFlags (),
199 &blendColor, &blendFlags);
200 }
201 // will the shader code reference the input color?
202 GrInvariantOutput::ReadInput readsInput = GrInvariantOutput::kWillNo t_ReadInput;
203 if (kDst_Child == fChild) {
204 if (kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoe ff)) {
205 readsInput = GrInvariantOutput::kWill_ReadInput;
206 }
207 } else {
208 if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoe ff)) {
209 readsInput = GrInvariantOutput::kWill_ReadInput;
210 }
211 }
212 inout->setToOther(blendFlags, blendColor, readsInput);
213 } else {
214 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
215 }
216 }
217
218 private:
219 GrGLFragmentProcessor* onCreateGLInstance() const override;
220
221 SkXfermode::Mode fMode;
222 Child fChild;
223
224 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
225
226 typedef GrFragmentProcessor INHERITED;
227 };
228
229 //////////////////////////////////////////////////////////////////////////////
230
231 class GLComposeOneFragmentProcessor : public GrGLFragmentProcessor {
232 public:
233 GLComposeOneFragmentProcessor(const GrProcessor& processor) {}
234
235 void emitCode(EmitArgs& args) override {
236 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder ();
237 SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mod e();
238 ComposeOneFragmentProcessor::Child child =
239 args.fFp.cast<ComposeOneFragmentProcessor>().child();
240 // declare _dstColor and emit the code for the two child
241 fsBuilder->codeAppendf("vec4 _child;");
242 this->emitChild(0, nullptr, "_child", args);
243
244 const char* inputColor = args.fInputColor;
245 // We don't try to optimize for this case at all
246 if (!inputColor) {
247 fsBuilder->codeAppendf("const vec4 ones = vec4(1);");
248 inputColor = "ones";
249 }
250
251 // emit blend code
252 fsBuilder->codeAppend("{");
253 fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeNam e(mode));
254 if (ComposeOneFragmentProcessor::kDst_Child == child) {
255 GrGLSLBlend::AppendMode(fsBuilder, inputColor, "_child", args.fOutpu tColor, mode);
256 } else {
257 GrGLSLBlend::AppendMode(fsBuilder, "_child", inputColor, args.fOutpu tColor, mode);
258 }
259 fsBuilder->codeAppend("}");
260 }
261
262 private:
263 typedef GrGLFragmentProcessor INHERITED;
264 };
265
266 /////////////////////////////////////////////////////////////////////
267
268 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
269
270 const GrFragmentProcessor* ComposeOneFragmentProcessor::TestCreate(GrProcessorTe stData* d) {
271 // Create one random frag procs.
272 // For now, we'll prevent either children from being a shader with children to prevent the
273 // possibility of an arbitrarily large tree of procs.
274 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChild FP(d));
275 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
276 d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
277 ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ?
278 ComposeOneFragmentProcessor::kDst_Child :
279 ComposeOneFragmentProcessor::kSrc_Child;
280 return new ComposeOneFragmentProcessor(dst, mode, child);
281 }
282
283 GrGLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLInstance() const {
284 return new GLComposeOneFragmentProcessor(*this);
285 }
286
287 //////////////////////////////////////////////////////////////////////////////
288
289 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromDstProcessor(
290 const GrFragmentProcessor* dst, SkXfermode::Mode mode) {
291 switch (mode) {
292 case SkXfermode::kClear_Mode:
293 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
294 GrConstColorProcessor::kIgnore_ InputMode);
295 case SkXfermode::kSrc_Mode:
296 return nullptr;
297 default:
298 return new ComposeOneFragmentProcessor(dst, mode,
299 ComposeOneFragmentProcessor:: kDst_Child);
300 }
301 }
302
303 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromSrcProcessor(
304 const GrFragmentProcessor* src, SkXfermode::Mode mode) {
305 switch (mode) {
306 case SkXfermode::kClear_Mode:
307 return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
308 GrConstColorProcessor::kIgnore_ InputMode);
309 case SkXfermode::kDst_Mode:
310 return nullptr;
311 default:
312 return new ComposeOneFragmentProcessor(src, mode,
313 ComposeOneFragmentProcessor:: kSrc_Child);
314 }
315 }
OLDNEW
« no previous file with comments | « src/gpu/effects/GrSimpleTextureEffect.h ('k') | src/gpu/gl/GrGLBlend.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698