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 "GrInvariantOutput.h"
11 #include "GrPipeline.h"
12 #include "GrProcOptInfo.h"
13 #include "glsl/GrGLSLFragmentProcessor.h"
14 #include "glsl/GrGLSLFragmentShaderBuilder.h"
15 #include "glsl/GrGLSLProgramDataManager.h"
16 #include "glsl/GrGLSLUniformHandler.h"
17 #include "effects/GrConstColorProcessor.h"
18 #include "effects/GrXfermodeFragmentProcessor.h"
19
~GrFragmentProcessor()20 GrFragmentProcessor::~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
isEqual(const GrFragmentProcessor & that) const28 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
29 if (this->classID() != that.classID() ||
30 !this->hasSameSamplers(that)) {
31 return false;
32 }
33 if (!this->hasSameTransforms(that)) {
34 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) {
43 if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
44 return false;
45 }
46 }
47 return true;
48 }
49
createGLSLInstance() const50 GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
51 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
52 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
53 for (int i = 0; i < fChildProcessors.count(); ++i) {
54 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
55 }
56 return glFragProc;
57 }
58
addTextureAccess(const GrTextureAccess * textureAccess)59 void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) {
60 INHERITED::addTextureAccess(textureAccess);
61 }
62
addBufferAccess(const GrBufferAccess * bufferAccess)63 void GrFragmentProcessor::addBufferAccess(const GrBufferAccess* bufferAccess) {
64 INHERITED::addBufferAccess(bufferAccess);
65 }
66
addCoordTransform(const GrCoordTransform * transform)67 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
68 fCoordTransforms.push_back(transform);
69 fUsesLocalCoords = true;
70 SkDEBUGCODE(transform->setInProcessor();)
71 }
72
registerChildProcessor(sk_sp<GrFragmentProcessor> child)73 int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
74 this->combineRequiredFeatures(*child);
75
76 if (child->usesLocalCoords()) {
77 fUsesLocalCoords = true;
78 }
79 if (child->usesDistanceVectorField()) {
80 fUsesDistanceVectorField = true;
81 }
82
83 int index = fChildProcessors.count();
84 fChildProcessors.push_back(child.release());
85
86 return index;
87 }
88
notifyRefCntIsZero() const89 void GrFragmentProcessor::notifyRefCntIsZero() const {
90 // See comment above GrProgramElement for a detailed explanation of why we do this.
91 for (int i = 0; i < fChildProcessors.count(); ++i) {
92 fChildProcessors[i]->addPendingExecution();
93 fChildProcessors[i]->unref();
94 }
95 }
96
hasSameTransforms(const GrFragmentProcessor & that) const97 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
98 if (this->numCoordTransforms() != that.numCoordTransforms()) {
99 return false;
100 }
101 int count = this->numCoordTransforms();
102 for (int i = 0; i < count; ++i) {
103 if (this->coordTransform(i) != that.coordTransform(i)) {
104 return false;
105 }
106 }
107 return true;
108 }
109
MulOutputByInputAlpha(sk_sp<GrFragmentProcessor> fp)110 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
111 sk_sp<GrFragmentProcessor> fp) {
112 if (!fp) {
113 return nullptr;
114 }
115 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp),
116 SkXfermode::kDstIn_Mode);
117 }
118
PremulInput(sk_sp<GrFragmentProcessor> fp)119 sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
120
121 class PremulInputFragmentProcessor : public GrFragmentProcessor {
122 public:
123 PremulInputFragmentProcessor() {
124 this->initClassID<PremulInputFragmentProcessor>();
125 }
126
127 const char* name() const override { return "PremultiplyInput"; }
128
129 private:
130 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
131 class GLFP : public GrGLSLFragmentProcessor {
132 public:
133 void emitCode(EmitArgs& args) override {
134 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
135
136 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
137 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
138 args.fOutputColor, args.fInputColor);
139 }
140 };
141 return new GLFP;
142 }
143
144 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
145
146 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
147
148 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
149 inout->premulFourChannelColor();
150 }
151 };
152 if (!fp) {
153 return nullptr;
154 }
155 sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
156 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
157 }
158
MulOutputByInputUnpremulColor(sk_sp<GrFragmentProcessor> fp)159 sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputUnpremulColor(
160 sk_sp<GrFragmentProcessor> fp) {
161
162 class PremulFragmentProcessor : public GrFragmentProcessor {
163 public:
164 PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
165 this->initClassID<PremulFragmentProcessor>();
166 this->registerChildProcessor(processor);
167 }
168
169 const char* name() const override { return "Premultiply"; }
170
171 private:
172 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
173 class GLFP : public GrGLSLFragmentProcessor {
174 public:
175 void emitCode(EmitArgs& args) override {
176 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
177 this->emitChild(0, nullptr, args);
178 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
179 args.fInputColor);
180 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
181 }
182 };
183 return new GLFP;
184 }
185
186 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
187
188 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
189
190 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
191 // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
192 if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
193 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
194 return;
195 }
196
197 GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
198 this->childProcessor(0).computeInvariantOutput(&childOutput);
199
200 if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
201 inout->mulByKnownFourComponents(0x0);
202 return;
203 }
204 GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
205 GrColor c0 = GrPremulColor(inout->color());
206 GrColor c1 = childOutput.color();
207 GrColor color = 0x0;
208 if (commonFlags & kR_GrColorComponentFlag) {
209 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
210 GrColor_SHIFT_R;
211 }
212 if (commonFlags & kG_GrColorComponentFlag) {
213 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
214 GrColor_SHIFT_G;
215 }
216 if (commonFlags & kB_GrColorComponentFlag) {
217 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
218 GrColor_SHIFT_B;
219 }
220 inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
221 }
222 };
223 if (!fp) {
224 return nullptr;
225 }
226 return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
227 }
228
229 //////////////////////////////////////////////////////////////////////////////
230
OverrideInput(sk_sp<GrFragmentProcessor> fp,GrColor4f color)231 sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
232 GrColor4f color) {
233 class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
234 public:
235 ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
236 : fColor(color) {
237 this->initClassID<ReplaceInputFragmentProcessor>();
238 this->registerChildProcessor(std::move(child));
239 }
240
241 const char* name() const override { return "Replace Color"; }
242
243 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
244 class GLFP : public GrGLSLFragmentProcessor {
245 public:
246 GLFP() : fHaveSetColor(false) {}
247 void emitCode(EmitArgs& args) override {
248 const char* colorName;
249 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
250 kVec4f_GrSLType,
251 kDefault_GrSLPrecision,
252 "Color", &colorName);
253 this->emitChild(0, colorName, args);
254 }
255
256 private:
257 void onSetData(const GrGLSLProgramDataManager& pdman,
258 const GrProcessor& fp) override {
259 GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
260 if (!fHaveSetColor || color != fPreviousColor) {
261 pdman.set4fv(fColorUni, 1, color.fRGBA);
262 fPreviousColor = color;
263 fHaveSetColor = true;
264 }
265 }
266
267 GrGLSLProgramDataManager::UniformHandle fColorUni;
268 bool fHaveSetColor;
269 GrColor4f fPreviousColor;
270 };
271
272 return new GLFP;
273 }
274
275 private:
276 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override
277 {}
278
279 bool onIsEqual(const GrFragmentProcessor& that) const override {
280 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
281 }
282
283 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
284 inout->setToOther(kRGBA_GrColorComponentFlags, fColor.toGrColor(),
285 GrInvariantOutput::kWillNot_ReadInput);
286 this->childProcessor(0).computeInvariantOutput(inout);
287 }
288
289 GrColor4f fColor;
290 };
291
292 GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
293 fp->computeInvariantOutput(&childOut);
294 if (childOut.willUseInputColor()) {
295 return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
296 } else {
297 return fp;
298 }
299 }
300
RunInSeries(sk_sp<GrFragmentProcessor> * series,int cnt)301 sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
302 int cnt) {
303 class SeriesFragmentProcessor : public GrFragmentProcessor {
304 public:
305 SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt){
306 SkASSERT(cnt > 1);
307 this->initClassID<SeriesFragmentProcessor>();
308 for (int i = 0; i < cnt; ++i) {
309 this->registerChildProcessor(std::move(children[i]));
310 }
311 }
312
313 const char* name() const override { return "Series"; }
314
315 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
316 class GLFP : public GrGLSLFragmentProcessor {
317 public:
318 void emitCode(EmitArgs& args) override {
319 // First guy's input might be nil.
320 SkString temp("out0");
321 this->emitChild(0, args.fInputColor, &temp, args);
322 SkString input = temp;
323 for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
324 temp.printf("out%d", i);
325 this->emitChild(i, input.c_str(), &temp, args);
326 input = temp;
327 }
328 // Last guy writes to our output variable.
329 this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
330 }
331 };
332 return new GLFP;
333 }
334
335 private:
336 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
337
338 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
339
340 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
341 GrProcOptInfo info;
342 info.calcWithInitialValues(fChildProcessors.begin(), fChildProcessors.count(),
343 inout->color(), inout->validFlags(), false, false);
344 for (int i = 0; i < this->numChildProcessors(); ++i) {
345 this->childProcessor(i).computeInvariantOutput(inout);
346 }
347 }
348 };
349
350 if (!cnt) {
351 return nullptr;
352 }
353
354 // Run the through the series, do the invariant output processing, and look for eliminations.
355 GrProcOptInfo info;
356 info.calcWithInitialValues(sk_sp_address_as_pointer_address(series), cnt,
357 0x0, kNone_GrColorComponentFlags, false, false);
358 if (kRGBA_GrColorComponentFlags == info.validFlags()) {
359 return GrConstColorProcessor::Make(info.color(), GrConstColorProcessor::kIgnore_InputMode);
360 }
361
362 SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
363
364 int firstIdx = info.firstEffectiveProcessorIndex();
365 cnt -= firstIdx;
366 if (firstIdx > 0 && info.inputColorIsUsed()) {
367 sk_sp<GrFragmentProcessor> colorFP(GrConstColorProcessor::Make(
368 info.inputColorToFirstEffectiveProccesor(), GrConstColorProcessor::kIgnore_InputMode));
369 cnt += 1;
370 replacementSeries.reserve(cnt);
371 replacementSeries.emplace_back(std::move(colorFP));
372 for (int i = 0; i < cnt - 1; ++i) {
373 replacementSeries.emplace_back(std::move(series[firstIdx + i]));
374 }
375 series = replacementSeries.begin();
376 } else {
377 series += firstIdx;
378 cnt -= firstIdx;
379 }
380
381 if (1 == cnt) {
382 return series[0];
383 }
384 return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
385 }
386
387 //////////////////////////////////////////////////////////////////////////////
388
Iter(const GrPipeline & pipeline)389 GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
390 for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
391 fFPStack.push_back(&pipeline.getFragmentProcessor(i));
392 }
393 }
394
next()395 const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
396 if (fFPStack.empty()) {
397 return nullptr;
398 }
399 const GrFragmentProcessor* back = fFPStack.back();
400 fFPStack.pop_back();
401 for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
402 fFPStack.push_back(&back->childProcessor(i));
403 }
404 return back;
405 }
406
407