1 /*
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 "GrFragmentProcessor.h"
9 #include "GrCoordTransform.h"
10 #include "GrPipeline.h"
11 #include "GrPipelineAnalysis.h"
12 #include "effects/GrConstColorProcessor.h"
13 #include "effects/GrXfermodeFragmentProcessor.h"
14 #include "glsl/GrGLSLFragmentProcessor.h"
15 #include "glsl/GrGLSLFragmentShaderBuilder.h"
16 #include "glsl/GrGLSLProgramDataManager.h"
17 #include "glsl/GrGLSLUniformHandler.h"
18
~GrFragmentProcessor()19 GrFragmentProcessor::~GrFragmentProcessor() {
20 // If we got here then our ref count must have reached zero, so we will have converted refs
21 // to pending executions for all children.
22 for (int i = 0; i < fChildProcessors.count(); ++i) {
23 fChildProcessors[i]->completedExecution();
24 }
25 }
26
isEqual(const GrFragmentProcessor & that) const27 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
28 if (this->classID() != that.classID() ||
29 !this->hasSameSamplersAndAccesses(that)) {
30 return false;
31 }
32 if (!this->hasSameTransforms(that)) {
33 return false;
34 }
35 if (!this->onIsEqual(that)) {
36 return false;
37 }
38 if (this->numChildProcessors() != that.numChildProcessors()) {
39 return false;
40 }
41 for (int i = 0; i < this->numChildProcessors(); ++i) {
42 if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
43 return false;
44 }
45 }
46 return true;
47 }
48
createGLSLInstance() const49 GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
50 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
51 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
52 for (int i = 0; i < fChildProcessors.count(); ++i) {
53 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
54 }
55 return glFragProc;
56 }
57
addCoordTransform(const GrCoordTransform * transform)58 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
59 fCoordTransforms.push_back(transform);
60 fFlags |= kUsesLocalCoords_Flag;
61 SkDEBUGCODE(transform->setInProcessor();)
62 }
63
registerChildProcessor(sk_sp<GrFragmentProcessor> child)64 int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
65 this->combineRequiredFeatures(*child);
66
67 if (child->usesLocalCoords()) {
68 fFlags |= kUsesLocalCoords_Flag;
69 }
70 if (child->usesDistanceVectorField()) {
71 fFlags |= kUsesDistanceVectorField_Flag;
72 }
73
74 int index = fChildProcessors.count();
75 fChildProcessors.push_back(child.release());
76
77 return index;
78 }
79
notifyRefCntIsZero() const80 void GrFragmentProcessor::notifyRefCntIsZero() const {
81 // See comment above GrProgramElement for a detailed explanation of why we do this.
82 for (int i = 0; i < fChildProcessors.count(); ++i) {
83 fChildProcessors[i]->addPendingExecution();
84 fChildProcessors[i]->unref();
85 }
86 }
87
hasSameTransforms(const GrFragmentProcessor & that) const88 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
89 if (this->numCoordTransforms() != that.numCoordTransforms()) {
90 return false;
91 }
92 int count = this->numCoordTransforms();
93 for (int i = 0; i < count; ++i) {
94 if (!this->coordTransform(i).hasSameEffectAs(that.coordTransform(i))) {
95 return false;
96 }
97 }
98 return true;
99 }
100
MulOutputByInputAlpha(sk_sp<GrFragmentProcessor> fp)101 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
102 sk_sp<GrFragmentProcessor> fp) {
103 if (!fp) {
104 return nullptr;
105 }
106 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
107 }
108
109 namespace {
110
111 class PremulInputFragmentProcessor : public GrFragmentProcessor {
112 public:
PremulInputFragmentProcessor()113 PremulInputFragmentProcessor()
114 : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
115 kConstantOutputForConstantInput_OptimizationFlag) {
116 this->initClassID<PremulInputFragmentProcessor>();
117 }
118
name() const119 const char* name() const override { return "PremultiplyInput"; }
120
121 private:
onCreateGLSLInstance() const122 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
123 class GLFP : public GrGLSLFragmentProcessor {
124 public:
125 void emitCode(EmitArgs& args) override {
126 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
127
128 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
129 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
130 args.fOutputColor, args.fInputColor);
131 }
132 };
133 return new GLFP;
134 }
135
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder *) const136 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
137
onIsEqual(const GrFragmentProcessor &) const138 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
139
constantOutputForConstantInput(GrColor4f input) const140 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
141 return input.premul();
142 }
143
144 typedef GrFragmentProcessor INHERITED;
145 };
146
147 class UnpremulInputFragmentProcessor : public GrFragmentProcessor {
148 public:
UnpremulInputFragmentProcessor()149 UnpremulInputFragmentProcessor()
150 : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
151 kConstantOutputForConstantInput_OptimizationFlag) {
152 this->initClassID<UnpremulInputFragmentProcessor>();
153 }
154
name() const155 const char* name() const override { return "UnpremultiplyInput"; }
156
157 private:
onCreateGLSLInstance() const158 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
159 class GLFP : public GrGLSLFragmentProcessor {
160 public:
161 void emitCode(EmitArgs& args) override {
162 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
163
164 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
165 fragBuilder->codeAppendf("float invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
166 args.fInputColor, args.fInputColor);
167 fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
168 }
169 };
170 return new GLFP;
171 }
172
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder *) const173 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
174
onIsEqual(const GrFragmentProcessor &) const175 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
176
constantOutputForConstantInput(GrColor4f input) const177 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
178 return input.unpremul();
179 }
180
181 typedef GrFragmentProcessor INHERITED;
182 };
183
184 }
185
PremulInput(sk_sp<GrFragmentProcessor> fp)186 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
187 if (!fp) {
188 return nullptr;
189 }
190 sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
191 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
192 }
193
PremulOutput(sk_sp<GrFragmentProcessor> fp)194 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulOutput(sk_sp<GrFragmentProcessor> fp) {
195 if (!fp) {
196 return nullptr;
197 }
198 sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<PremulInputFragmentProcessor>() };
199 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
200 }
201
UnpremulOutput(sk_sp<GrFragmentProcessor> fp)202 sk_sp<GrFragmentProcessor> GrFragmentProcessor::UnpremulOutput(sk_sp<GrFragmentProcessor> fp) {
203 if (!fp) {
204 return nullptr;
205 }
206 sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<UnpremulInputFragmentProcessor>() };
207 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
208 }
209
SwizzleOutput(sk_sp<GrFragmentProcessor> fp,const GrSwizzle & swizzle)210 sk_sp<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(sk_sp<GrFragmentProcessor> fp,
211 const GrSwizzle& swizzle) {
212 class SwizzleFragmentProcessor : public GrFragmentProcessor {
213 public:
214 SwizzleFragmentProcessor(const GrSwizzle& swizzle)
215 : INHERITED(kAll_OptimizationFlags)
216 , fSwizzle(swizzle) {
217 this->initClassID<SwizzleFragmentProcessor>();
218 }
219
220 const char* name() const override { return "Swizzle"; }
221 const GrSwizzle& swizzle() const { return fSwizzle; }
222
223 private:
224 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
225 class GLFP : public GrGLSLFragmentProcessor {
226 public:
227 void emitCode(EmitArgs& args) override {
228 const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
229 const GrSwizzle& swizzle = sfp.swizzle();
230 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
231
232 fragBuilder->codeAppendf("%s = %s.%s;",
233 args.fOutputColor, args.fInputColor, swizzle.c_str());
234 }
235 };
236 return new GLFP;
237 }
238
239 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
240 b->add32(fSwizzle.asKey());
241 }
242
243 bool onIsEqual(const GrFragmentProcessor& other) const override {
244 const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
245 return fSwizzle == sfp.fSwizzle;
246 }
247
248 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
249 return fSwizzle.applyTo(input);
250 }
251
252 GrSwizzle fSwizzle;
253
254 typedef GrFragmentProcessor INHERITED;
255 };
256
257 if (!fp) {
258 return nullptr;
259 }
260 if (GrSwizzle::RGBA() == swizzle) {
261 return fp;
262 }
263 sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<SwizzleFragmentProcessor>(swizzle) };
264 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
265 }
266
MakeInputPremulAndMulByOutput(sk_sp<GrFragmentProcessor> fp)267 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
268 sk_sp<GrFragmentProcessor> fp) {
269
270 class PremulFragmentProcessor : public GrFragmentProcessor {
271 public:
272 PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor)
273 : INHERITED(OptFlags(processor.get())) {
274 this->initClassID<PremulFragmentProcessor>();
275 this->registerChildProcessor(processor);
276 }
277
278 const char* name() const override { return "Premultiply"; }
279
280 private:
281 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
282 class GLFP : public GrGLSLFragmentProcessor {
283 public:
284 void emitCode(EmitArgs& args) override {
285 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
286 this->emitChild(0, nullptr, args);
287 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
288 args.fInputColor);
289 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
290 }
291 };
292 return new GLFP;
293 }
294
295 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
296
297 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
298
299 static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
300 OptimizationFlags flags = kNone_OptimizationFlags;
301 if (inner->preservesOpaqueInput()) {
302 flags |= kPreservesOpaqueInput_OptimizationFlag;
303 }
304 if (inner->hasConstantOutputForConstantInput()) {
305 flags |= kConstantOutputForConstantInput_OptimizationFlag;
306 }
307 return flags;
308 }
309
310 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
311 GrColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
312 GrColor4f::OpaqueWhite());
313 return GrColor4f(input.fRGBA[3] * input.fRGBA[0] * childColor.fRGBA[0],
314 input.fRGBA[3] * input.fRGBA[1] * childColor.fRGBA[1],
315 input.fRGBA[3] * input.fRGBA[2] * childColor.fRGBA[2],
316 input.fRGBA[3] * childColor.fRGBA[3]);
317 }
318
319 typedef GrFragmentProcessor INHERITED;
320 };
321 if (!fp) {
322 return nullptr;
323 }
324 return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
325 }
326
327 //////////////////////////////////////////////////////////////////////////////
328
OverrideInput(sk_sp<GrFragmentProcessor> fp,GrColor4f color)329 sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
330 GrColor4f color) {
331 class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
332 public:
333 ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
334 : INHERITED(OptFlags(child.get(), color)), fColor(color) {
335 this->initClassID<ReplaceInputFragmentProcessor>();
336 this->registerChildProcessor(std::move(child));
337 }
338
339 const char* name() const override { return "Replace Color"; }
340
341 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
342 class GLFP : public GrGLSLFragmentProcessor {
343 public:
344 GLFP() : fHaveSetColor(false) {}
345 void emitCode(EmitArgs& args) override {
346 const char* colorName;
347 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
348 kVec4f_GrSLType,
349 kDefault_GrSLPrecision,
350 "Color", &colorName);
351 this->emitChild(0, colorName, args);
352 }
353
354 private:
355 void onSetData(const GrGLSLProgramDataManager& pdman,
356 const GrProcessor& fp) override {
357 GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
358 if (!fHaveSetColor || color != fPreviousColor) {
359 pdman.set4fv(fColorUni, 1, color.fRGBA);
360 fPreviousColor = color;
361 fHaveSetColor = true;
362 }
363 }
364
365 GrGLSLProgramDataManager::UniformHandle fColorUni;
366 bool fHaveSetColor;
367 GrColor4f fPreviousColor;
368 };
369
370 return new GLFP;
371 }
372
373 private:
374 static OptimizationFlags OptFlags(const GrFragmentProcessor* child, GrColor4f color) {
375 OptimizationFlags childFlags = child->optimizationFlags();
376 OptimizationFlags flags = kNone_OptimizationFlags;
377 if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
378 flags |= kConstantOutputForConstantInput_OptimizationFlag;
379 }
380 if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
381 flags |= kPreservesOpaqueInput_OptimizationFlag;
382 }
383 return flags;
384 }
385
386 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
387 {}
388
389 bool onIsEqual(const GrFragmentProcessor& that) const override {
390 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
391 }
392
393 GrColor4f constantOutputForConstantInput(GrColor4f) const override {
394 return ConstantOutputForConstantInput(this->childProcessor(0), fColor);
395 }
396
397 GrColor4f fColor;
398
399 typedef GrFragmentProcessor INHERITED;
400 };
401
402 return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
403 }
404
RunInSeries(sk_sp<GrFragmentProcessor> * series,int cnt)405 sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
406 int cnt) {
407 class SeriesFragmentProcessor : public GrFragmentProcessor {
408 public:
409 SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt)
410 : INHERITED(OptFlags(children, cnt)) {
411 SkASSERT(cnt > 1);
412 this->initClassID<SeriesFragmentProcessor>();
413 for (int i = 0; i < cnt; ++i) {
414 this->registerChildProcessor(std::move(children[i]));
415 }
416 }
417
418 const char* name() const override { return "Series"; }
419
420 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
421 class GLFP : public GrGLSLFragmentProcessor {
422 public:
423 void emitCode(EmitArgs& args) override {
424 // First guy's input might be nil.
425 SkString temp("out0");
426 this->emitChild(0, args.fInputColor, &temp, args);
427 SkString input = temp;
428 for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
429 temp.printf("out%d", i);
430 this->emitChild(i, input.c_str(), &temp, args);
431 input = temp;
432 }
433 // Last guy writes to our output variable.
434 this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
435 }
436 };
437 return new GLFP;
438 }
439 private:
440 static OptimizationFlags OptFlags(sk_sp<GrFragmentProcessor>* children, int cnt) {
441 OptimizationFlags flags = kAll_OptimizationFlags;
442 for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
443 flags &= children[i]->optimizationFlags();
444 }
445 return flags;
446 }
447 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
448
449 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
450
451 GrColor4f constantOutputForConstantInput(GrColor4f color) const override {
452 int childCnt = this->numChildProcessors();
453 for (int i = 0; i < childCnt; ++i) {
454 color = ConstantOutputForConstantInput(this->childProcessor(i), color);
455 }
456 return color;
457 }
458
459 typedef GrFragmentProcessor INHERITED;
460 };
461
462 if (!cnt) {
463 return nullptr;
464 }
465 if (1 == cnt) {
466 return series[0];
467 }
468 // Run the through the series, do the invariant output processing, and look for eliminations.
469 GrColorFragmentProcessorAnalysis info;
470 info.analyzeProcessors(sk_sp_address_as_pointer_address(series), cnt);
471 SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
472 GrColor4f knownColor;
473 int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
474 if (leadingFPsToEliminate) {
475 sk_sp<GrFragmentProcessor> colorFP(
476 GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::kIgnore_InputMode));
477 if (leadingFPsToEliminate == cnt) {
478 return colorFP;
479 }
480 cnt = cnt - leadingFPsToEliminate + 1;
481 replacementSeries.reserve(cnt);
482 replacementSeries.emplace_back(std::move(colorFP));
483 for (int i = 0; i < cnt - 1; ++i) {
484 replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
485 }
486 series = replacementSeries.begin();
487 }
488 return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
489 }
490
491 //////////////////////////////////////////////////////////////////////////////
492
Iter(const GrPipeline & pipeline)493 GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
494 for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
495 fFPStack.push_back(&pipeline.getFragmentProcessor(i));
496 }
497 }
498
next()499 const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
500 if (fFPStack.empty()) {
501 return nullptr;
502 }
503 const GrFragmentProcessor* back = fFPStack.back();
504 fFPStack.pop_back();
505 for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
506 fFPStack.push_back(&back->childProcessor(i));
507 }
508 return back;
509 }
510
511