blob: fdba610356c2dd74a0c786027809a29b0255f7a0 [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 }
109
bungeman06ca8ec2016-06-09 08:01:03 -0700110 int index = fChildProcessors.count();
111 fChildProcessors.push_back(child.release());
112
bsalomonbf877302015-09-22 09:06:13 -0700113 return index;
114}
115
116void GrFragmentProcessor::notifyRefCntIsZero() const {
117 // See comment above GrProgramElement for a detailed explanation of why we do this.
118 for (int i = 0; i < fChildProcessors.count(); ++i) {
119 fChildProcessors[i]->addPendingExecution();
120 fChildProcessors[i]->unref();
121 }
122}
123
124bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
125 if (this->numTransforms() != that.numTransforms()) {
126 return false;
127 }
128 int count = this->numTransforms();
129 for (int i = 0; i < count; ++i) {
130 if (this->coordTransform(i) != that.coordTransform(i)) {
131 return false;
132 }
133 }
134 return true;
135}
136
bungeman06ca8ec2016-06-09 08:01:03 -0700137sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
138 sk_sp<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700139 if (!fp) {
140 return nullptr;
141 }
bungeman06ca8ec2016-06-09 08:01:03 -0700142 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp),
143 SkXfermode::kDstIn_Mode);
bsalomonbf877302015-09-22 09:06:13 -0700144}
145
dvonbeckc526da92016-07-20 11:20:30 -0700146sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
147
148 class PremulInputFragmentProcessor : public GrFragmentProcessor {
149 public:
150 PremulInputFragmentProcessor() {
151 this->initClassID<PremulInputFragmentProcessor>();
152 }
153
154 const char* name() const override { return "PremultiplyInput"; }
155
156 private:
157 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
158 class GLFP : public GrGLSLFragmentProcessor {
159 public:
160 void emitCode(EmitArgs& args) override {
161 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
162
163 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
164 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
165 args.fOutputColor, args.fInputColor);
166 }
167 };
168 return new GLFP;
169 }
170
171 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
172
173 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
174
175 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
176 inout->premulFourChannelColor();
177 }
178 };
179 if (!fp) {
180 return nullptr;
181 }
182 sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
183 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
184}
185
bungeman06ca8ec2016-06-09 08:01:03 -0700186sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputUnpremulColor(
187 sk_sp<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700188
189 class PremulFragmentProcessor : public GrFragmentProcessor {
190 public:
bungeman06ca8ec2016-06-09 08:01:03 -0700191 PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700192 this->initClassID<PremulFragmentProcessor>();
193 this->registerChildProcessor(processor);
194 }
195
196 const char* name() const override { return "Premultiply"; }
197
198 private:
egdaniel57d3b032015-11-13 11:57:27 -0800199 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800200 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700201 public:
bsalomonf1b7a1d2015-09-28 06:26:28 -0700202 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800203 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700204 this->emitChild(0, nullptr, args);
egdaniel4ca2e602015-11-18 08:01:26 -0800205 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700206 args.fInputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800207 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700208 }
209 };
210 return new GLFP;
211 }
212
egdaniel57d3b032015-11-13 11:57:27 -0800213 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700214
215 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
216
217 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
218 // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
219 if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
220 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
221 return;
222 }
223
224 GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
225 this->childProcessor(0).computeInvariantOutput(&childOutput);
226
227 if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
228 inout->mulByKnownFourComponents(0x0);
229 return;
230 }
231 GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
232 GrColor c0 = GrPremulColor(inout->color());
233 GrColor c1 = childOutput.color();
234 GrColor color = 0x0;
235 if (commonFlags & kR_GrColorComponentFlag) {
236 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
237 GrColor_SHIFT_R;
238 }
239 if (commonFlags & kG_GrColorComponentFlag) {
240 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
241 GrColor_SHIFT_G;
242 }
243 if (commonFlags & kB_GrColorComponentFlag) {
244 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
245 GrColor_SHIFT_B;
246 }
247 inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
248 }
249 };
250 if (!fp) {
251 return nullptr;
252 }
bungeman06ca8ec2016-06-09 08:01:03 -0700253 return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700254}
255
256//////////////////////////////////////////////////////////////////////////////
257
bungeman06ca8ec2016-06-09 08:01:03 -0700258sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700259 GrColor color) {
260 class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
261 public:
bungeman06ca8ec2016-06-09 08:01:03 -0700262 ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor color)
bsalomonf1b7a1d2015-09-28 06:26:28 -0700263 : fColor(color) {
264 this->initClassID<ReplaceInputFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -0700265 this->registerChildProcessor(std::move(child));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700266 }
267
268 const char* name() const override { return "Replace Color"; }
269
egdaniel57d3b032015-11-13 11:57:27 -0800270 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800271 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700272 public:
273 GLFP() : fHaveSetColor(false) {}
274 void emitCode(EmitArgs& args) override {
275 const char* colorName;
cdalton5e58cee2016-02-11 12:49:47 -0800276 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
277 kVec4f_GrSLType,
278 kDefault_GrSLPrecision,
279 "Color", &colorName);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700280 this->emitChild(0, colorName, args);
281 }
282
283 private:
egdaniel018fb622015-10-28 07:26:40 -0700284 void onSetData(const GrGLSLProgramDataManager& pdman,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700285 const GrProcessor& fp) override {
286 GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
287 if (!fHaveSetColor || color != fPreviousColor) {
egdaniel018fb622015-10-28 07:26:40 -0700288 static const float scale = 1.f / 255.f;
289 float floatColor[4] = {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700290 GrColorUnpackR(color) * scale,
291 GrColorUnpackG(color) * scale,
292 GrColorUnpackB(color) * scale,
293 GrColorUnpackA(color) * scale,
294 };
295 pdman.set4fv(fColorUni, 1, floatColor);
296 fPreviousColor = color;
297 fHaveSetColor = true;
298 }
299 }
300
egdaniel018fb622015-10-28 07:26:40 -0700301 GrGLSLProgramDataManager::UniformHandle fColorUni;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700302 bool fHaveSetColor;
303 GrColor fPreviousColor;
304 };
305
306 return new GLFP;
307 }
308
309 private:
egdaniel57d3b032015-11-13 11:57:27 -0800310 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override
311 {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700312
313 bool onIsEqual(const GrFragmentProcessor& that) const override {
314 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
315 }
316
317 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
318 inout->setToOther(kRGBA_GrColorComponentFlags, fColor,
319 GrInvariantOutput::kWillNot_ReadInput);
320 this->childProcessor(0).computeInvariantOutput(inout);
321 }
322
323 GrColor fColor;
324 };
325
326 GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
327 fp->computeInvariantOutput(&childOut);
328 if (childOut.willUseInputColor()) {
bungeman06ca8ec2016-06-09 08:01:03 -0700329 return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700330 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700331 return fp;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700332 }
333}
bsalomone25eea42015-09-29 06:38:55 -0700334
bungeman06ca8ec2016-06-09 08:01:03 -0700335sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
bsalomone25eea42015-09-29 06:38:55 -0700336 int cnt) {
337 class SeriesFragmentProcessor : public GrFragmentProcessor {
338 public:
bungeman06ca8ec2016-06-09 08:01:03 -0700339 SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt){
bsalomone25eea42015-09-29 06:38:55 -0700340 SkASSERT(cnt > 1);
341 this->initClassID<SeriesFragmentProcessor>();
342 for (int i = 0; i < cnt; ++i) {
bungeman06ca8ec2016-06-09 08:01:03 -0700343 this->registerChildProcessor(std::move(children[i]));
bsalomone25eea42015-09-29 06:38:55 -0700344 }
345 }
346
347 const char* name() const override { return "Series"; }
348
egdaniel57d3b032015-11-13 11:57:27 -0800349 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800350 class GLFP : public GrGLSLFragmentProcessor {
bsalomone25eea42015-09-29 06:38:55 -0700351 public:
bsalomone25eea42015-09-29 06:38:55 -0700352 void emitCode(EmitArgs& args) override {
dvonbeckca9eeab2016-07-06 12:00:06 -0700353 // First guy's input might be nil.
354 SkString temp("out0");
355 this->emitChild(0, args.fInputColor, &temp, args);
356 SkString input = temp;
357 for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
bsalomone25eea42015-09-29 06:38:55 -0700358 temp.printf("out%d", i);
359 this->emitChild(i, input.c_str(), &temp, args);
360 input = temp;
361 }
362 // Last guy writes to our output variable.
363 this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
364 }
365 };
366 return new GLFP;
367 }
368
369 private:
egdaniel57d3b032015-11-13 11:57:27 -0800370 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
bsalomone25eea42015-09-29 06:38:55 -0700371
372 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
373
374 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
375 GrProcOptInfo info;
bungeman06ca8ec2016-06-09 08:01:03 -0700376 info.calcWithInitialValues(fChildProcessors.begin(), fChildProcessors.count(),
377 inout->color(), inout->validFlags(), false, false);
bsalomone25eea42015-09-29 06:38:55 -0700378 for (int i = 0; i < this->numChildProcessors(); ++i) {
379 this->childProcessor(i).computeInvariantOutput(inout);
380 }
381 }
382 };
383
384 if (!cnt) {
385 return nullptr;
386 }
387
388 // Run the through the series, do the invariant output processing, and look for eliminations.
bsalomone25eea42015-09-29 06:38:55 -0700389 GrProcOptInfo info;
bungeman06ca8ec2016-06-09 08:01:03 -0700390 info.calcWithInitialValues(sk_sp_address_as_pointer_address(series), cnt,
391 0x0, kNone_GrColorComponentFlags, false, false);
bsalomone25eea42015-09-29 06:38:55 -0700392 if (kRGBA_GrColorComponentFlags == info.validFlags()) {
bungeman06ca8ec2016-06-09 08:01:03 -0700393 return GrConstColorProcessor::Make(info.color(), GrConstColorProcessor::kIgnore_InputMode);
394 }
395
396 SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
397
398 int firstIdx = info.firstEffectiveProcessorIndex();
399 cnt -= firstIdx;
400 if (firstIdx > 0 && info.inputColorIsUsed()) {
401 sk_sp<GrFragmentProcessor> colorFP(GrConstColorProcessor::Make(
402 info.inputColorToFirstEffectiveProccesor(), GrConstColorProcessor::kIgnore_InputMode));
403 cnt += 1;
404 replacementSeries.reserve(cnt);
405 replacementSeries.emplace_back(std::move(colorFP));
406 for (int i = 0; i < cnt - 1; ++i) {
407 replacementSeries.emplace_back(std::move(series[firstIdx + i]));
bsalomone25eea42015-09-29 06:38:55 -0700408 }
bungeman06ca8ec2016-06-09 08:01:03 -0700409 series = replacementSeries.begin();
410 } else {
411 series += firstIdx;
412 cnt -= firstIdx;
bsalomone25eea42015-09-29 06:38:55 -0700413 }
414
415 if (1 == cnt) {
bungeman06ca8ec2016-06-09 08:01:03 -0700416 return series[0];
bsalomone25eea42015-09-29 06:38:55 -0700417 }
bungeman06ca8ec2016-06-09 08:01:03 -0700418 return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
bsalomone25eea42015-09-29 06:38:55 -0700419}