blob: a8a4898e78d99fd7baa3cafbde772f2fc49ac386 [file] [log] [blame]
bsalomonbf877302015-09-22 09:06:13 -07001/*
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"
egdaniel7ea439b2015-12-03 09:20:44 -080010#include "GrInvariantOutput.h"
11#include "GrProcOptInfo.h"
egdaniel64c47282015-11-13 06:54:19 -080012#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080013#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070014#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080015#include "glsl/GrGLSLUniformHandler.h"
bsalomone25eea42015-09-29 06:38:55 -070016#include "effects/GrConstColorProcessor.h"
bsalomonbf877302015-09-22 09:06:13 -070017#include "effects/GrXfermodeFragmentProcessor.h"
18
19GrFragmentProcessor::~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
27bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that,
28 bool ignoreCoordTransforms) const {
29 if (this->classID() != that.classID() ||
cdalton74b8d322016-04-11 14:47:28 -070030 !this->hasSameSamplers(that)) {
bsalomonbf877302015-09-22 09:06:13 -070031 return false;
32 }
33 if (ignoreCoordTransforms) {
34 if (this->numTransforms() != that.numTransforms()) {
35 return false;
36 }
37 } else if (!this->hasSameTransforms(that)) {
38 return false;
39 }
40 if (!this->onIsEqual(that)) {
41 return false;
42 }
43 if (this->numChildProcessors() != that.numChildProcessors()) {
44 return false;
45 }
46 for (int i = 0; i < this->numChildProcessors(); ++i) {
47 if (!this->childProcessor(i).isEqual(that.childProcessor(i), ignoreCoordTransforms)) {
48 return false;
49 }
50 }
51 return true;
52}
53
egdaniel57d3b032015-11-13 11:57:27 -080054GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
55 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070056 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
57 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -080058 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070059 }
60 return glFragProc;
61}
62
63void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) {
64 // Can't add texture accesses after registering any children since their texture accesses have
65 // already been bubbled up into our fTextureAccesses array
66 SkASSERT(fChildProcessors.empty());
67
68 INHERITED::addTextureAccess(textureAccess);
69 fNumTexturesExclChildren++;
70}
71
cdalton74b8d322016-04-11 14:47:28 -070072void GrFragmentProcessor::addBufferAccess(const GrBufferAccess* bufferAccess) {
73 // Can't add buffer accesses after registering any children since their buffer accesses have
74 // already been bubbled up into our fBufferAccesses array
75 SkASSERT(fChildProcessors.empty());
76
77 INHERITED::addBufferAccess(bufferAccess);
78 fNumBuffersExclChildren++;
79}
80
bsalomonbf877302015-09-22 09:06:13 -070081void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
82 // Can't add transforms after registering any children since their transforms have already been
83 // bubbled up into our fCoordTransforms array
84 SkASSERT(fChildProcessors.empty());
85
86 fCoordTransforms.push_back(transform);
87 fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet;
88 SkDEBUGCODE(transform->setInProcessor();)
89 fNumTransformsExclChildren++;
90}
91
bungeman06ca8ec2016-06-09 08:01:03 -070092int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
bsalomonbf877302015-09-22 09:06:13 -070093 // Append the child's transforms to our transforms array and the child's textures array to our
94 // textures array
95 if (!child->fCoordTransforms.empty()) {
96 fCoordTransforms.push_back_n(child->fCoordTransforms.count(),
97 child->fCoordTransforms.begin());
98 }
99 if (!child->fTextureAccesses.empty()) {
100 fTextureAccesses.push_back_n(child->fTextureAccesses.count(),
101 child->fTextureAccesses.begin());
102 }
103
cdalton87332102016-02-26 12:22:02 -0800104 this->combineRequiredFeatures(*child);
bsalomonbf877302015-09-22 09:06:13 -0700105
106 if (child->usesLocalCoords()) {
107 fUsesLocalCoords = true;
108 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700109 if (child->usesDistanceVectorField()) {
110 fUsesDistanceVectorField = true;
111 }
bsalomonbf877302015-09-22 09:06:13 -0700112
bungeman06ca8ec2016-06-09 08:01:03 -0700113 int index = fChildProcessors.count();
114 fChildProcessors.push_back(child.release());
115
bsalomonbf877302015-09-22 09:06:13 -0700116 return index;
117}
118
119void GrFragmentProcessor::notifyRefCntIsZero() const {
120 // See comment above GrProgramElement for a detailed explanation of why we do this.
121 for (int i = 0; i < fChildProcessors.count(); ++i) {
122 fChildProcessors[i]->addPendingExecution();
123 fChildProcessors[i]->unref();
124 }
125}
126
127bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
128 if (this->numTransforms() != that.numTransforms()) {
129 return false;
130 }
131 int count = this->numTransforms();
132 for (int i = 0; i < count; ++i) {
133 if (this->coordTransform(i) != that.coordTransform(i)) {
134 return false;
135 }
136 }
137 return true;
138}
139
bungeman06ca8ec2016-06-09 08:01:03 -0700140sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
141 sk_sp<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700142 if (!fp) {
143 return nullptr;
144 }
bungeman06ca8ec2016-06-09 08:01:03 -0700145 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp),
146 SkXfermode::kDstIn_Mode);
bsalomonbf877302015-09-22 09:06:13 -0700147}
148
dvonbeckc526da92016-07-20 11:20:30 -0700149sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
150
151 class PremulInputFragmentProcessor : public GrFragmentProcessor {
152 public:
153 PremulInputFragmentProcessor() {
154 this->initClassID<PremulInputFragmentProcessor>();
155 }
156
157 const char* name() const override { return "PremultiplyInput"; }
158
159 private:
160 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
161 class GLFP : public GrGLSLFragmentProcessor {
162 public:
163 void emitCode(EmitArgs& args) override {
164 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
165
166 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
167 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
168 args.fOutputColor, args.fInputColor);
169 }
170 };
171 return new GLFP;
172 }
173
174 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
175
176 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
177
178 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
179 inout->premulFourChannelColor();
180 }
181 };
182 if (!fp) {
183 return nullptr;
184 }
185 sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
186 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
187}
188
bungeman06ca8ec2016-06-09 08:01:03 -0700189sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputUnpremulColor(
190 sk_sp<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700191
192 class PremulFragmentProcessor : public GrFragmentProcessor {
193 public:
bungeman06ca8ec2016-06-09 08:01:03 -0700194 PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700195 this->initClassID<PremulFragmentProcessor>();
196 this->registerChildProcessor(processor);
197 }
198
199 const char* name() const override { return "Premultiply"; }
200
201 private:
egdaniel57d3b032015-11-13 11:57:27 -0800202 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800203 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700204 public:
bsalomonf1b7a1d2015-09-28 06:26:28 -0700205 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800206 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700207 this->emitChild(0, nullptr, args);
egdaniel4ca2e602015-11-18 08:01:26 -0800208 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700209 args.fInputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800210 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700211 }
212 };
213 return new GLFP;
214 }
215
egdaniel57d3b032015-11-13 11:57:27 -0800216 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700217
218 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
219
220 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
221 // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
222 if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
223 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
224 return;
225 }
226
227 GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
228 this->childProcessor(0).computeInvariantOutput(&childOutput);
229
230 if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
231 inout->mulByKnownFourComponents(0x0);
232 return;
233 }
234 GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
235 GrColor c0 = GrPremulColor(inout->color());
236 GrColor c1 = childOutput.color();
237 GrColor color = 0x0;
238 if (commonFlags & kR_GrColorComponentFlag) {
239 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
240 GrColor_SHIFT_R;
241 }
242 if (commonFlags & kG_GrColorComponentFlag) {
243 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
244 GrColor_SHIFT_G;
245 }
246 if (commonFlags & kB_GrColorComponentFlag) {
247 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
248 GrColor_SHIFT_B;
249 }
250 inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
251 }
252 };
253 if (!fp) {
254 return nullptr;
255 }
bungeman06ca8ec2016-06-09 08:01:03 -0700256 return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700257}
258
259//////////////////////////////////////////////////////////////////////////////
260
bungeman06ca8ec2016-06-09 08:01:03 -0700261sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700262 GrColor color) {
263 class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
264 public:
bungeman06ca8ec2016-06-09 08:01:03 -0700265 ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor color)
bsalomonf1b7a1d2015-09-28 06:26:28 -0700266 : fColor(color) {
267 this->initClassID<ReplaceInputFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -0700268 this->registerChildProcessor(std::move(child));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700269 }
270
271 const char* name() const override { return "Replace Color"; }
272
egdaniel57d3b032015-11-13 11:57:27 -0800273 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800274 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700275 public:
276 GLFP() : fHaveSetColor(false) {}
277 void emitCode(EmitArgs& args) override {
278 const char* colorName;
cdalton5e58cee2016-02-11 12:49:47 -0800279 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
280 kVec4f_GrSLType,
281 kDefault_GrSLPrecision,
282 "Color", &colorName);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700283 this->emitChild(0, colorName, args);
284 }
285
286 private:
egdaniel018fb622015-10-28 07:26:40 -0700287 void onSetData(const GrGLSLProgramDataManager& pdman,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700288 const GrProcessor& fp) override {
289 GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
290 if (!fHaveSetColor || color != fPreviousColor) {
egdaniel018fb622015-10-28 07:26:40 -0700291 static const float scale = 1.f / 255.f;
292 float floatColor[4] = {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700293 GrColorUnpackR(color) * scale,
294 GrColorUnpackG(color) * scale,
295 GrColorUnpackB(color) * scale,
296 GrColorUnpackA(color) * scale,
297 };
298 pdman.set4fv(fColorUni, 1, floatColor);
299 fPreviousColor = color;
300 fHaveSetColor = true;
301 }
302 }
303
egdaniel018fb622015-10-28 07:26:40 -0700304 GrGLSLProgramDataManager::UniformHandle fColorUni;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700305 bool fHaveSetColor;
306 GrColor fPreviousColor;
307 };
308
309 return new GLFP;
310 }
311
312 private:
egdaniel57d3b032015-11-13 11:57:27 -0800313 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override
314 {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700315
316 bool onIsEqual(const GrFragmentProcessor& that) const override {
317 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
318 }
319
320 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
321 inout->setToOther(kRGBA_GrColorComponentFlags, fColor,
322 GrInvariantOutput::kWillNot_ReadInput);
323 this->childProcessor(0).computeInvariantOutput(inout);
324 }
325
326 GrColor fColor;
327 };
328
329 GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
330 fp->computeInvariantOutput(&childOut);
331 if (childOut.willUseInputColor()) {
bungeman06ca8ec2016-06-09 08:01:03 -0700332 return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700333 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700334 return fp;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700335 }
336}
bsalomone25eea42015-09-29 06:38:55 -0700337
bungeman06ca8ec2016-06-09 08:01:03 -0700338sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
bsalomone25eea42015-09-29 06:38:55 -0700339 int cnt) {
340 class SeriesFragmentProcessor : public GrFragmentProcessor {
341 public:
bungeman06ca8ec2016-06-09 08:01:03 -0700342 SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt){
bsalomone25eea42015-09-29 06:38:55 -0700343 SkASSERT(cnt > 1);
344 this->initClassID<SeriesFragmentProcessor>();
345 for (int i = 0; i < cnt; ++i) {
bungeman06ca8ec2016-06-09 08:01:03 -0700346 this->registerChildProcessor(std::move(children[i]));
bsalomone25eea42015-09-29 06:38:55 -0700347 }
348 }
349
350 const char* name() const override { return "Series"; }
351
egdaniel57d3b032015-11-13 11:57:27 -0800352 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800353 class GLFP : public GrGLSLFragmentProcessor {
bsalomone25eea42015-09-29 06:38:55 -0700354 public:
bsalomone25eea42015-09-29 06:38:55 -0700355 void emitCode(EmitArgs& args) override {
dvonbeckca9eeab2016-07-06 12:00:06 -0700356 // First guy's input might be nil.
357 SkString temp("out0");
358 this->emitChild(0, args.fInputColor, &temp, args);
359 SkString input = temp;
360 for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
bsalomone25eea42015-09-29 06:38:55 -0700361 temp.printf("out%d", i);
362 this->emitChild(i, input.c_str(), &temp, args);
363 input = temp;
364 }
365 // Last guy writes to our output variable.
366 this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
367 }
368 };
369 return new GLFP;
370 }
371
372 private:
egdaniel57d3b032015-11-13 11:57:27 -0800373 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
bsalomone25eea42015-09-29 06:38:55 -0700374
375 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
376
377 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
378 GrProcOptInfo info;
bungeman06ca8ec2016-06-09 08:01:03 -0700379 info.calcWithInitialValues(fChildProcessors.begin(), fChildProcessors.count(),
380 inout->color(), inout->validFlags(), false, false);
bsalomone25eea42015-09-29 06:38:55 -0700381 for (int i = 0; i < this->numChildProcessors(); ++i) {
382 this->childProcessor(i).computeInvariantOutput(inout);
383 }
384 }
385 };
386
387 if (!cnt) {
388 return nullptr;
389 }
390
391 // Run the through the series, do the invariant output processing, and look for eliminations.
bsalomone25eea42015-09-29 06:38:55 -0700392 GrProcOptInfo info;
bungeman06ca8ec2016-06-09 08:01:03 -0700393 info.calcWithInitialValues(sk_sp_address_as_pointer_address(series), cnt,
394 0x0, kNone_GrColorComponentFlags, false, false);
bsalomone25eea42015-09-29 06:38:55 -0700395 if (kRGBA_GrColorComponentFlags == info.validFlags()) {
bungeman06ca8ec2016-06-09 08:01:03 -0700396 return GrConstColorProcessor::Make(info.color(), GrConstColorProcessor::kIgnore_InputMode);
397 }
398
399 SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
400
401 int firstIdx = info.firstEffectiveProcessorIndex();
402 cnt -= firstIdx;
403 if (firstIdx > 0 && info.inputColorIsUsed()) {
404 sk_sp<GrFragmentProcessor> colorFP(GrConstColorProcessor::Make(
405 info.inputColorToFirstEffectiveProccesor(), GrConstColorProcessor::kIgnore_InputMode));
406 cnt += 1;
407 replacementSeries.reserve(cnt);
408 replacementSeries.emplace_back(std::move(colorFP));
409 for (int i = 0; i < cnt - 1; ++i) {
410 replacementSeries.emplace_back(std::move(series[firstIdx + i]));
bsalomone25eea42015-09-29 06:38:55 -0700411 }
bungeman06ca8ec2016-06-09 08:01:03 -0700412 series = replacementSeries.begin();
413 } else {
414 series += firstIdx;
415 cnt -= firstIdx;
bsalomone25eea42015-09-29 06:38:55 -0700416 }
417
418 if (1 == cnt) {
bungeman06ca8ec2016-06-09 08:01:03 -0700419 return series[0];
bsalomone25eea42015-09-29 06:38:55 -0700420 }
bungeman06ca8ec2016-06-09 08:01:03 -0700421 return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
bsalomone25eea42015-09-29 06:38:55 -0700422}