1
2 /*
3 * Copyright 2015 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9 #include "GrFragmentProcessor.h"
10 #include "GrCoordTransform.h"
11 #include "GrInvariantOutput.h"
12 #include "GrProcOptInfo.h"
13 #include "glsl/GrGLSLFragmentProcessor.h"
14 #include "glsl/GrGLSLFragmentShaderBuilder.h"
15 #include "glsl/GrGLSLProgramDataManager.h"
16 #include "glsl/GrGLSLUniformHandler.h"
17 #include "effects/GrConstColorProcessor.h"
18 #include "effects/GrXfermodeFragmentProcessor.h"
19
~GrFragmentProcessor()20 GrFragmentProcessor::~GrFragmentProcessor() {
21 // If we got here then our ref count must have reached zero, so we will have converted refs
22 // to pending executions for all children.
23 for (int i = 0; i < fChildProcessors.count(); ++i) {
24 fChildProcessors[i]->completedExecution();
25 }
26 }
27
isEqual(const GrFragmentProcessor & that,bool ignoreCoordTransforms) const28 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that,
29 bool ignoreCoordTransforms) const {
30 if (this->classID() != that.classID() ||
31 !this->hasSameTextureAccesses(that)) {
32 return false;
33 }
34 if (ignoreCoordTransforms) {
35 if (this->numTransforms() != that.numTransforms()) {
36 return false;
37 }
38 } else if (!this->hasSameTransforms(that)) {
39 return false;
40 }
41 if (!this->onIsEqual(that)) {
42 return false;
43 }
44 if (this->numChildProcessors() != that.numChildProcessors()) {
45 return false;
46 }
47 for (int i = 0; i < this->numChildProcessors(); ++i) {
48 if (!this->childProcessor(i).isEqual(that.childProcessor(i), ignoreCoordTransforms)) {
49 return false;
50 }
51 }
52 return true;
53 }
54
createGLSLInstance() const55 GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
56 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
57 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
58 for (int i = 0; i < fChildProcessors.count(); ++i) {
59 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
60 }
61 return glFragProc;
62 }
63
addTextureAccess(const GrTextureAccess * textureAccess)64 void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) {
65 // Can't add texture accesses after registering any children since their texture accesses have
66 // already been bubbled up into our fTextureAccesses array
67 SkASSERT(fChildProcessors.empty());
68
69 INHERITED::addTextureAccess(textureAccess);
70 fNumTexturesExclChildren++;
71 }
72
addCoordTransform(const GrCoordTransform * transform)73 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
74 // Can't add transforms after registering any children since their transforms have already been
75 // bubbled up into our fCoordTransforms array
76 SkASSERT(fChildProcessors.empty());
77
78 fCoordTransforms.push_back(transform);
79 fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet;
80 SkDEBUGCODE(transform->setInProcessor();)
81 fNumTransformsExclChildren++;
82 }
83
registerChildProcessor(const GrFragmentProcessor * child)84 int GrFragmentProcessor::registerChildProcessor(const GrFragmentProcessor* child) {
85 // Append the child's transforms to our transforms array and the child's textures array to our
86 // textures array
87 if (!child->fCoordTransforms.empty()) {
88 fCoordTransforms.push_back_n(child->fCoordTransforms.count(),
89 child->fCoordTransforms.begin());
90 }
91 if (!child->fTextureAccesses.empty()) {
92 fTextureAccesses.push_back_n(child->fTextureAccesses.count(),
93 child->fTextureAccesses.begin());
94 }
95
96 int index = fChildProcessors.count();
97 fChildProcessors.push_back(SkRef(child));
98
99 if (child->willReadFragmentPosition()) {
100 this->setWillReadFragmentPosition();
101 }
102
103 if (child->usesLocalCoords()) {
104 fUsesLocalCoords = true;
105 }
106
107 return index;
108 }
109
notifyRefCntIsZero() const110 void GrFragmentProcessor::notifyRefCntIsZero() const {
111 // See comment above GrProgramElement for a detailed explanation of why we do this.
112 for (int i = 0; i < fChildProcessors.count(); ++i) {
113 fChildProcessors[i]->addPendingExecution();
114 fChildProcessors[i]->unref();
115 }
116 }
117
hasSameTransforms(const GrFragmentProcessor & that) const118 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
119 if (this->numTransforms() != that.numTransforms()) {
120 return false;
121 }
122 int count = this->numTransforms();
123 for (int i = 0; i < count; ++i) {
124 if (this->coordTransform(i) != that.coordTransform(i)) {
125 return false;
126 }
127 }
128 return true;
129 }
130
MulOutputByInputAlpha(const GrFragmentProcessor * fp)131 const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputAlpha(
132 const GrFragmentProcessor* fp) {
133 if (!fp) {
134 return nullptr;
135 }
136 return GrXfermodeFragmentProcessor::CreateFromDstProcessor(fp, SkXfermode::kDstIn_Mode);
137 }
138
MulOutputByInputUnpremulColor(const GrFragmentProcessor * fp)139 const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputUnpremulColor(
140 const GrFragmentProcessor* fp) {
141
142 class PremulFragmentProcessor : public GrFragmentProcessor {
143 public:
144 PremulFragmentProcessor(const GrFragmentProcessor* processor) {
145 this->initClassID<PremulFragmentProcessor>();
146 this->registerChildProcessor(processor);
147 }
148
149 const char* name() const override { return "Premultiply"; }
150
151 private:
152 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
153 class GLFP : public GrGLSLFragmentProcessor {
154 public:
155 void emitCode(EmitArgs& args) override {
156 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
157 this->emitChild(0, nullptr, args);
158 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
159 args.fInputColor);
160 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
161 }
162 };
163 return new GLFP;
164 }
165
166 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
167
168 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
169
170 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
171 // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
172 if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
173 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
174 return;
175 }
176
177 GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
178 this->childProcessor(0).computeInvariantOutput(&childOutput);
179
180 if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
181 inout->mulByKnownFourComponents(0x0);
182 return;
183 }
184 GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
185 GrColor c0 = GrPremulColor(inout->color());
186 GrColor c1 = childOutput.color();
187 GrColor color = 0x0;
188 if (commonFlags & kR_GrColorComponentFlag) {
189 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
190 GrColor_SHIFT_R;
191 }
192 if (commonFlags & kG_GrColorComponentFlag) {
193 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
194 GrColor_SHIFT_G;
195 }
196 if (commonFlags & kB_GrColorComponentFlag) {
197 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
198 GrColor_SHIFT_B;
199 }
200 inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
201 }
202 };
203 if (!fp) {
204 return nullptr;
205 }
206 return new PremulFragmentProcessor(fp);
207 }
208
209 //////////////////////////////////////////////////////////////////////////////
210
OverrideInput(const GrFragmentProcessor * fp,GrColor color)211 const GrFragmentProcessor* GrFragmentProcessor::OverrideInput(const GrFragmentProcessor* fp,
212 GrColor color) {
213 class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
214 public:
215 ReplaceInputFragmentProcessor(const GrFragmentProcessor* child, GrColor color)
216 : fColor(color) {
217 this->initClassID<ReplaceInputFragmentProcessor>();
218 this->registerChildProcessor(child);
219 }
220
221 const char* name() const override { return "Replace Color"; }
222
223 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
224 class GLFP : public GrGLSLFragmentProcessor {
225 public:
226 GLFP() : fHaveSetColor(false) {}
227 void emitCode(EmitArgs& args) override {
228 const char* colorName;
229 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
230 kVec4f_GrSLType,
231 kDefault_GrSLPrecision,
232 "Color", &colorName);
233 this->emitChild(0, colorName, args);
234 }
235
236 private:
237 void onSetData(const GrGLSLProgramDataManager& pdman,
238 const GrProcessor& fp) override {
239 GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
240 if (!fHaveSetColor || color != fPreviousColor) {
241 static const float scale = 1.f / 255.f;
242 float floatColor[4] = {
243 GrColorUnpackR(color) * scale,
244 GrColorUnpackG(color) * scale,
245 GrColorUnpackB(color) * scale,
246 GrColorUnpackA(color) * scale,
247 };
248 pdman.set4fv(fColorUni, 1, floatColor);
249 fPreviousColor = color;
250 fHaveSetColor = true;
251 }
252 }
253
254 GrGLSLProgramDataManager::UniformHandle fColorUni;
255 bool fHaveSetColor;
256 GrColor fPreviousColor;
257 };
258
259 return new GLFP;
260 }
261
262 private:
263 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override
264 {}
265
266 bool onIsEqual(const GrFragmentProcessor& that) const override {
267 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
268 }
269
270 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
271 inout->setToOther(kRGBA_GrColorComponentFlags, fColor,
272 GrInvariantOutput::kWillNot_ReadInput);
273 this->childProcessor(0).computeInvariantOutput(inout);
274 }
275
276 GrColor fColor;
277 };
278
279 GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
280 fp->computeInvariantOutput(&childOut);
281 if (childOut.willUseInputColor()) {
282 return new ReplaceInputFragmentProcessor(fp, color);
283 } else {
284 return SkRef(fp);
285 }
286 }
287
RunInSeries(const GrFragmentProcessor * series[],int cnt)288 const GrFragmentProcessor* GrFragmentProcessor::RunInSeries(const GrFragmentProcessor* series[],
289 int cnt) {
290 class SeriesFragmentProcessor : public GrFragmentProcessor {
291 public:
292 SeriesFragmentProcessor(const GrFragmentProcessor* children[], int cnt){
293 SkASSERT(cnt > 1);
294 this->initClassID<SeriesFragmentProcessor>();
295 for (int i = 0; i < cnt; ++i) {
296 this->registerChildProcessor(children[i]);
297 }
298 }
299
300 const char* name() const override { return "Series"; }
301
302 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
303 class GLFP : public GrGLSLFragmentProcessor {
304 public:
305 void emitCode(EmitArgs& args) override {
306 SkString input(args.fInputColor);
307 for (int i = 0; i < this->numChildProcessors() - 1; ++i) {
308 SkString temp;
309 temp.printf("out%d", i);
310 this->emitChild(i, input.c_str(), &temp, args);
311 input = temp;
312 }
313 // Last guy writes to our output variable.
314 this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
315 }
316 };
317 return new GLFP;
318 }
319
320 private:
321 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
322
323 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
324
325 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
326 GrProcOptInfo info;
327 SkTDArray<const GrFragmentProcessor*> children;
328 children.setCount(this->numChildProcessors());
329 for (int i = 0; i < children.count(); ++i) {
330 children[i] = &this->childProcessor(i);
331 }
332 info.calcWithInitialValues(children.begin(), children.count(), inout->color(),
333 inout->validFlags(), false, false);
334 for (int i = 0; i < this->numChildProcessors(); ++i) {
335 this->childProcessor(i).computeInvariantOutput(inout);
336 }
337 }
338 };
339
340 if (!cnt) {
341 return nullptr;
342 }
343
344 // Run the through the series, do the invariant output processing, and look for eliminations.
345 SkTDArray<const GrFragmentProcessor*> replacementSeries;
346 SkAutoTUnref<const GrFragmentProcessor> colorFP;
347 GrProcOptInfo info;
348
349 info.calcWithInitialValues(series, cnt, 0x0, kNone_GrColorComponentFlags, false, false);
350 if (kRGBA_GrColorComponentFlags == info.validFlags()) {
351 return GrConstColorProcessor::Create(info.color(),
352 GrConstColorProcessor::kIgnore_InputMode);
353 } else {
354 int firstIdx = info.firstEffectiveProcessorIndex();
355 cnt -= firstIdx;
356 if (firstIdx > 0 && info.inputColorIsUsed()) {
357 colorFP.reset(GrConstColorProcessor::Create(info.inputColorToFirstEffectiveProccesor(),
358 GrConstColorProcessor::kIgnore_InputMode));
359 cnt += 1;
360 replacementSeries.setCount(cnt);
361 replacementSeries[0] = colorFP;
362 for (int i = 0; i < cnt - 1; ++i) {
363 replacementSeries[i + 1] = series[firstIdx + i];
364 }
365 series = replacementSeries.begin();
366 } else {
367 series += firstIdx;
368 cnt -= firstIdx;
369 }
370 }
371
372 if (1 == cnt) {
373 return SkRef(series[0]);
374 } else {
375 return new SeriesFragmentProcessor(series, cnt);
376 }
377 }
378
379