blob: 977974d78d91c8d184d6be9f942d89240a8e3dce [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"
bsalomona624bf32016-09-20 09:12:47 -070011#include "GrPipeline.h"
egdaniel7ea439b2015-12-03 09:20:44 -080012#include "GrProcOptInfo.h"
egdaniel64c47282015-11-13 06:54:19 -080013#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080014#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070015#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080016#include "glsl/GrGLSLUniformHandler.h"
bsalomone25eea42015-09-29 06:38:55 -070017#include "effects/GrConstColorProcessor.h"
bsalomonbf877302015-09-22 09:06:13 -070018#include "effects/GrXfermodeFragmentProcessor.h"
19
20GrFragmentProcessor::~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
bsalomon7312ff82016-09-12 08:55:38 -070028bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
bsalomonbf877302015-09-22 09:06:13 -070029 if (this->classID() != that.classID() ||
Brian Salomonf9f45122016-11-29 11:59:17 -050030 !this->hasSameSamplersAndAccesses(that)) {
bsalomonbf877302015-09-22 09:06:13 -070031 return false;
32 }
bsalomon7312ff82016-09-12 08:55:38 -070033 if (!this->hasSameTransforms(that)) {
bsalomonbf877302015-09-22 09:06:13 -070034 return false;
35 }
36 if (!this->onIsEqual(that)) {
37 return false;
38 }
39 if (this->numChildProcessors() != that.numChildProcessors()) {
40 return false;
41 }
42 for (int i = 0; i < this->numChildProcessors(); ++i) {
bsalomon7312ff82016-09-12 08:55:38 -070043 if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
bsalomonbf877302015-09-22 09:06:13 -070044 return false;
45 }
46 }
47 return true;
48}
49
egdaniel57d3b032015-11-13 11:57:27 -080050GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
51 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070052 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
53 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -080054 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070055 }
56 return glFragProc;
57}
58
bsalomonbf877302015-09-22 09:06:13 -070059void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
bsalomonbf877302015-09-22 09:06:13 -070060 fCoordTransforms.push_back(transform);
Brian Salomon2ebd0c82016-10-03 17:15:28 -040061 fUsesLocalCoords = true;
bsalomonbf877302015-09-22 09:06:13 -070062 SkDEBUGCODE(transform->setInProcessor();)
bsalomonbf877302015-09-22 09:06:13 -070063}
64
bungeman06ca8ec2016-06-09 08:01:03 -070065int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
cdalton87332102016-02-26 12:22:02 -080066 this->combineRequiredFeatures(*child);
bsalomonbf877302015-09-22 09:06:13 -070067
68 if (child->usesLocalCoords()) {
69 fUsesLocalCoords = true;
70 }
dvonbeck9b03e7b2016-08-01 11:01:56 -070071 if (child->usesDistanceVectorField()) {
72 fUsesDistanceVectorField = true;
73 }
bsalomonbf877302015-09-22 09:06:13 -070074
bungeman06ca8ec2016-06-09 08:01:03 -070075 int index = fChildProcessors.count();
76 fChildProcessors.push_back(child.release());
77
bsalomonbf877302015-09-22 09:06:13 -070078 return index;
79}
80
81void GrFragmentProcessor::notifyRefCntIsZero() const {
82 // See comment above GrProgramElement for a detailed explanation of why we do this.
83 for (int i = 0; i < fChildProcessors.count(); ++i) {
84 fChildProcessors[i]->addPendingExecution();
85 fChildProcessors[i]->unref();
86 }
87}
88
89bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
bsalomona624bf32016-09-20 09:12:47 -070090 if (this->numCoordTransforms() != that.numCoordTransforms()) {
bsalomonbf877302015-09-22 09:06:13 -070091 return false;
92 }
bsalomona624bf32016-09-20 09:12:47 -070093 int count = this->numCoordTransforms();
bsalomonbf877302015-09-22 09:06:13 -070094 for (int i = 0; i < count; ++i) {
95 if (this->coordTransform(i) != that.coordTransform(i)) {
96 return false;
97 }
98 }
99 return true;
100}
101
bungeman06ca8ec2016-06-09 08:01:03 -0700102sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
103 sk_sp<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700104 if (!fp) {
105 return nullptr;
106 }
Mike Reed7d954ad2016-10-28 15:42:34 -0400107 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
bsalomonbf877302015-09-22 09:06:13 -0700108}
109
dvonbeckc526da92016-07-20 11:20:30 -0700110sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
111
112 class PremulInputFragmentProcessor : public GrFragmentProcessor {
113 public:
114 PremulInputFragmentProcessor() {
115 this->initClassID<PremulInputFragmentProcessor>();
116 }
117
118 const char* name() const override { return "PremultiplyInput"; }
119
120 private:
121 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
122 class GLFP : public GrGLSLFragmentProcessor {
123 public:
124 void emitCode(EmitArgs& args) override {
125 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
126
127 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
128 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
129 args.fOutputColor, args.fInputColor);
130 }
131 };
132 return new GLFP;
133 }
134
Brian Salomon94efbf52016-11-29 13:43:05 -0500135 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
dvonbeckc526da92016-07-20 11:20:30 -0700136
137 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
138
139 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
140 inout->premulFourChannelColor();
141 }
142 };
143 if (!fp) {
144 return nullptr;
145 }
146 sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
147 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
148}
149
bungeman06ca8ec2016-06-09 08:01:03 -0700150sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputUnpremulColor(
151 sk_sp<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700152
153 class PremulFragmentProcessor : public GrFragmentProcessor {
154 public:
bungeman06ca8ec2016-06-09 08:01:03 -0700155 PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700156 this->initClassID<PremulFragmentProcessor>();
157 this->registerChildProcessor(processor);
158 }
159
160 const char* name() const override { return "Premultiply"; }
161
162 private:
egdaniel57d3b032015-11-13 11:57:27 -0800163 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800164 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700165 public:
bsalomonf1b7a1d2015-09-28 06:26:28 -0700166 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800167 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700168 this->emitChild(0, nullptr, args);
egdaniel4ca2e602015-11-18 08:01:26 -0800169 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700170 args.fInputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800171 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700172 }
173 };
174 return new GLFP;
175 }
176
Brian Salomon94efbf52016-11-29 13:43:05 -0500177 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700178
179 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
180
181 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
182 // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
183 if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
184 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
185 return;
186 }
187
Brian Salomonaab259e2017-01-17 10:44:34 -0500188 GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700189 this->childProcessor(0).computeInvariantOutput(&childOutput);
190
191 if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
192 inout->mulByKnownFourComponents(0x0);
193 return;
194 }
195 GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
196 GrColor c0 = GrPremulColor(inout->color());
197 GrColor c1 = childOutput.color();
198 GrColor color = 0x0;
199 if (commonFlags & kR_GrColorComponentFlag) {
200 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
201 GrColor_SHIFT_R;
202 }
203 if (commonFlags & kG_GrColorComponentFlag) {
204 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
205 GrColor_SHIFT_G;
206 }
207 if (commonFlags & kB_GrColorComponentFlag) {
208 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
209 GrColor_SHIFT_B;
210 }
211 inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
212 }
213 };
214 if (!fp) {
215 return nullptr;
216 }
bungeman06ca8ec2016-06-09 08:01:03 -0700217 return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700218}
219
220//////////////////////////////////////////////////////////////////////////////
221
bungeman06ca8ec2016-06-09 08:01:03 -0700222sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
brianosman4cea3b92016-09-08 09:33:50 -0700223 GrColor4f color) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700224 class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
225 public:
brianosman4cea3b92016-09-08 09:33:50 -0700226 ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
bsalomonf1b7a1d2015-09-28 06:26:28 -0700227 : fColor(color) {
228 this->initClassID<ReplaceInputFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -0700229 this->registerChildProcessor(std::move(child));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700230 }
231
232 const char* name() const override { return "Replace Color"; }
233
egdaniel57d3b032015-11-13 11:57:27 -0800234 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800235 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700236 public:
237 GLFP() : fHaveSetColor(false) {}
238 void emitCode(EmitArgs& args) override {
239 const char* colorName;
cdalton5e58cee2016-02-11 12:49:47 -0800240 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
241 kVec4f_GrSLType,
242 kDefault_GrSLPrecision,
243 "Color", &colorName);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700244 this->emitChild(0, colorName, args);
245 }
246
247 private:
egdaniel018fb622015-10-28 07:26:40 -0700248 void onSetData(const GrGLSLProgramDataManager& pdman,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700249 const GrProcessor& fp) override {
brianosman4cea3b92016-09-08 09:33:50 -0700250 GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700251 if (!fHaveSetColor || color != fPreviousColor) {
brianosman4cea3b92016-09-08 09:33:50 -0700252 pdman.set4fv(fColorUni, 1, color.fRGBA);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700253 fPreviousColor = color;
254 fHaveSetColor = true;
255 }
256 }
257
egdaniel018fb622015-10-28 07:26:40 -0700258 GrGLSLProgramDataManager::UniformHandle fColorUni;
brianosman4cea3b92016-09-08 09:33:50 -0700259 bool fHaveSetColor;
260 GrColor4f fPreviousColor;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700261 };
262
263 return new GLFP;
264 }
265
266 private:
Brian Salomon94efbf52016-11-29 13:43:05 -0500267 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
egdaniel57d3b032015-11-13 11:57:27 -0800268 {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700269
270 bool onIsEqual(const GrFragmentProcessor& that) const override {
271 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
272 }
273
274 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
brianosman4cea3b92016-09-08 09:33:50 -0700275 inout->setToOther(kRGBA_GrColorComponentFlags, fColor.toGrColor(),
bsalomonf1b7a1d2015-09-28 06:26:28 -0700276 GrInvariantOutput::kWillNot_ReadInput);
277 this->childProcessor(0).computeInvariantOutput(inout);
278 }
279
brianosman4cea3b92016-09-08 09:33:50 -0700280 GrColor4f fColor;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700281 };
282
Brian Salomonaab259e2017-01-17 10:44:34 -0500283 GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700284 fp->computeInvariantOutput(&childOut);
285 if (childOut.willUseInputColor()) {
bungeman06ca8ec2016-06-09 08:01:03 -0700286 return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700287 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700288 return fp;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700289 }
290}
bsalomone25eea42015-09-29 06:38:55 -0700291
bungeman06ca8ec2016-06-09 08:01:03 -0700292sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
bsalomone25eea42015-09-29 06:38:55 -0700293 int cnt) {
294 class SeriesFragmentProcessor : public GrFragmentProcessor {
295 public:
bungeman06ca8ec2016-06-09 08:01:03 -0700296 SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt){
bsalomone25eea42015-09-29 06:38:55 -0700297 SkASSERT(cnt > 1);
298 this->initClassID<SeriesFragmentProcessor>();
299 for (int i = 0; i < cnt; ++i) {
bungeman06ca8ec2016-06-09 08:01:03 -0700300 this->registerChildProcessor(std::move(children[i]));
bsalomone25eea42015-09-29 06:38:55 -0700301 }
302 }
303
304 const char* name() const override { return "Series"; }
305
egdaniel57d3b032015-11-13 11:57:27 -0800306 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800307 class GLFP : public GrGLSLFragmentProcessor {
bsalomone25eea42015-09-29 06:38:55 -0700308 public:
bsalomone25eea42015-09-29 06:38:55 -0700309 void emitCode(EmitArgs& args) override {
dvonbeckca9eeab2016-07-06 12:00:06 -0700310 // First guy's input might be nil.
311 SkString temp("out0");
312 this->emitChild(0, args.fInputColor, &temp, args);
313 SkString input = temp;
314 for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
bsalomone25eea42015-09-29 06:38:55 -0700315 temp.printf("out%d", i);
316 this->emitChild(i, input.c_str(), &temp, args);
317 input = temp;
318 }
319 // Last guy writes to our output variable.
320 this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
321 }
322 };
323 return new GLFP;
324 }
325
326 private:
Brian Salomon94efbf52016-11-29 13:43:05 -0500327 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bsalomone25eea42015-09-29 06:38:55 -0700328
329 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
330
331 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
bsalomone25eea42015-09-29 06:38:55 -0700332 for (int i = 0; i < this->numChildProcessors(); ++i) {
333 this->childProcessor(i).computeInvariantOutput(inout);
334 }
335 }
336 };
337
338 if (!cnt) {
339 return nullptr;
340 }
341
342 // Run the through the series, do the invariant output processing, and look for eliminations.
Brian Salomonaab259e2017-01-17 10:44:34 -0500343 GrProcOptInfo info(0x0, kNone_GrColorComponentFlags);
344 info.addProcessors(sk_sp_address_as_pointer_address(series), cnt);
bsalomone25eea42015-09-29 06:38:55 -0700345 if (kRGBA_GrColorComponentFlags == info.validFlags()) {
Brian Osman618d3042016-10-25 10:51:28 -0400346 // TODO: We need to preserve 4f and color spaces during invariant processing. This color
347 // has definitely lost precision, and could easily be in the wrong gamut (or have been
348 // built from colors in multiple spaces).
349 return GrConstColorProcessor::Make(GrColor4f::FromGrColor(info.color()),
350 GrConstColorProcessor::kIgnore_InputMode);
bungeman06ca8ec2016-06-09 08:01:03 -0700351 }
352
353 SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
354
355 int firstIdx = info.firstEffectiveProcessorIndex();
356 cnt -= firstIdx;
357 if (firstIdx > 0 && info.inputColorIsUsed()) {
Brian Osman618d3042016-10-25 10:51:28 -0400358 // See comment above - need to preserve 4f and color spaces during invariant processing.
bungeman06ca8ec2016-06-09 08:01:03 -0700359 sk_sp<GrFragmentProcessor> colorFP(GrConstColorProcessor::Make(
Brian Osman618d3042016-10-25 10:51:28 -0400360 GrColor4f::FromGrColor(info.inputColorToFirstEffectiveProccesor()),
361 GrConstColorProcessor::kIgnore_InputMode));
bungeman06ca8ec2016-06-09 08:01:03 -0700362 cnt += 1;
363 replacementSeries.reserve(cnt);
364 replacementSeries.emplace_back(std::move(colorFP));
365 for (int i = 0; i < cnt - 1; ++i) {
366 replacementSeries.emplace_back(std::move(series[firstIdx + i]));
bsalomone25eea42015-09-29 06:38:55 -0700367 }
bungeman06ca8ec2016-06-09 08:01:03 -0700368 series = replacementSeries.begin();
369 } else {
370 series += firstIdx;
371 cnt -= firstIdx;
bsalomone25eea42015-09-29 06:38:55 -0700372 }
373
374 if (1 == cnt) {
bungeman06ca8ec2016-06-09 08:01:03 -0700375 return series[0];
bsalomone25eea42015-09-29 06:38:55 -0700376 }
bungeman06ca8ec2016-06-09 08:01:03 -0700377 return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
bsalomone25eea42015-09-29 06:38:55 -0700378}
bsalomona624bf32016-09-20 09:12:47 -0700379
380//////////////////////////////////////////////////////////////////////////////
381
382GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
383 for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
384 fFPStack.push_back(&pipeline.getFragmentProcessor(i));
385 }
386}
387
388const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
389 if (fFPStack.empty()) {
390 return nullptr;
391 }
392 const GrFragmentProcessor* back = fFPStack.back();
393 fFPStack.pop_back();
394 for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
395 fFPStack.push_back(&back->childProcessor(i));
396 }
397 return back;
398}
399