blob: 9524c84df1e0d881b2f94524194385bfc5edc07d [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
92int GrFragmentProcessor::registerChildProcessor(const GrFragmentProcessor* child) {
93 // 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
104 int index = fChildProcessors.count();
105 fChildProcessors.push_back(SkRef(child));
106
cdalton87332102016-02-26 12:22:02 -0800107 this->combineRequiredFeatures(*child);
bsalomonbf877302015-09-22 09:06:13 -0700108
109 if (child->usesLocalCoords()) {
110 fUsesLocalCoords = true;
111 }
112
113 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
bsalomonf1b7a1d2015-09-28 06:26:28 -0700137const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputAlpha(
bsalomonbf877302015-09-22 09:06:13 -0700138 const GrFragmentProcessor* fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700139 if (!fp) {
140 return nullptr;
141 }
bsalomonbf877302015-09-22 09:06:13 -0700142 return GrXfermodeFragmentProcessor::CreateFromDstProcessor(fp, SkXfermode::kDstIn_Mode);
143}
144
bsalomonf1b7a1d2015-09-28 06:26:28 -0700145const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputUnpremulColor(
146 const GrFragmentProcessor* fp) {
147
148 class PremulFragmentProcessor : public GrFragmentProcessor {
149 public:
150 PremulFragmentProcessor(const GrFragmentProcessor* processor) {
151 this->initClassID<PremulFragmentProcessor>();
152 this->registerChildProcessor(processor);
153 }
154
155 const char* name() const override { return "Premultiply"; }
156
157 private:
egdaniel57d3b032015-11-13 11:57:27 -0800158 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800159 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700160 public:
bsalomonf1b7a1d2015-09-28 06:26:28 -0700161 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800162 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700163 this->emitChild(0, nullptr, args);
egdaniel4ca2e602015-11-18 08:01:26 -0800164 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700165 args.fInputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800166 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700167 }
168 };
169 return new GLFP;
170 }
171
egdaniel57d3b032015-11-13 11:57:27 -0800172 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700173
174 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
175
176 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
177 // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
178 if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
179 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
180 return;
181 }
182
183 GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
184 this->childProcessor(0).computeInvariantOutput(&childOutput);
185
186 if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
187 inout->mulByKnownFourComponents(0x0);
188 return;
189 }
190 GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
191 GrColor c0 = GrPremulColor(inout->color());
192 GrColor c1 = childOutput.color();
193 GrColor color = 0x0;
194 if (commonFlags & kR_GrColorComponentFlag) {
195 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
196 GrColor_SHIFT_R;
197 }
198 if (commonFlags & kG_GrColorComponentFlag) {
199 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
200 GrColor_SHIFT_G;
201 }
202 if (commonFlags & kB_GrColorComponentFlag) {
203 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
204 GrColor_SHIFT_B;
205 }
206 inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
207 }
208 };
209 if (!fp) {
210 return nullptr;
211 }
212 return new PremulFragmentProcessor(fp);
213}
214
215//////////////////////////////////////////////////////////////////////////////
216
217const GrFragmentProcessor* GrFragmentProcessor::OverrideInput(const GrFragmentProcessor* fp,
218 GrColor color) {
219 class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
220 public:
221 ReplaceInputFragmentProcessor(const GrFragmentProcessor* child, GrColor color)
222 : fColor(color) {
223 this->initClassID<ReplaceInputFragmentProcessor>();
224 this->registerChildProcessor(child);
225 }
226
227 const char* name() const override { return "Replace Color"; }
228
egdaniel57d3b032015-11-13 11:57:27 -0800229 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800230 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700231 public:
232 GLFP() : fHaveSetColor(false) {}
233 void emitCode(EmitArgs& args) override {
234 const char* colorName;
cdalton5e58cee2016-02-11 12:49:47 -0800235 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
236 kVec4f_GrSLType,
237 kDefault_GrSLPrecision,
238 "Color", &colorName);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700239 this->emitChild(0, colorName, args);
240 }
241
242 private:
egdaniel018fb622015-10-28 07:26:40 -0700243 void onSetData(const GrGLSLProgramDataManager& pdman,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700244 const GrProcessor& fp) override {
245 GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
246 if (!fHaveSetColor || color != fPreviousColor) {
egdaniel018fb622015-10-28 07:26:40 -0700247 static const float scale = 1.f / 255.f;
248 float floatColor[4] = {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700249 GrColorUnpackR(color) * scale,
250 GrColorUnpackG(color) * scale,
251 GrColorUnpackB(color) * scale,
252 GrColorUnpackA(color) * scale,
253 };
254 pdman.set4fv(fColorUni, 1, floatColor);
255 fPreviousColor = color;
256 fHaveSetColor = true;
257 }
258 }
259
egdaniel018fb622015-10-28 07:26:40 -0700260 GrGLSLProgramDataManager::UniformHandle fColorUni;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700261 bool fHaveSetColor;
262 GrColor fPreviousColor;
263 };
264
265 return new GLFP;
266 }
267
268 private:
egdaniel57d3b032015-11-13 11:57:27 -0800269 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override
270 {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700271
272 bool onIsEqual(const GrFragmentProcessor& that) const override {
273 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
274 }
275
276 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
277 inout->setToOther(kRGBA_GrColorComponentFlags, fColor,
278 GrInvariantOutput::kWillNot_ReadInput);
279 this->childProcessor(0).computeInvariantOutput(inout);
280 }
281
282 GrColor fColor;
283 };
284
285 GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
286 fp->computeInvariantOutput(&childOut);
287 if (childOut.willUseInputColor()) {
288 return new ReplaceInputFragmentProcessor(fp, color);
289 } else {
290 return SkRef(fp);
291 }
292}
bsalomone25eea42015-09-29 06:38:55 -0700293
294const GrFragmentProcessor* GrFragmentProcessor::RunInSeries(const GrFragmentProcessor* series[],
295 int cnt) {
296 class SeriesFragmentProcessor : public GrFragmentProcessor {
297 public:
298 SeriesFragmentProcessor(const GrFragmentProcessor* children[], int cnt){
299 SkASSERT(cnt > 1);
300 this->initClassID<SeriesFragmentProcessor>();
301 for (int i = 0; i < cnt; ++i) {
302 this->registerChildProcessor(children[i]);
303 }
304 }
305
306 const char* name() const override { return "Series"; }
307
egdaniel57d3b032015-11-13 11:57:27 -0800308 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800309 class GLFP : public GrGLSLFragmentProcessor {
bsalomone25eea42015-09-29 06:38:55 -0700310 public:
bsalomone25eea42015-09-29 06:38:55 -0700311 void emitCode(EmitArgs& args) override {
312 SkString input(args.fInputColor);
313 for (int i = 0; i < this->numChildProcessors() - 1; ++i) {
314 SkString temp;
315 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:
egdaniel57d3b032015-11-13 11:57:27 -0800327 void onGetGLSLProcessorKey(const GrGLSLCaps&, 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 {
332 GrProcOptInfo info;
333 SkTDArray<const GrFragmentProcessor*> children;
334 children.setCount(this->numChildProcessors());
335 for (int i = 0; i < children.count(); ++i) {
336 children[i] = &this->childProcessor(i);
337 }
338 info.calcWithInitialValues(children.begin(), children.count(), inout->color(),
339 inout->validFlags(), false, false);
340 for (int i = 0; i < this->numChildProcessors(); ++i) {
341 this->childProcessor(i).computeInvariantOutput(inout);
342 }
343 }
344 };
345
346 if (!cnt) {
347 return nullptr;
348 }
349
350 // Run the through the series, do the invariant output processing, and look for eliminations.
351 SkTDArray<const GrFragmentProcessor*> replacementSeries;
352 SkAutoTUnref<const GrFragmentProcessor> colorFP;
353 GrProcOptInfo info;
354
355 info.calcWithInitialValues(series, cnt, 0x0, kNone_GrColorComponentFlags, false, false);
356 if (kRGBA_GrColorComponentFlags == info.validFlags()) {
357 return GrConstColorProcessor::Create(info.color(),
358 GrConstColorProcessor::kIgnore_InputMode);
359 } else {
360 int firstIdx = info.firstEffectiveProcessorIndex();
361 cnt -= firstIdx;
362 if (firstIdx > 0 && info.inputColorIsUsed()) {
363 colorFP.reset(GrConstColorProcessor::Create(info.inputColorToFirstEffectiveProccesor(),
364 GrConstColorProcessor::kIgnore_InputMode));
365 cnt += 1;
366 replacementSeries.setCount(cnt);
367 replacementSeries[0] = colorFP;
368 for (int i = 0; i < cnt - 1; ++i) {
369 replacementSeries[i + 1] = series[firstIdx + i];
370 }
371 series = replacementSeries.begin();
372 } else {
373 series += firstIdx;
374 cnt -= firstIdx;
375 }
376 }
377
378 if (1 == cnt) {
379 return SkRef(series[0]);
380 } else {
381 return new SeriesFragmentProcessor(series, cnt);
382 }
383}